Browse Source

Fixes issues with Close Unchanged Files and prompts for repo

main
Eric Amodio 6 years ago
parent
commit
1fa211d084
2 changed files with 102 additions and 94 deletions
  1. +102
    -36
      src/commands/closeUnchangedFiles.ts
  2. +0
    -58
      src/trackers/activeEditorTracker.ts

+ 102
- 36
src/commands/closeUnchangedFiles.ts View File

@ -5,14 +5,16 @@ import { BuiltInCommands, GlyphChars } from '../constants';
import { Container } from '../container';
import { Logger } from '../logger';
import { Messages } from '../messages';
import { ActiveEditorTracker } from '../trackers/activeEditorTracker';
import { ActiveEditorCommand, Commands, getCommandUri, getRepoPathOrActiveOrPrompt } from './common';
import { Functions } from '../system';
import { ActiveEditorCommand, Commands, getCommandUri, getRepoPathOrPrompt } from './common';
export interface CloseUnchangedFilesCommandArgs {
uris?: Uri[];
}
export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
private _onEditorChangedFn: ((editor: TextEditor | undefined) => void) | undefined;
constructor() {
super(Commands.CloseUnchangedFiles);
}
@ -24,10 +26,9 @@ export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
if (args.uris === undefined) {
args = { ...args };
const repoPath = await getRepoPathOrActiveOrPrompt(
uri,
editor,
`Close unchanged files in which repository${GlyphChars.Ellipsis}`
const repoPath = await getRepoPathOrPrompt(
undefined,
`Close all files except those changed in which repository${GlyphChars.Ellipsis}`
);
if (!repoPath) return undefined;
@ -39,55 +40,120 @@ export class CloseUnchangedFilesCommand extends ActiveEditorCommand {
if (args.uris.length === 0) return commands.executeCommand(BuiltInCommands.CloseAllEditors);
const editorTracker = new ActiveEditorTracker();
const disposable = window.onDidChangeActiveTextEditor(
Functions.debounce(
(e: TextEditor | undefined) => this._onEditorChangedFn && this._onEditorChangedFn(e),
50
)
);
let count = 0;
let previous = undefined;
editor = window.activeTextEditor;
while (true) {
if (editor != null) {
if (TextEditorComparer.equals(previous, editor, { useId: true, usePosition: true })) {
break;
}
if (
editor.document !== undefined &&
(editor.document.isDirty ||
args.uris.some(uri => UriComparer.equals(uri, editor!.document && editor!.document.uri)))
) {
const lastPrevious = previous;
previous = editor;
editor = await editorTracker.awaitNext(500);
let count = 0;
let loopCount = 0;
const editors: TextEditor[] = [];
if (TextEditorComparer.equals(lastPrevious, editor, { useId: true, usePosition: true })) {
// Find out how many editors there are
while (true) {
if (editor != null) {
let found = false;
for (const e of editors) {
if (TextEditorComparer.equals(e, editor, { useId: true, usePosition: true })) {
found = true;
break;
}
continue;
}
}
if (found) break;
previous = editor;
editor = await editorTracker.awaitClose(500);
if (previous === undefined && editor == null) {
// Start counting at the first real editor
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;
}
editors.push(editor);
}
else {
count = 0;
if (count !== 0) {
count++;
}
}
editor = await this.nextEditor();
loopCount++;
// Break out if we've looped 4 times and haven't found any editors
if (loopCount >= 4 && editors.length === 0) break;
}
editorTracker.dispose();
if (editors.length) {
editor = window.activeTextEditor;
for (let i = 0; i <= count; i++) {
if (
editor == null ||
(editor.document !== undefined &&
(editor.document.isDirty ||
args.uris.some(uri =>
UriComparer.equals(uri, editor!.document && editor!.document.uri)
)))
) {
editor = await this.nextEditor();
}
else {
editor = await this.closeEditor();
}
}
}
disposable.dispose();
return undefined;
}
catch (ex) {
Logger.error(ex, 'CloseUnchangedFilesCommand');
return Messages.showGenericErrorMessage('Unable to close unchanged files');
return Messages.showGenericErrorMessage('Unable to close all unchanged files');
}
}
private async closeEditor(timeout: number = 500): Promise<TextEditor | undefined> {
const editor = window.activeTextEditor;
void (await commands.executeCommand(BuiltInCommands.CloseActiveEditor));
if (editor !== window.activeTextEditor) {
return window.activeTextEditor;
}
return this.waitForEditorChange(timeout);
}
private async nextEditor(timeout: number = 500): Promise<TextEditor | undefined> {
const editor = window.activeTextEditor;
void (await commands.executeCommand(BuiltInCommands.NextEditor));
if (editor !== window.activeTextEditor) {
return window.activeTextEditor;
}
return this.waitForEditorChange(timeout);
}
private waitForEditorChange(timeout: number = 500): Promise<TextEditor | undefined> {
return new Promise<TextEditor>((resolve, reject) => {
let timer: NodeJS.Timer | undefined;
this._onEditorChangedFn = (editor: TextEditor | undefined) => {
if (timer) {
clearTimeout(timer);
timer = undefined;
resolve(editor);
}
};
timer = setTimeout(() => {
timer = undefined;
resolve(window.activeTextEditor);
}, timeout);
});
}
}

+ 0
- 58
src/trackers/activeEditorTracker.ts View File

@ -1,58 +0,0 @@
'use strict';
import { commands, Disposable, TextEditor, window } from 'vscode';
import { BuiltInCommands } from '../constants';
import { Functions } from '../system';
export class ActiveEditorTracker implements Disposable {
private _disposable: Disposable;
private _resolver: ((editor: TextEditor | undefined) => void) | undefined;
constructor() {
const fn = Functions.debounce((e: TextEditor | undefined) => this._resolver && this._resolver(e), 50);
this._disposable = window.onDidChangeActiveTextEditor(fn);
}
dispose() {
this._disposable && this._disposable.dispose();
}
async awaitClose(timeout: number = 500): Promise<TextEditor | undefined> {
void this.close();
return this.wait(timeout);
}
async awaitNext(timeout: number = 500): Promise<TextEditor | undefined> {
void this.next();
return this.wait(timeout);
}
async close(): Promise<{} | undefined> {
return commands.executeCommand(BuiltInCommands.CloseActiveEditor);
}
async next(): Promise<{} | undefined> {
return commands.executeCommand(BuiltInCommands.NextEditor);
}
async wait(timeout: number = 500): Promise<TextEditor | undefined> {
const editor = await new Promise<TextEditor>((resolve, reject) => {
let timer: NodeJS.Timer | undefined;
this._resolver = (editor: TextEditor | undefined) => {
if (timer) {
clearTimeout(timer);
timer = undefined;
resolve(editor);
}
};
timer = setTimeout(() => {
resolve(window.activeTextEditor);
timer = undefined;
}, timeout);
});
this._resolver = undefined;
return editor;
}
}

Loading…
Cancel
Save