mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-28 10:00:29 -05:00
57
extensions/git/src/iterators.ts
Normal file
57
extensions/git/src/iterators.ts
Normal file
@@ -0,0 +1,57 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
function* filter<T>(it: IterableIterator<T>, condition: (t: T, i: number) => boolean): IterableIterator<T> {
|
||||
let i = 0;
|
||||
for (let t of it) {
|
||||
if (condition(t, i++)) {
|
||||
yield t;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* map<T, R>(it: IterableIterator<T>, fn: (t: T, i: number) => R): IterableIterator<R> {
|
||||
let i = 0;
|
||||
for (let t of it) {
|
||||
yield fn(t, i++);
|
||||
}
|
||||
}
|
||||
|
||||
export interface FunctionalIterator<T> extends Iterable<T> {
|
||||
filter(condition: (t: T, i: number) => boolean): FunctionalIterator<T>;
|
||||
map<R>(fn: (t: T, i: number) => R): FunctionalIterator<R>;
|
||||
toArray(): T[];
|
||||
}
|
||||
|
||||
class FunctionalIteratorImpl<T> implements FunctionalIterator<T> {
|
||||
|
||||
constructor(private iterator: IterableIterator<T>) { }
|
||||
|
||||
filter(condition: (t: T, i: number) => boolean): FunctionalIterator<T> {
|
||||
return new FunctionalIteratorImpl(filter(this.iterator, condition));
|
||||
}
|
||||
|
||||
map<R>(fn: (t: T, i: number) => R): FunctionalIterator<R> {
|
||||
return new FunctionalIteratorImpl(map<T, R>(this.iterator, fn));
|
||||
}
|
||||
|
||||
toArray(): T[] {
|
||||
return Array.from(this.iterator);
|
||||
}
|
||||
|
||||
[Symbol.iterator](): IterableIterator<T> {
|
||||
return this.iterator;
|
||||
}
|
||||
}
|
||||
|
||||
export function iterate<T>(obj: T[] | IterableIterator<T>): FunctionalIterator<T> {
|
||||
if (Array.isArray(obj)) {
|
||||
return new FunctionalIteratorImpl(obj[Symbol.iterator]());
|
||||
}
|
||||
|
||||
return new FunctionalIteratorImpl(obj);
|
||||
}
|
||||
@@ -14,6 +14,7 @@ import { CheckoutStatusBar, SyncStatusBar } from './statusbar';
|
||||
import { filterEvent, anyEvent } from './util';
|
||||
import { GitContentProvider } from './contentProvider';
|
||||
import { AutoFetcher } from './autofetch';
|
||||
import { MergeDecorator } from './merge';
|
||||
import * as nls from 'vscode-nls';
|
||||
|
||||
const localize = nls.config()();
|
||||
@@ -46,6 +47,7 @@ async function init(disposables: Disposable[]): Promise<void> {
|
||||
const checkoutStatusBar = new CheckoutStatusBar(model);
|
||||
const syncStatusBar = new SyncStatusBar(model);
|
||||
const autoFetcher = new AutoFetcher(model);
|
||||
const mergeDecorator = new MergeDecorator(model);
|
||||
|
||||
disposables.push(
|
||||
commandCenter,
|
||||
@@ -55,7 +57,8 @@ async function init(disposables: Disposable[]): Promise<void> {
|
||||
fsWatcher,
|
||||
checkoutStatusBar,
|
||||
syncStatusBar,
|
||||
autoFetcher
|
||||
autoFetcher,
|
||||
mergeDecorator
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
96
extensions/git/src/merge.ts
Normal file
96
extensions/git/src/merge.ts
Normal file
@@ -0,0 +1,96 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
'use strict';
|
||||
|
||||
import { window, workspace, Disposable, TextEditor, TextDocument, Range } from 'vscode';
|
||||
import { Model, Status } from './model';
|
||||
import { filterEvent } from './util';
|
||||
import { debounce } from './decorators';
|
||||
import { iterate } from './iterators';
|
||||
|
||||
function* lines(document: TextDocument): IterableIterator<string> {
|
||||
for (let i = 0; i < document.lineCount; i++) {
|
||||
yield document.lineAt(i).text;
|
||||
}
|
||||
}
|
||||
|
||||
const pattern = /^<<<<<<<|^=======|^>>>>>>>/;
|
||||
|
||||
function decorate(document: TextDocument): Range[] {
|
||||
return iterate(lines(document))
|
||||
.map((line, i) => pattern.test(line) ? i : null)
|
||||
.filter(i => i !== null)
|
||||
.map((i: number) => new Range(i, 1, i, 1))
|
||||
.toArray();
|
||||
}
|
||||
|
||||
class TextEditorMergeDecorator {
|
||||
|
||||
private static DecorationType = window.createTextEditorDecorationType({
|
||||
backgroundColor: 'rgba(255, 139, 0, 0.3)',
|
||||
isWholeLine: true,
|
||||
dark: {
|
||||
backgroundColor: 'rgba(235, 59, 0, 0.3)'
|
||||
}
|
||||
});
|
||||
|
||||
private uri: string;
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(
|
||||
private model: Model,
|
||||
private editor: TextEditor
|
||||
) {
|
||||
this.uri = this.editor.document.uri.toString();
|
||||
|
||||
const onDidChange = filterEvent(workspace.onDidChangeTextDocument, e => e.document && e.document.uri.toString() === this.uri);
|
||||
onDidChange(this.redecorate, this, this.disposables);
|
||||
model.onDidChange(this.redecorate, this, this.disposables);
|
||||
|
||||
this.redecorate();
|
||||
}
|
||||
|
||||
@debounce(300)
|
||||
private redecorate(): void {
|
||||
let decorations: Range[] = [];
|
||||
|
||||
if (window.visibleTextEditors.every(e => e !== this.editor)) {
|
||||
this.dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.model.mergeGroup.resources.some(r => r.type === Status.BOTH_MODIFIED && r.uri.toString() === this.uri)) {
|
||||
decorations = decorate(this.editor.document);
|
||||
}
|
||||
|
||||
this.editor.setDecorations(TextEditorMergeDecorator.DecorationType, decorations);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
}
|
||||
}
|
||||
|
||||
export class MergeDecorator {
|
||||
|
||||
private textEditorDecorators: TextEditorMergeDecorator[] = [];
|
||||
private disposables: Disposable[] = [];
|
||||
|
||||
constructor(private model: Model) {
|
||||
window.onDidChangeVisibleTextEditors(this.onDidChangeVisibleTextEditors, this, this.disposables);
|
||||
this.onDidChangeVisibleTextEditors(window.visibleTextEditors);
|
||||
}
|
||||
|
||||
private onDidChangeVisibleTextEditors(editors: TextEditor[]): void {
|
||||
this.textEditorDecorators.forEach(d => d.dispose());
|
||||
this.textEditorDecorators = editors.map(e => new TextEditorMergeDecorator(this.model, e));
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.textEditorDecorators.forEach(d => d.dispose());
|
||||
this.disposables.forEach(d => d.dispose());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user