mirror of
https://github.com/ckaczor/vscode-gitlens.git
synced 2026-02-17 02:51:47 -05:00
Fixes #83 - Close Unchanged Files command can infinitely loop
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
import { Functions } from './system';
|
||||||
import { commands, Disposable, TextEditor, window } from 'vscode';
|
import { commands, Disposable, TextEditor, window } from 'vscode';
|
||||||
import { BuiltInCommands } from './constants';
|
import { BuiltInCommands } from './constants';
|
||||||
|
|
||||||
@@ -11,19 +12,20 @@ export class ActiveEditorTracker extends Disposable {
|
|||||||
constructor() {
|
constructor() {
|
||||||
super(() => this.dispose());
|
super(() => this.dispose());
|
||||||
|
|
||||||
this._disposable = window.onDidChangeActiveTextEditor(e => this._resolver && this._resolver(e));
|
const fn = Functions.debounce((e: TextEditor) => this._resolver && this._resolver(e), 50);
|
||||||
|
this._disposable = window.onDidChangeActiveTextEditor(fn);
|
||||||
}
|
}
|
||||||
|
|
||||||
dispose() {
|
dispose() {
|
||||||
this._disposable && this._disposable.dispose();
|
this._disposable && this._disposable.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
async awaitClose(timeout: number = 500): Promise<TextEditor> {
|
async awaitClose(timeout: number = 500): Promise<TextEditor | undefined> {
|
||||||
this.close();
|
this.close();
|
||||||
return this.wait(timeout);
|
return this.wait(timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
async awaitNext(timeout: number = 500): Promise<TextEditor> {
|
async awaitNext(timeout: number = 500): Promise<TextEditor | undefined> {
|
||||||
this.next();
|
this.next();
|
||||||
return this.wait(timeout);
|
return this.wait(timeout);
|
||||||
}
|
}
|
||||||
@@ -36,15 +38,15 @@ export class ActiveEditorTracker extends Disposable {
|
|||||||
return commands.executeCommand(BuiltInCommands.NextEditor);
|
return commands.executeCommand(BuiltInCommands.NextEditor);
|
||||||
}
|
}
|
||||||
|
|
||||||
async wait(timeout: number = 500): Promise<TextEditor> {
|
async wait(timeout: number = 500): Promise<TextEditor | undefined> {
|
||||||
const editor = await new Promise<TextEditor>((resolve, reject) => {
|
const editor = await new Promise<TextEditor>((resolve, reject) => {
|
||||||
let timer: any;
|
let timer: any;
|
||||||
|
|
||||||
this._resolver = (editor: TextEditor) => {
|
this._resolver = (e: TextEditor) => {
|
||||||
if (timer) {
|
if (timer) {
|
||||||
clearTimeout(timer as any);
|
clearTimeout(timer as any);
|
||||||
timer = 0;
|
timer = 0;
|
||||||
resolve(editor);
|
resolve(e);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -53,6 +55,7 @@ export class ActiveEditorTracker extends Disposable {
|
|||||||
timer = 0;
|
timer = 0;
|
||||||
}, timeout) as any;
|
}, timeout) as any;
|
||||||
});
|
});
|
||||||
|
|
||||||
this._resolver = undefined;
|
this._resolver = undefined;
|
||||||
return editor;
|
return editor;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
import { TextEditor, Uri, window } from 'vscode';
|
import { commands, TextEditor, Uri, window } from 'vscode';
|
||||||
import { ActiveEditorTracker } from '../activeEditorTracker';
|
import { ActiveEditorTracker } from '../activeEditorTracker';
|
||||||
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
import { ActiveEditorCommand, Commands, getCommandUri } from './common';
|
||||||
import { TextEditorComparer, UriComparer } from '../comparers';
|
import { TextEditorComparer, UriComparer } from '../comparers';
|
||||||
|
import { BuiltInCommands } from '../constants';
|
||||||
import { GitService } from '../gitService';
|
import { GitService } from '../gitService';
|
||||||
import { Logger } from '../logger';
|
import { Logger } from '../logger';
|
||||||
|
|
||||||
@@ -30,34 +31,41 @@ export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
|
|||||||
args.uris = status.files.map(_ => _.Uri);
|
args.uris = status.files.map(_ => _.Uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors);
|
||||||
|
|
||||||
const editorTracker = new ActiveEditorTracker();
|
const editorTracker = new ActiveEditorTracker();
|
||||||
|
|
||||||
let active = window.activeTextEditor;
|
let count = 0;
|
||||||
let editor = active;
|
let previous = undefined;
|
||||||
do {
|
let editor = window.activeTextEditor;
|
||||||
|
while (true) {
|
||||||
if (editor !== undefined) {
|
if (editor !== undefined) {
|
||||||
if ((editor.document !== undefined && editor.document.isDirty) ||
|
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) {
|
||||||
args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri))) {
|
break;
|
||||||
// If we didn't start with a valid editor, set one once we find it
|
|
||||||
if (active === undefined) {
|
|
||||||
active = editor;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editor.document !== undefined &&
|
||||||
|
(editor.document.isDirty || args.uris.some(_ => UriComparer.equals(_, editor!.document && editor!.document.uri)))) {
|
||||||
|
previous = editor;
|
||||||
editor = await editorTracker.awaitNext(500);
|
editor = await editorTracker.awaitNext(500);
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
if (active === editor) {
|
|
||||||
active = undefined;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
previous = editor;
|
||||||
editor = await editorTracker.awaitClose(500);
|
editor = await editorTracker.awaitClose(500);
|
||||||
|
|
||||||
|
if (previous === undefined && editor === undefined) {
|
||||||
|
count++;
|
||||||
|
// This is such a shitty hack, but I can't figure out any other reliable way to know that we've cycled through all the editors :(
|
||||||
|
if (count >= 4) {
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (active === editor) {
|
count = 0;
|
||||||
active = undefined;
|
|
||||||
}
|
}
|
||||||
editor = await editorTracker.awaitClose(500);
|
|
||||||
}
|
}
|
||||||
} while ((active === undefined && editor === undefined) || !TextEditorComparer.equals(active, editor, { useId: true, usePosition: true }));
|
|
||||||
|
|
||||||
editorTracker.dispose();
|
editorTracker.dispose();
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,10 @@ export const QualifiedExtensionId = `eamodio.${ExtensionId}`;
|
|||||||
|
|
||||||
export const ApplicationInsightsKey = 'a9c302f8-6483-4d01-b92c-c159c799c679';
|
export const ApplicationInsightsKey = 'a9c302f8-6483-4d01-b92c-c159c799c679';
|
||||||
|
|
||||||
export type BuiltInCommands = 'cursorMove' | 'editor.action.showReferences' | 'editor.action.toggleRenderWhitespace' | 'editorScroll' | 'revealLine' | 'setContext' | 'vscode.diff' | 'vscode.executeDocumentSymbolProvider' | 'vscode.executeCodeLensProvider' | 'vscode.open' | 'vscode.previewHtml' | 'workbench.action.closeActiveEditor' | 'workbench.action.nextEditor';
|
export type BuiltInCommands = 'cursorMove' | 'editor.action.showReferences' | 'editor.action.toggleRenderWhitespace' | 'editorScroll' | 'revealLine' | 'setContext' | 'vscode.diff' | 'vscode.executeDocumentSymbolProvider' | 'vscode.executeCodeLensProvider' | 'vscode.open' | 'vscode.previewHtml' | 'workbench.action.closeActiveEditor' | 'workbench.action.closeAllEditors' | 'workbench.action.nextEditor';
|
||||||
export const BuiltInCommands = {
|
export const BuiltInCommands = {
|
||||||
CloseActiveEditor: 'workbench.action.closeActiveEditor' as BuiltInCommands,
|
CloseActiveEditor: 'workbench.action.closeActiveEditor' as BuiltInCommands,
|
||||||
|
CloseAllEditors: 'workbench.action.closeAllEditors' as BuiltInCommands,
|
||||||
CursorMove: 'cursorMove' as BuiltInCommands,
|
CursorMove: 'cursorMove' as BuiltInCommands,
|
||||||
Diff: 'vscode.diff' as BuiltInCommands,
|
Diff: 'vscode.diff' as BuiltInCommands,
|
||||||
EditorScroll: 'editorScroll' as BuiltInCommands,
|
EditorScroll: 'editorScroll' as BuiltInCommands,
|
||||||
|
|||||||
Reference in New Issue
Block a user