From 6173cf8a99005aa90ee25b92c8385395caccb8bd Mon Sep 17 00:00:00 2001 From: Benjamin Pasero Date: Thu, 10 Sep 2020 10:23:23 +0200 Subject: [PATCH] pinned tabs - closing pinned tab should open next non-pinned --- .../browser/parts/editor/editorCommands.ts | 31 +++++++++++++++- .../services/editor/browser/editorService.ts | 37 +++++++++---------- .../services/editor/common/editorService.ts | 4 +- .../editor/test/browser/editorService.test.ts | 5 +++ 4 files changed, 55 insertions(+), 22 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 3ba68a4a924..d5b43851ab0 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -478,15 +478,44 @@ function registerSplitEditorCommands() { function registerCloseEditorCommands() { + // A special handler for "Close Editor" depending on context + // - keybindining: do not close sticky editors, rather open the next non-sticky editor + // - menu: always close editor, even sticky ones function closeEditorHandler(accessor: ServicesAccessor, forceCloseStickyEditors: boolean, resourceOrContext?: URI | IEditorCommandsContext, context?: IEditorCommandsContext): Promise { + const editorGroupsService = accessor.get(IEditorGroupsService); + const editorService = accessor.get(IEditorService); + let keepStickyEditors = true; if (forceCloseStickyEditors) { keepStickyEditors = false; // explicitly close sticky editors - } else if (resourceOrContext) { + } else if (resourceOrContext || context) { keepStickyEditors = false; // we have a context, as such this command was used e.g. from the tab context menu } + // Without context: skip over sticky editor and select next if active editor is sticky + if (keepStickyEditors && !resourceOrContext && !context) { + const activeGroup = editorGroupsService.activeGroup; + const activeEditor = activeGroup.activeEditor; + + if (activeEditor && activeGroup.isSticky(activeEditor)) { + + // Open next recently active in same group + const nextNonStickyEditorInGroup = activeGroup.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: true })[0]; + if (nextNonStickyEditorInGroup) { + return activeGroup.openEditor(nextNonStickyEditorInGroup); + } + + // Open next recently active across all groups + const nextNonStickyEditorInAllGroups = editorService.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: true })[0]; + if (nextNonStickyEditorInAllGroups) { + return Promise.resolve(editorGroupsService.getGroup(nextNonStickyEditorInAllGroups.groupId)?.openEditor(nextNonStickyEditorInAllGroups.editor)); + } + } + } + + // With context: proceed to close editors as instructed const { editors, groups } = getEditorsContext(accessor, resourceOrContext, context); + return Promise.all(groups.map(async group => { if (group) { const editorsToClose = coalesce(editors diff --git a/src/vs/workbench/services/editor/browser/editorService.ts b/src/vs/workbench/services/editor/browser/editorService.ts index 2f64b62a888..be65afb3a83 100644 --- a/src/vs/workbench/services/editor/browser/editorService.ts +++ b/src/vs/workbench/services/editor/browser/editorService.ts @@ -436,20 +436,27 @@ export class EditorService extends Disposable implements EditorServiceImpl { return this.getEditors(EditorsOrder.SEQUENTIAL).map(({ editor }) => editor); } - getEditors(order: EditorsOrder.MOST_RECENTLY_ACTIVE): ReadonlyArray; - getEditors(order: EditorsOrder.SEQUENTIAL, options?: { excludeSticky?: boolean }): ReadonlyArray; getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): ReadonlyArray { - if (order === EditorsOrder.MOST_RECENTLY_ACTIVE) { - return this.editorsObserver.editors; - } + switch (order) { - const editors: IEditorIdentifier[] = []; + // MRU + case EditorsOrder.MOST_RECENTLY_ACTIVE: + if (options?.excludeSticky) { + return this.editorsObserver.editors.filter(({ groupId, editor }) => !this.editorGroupService.getGroup(groupId)?.isSticky(editor)); + } - this.editorGroupService.getGroups(GroupsOrder.GRID_APPEARANCE).forEach(group => { - editors.push(...group.getEditors(EditorsOrder.SEQUENTIAL, options).map(editor => ({ editor, groupId: group.id }))); - }); + return this.editorsObserver.editors; - return editors; + // Sequential + case EditorsOrder.SEQUENTIAL: + const editors: IEditorIdentifier[] = []; + + this.editorGroupService.getGroups(GroupsOrder.GRID_APPEARANCE).forEach(group => { + editors.push(...group.getEditors(EditorsOrder.SEQUENTIAL, options).map(editor => ({ editor, groupId: group.id }))); + }); + + return editors; + } } get activeEditor(): IEditorInput | undefined { @@ -1323,15 +1330,7 @@ export class DelegatingEditorService implements IEditorService { get editors(): ReadonlyArray { return this.editorService.editors; } get count(): number { return this.editorService.count; } - getEditors(order: EditorsOrder.MOST_RECENTLY_ACTIVE): ReadonlyArray; - getEditors(order: EditorsOrder.SEQUENTIAL, options?: { excludeSticky?: boolean }): ReadonlyArray; - getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): ReadonlyArray { - if (order === EditorsOrder.MOST_RECENTLY_ACTIVE) { - return this.editorService.getEditors(order); - } - - return this.editorService.getEditors(order, options); - } + getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): ReadonlyArray { return this.editorService.getEditors(order, options); } openEditors(editors: IEditorInputWithOptions[], group?: OpenInEditorGroup): Promise; openEditors(editors: IResourceEditorInputType[], group?: OpenInEditorGroup): Promise; diff --git a/src/vs/workbench/services/editor/common/editorService.ts b/src/vs/workbench/services/editor/common/editorService.ts index 8e481661296..acf29c20162 100644 --- a/src/vs/workbench/services/editor/common/editorService.ts +++ b/src/vs/workbench/services/editor/common/editorService.ts @@ -175,9 +175,9 @@ export interface IEditorService { * identifier. * * @param order the order of the editors to use + * @param options wether to exclude sticky editors or not */ - getEditors(order: EditorsOrder.MOST_RECENTLY_ACTIVE): ReadonlyArray; - getEditors(order: EditorsOrder.SEQUENTIAL, options?: { excludeSticky?: boolean }): ReadonlyArray; + getEditors(order: EditorsOrder, options?: { excludeSticky?: boolean }): ReadonlyArray; /** * Open an editor in an editor group. diff --git a/src/vs/workbench/services/editor/test/browser/editorService.test.ts b/src/vs/workbench/services/editor/test/browser/editorService.test.ts index 817616f1ccd..3f8b9cba412 100644 --- a/src/vs/workbench/services/editor/test/browser/editorService.test.ts +++ b/src/vs/workbench/services/editor/test/browser/editorService.test.ts @@ -163,6 +163,11 @@ suite('EditorService', () => { assert.equal(input, sequentialEditorsExcludingSticky[0].editor); assert.equal(otherInput, sequentialEditorsExcludingSticky[1].editor); + const mruEditorsExcludingSticky = service.getEditors(EditorsOrder.MOST_RECENTLY_ACTIVE, { excludeSticky: true }); + assert.equal(mruEditorsExcludingSticky.length, 2); + assert.equal(input, sequentialEditorsExcludingSticky[0].editor); + assert.equal(otherInput, sequentialEditorsExcludingSticky[1].editor); + activeEditorChangeListener.dispose(); visibleEditorChangeListener.dispose(); didCloseEditorListener.dispose(); -- GitLab