From 83f695ad2ae4befe613dfd1bb1b1d8547d647d53 Mon Sep 17 00:00:00 2001 From: Benjamin Christopher Simmonds <44439583+benibenj@users.noreply.github.com> Date: Wed, 18 Dec 2024 09:29:54 +0100 Subject: [PATCH] Move selected editors instead of only activ ones (#236327) * move selected editors * :lipstick: * :lipstick: --- .../browser/parts/editor/editorActions.ts | 38 +++++++------- .../browser/parts/editor/editorCommands.ts | 52 ++++++++++++------- 2 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/vs/workbench/browser/parts/editor/editorActions.ts b/src/vs/workbench/browser/parts/editor/editorActions.ts index be79b3f0af2f8..9d9766f4eb503 100644 --- a/src/vs/workbench/browser/parts/editor/editorActions.ts +++ b/src/vs/workbench/browser/parts/editor/editorActions.ts @@ -12,7 +12,7 @@ import { IWorkbenchLayoutService, Parts } from '../../../services/layout/browser import { GoFilter, IHistoryService } from '../../../services/history/common/history.js'; import { IKeybindingService } from '../../../../platform/keybinding/common/keybinding.js'; import { ICommandService } from '../../../../platform/commands/common/commands.js'; -import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, ActiveEditorMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, TOGGLE_MAXIMIZE_EDITOR_GROUP, MOVE_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, MOVE_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID as NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID } from './editorCommands.js'; +import { CLOSE_EDITOR_COMMAND_ID, MOVE_ACTIVE_EDITOR_COMMAND_ID, SelectedEditorsMoveCopyArguments, SPLIT_EDITOR_LEFT, SPLIT_EDITOR_RIGHT, SPLIT_EDITOR_UP, SPLIT_EDITOR_DOWN, splitEditor, LAYOUT_EDITOR_GROUPS_COMMAND_ID, UNPIN_EDITOR_COMMAND_ID, COPY_ACTIVE_EDITOR_COMMAND_ID, SPLIT_EDITOR, TOGGLE_MAXIMIZE_EDITOR_GROUP, MOVE_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_INTO_NEW_WINDOW_COMMAND_ID, MOVE_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, COPY_EDITOR_GROUP_INTO_NEW_WINDOW_COMMAND_ID, NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID as NEW_EMPTY_EDITOR_WINDOW_COMMAND_ID } from './editorCommands.js'; import { IEditorGroupsService, IEditorGroup, GroupsArrangement, GroupLocation, GroupDirection, preferredSideBySideGroupDirection, IFindGroupScope, GroupOrientation, EditorGroupLayout, GroupsOrder, MergeGroupMode } from '../../../services/editor/common/editorGroupsService.js'; import { IEditorService } from '../../../services/editor/common/editorService.js'; import { IConfigurationService } from '../../../../platform/configuration/common/configuration.js'; @@ -1996,7 +1996,7 @@ export class MoveEditorLeftInGroupAction extends ExecuteCommandAction { }, f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'left' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'left' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2015,7 +2015,7 @@ export class MoveEditorRightInGroupAction extends ExecuteCommandAction { }, f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'right' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'right' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2034,7 +2034,7 @@ export class MoveEditorToPreviousGroupAction extends ExecuteCommandAction { }, f1: true, category: Categories.View, - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'previous', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'previous', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2053,7 +2053,7 @@ export class MoveEditorToNextGroupAction extends ExecuteCommandAction { } }, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'next', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'next', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2065,7 +2065,7 @@ export class MoveEditorToAboveGroupAction extends ExecuteCommandAction { title: localize2('moveEditorToAboveGroup', 'Move Editor into Group Above'), f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'up', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'up', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2077,7 +2077,7 @@ export class MoveEditorToBelowGroupAction extends ExecuteCommandAction { title: localize2('moveEditorToBelowGroup', 'Move Editor into Group Below'), f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'down', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'down', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2089,7 +2089,7 @@ export class MoveEditorToLeftGroupAction extends ExecuteCommandAction { title: localize2('moveEditorToLeftGroup', 'Move Editor into Left Group'), f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'left', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'left', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2101,7 +2101,7 @@ export class MoveEditorToRightGroupAction extends ExecuteCommandAction { title: localize2('moveEditorToRightGroup', 'Move Editor into Right Group'), f1: true, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'right', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'right', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2120,7 +2120,7 @@ export class MoveEditorToFirstGroupAction extends ExecuteCommandAction { } }, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'first', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'first', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2139,7 +2139,7 @@ export class MoveEditorToLastGroupAction extends ExecuteCommandAction { } }, category: Categories.View - }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'last', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, MOVE_ACTIVE_EDITOR_COMMAND_ID, { to: 'last', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2151,7 +2151,7 @@ export class SplitEditorToPreviousGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToPreviousGroup', 'Split Editor into Previous Group'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'previous', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'previous', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2163,7 +2163,7 @@ export class SplitEditorToNextGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToNextGroup', 'Split Editor into Next Group'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'next', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'next', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2175,7 +2175,7 @@ export class SplitEditorToAboveGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToAboveGroup', 'Split Editor into Group Above'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'up', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'up', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2187,7 +2187,7 @@ export class SplitEditorToBelowGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToBelowGroup', 'Split Editor into Group Below'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'down', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'down', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2202,7 +2202,7 @@ export class SplitEditorToLeftGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToLeftGroup', "Split Editor into Left Group"), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'left', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'left', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2214,7 +2214,7 @@ export class SplitEditorToRightGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToRightGroup', 'Split Editor into Right Group'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'right', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'right', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2226,7 +2226,7 @@ export class SplitEditorToFirstGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToFirstGroup', 'Split Editor into First Group'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'first', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'first', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } @@ -2238,7 +2238,7 @@ export class SplitEditorToLastGroupAction extends ExecuteCommandAction { title: localize2('splitEditorToLastGroup', 'Split Editor into Last Group'), f1: true, category: Categories.View - }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'last', by: 'group' } satisfies ActiveEditorMoveCopyArguments); + }, COPY_ACTIVE_EDITOR_COMMAND_ID, { to: 'last', by: 'group' } satisfies SelectedEditorsMoveCopyArguments); } } diff --git a/src/vs/workbench/browser/parts/editor/editorCommands.ts b/src/vs/workbench/browser/parts/editor/editorCommands.ts index 83f88bd7b749d..1bbe6258eb05e 100644 --- a/src/vs/workbench/browser/parts/editor/editorCommands.ts +++ b/src/vs/workbench/browser/parts/editor/editorCommands.ts @@ -28,7 +28,7 @@ import { ActiveGroupEditorsByMostRecentlyUsedQuickAccess } from './editorQuickAc import { SideBySideEditor } from './sideBySideEditor.js'; import { TextDiffEditor } from './textDiffEditor.js'; import { ActiveEditorCanSplitInGroupContext, ActiveEditorGroupEmptyContext, ActiveEditorGroupLockedContext, ActiveEditorStickyContext, MultipleEditorGroupsContext, SideBySideEditorActiveContext, TextCompareEditorActiveContext } from '../../../common/contextkeys.js'; -import { CloseDirection, EditorInputCapabilities, EditorsOrder, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, IVisibleEditorPane, isEditorInputWithOptionsAndGroup } from '../../../common/editor.js'; +import { CloseDirection, EditorInputCapabilities, EditorsOrder, IResourceDiffEditorInput, IUntitledTextResourceEditorInput, isEditorInputWithOptionsAndGroup } from '../../../common/editor.js'; import { DiffEditorInput } from '../../../common/editor/diffEditorInput.js'; import { EditorInput } from '../../../common/editor/editorInput.js'; import { SideBySideEditorInput } from '../../../common/editor/sideBySideEditorInput.js'; @@ -108,13 +108,13 @@ export const EDITOR_CORE_NAVIGATION_COMMANDS = [ TOGGLE_MAXIMIZE_EDITOR_GROUP ]; -export interface ActiveEditorMoveCopyArguments { +export interface SelectedEditorsMoveCopyArguments { to?: 'first' | 'last' | 'left' | 'right' | 'up' | 'down' | 'center' | 'position' | 'previous' | 'next'; by?: 'tab' | 'group'; value?: number; } -const isActiveEditorMoveCopyArg = function (arg: ActiveEditorMoveCopyArguments): boolean { +const isSelectedEditorsMoveCopyArg = function (arg: SelectedEditorsMoveCopyArguments): boolean { if (!isObject(arg)) { return false; } @@ -159,14 +159,14 @@ function registerActiveEditorMoveCopyCommand(): void { weight: KeybindingWeight.WorkbenchContrib, when: EditorContextKeys.editorTextFocus, primary: 0, - handler: (accessor, args) => moveCopyActiveEditor(true, args, accessor), + handler: (accessor, args) => moveCopySelectedEditors(true, args, accessor), metadata: { description: localize('editorCommand.activeEditorMove.description', "Move the active editor by tabs or groups"), args: [ { name: localize('editorCommand.activeEditorMove.arg.name', "Active editor move argument"), description: localize('editorCommand.activeEditorMove.arg.description', "Argument Properties:\n\t* 'to': String value providing where to move.\n\t* 'by': String value providing the unit for move (by tab or by group).\n\t* 'value': Number value providing how many positions or an absolute position to move."), - constraint: isActiveEditorMoveCopyArg, + constraint: isSelectedEditorsMoveCopyArg, schema: moveCopyJSONSchema } ] @@ -178,42 +178,55 @@ function registerActiveEditorMoveCopyCommand(): void { weight: KeybindingWeight.WorkbenchContrib, when: EditorContextKeys.editorTextFocus, primary: 0, - handler: (accessor, args) => moveCopyActiveEditor(false, args, accessor), + handler: (accessor, args) => moveCopySelectedEditors(false, args, accessor), metadata: { description: localize('editorCommand.activeEditorCopy.description', "Copy the active editor by groups"), args: [ { name: localize('editorCommand.activeEditorCopy.arg.name', "Active editor copy argument"), description: localize('editorCommand.activeEditorCopy.arg.description', "Argument Properties:\n\t* 'to': String value providing where to copy.\n\t* 'value': Number value providing how many positions or an absolute position to copy."), - constraint: isActiveEditorMoveCopyArg, + constraint: isSelectedEditorsMoveCopyArg, schema: moveCopyJSONSchema } ] } }); - function moveCopyActiveEditor(isMove: boolean, args: ActiveEditorMoveCopyArguments = Object.create(null), accessor: ServicesAccessor): void { + function moveCopySelectedEditors(isMove: boolean, args: SelectedEditorsMoveCopyArguments = Object.create(null), accessor: ServicesAccessor): void { args.to = args.to || 'right'; args.by = args.by || 'tab'; args.value = typeof args.value === 'number' ? args.value : 1; - const activeEditorPane = accessor.get(IEditorService).activeEditorPane; - if (activeEditorPane) { + const activeGroup = accessor.get(IEditorGroupsService).activeGroup; + const selectedEditors = activeGroup.selectedEditors; + if (selectedEditors.length > 0) { switch (args.by) { case 'tab': if (isMove) { - return moveActiveTab(args, activeEditorPane); + return moveTabs(args, activeGroup, selectedEditors); } break; case 'group': - return moveCopyActiveEditorToGroup(isMove, args, activeEditorPane, accessor); + return moveCopyActiveEditorToGroup(isMove, args, activeGroup, selectedEditors, accessor); } } } - function moveActiveTab(args: ActiveEditorMoveCopyArguments, control: IVisibleEditorPane): void { - const group = control.group; - let index = group.getIndexOfEditor(control.input); + function moveTabs(args: SelectedEditorsMoveCopyArguments, group: IEditorGroup, editors: EditorInput[]): void { + const to = args.to; + if (to === 'first' || to === 'right') { + editors = [...editors].reverse(); + } else if (to === 'position' && (args.value ?? 1) < group.getIndexOfEditor(editors[0])) { + editors = [...editors].reverse(); + } + + for (const editor of editors) { + moveTab(args, group, editor); + } + } + + function moveTab(args: SelectedEditorsMoveCopyArguments, group: IEditorGroup, editor: EditorInput): void { + let index = group.getIndexOfEditor(editor); switch (args.to) { case 'first': index = 0; @@ -236,14 +249,13 @@ function registerActiveEditorMoveCopyCommand(): void { } index = index < 0 ? 0 : index >= group.count ? group.count - 1 : index; - group.moveEditor(control.input, group, { index }); + group.moveEditor(editor, group, { index }); } - function moveCopyActiveEditorToGroup(isMove: boolean, args: ActiveEditorMoveCopyArguments, control: IVisibleEditorPane, accessor: ServicesAccessor): void { + function moveCopyActiveEditorToGroup(isMove: boolean, args: SelectedEditorsMoveCopyArguments, sourceGroup: IEditorGroup, editors: EditorInput[], accessor: ServicesAccessor): void { const editorGroupsService = accessor.get(IEditorGroupsService); const configurationService = accessor.get(IConfigurationService); - const sourceGroup = control.group; let targetGroup: IEditorGroup | undefined; switch (args.to) { @@ -296,9 +308,9 @@ function registerActiveEditorMoveCopyCommand(): void { if (targetGroup) { if (isMove) { - sourceGroup.moveEditor(control.input, targetGroup); + sourceGroup.moveEditors(editors.map(editor => ({ editor })), targetGroup); } else if (sourceGroup.id !== targetGroup.id) { - sourceGroup.copyEditor(control.input, targetGroup); + sourceGroup.copyEditors(editors.map(editor => ({ editor })), targetGroup); } targetGroup.focus(); }