Merge pull request #127120 from microsoft/tyriar/126256
Terminal editor + button
This commit is contained in:
commit
3c1fc33b75
|
@ -32,8 +32,8 @@ export class DropdownWithPrimaryActionViewItem extends BaseActionViewItem {
|
|||
dropdownMenuActions: IAction[],
|
||||
className: string,
|
||||
private readonly _contextMenuProvider: IContextMenuProvider,
|
||||
_keybindingService: IKeybindingService,
|
||||
_notificationService: INotificationService
|
||||
@IKeybindingService _keybindingService: IKeybindingService,
|
||||
@INotificationService _notificationService: INotificationService
|
||||
) {
|
||||
super(null, primaryAction);
|
||||
this._primaryAction = new MenuEntryActionViewItem(primaryAction, _keybindingService, _notificationService);
|
||||
|
|
|
@ -594,7 +594,7 @@ export interface IBaseUnresolvedTerminalProfile {
|
|||
args?: string | string[] | undefined;
|
||||
isAutoDetected?: boolean;
|
||||
overrideName?: boolean;
|
||||
icon?: ThemeIcon | URI | { light: URI, dark: URI };
|
||||
icon?: string | ThemeIcon | URI | { light: URI, dark: URI };
|
||||
color?: string;
|
||||
env?: ITerminalEnvironment;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import { findExecutable, getWindowsBuildNumber } from 'vs/platform/terminal/node
|
|||
import * as cp from 'child_process';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import * as pfs from 'vs/base/node/pfs';
|
||||
import { ITerminalEnvironment, ITerminalProfile, ITerminalProfileObject, ProfileSource, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { ITerminalEnvironment, ITerminalProfile, ITerminalProfileObject, ProfileSource, TerminalIcon, TerminalSettingId } from 'vs/platform/terminal/common/terminal';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { isLinux, isWindows } from 'vs/base/common/platform';
|
||||
import { ThemeIcon } from 'vs/platform/theme/common/themeService';
|
||||
|
@ -156,14 +156,14 @@ async function transformToTerminalProfiles(
|
|||
// if there are configured args, override the default ones
|
||||
args = profile.args || source.args;
|
||||
if (profile.icon) {
|
||||
icon = profile.icon;
|
||||
icon = validateIcon(profile.icon);
|
||||
} else if (source.icon) {
|
||||
icon = source.icon;
|
||||
}
|
||||
} else {
|
||||
originalPaths = Array.isArray(profile.path) ? profile.path : [profile.path];
|
||||
args = isWindows ? profile.args : Array.isArray(profile.args) ? profile.args : undefined;
|
||||
icon = profile.icon || undefined;
|
||||
icon = validateIcon(profile.icon) || undefined;
|
||||
}
|
||||
|
||||
const paths = (await variableResolver?.(originalPaths)) || originalPaths.slice();
|
||||
|
@ -180,6 +180,13 @@ async function transformToTerminalProfiles(
|
|||
return resultProfiles;
|
||||
}
|
||||
|
||||
function validateIcon(icon: string | TerminalIcon | undefined): TerminalIcon | undefined {
|
||||
if (typeof icon === 'string') {
|
||||
return { id: icon };
|
||||
}
|
||||
return icon;
|
||||
}
|
||||
|
||||
async function initializeWindowsProfiles(testPwshSourcePaths?: string[]): Promise<void> {
|
||||
if (profileSources && !testPwshSourcePaths) {
|
||||
return;
|
||||
|
|
|
@ -153,6 +153,7 @@ export interface ITerminalService extends ITerminalInstanceHost {
|
|||
/**
|
||||
* Creates a raw terminal instance, this should not be used outside of the terminal part.
|
||||
*/
|
||||
createInstance(profile: ITerminalProfile): ITerminalInstance;
|
||||
createInstance(shellLaunchConfig: IShellLaunchConfig): ITerminalInstance;
|
||||
getInstanceFromId(terminalId: number): ITerminalInstance | undefined;
|
||||
getInstanceFromIndex(terminalIndex: number): ITerminalInstance;
|
||||
|
@ -197,7 +198,9 @@ export interface ITerminalService extends ITerminalInstanceHost {
|
|||
setEditable(instance: ITerminalInstance, data: IEditableData | null): Promise<void>;
|
||||
safeDisposeTerminal(instance: ITerminalInstance): Promise<void>;
|
||||
|
||||
getFindHost(): ITerminalFindHost;
|
||||
getDefaultInstanceHost(): ITerminalInstanceHost;
|
||||
getInstanceHost(target: TerminalLocation | undefined): ITerminalInstanceHost;
|
||||
getFindHost(instance?: ITerminalInstance): ITerminalFindHost;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -214,6 +217,7 @@ export interface ITerminalEditorService extends ITerminalInstanceHost, ITerminal
|
|||
getOrCreateEditorInput(instance: ITerminalInstance | SerializedTerminalEditorInput): TerminalEditorInput;
|
||||
detachActiveEditorInstance(): ITerminalInstance;
|
||||
detachInstance(instance: ITerminalInstance): void;
|
||||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,7 +30,7 @@ import { ILocalTerminalService, ITerminalProfile, TerminalSettingId, TitleEventS
|
|||
import { IWorkspaceContextService, IWorkspaceFolder } from 'vs/platform/workspace/common/workspace';
|
||||
import { PICK_WORKSPACE_FOLDER_COMMAND_ID } from 'vs/workbench/browser/actions/workspaceCommands';
|
||||
import { FindInFilesCommand, IFindInFilesArgs } from 'vs/workbench/contrib/search/browser/searchActions';
|
||||
import { Direction, IRemoteTerminalService, ITerminalEditorService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { Direction, ICreateTerminalOptions, IRemoteTerminalService, ITerminalGroupService, ITerminalInstance, ITerminalInstanceService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalQuickAccessProvider } from 'vs/workbench/contrib/terminal/browser/terminalQuickAccess';
|
||||
import { IRemoteTerminalAttachTarget, ITerminalConfigHelper, KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, KEYBINDING_CONTEXT_TERMINAL_FIND_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FIND_NOT_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_IS_OPEN, KEYBINDING_CONTEXT_TERMINAL_PROCESS_SUPPORTED, KEYBINDING_CONTEXT_TERMINAL_TABS_FOCUS, KEYBINDING_CONTEXT_TERMINAL_TABS_SINGULAR_SELECTION, KEYBINDING_CONTEXT_TERMINAL_TEXT_SELECTED, TerminalCommandId, TerminalLocation, TERMINAL_ACTION_CATEGORY } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
|
@ -141,22 +141,27 @@ export function registerTerminalActions() {
|
|||
},
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor, eventOrProfile: unknown | ITerminalProfile, profile?: ITerminalProfile) {
|
||||
let event: MouseEvent | undefined;
|
||||
if (eventOrProfile && typeof eventOrProfile === 'object' && 'profileName' in eventOrProfile) {
|
||||
profile = eventOrProfile as ITerminalProfile;
|
||||
} else {
|
||||
event = eventOrProfile as MouseEvent;
|
||||
}
|
||||
async run(accessor: ServicesAccessor, eventOrOptionsOrProfile: MouseEvent | ICreateTerminalOptions | ITerminalProfile | undefined, profile?: ITerminalProfile) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const workspaceContextService = accessor.get(IWorkspaceContextService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
|
||||
let event: MouseEvent | PointerEvent | KeyboardEvent | undefined;
|
||||
let options: ICreateTerminalOptions | undefined;
|
||||
if (eventOrOptionsOrProfile instanceof MouseEvent || eventOrOptionsOrProfile instanceof PointerEvent || eventOrOptionsOrProfile instanceof KeyboardEvent) {
|
||||
event = eventOrOptionsOrProfile;
|
||||
options = profile ? { config: profile } : undefined;
|
||||
} else {
|
||||
options = convertOptionsOrProfileToOptions(eventOrOptionsOrProfile);
|
||||
}
|
||||
|
||||
const folders = workspaceContextService.getWorkspace().folders;
|
||||
if (event instanceof MouseEvent && (event.altKey || event.ctrlKey)) {
|
||||
if (event && (event.altKey || event.ctrlKey)) {
|
||||
const activeInstance = terminalService.activeInstance;
|
||||
if (activeInstance) {
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, activeInstance);
|
||||
terminalService.splitInstance(activeInstance, profile, cwd);
|
||||
terminalService.splitInstance(activeInstance, options?.config, cwd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -177,8 +182,8 @@ export function registerTerminalActions() {
|
|||
cwd = workspace.uri;
|
||||
}
|
||||
|
||||
if (profile) {
|
||||
instance = terminalService.createTerminal({ config: profile, cwd });
|
||||
if (options) {
|
||||
instance = terminalService.createTerminal(options);
|
||||
} else {
|
||||
instance = await terminalService.showProfileQuickPick('createInstance', cwd);
|
||||
}
|
||||
|
@ -187,7 +192,7 @@ export function registerTerminalActions() {
|
|||
terminalService.setActiveInstance(instance);
|
||||
}
|
||||
}
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -299,8 +304,9 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalGroupService).activeGroup?.focusPreviousPane();
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
terminalGroupService.activeGroup?.focusPreviousPane();
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -324,8 +330,9 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalGroupService).activeGroup?.focusNextPane();
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
terminalGroupService.activeGroup?.focusNextPane();
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -464,8 +471,9 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalGroupService).setActiveGroupToNext();
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
terminalGroupService.setActiveGroupToNext();
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -487,8 +495,9 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
accessor.get(ITerminalGroupService).setActiveGroupToPrevious();
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
terminalGroupService.setActiveGroupToPrevious();
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -503,6 +512,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
|
||||
const instance = terminalService.getActiveOrCreateInstance();
|
||||
|
@ -519,7 +529,7 @@ export function registerTerminalActions() {
|
|||
text = editor.getModel().getValueInRange(selection, endOfLinePreference);
|
||||
}
|
||||
instance.sendText(text, true);
|
||||
return accessor.get(ITerminalGroupService).showPanel();
|
||||
return terminalGroupService.showPanel();
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -534,6 +544,8 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const terminalInstanceService = accessor.get(ITerminalInstanceService);
|
||||
const codeEditorService = accessor.get(ICodeEditorService);
|
||||
const notificationService = accessor.get(INotificationService);
|
||||
|
||||
|
@ -550,9 +562,9 @@ export function registerTerminalActions() {
|
|||
|
||||
// TODO: Convert this to ctrl+c, ctrl+v for pwsh?
|
||||
const instance = terminalService.getActiveOrCreateInstance();
|
||||
const path = await accessor.get(ITerminalInstanceService).preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType, instance.isRemote);
|
||||
const path = await terminalInstanceService.preparePathForTerminalAsync(uri.fsPath, instance.shellLaunchConfig.executable, instance.title, instance.shellType, instance.isRemote);
|
||||
instance.sendText(path, true);
|
||||
return accessor.get(ITerminalGroupService).showPanel();
|
||||
return terminalGroupService.showPanel();
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1246,13 +1258,10 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor) {
|
||||
if (accessor.get(ITerminalService).activeInstance?.target === TerminalLocation.Editor) {
|
||||
const state = accessor.get(ITerminalEditorService).getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
} else {
|
||||
const state = accessor.get(ITerminalGroupService).getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
}
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const instanceHost = terminalService.getFindHost();
|
||||
const state = instanceHost.getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1272,13 +1281,10 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor) {
|
||||
if (accessor.get(ITerminalService).activeInstance?.target === TerminalLocation.Editor) {
|
||||
const state = accessor.get(ITerminalEditorService).getFindState();
|
||||
state.change({ wholeWord: !state.wholeWord }, false);
|
||||
} else {
|
||||
const state = accessor.get(ITerminalGroupService).getFindState();
|
||||
state.change({ wholeWord: !state.wholeWord }, false);
|
||||
}
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const instanceHost = terminalService.getFindHost();
|
||||
const state = instanceHost.getFindState();
|
||||
state.change({ wholeWord: !state.wholeWord }, false);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1298,13 +1304,10 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
run(accessor: ServicesAccessor) {
|
||||
if (accessor.get(ITerminalService).activeInstance?.target === TerminalLocation.Editor) {
|
||||
const state = accessor.get(ITerminalEditorService).getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
} else {
|
||||
const state = accessor.get(ITerminalGroupService).getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
}
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const instanceHost = terminalService.getFindHost();
|
||||
const state = instanceHost.getFindState();
|
||||
state.change({ matchCase: !state.matchCase }, false);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1440,21 +1443,24 @@ export function registerTerminalActions() {
|
|||
}
|
||||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor, profile?: ITerminalProfile) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
async run(accessor: ServicesAccessor, optionsOrProfile?: ICreateTerminalOptions | ITerminalProfile) {
|
||||
const commandService = accessor.get(ICommandService);
|
||||
await terminalService.doWithActiveInstance(async t => {
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, t, accessor.get(IWorkspaceContextService).getWorkspace().folders, accessor.get(ICommandService));
|
||||
if (cwd === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
if (t.target === TerminalLocation.Editor) {
|
||||
commandService.executeCommand('workbench.action.splitEditor');
|
||||
} else {
|
||||
terminalService.splitInstance(t, profile, cwd);
|
||||
return accessor.get(ITerminalGroupService).showPanel(true);
|
||||
}
|
||||
});
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const workspaceContextService = accessor.get(IWorkspaceContextService);
|
||||
const options = convertOptionsOrProfileToOptions(optionsOrProfile);
|
||||
const activeInstance = terminalService.getInstanceHost(options?.target).activeInstance;
|
||||
if (!activeInstance) {
|
||||
return;
|
||||
}
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, activeInstance, workspaceContextService.getWorkspace().folders, commandService);
|
||||
if (cwd === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
const instance = terminalService.splitInstance(activeInstance, options?.config, cwd);
|
||||
if (instance?.target !== TerminalLocation.Editor) {
|
||||
return terminalGroupService.showPanel(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1478,6 +1484,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const instances = getSelectedInstances(accessor);
|
||||
if (instances) {
|
||||
for (const t of instances) {
|
||||
|
@ -1485,7 +1492,7 @@ export function registerTerminalActions() {
|
|||
terminalService.doWithActiveInstance(async instance => {
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, instance);
|
||||
terminalService.splitInstance(instance, { cwd });
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
await terminalGroupService.showPanel(true);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -1556,14 +1563,12 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
await terminalService.doWithActiveInstance(async t => {
|
||||
if (t.target === TerminalLocation.Editor) {
|
||||
commandService.executeCommand('workbench.action.splitEditor');
|
||||
} else {
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, t);
|
||||
terminalService.splitInstance(t, { cwd });
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
const cwd = await getCwdForSplit(terminalService.configHelper, t);
|
||||
const instance = terminalService.splitInstance(t, { cwd });
|
||||
if (instance?.target !== TerminalLocation.Editor) {
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1611,6 +1616,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor, event: unknown) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const workspaceContextService = accessor.get(IWorkspaceContextService);
|
||||
const commandService = accessor.get(ICommandService);
|
||||
const folders = workspaceContextService.getWorkspace().folders;
|
||||
|
@ -1646,7 +1652,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
terminalService.setActiveInstance(instance);
|
||||
}
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
});
|
||||
registerAction2(class extends Action2 {
|
||||
|
@ -1661,16 +1667,15 @@ export function registerTerminalActions() {
|
|||
});
|
||||
}
|
||||
async run(accessor: ServicesAccessor) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
await terminalService.doWithActiveInstance(async t => {
|
||||
if (t.target === TerminalLocation.Editor) {
|
||||
return;
|
||||
}
|
||||
t.dispose(true);
|
||||
if (terminalService.instances.length > 0) {
|
||||
await accessor.get(ITerminalGroupService).showPanel(true);
|
||||
}
|
||||
});
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
const instance = terminalGroupService.activeInstance;
|
||||
if (!instance) {
|
||||
return;
|
||||
}
|
||||
instance.dispose(true);
|
||||
if (terminalGroupService.instances.length > 0) {
|
||||
await terminalGroupService.showPanel(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -1859,6 +1864,7 @@ export function registerTerminalActions() {
|
|||
}
|
||||
async run(accessor: ServicesAccessor, item?: string) {
|
||||
const terminalService = accessor.get(ITerminalService);
|
||||
const terminalGroupService = accessor.get(ITerminalGroupService);
|
||||
if (!item || !item.split) {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
@ -1872,8 +1878,8 @@ export function registerTerminalActions() {
|
|||
}
|
||||
const indexMatches = terminalIndexRe.exec(item);
|
||||
if (indexMatches) {
|
||||
accessor.get(ITerminalGroupService).setActiveGroupByIndex(Number(indexMatches[1]) - 1);
|
||||
return accessor.get(ITerminalGroupService).showPanel(true);
|
||||
terminalGroupService.setActiveGroupByIndex(Number(indexMatches[1]) - 1);
|
||||
return terminalGroupService.showPanel(true);
|
||||
}
|
||||
|
||||
const quickSelectProfiles = terminalService.availableProfiles;
|
||||
|
@ -1942,3 +1948,10 @@ export function validateTerminalName(name: string): { content: string, severity:
|
|||
|
||||
return null;
|
||||
}
|
||||
|
||||
function convertOptionsOrProfileToOptions(optionsOrProfile?: ICreateTerminalOptions | ITerminalProfile): ICreateTerminalOptions | undefined {
|
||||
if (typeof optionsOrProfile === 'object' && 'profileName' in optionsOrProfile) {
|
||||
return { config: optionsOrProfile as ITerminalProfile };
|
||||
}
|
||||
return optionsOrProfile;
|
||||
}
|
||||
|
|
|
@ -4,20 +4,30 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { Dimension } from 'vs/base/browser/dom';
|
||||
import { IActionViewItem } from 'vs/base/browser/ui/actionbar/actionbar';
|
||||
import { Action, IAction, Separator, SubmenuAction } from 'vs/base/common/actions';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { Codicon } from 'vs/base/common/codicons';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { localize } from 'vs/nls';
|
||||
import { DropdownWithPrimaryActionViewItem } from 'vs/platform/actions/browser/dropdownWithPrimaryActionViewItem';
|
||||
import { IMenu, IMenuActionOptions, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IEditorOptions } from 'vs/platform/editor/common/editor';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { ITerminalProfile } from 'vs/platform/terminal/common/terminal';
|
||||
import { IThemeService } from 'vs/platform/theme/common/themeService';
|
||||
import { EditorPane } from 'vs/workbench/browser/parts/editor/editorPane';
|
||||
import { IEditorOpenContext } from 'vs/workbench/common/editor';
|
||||
import { ITerminalEditorService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ICreateTerminalOptions, ITerminalEditorService, ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
|
||||
import { TerminalFindWidget } from 'vs/workbench/contrib/terminal/browser/terminalFindWidget';
|
||||
import { KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TerminalTabContextMenuGroup } from 'vs/workbench/contrib/terminal/browser/terminalMenus';
|
||||
import { ITerminalProfileResolverService, KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE, TerminalCommandId, TerminalLocation } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
import { IEditorGroup } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
|
||||
const xtermSelector = '.terminal.xterm';
|
||||
|
@ -33,6 +43,8 @@ export class TerminalEditor extends EditorPane {
|
|||
|
||||
private _lastDimension?: Dimension;
|
||||
|
||||
private readonly _dropdownMenu: IMenu;
|
||||
|
||||
private _findWidget: TerminalFindWidget;
|
||||
private _findWidgetVisible: IContextKey<boolean>;
|
||||
private _findState: FindReplaceState;
|
||||
|
@ -44,13 +56,20 @@ export class TerminalEditor extends EditorPane {
|
|||
@IThemeService themeService: IThemeService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@ITerminalEditorService private readonly _terminalEditorService: ITerminalEditorService,
|
||||
@ITerminalProfileResolverService private readonly _terminalProfileResolverService: ITerminalProfileResolverService,
|
||||
// @ITerminalContributionService private readonly _terminalContributionService: ITerminalContributionService,
|
||||
@ITerminalService private readonly _terminalService: ITerminalService,
|
||||
@IInstantiationService instantiationService: IInstantiationService,
|
||||
@IContextKeyService contextKeyService: IContextKeyService
|
||||
@IContextKeyService contextKeyService: IContextKeyService,
|
||||
@IMenuService menuService: IMenuService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService,
|
||||
@IContextMenuService private readonly _contextMenuService: IContextMenuService,
|
||||
) {
|
||||
super(TerminalEditor.ID, telemetryService, themeService, storageService);
|
||||
this._findState = new FindReplaceState();
|
||||
this._findWidget = instantiationService.createInstance(TerminalFindWidget, this._findState);
|
||||
this._findWidgetVisible = KEYBINDING_CONTEXT_TERMINAL_FIND_VISIBLE.bindTo(contextKeyService);
|
||||
this._dropdownMenu = this._register(menuService.createMenu(MenuId.TerminalNewDropdownContext, contextKeyService));
|
||||
}
|
||||
|
||||
override async setInput(newInput: TerminalEditorInput, options: IEditorOptions | undefined, context: IEditorOpenContext, token: CancellationToken) {
|
||||
|
@ -96,6 +115,84 @@ export class TerminalEditor extends EditorPane {
|
|||
return this._editorInput?.terminalInstance?.setVisible(visible);
|
||||
}
|
||||
|
||||
override getActionViewItem(action: IAction): IActionViewItem | undefined {
|
||||
switch (action.id) {
|
||||
case TerminalCommandId.CreateWithProfileButton: {
|
||||
const actions = this._getTabActionBarArgs(this._terminalService.availableProfiles);
|
||||
const button = this._instantiationService.createInstance(DropdownWithPrimaryActionViewItem, actions.primaryAction, actions.dropdownAction, actions.dropdownMenuActions, actions.className, this._contextMenuService);
|
||||
return button;
|
||||
}
|
||||
}
|
||||
return super.getActionViewItem(action);
|
||||
}
|
||||
|
||||
private _getTabActionBarArgs(profiles: ITerminalProfile[]): {
|
||||
primaryAction: MenuItemAction,
|
||||
dropdownAction: IAction,
|
||||
dropdownMenuActions: IAction[],
|
||||
className: string,
|
||||
dropdownIcon?: string
|
||||
} {
|
||||
const dropdownActions: IAction[] = [];
|
||||
const submenuActions: IAction[] = [];
|
||||
|
||||
const defaultProfileName = this._terminalProfileResolverService.defaultProfileName;
|
||||
for (const p of profiles) {
|
||||
const isDefault = p.profileName === defaultProfileName;
|
||||
const options: IMenuActionOptions = {
|
||||
arg: {
|
||||
config: p,
|
||||
target: TerminalLocation.Editor
|
||||
} as ICreateTerminalOptions,
|
||||
shouldForwardArgs: true
|
||||
};
|
||||
if (isDefault) {
|
||||
dropdownActions.unshift(this._instantiationService.createInstance(MenuItemAction, { id: TerminalCommandId.NewWithProfile, title: localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, options));
|
||||
submenuActions.unshift(this._instantiationService.createInstance(MenuItemAction, { id: TerminalCommandId.Split, title: localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, options));
|
||||
} else {
|
||||
dropdownActions.push(this._instantiationService.createInstance(MenuItemAction, { id: TerminalCommandId.NewWithProfile, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, options));
|
||||
submenuActions.push(this._instantiationService.createInstance(MenuItemAction, { id: TerminalCommandId.Split, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, options));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Support contributed profiles with editor target
|
||||
// for (const contributed of this._terminalContributionService.terminalProfiles) {
|
||||
// dropdownActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title.replace(/[\n\r\t]/g, ''), undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.extensionIdentifier, contributed.id, false)));
|
||||
// submenuActions.push(new Action(TerminalCommandId.NewWithProfile, contributed.title.replace(/[\n\r\t]/g, ''), undefined, true, () => this._terminalService.createContributedTerminalProfile(contributed.extensionIdentifier, contributed.id, true)));
|
||||
// }
|
||||
|
||||
if (dropdownActions.length > 0) {
|
||||
dropdownActions.push(new SubmenuAction('split.profile', 'Split...', submenuActions));
|
||||
dropdownActions.push(new Separator());
|
||||
}
|
||||
|
||||
for (const [, configureActions] of this._dropdownMenu.getActions()) {
|
||||
for (const action of configureActions) {
|
||||
// make sure the action is a MenuItemAction
|
||||
if ('alt' in action) {
|
||||
dropdownActions.push(action);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const primaryAction = this._instantiationService.createInstance(
|
||||
MenuItemAction,
|
||||
{
|
||||
id: TerminalCommandId.CreateTerminalEditor,
|
||||
title: localize('terminal.new', "New Terminal"),
|
||||
icon: Codicon.plus
|
||||
},
|
||||
{
|
||||
id: 'workbench.action.splitEditor',
|
||||
title: terminalStrings.split.value,
|
||||
icon: Codicon.splitHorizontal
|
||||
},
|
||||
undefined);
|
||||
|
||||
const dropdownAction = new Action('refresh profiles', 'Launch Profile...', 'codicon-chevron-down', true);
|
||||
return { primaryAction, dropdownAction, dropdownMenuActions: dropdownActions, className: 'terminal-tab-actions' };
|
||||
}
|
||||
|
||||
focusFindWidget() {
|
||||
if (this._parentElement && !this._parentElement?.querySelector(findWidgetSelector)) {
|
||||
this._parentElement.querySelector(xtermSelector)!.appendChild(this._findWidget.getDomNode());
|
||||
|
|
|
@ -19,6 +19,7 @@ export class TerminalEditorInput extends EditorInput {
|
|||
static readonly ID = 'workbench.editors.terminal';
|
||||
|
||||
private _isDetached = false;
|
||||
private _copyInstance?: ITerminalInstance;
|
||||
|
||||
override get typeId(): string {
|
||||
return TerminalEditorInput.ID;
|
||||
|
@ -29,10 +30,19 @@ export class TerminalEditorInput extends EditorInput {
|
|||
}
|
||||
|
||||
override copy(): IEditorInput {
|
||||
const instance = this._terminalInstanceService.createInstance({}, TerminalLocation.Editor);
|
||||
const instance = this._copyInstance || this._terminalInstanceService.createInstance({}, TerminalLocation.Editor);
|
||||
this._copyInstance = undefined;
|
||||
return this._instantiationService.createInstance(TerminalEditorInput, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets what instance to use for the next call to IEditorInput.copy, this is used to define what
|
||||
* terminal instance is used when the editor's split command is run.
|
||||
*/
|
||||
setCopyInstance(instance: ITerminalInstance) {
|
||||
this._copyInstance = instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the terminal instance for this input if it has not yet been detached from the input.
|
||||
*/
|
||||
|
@ -48,7 +58,7 @@ export class TerminalEditorInput extends EditorInput {
|
|||
private readonly _terminalInstance: ITerminalInstance,
|
||||
@IThemeService private readonly _themeService: IThemeService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
private readonly _instantiationService: IInstantiationService
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
) {
|
||||
super();
|
||||
this._register(this._terminalInstance.onTitleChanged(() => this._onDidChangeLabel.fire()));
|
||||
|
|
|
@ -6,16 +6,18 @@
|
|||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { Disposable, dispose, IDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { FindReplaceState } from 'vs/editor/contrib/find/findState';
|
||||
import { ICommandService } from 'vs/platform/commands/common/commands';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IShellLaunchConfig } from 'vs/platform/terminal/common/terminal';
|
||||
import { IEditorInput } from 'vs/workbench/common/editor';
|
||||
import { ITerminalEditorService, ITerminalFindHost, ITerminalInstance, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ITerminalEditorService, ITerminalInstance, ITerminalInstanceService } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { TerminalEditor } from 'vs/workbench/contrib/terminal/browser/terminalEditor';
|
||||
import { TerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorInput';
|
||||
import { SerializedTerminalEditorInput } from 'vs/workbench/contrib/terminal/browser/terminalEditorSerializer';
|
||||
import { TerminalLocation } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
|
||||
export class TerminalEditorService extends Disposable implements ITerminalEditorService, ITerminalFindHost {
|
||||
export class TerminalEditorService extends Disposable implements ITerminalEditorService {
|
||||
declare _serviceBrand: undefined;
|
||||
|
||||
instances: ITerminalInstance[] = [];
|
||||
|
@ -32,6 +34,7 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor
|
|||
get onDidChangeInstances(): Event<void> { return this._onDidChangeInstances.event; }
|
||||
|
||||
constructor(
|
||||
@ICommandService private readonly _commandService: ICommandService,
|
||||
@IEditorService private readonly _editorService: IEditorService,
|
||||
@ITerminalInstanceService private readonly _terminalInstanceService: ITerminalInstanceService,
|
||||
@IInstantiationService private readonly _instantiationService: IInstantiationService
|
||||
|
@ -125,7 +128,7 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor
|
|||
});
|
||||
}
|
||||
|
||||
getOrCreateEditorInput(instance: ITerminalInstance | SerializedTerminalEditorInput): TerminalEditorInput {
|
||||
getOrCreateEditorInput(instance: ITerminalInstance | SerializedTerminalEditorInput, isFutureSplit: boolean = false): TerminalEditorInput {
|
||||
let cachedEditor;
|
||||
if ('id' in instance) {
|
||||
cachedEditor = this._editorInputs.get(instance.id);
|
||||
|
@ -151,6 +154,14 @@ export class TerminalEditorService extends Disposable implements ITerminalEditor
|
|||
return input;
|
||||
}
|
||||
|
||||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig: IShellLaunchConfig = {}): ITerminalInstance {
|
||||
const input = this.getOrCreateEditorInput(instanceToSplit);
|
||||
const instance = this._terminalInstanceService.createInstance(shellLaunchConfig, TerminalLocation.Editor);
|
||||
input.setCopyInstance(instance);
|
||||
this._commandService.executeCommand('workbench.action.splitEditor');
|
||||
return instance;
|
||||
}
|
||||
|
||||
detachActiveEditorInstance(): ITerminalInstance {
|
||||
const activeEditor = this._editorService.activeEditor;
|
||||
if (!(activeEditor instanceof TerminalEditorInput)) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import type { Unicode11Addon as XTermUnicode11Addon } from 'xterm-addon-unicode1
|
|||
import type { WebglAddon as XTermWebglAddon } from 'xterm-addon-webgl';
|
||||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { ILocalTerminalService, IShellLaunchConfig, TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { ILocalTerminalService, IShellLaunchConfig, ITerminalProfile, TerminalShellType, WindowsShellType } from 'vs/platform/terminal/common/terminal';
|
||||
import { IInstantiationService, optional } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { escapeNonWindowsPath } from 'vs/platform/terminal/common/terminalEnvironment';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
|
@ -19,6 +19,7 @@ import { TerminalInstance } from 'vs/workbench/contrib/terminal/browser/terminal
|
|||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { TerminalConfigHelper } from 'vs/workbench/contrib/terminal/browser/terminalConfigHelper';
|
||||
import { KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_SHELL_TYPE, KEYBINDING_CONTEXT_TERMINAL_ALT_BUFFER_ACTIVE, TerminalLocation } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
let Terminal: typeof XTermTerminal;
|
||||
let SearchAddon: typeof XTermSearchAddon;
|
||||
|
@ -47,20 +48,48 @@ export class TerminalInstanceService extends Disposable implements ITerminalInst
|
|||
this._configHelper = _instantiationService.createInstance(TerminalConfigHelper);
|
||||
}
|
||||
|
||||
createInstance(launchConfig: IShellLaunchConfig, target?: TerminalLocation): ITerminalInstance {
|
||||
createInstance(profile: ITerminalProfile, target?: TerminalLocation): ITerminalInstance;
|
||||
createInstance(shellLaunchConfig: IShellLaunchConfig, target?: TerminalLocation): ITerminalInstance;
|
||||
createInstance(config: IShellLaunchConfig | ITerminalProfile, target?: TerminalLocation): ITerminalInstance {
|
||||
const shellLaunchConfig = this._convertProfileToShellLaunchConfig(config);
|
||||
const instance = this._instantiationService.createInstance(TerminalInstance,
|
||||
this._terminalFocusContextKey,
|
||||
this._terminalShellTypeContextKey,
|
||||
this._terminalAltBufferActiveContextKey,
|
||||
this._configHelper,
|
||||
launchConfig
|
||||
shellLaunchConfig
|
||||
);
|
||||
if (target) {
|
||||
instance.target = TerminalLocation.Editor;
|
||||
}
|
||||
instance.target = target;
|
||||
return instance;
|
||||
}
|
||||
|
||||
private _convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile?: IShellLaunchConfig | ITerminalProfile, cwd?: string | URI): IShellLaunchConfig {
|
||||
// Profile was provided
|
||||
if (shellLaunchConfigOrProfile && 'profileName' in shellLaunchConfigOrProfile) {
|
||||
const profile = shellLaunchConfigOrProfile;
|
||||
return {
|
||||
executable: profile.path,
|
||||
args: profile.args,
|
||||
env: profile.env,
|
||||
icon: profile.icon,
|
||||
color: profile.color,
|
||||
name: profile.overrideName ? profile.profileName : undefined,
|
||||
cwd
|
||||
};
|
||||
}
|
||||
|
||||
// Shell launch config was provided
|
||||
if (shellLaunchConfigOrProfile) {
|
||||
if (cwd) {
|
||||
shellLaunchConfigOrProfile.cwd = cwd;
|
||||
}
|
||||
return shellLaunchConfigOrProfile;
|
||||
}
|
||||
|
||||
// Return empty shell launch config
|
||||
return {};
|
||||
}
|
||||
|
||||
async getXtermConstructor(): Promise<typeof XTermTerminal> {
|
||||
if (!Terminal) {
|
||||
Terminal = (await import('xterm')).Terminal;
|
||||
|
|
|
@ -529,4 +529,14 @@ export function setupTerminalMenus(): void {
|
|||
when: ResourceContextKey.Scheme.isEqualTo(Schemas.vscodeTerminal),
|
||||
group: '2_files'
|
||||
});
|
||||
|
||||
MenuRegistry.appendMenuItem(MenuId.EditorTitle, {
|
||||
command: {
|
||||
id: TerminalCommandId.CreateWithProfileButton,
|
||||
title: TerminalCommandId.CreateWithProfileButton
|
||||
},
|
||||
group: 'navigation',
|
||||
order: 0,
|
||||
when: ResourceContextKey.Scheme.isEqualTo(Schemas.vscodeTerminal)
|
||||
});
|
||||
}
|
||||
|
|
|
@ -597,10 +597,6 @@ export class TerminalService implements ITerminalService {
|
|||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfig?: IShellLaunchConfig): ITerminalInstance | null;
|
||||
splitInstance(instanceToSplit: ITerminalInstance, profile: ITerminalProfile, cwd?: string | URI): ITerminalInstance | null
|
||||
splitInstance(instanceToSplit: ITerminalInstance, shellLaunchConfigOrProfile: IShellLaunchConfig | ITerminalProfile = {}, cwd?: string | URI): ITerminalInstance | null {
|
||||
const group = this._terminalGroupService.getGroupForInstance(instanceToSplit);
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
const shellLaunchConfig = this._convertProfileToShellLaunchConfig(shellLaunchConfigOrProfile, cwd);
|
||||
|
||||
// Use the URI from the base instance if it exists, this will correctly split local terminals
|
||||
|
@ -612,11 +608,27 @@ export class TerminalService implements ITerminalService {
|
|||
this._evaluateLocalCwd(shellLaunchConfig);
|
||||
}
|
||||
|
||||
const instance = group.split(shellLaunchConfig);
|
||||
// Handle editor terminals
|
||||
let instance: ITerminalInstance;
|
||||
switch (instanceToSplit.target) {
|
||||
case TerminalLocation.Editor:
|
||||
instance = this._terminalEditorService.splitInstance(instanceToSplit, shellLaunchConfig);
|
||||
break;
|
||||
case TerminalLocation.TerminalView:
|
||||
default:
|
||||
const group = this._terminalGroupService.getGroupForInstance(instanceToSplit);
|
||||
if (!group) {
|
||||
return null;
|
||||
}
|
||||
instance = group.split(shellLaunchConfig);
|
||||
break;
|
||||
}
|
||||
|
||||
this._initInstanceListeners(instance);
|
||||
|
||||
this._terminalGroupService.groups.forEach((g, i) => g.setVisible(i === this._terminalGroupService.activeGroupIndex));
|
||||
if (instanceToSplit.target !== TerminalLocation.Editor) {
|
||||
this._terminalGroupService.groups.forEach((g, i) => g.setVisible(i === this._terminalGroupService.activeGroupIndex));
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
|
@ -865,7 +877,7 @@ export class TerminalService implements ITerminalService {
|
|||
return;
|
||||
}
|
||||
if (type === 'createInstance') {
|
||||
const activeInstance = this.activeInstance;
|
||||
const activeInstance = this.getDefaultInstanceHost().activeInstance;
|
||||
let instance;
|
||||
|
||||
if ('id' in value.profile) {
|
||||
|
@ -910,8 +922,25 @@ export class TerminalService implements ITerminalService {
|
|||
return undefined;
|
||||
}
|
||||
|
||||
getFindHost(): ITerminalFindHost {
|
||||
return this.activeInstance?.target === TerminalLocation.Editor ? this._terminalEditorService : this._terminalGroupService;
|
||||
getDefaultInstanceHost(): ITerminalInstanceHost {
|
||||
if (this.configHelper.config.defaultLocation === TerminalLocation.Editor) {
|
||||
return this._terminalEditorService;
|
||||
}
|
||||
return this._terminalGroupService;
|
||||
}
|
||||
|
||||
getInstanceHost(target: TerminalLocation | undefined): ITerminalInstanceHost {
|
||||
if (target) {
|
||||
if (target === TerminalLocation.Editor) {
|
||||
return this._terminalEditorService;
|
||||
}
|
||||
return this._terminalGroupService;
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
getFindHost(instance: ITerminalInstance | undefined = this.activeInstance): ITerminalFindHost {
|
||||
return instance?.target === TerminalLocation.Editor ? this._terminalEditorService : this._terminalGroupService;
|
||||
}
|
||||
|
||||
async createContributedTerminalProfile(extensionIdentifier: string, id: string, isSplitTerminal: boolean): Promise<void> {
|
||||
|
|
|
@ -14,17 +14,17 @@ import { IThemeService, IColorTheme, registerThemingParticipant, ICssStyleCollec
|
|||
import { switchTerminalActionViewItemSeparator, switchTerminalShowTabsTitle } from 'vs/workbench/contrib/terminal/browser/terminalActions';
|
||||
import { TERMINAL_BACKGROUND_COLOR, TERMINAL_BORDER_COLOR, TERMINAL_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/contrib/terminal/common/terminalColorRegistry';
|
||||
import { INotificationService, IPromptChoice, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ICreateTerminalOptions, ITerminalGroupService, ITerminalInstance, ITerminalService, TerminalConnectionState } from 'vs/workbench/contrib/terminal/browser/terminal';
|
||||
import { ViewPane, IViewPaneOptions } from 'vs/workbench/browser/parts/views/viewPane';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IViewDescriptorService } from 'vs/workbench/common/views';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { PANEL_BACKGROUND, SIDE_BAR_BACKGROUND, EDITOR_DRAG_AND_DROP_BACKGROUND } from 'vs/workbench/common/theme';
|
||||
import { IMenu, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { ITerminalProfileResolverService, TerminalCommandId } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { IMenu, IMenuActionOptions, IMenuService, MenuId, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { ITerminalProfileResolverService, TerminalCommandId, TerminalLocation } from 'vs/workbench/contrib/terminal/common/terminal';
|
||||
import { TerminalSettingId, ITerminalProfile } from 'vs/platform/terminal/common/terminal';
|
||||
import { SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { ActionViewItem, SelectActionViewItem } from 'vs/base/browser/ui/actionbar/actionViewItems';
|
||||
import { ITerminalContributionService } from 'vs/workbench/contrib/terminal/common/terminalExtensionPoints';
|
||||
import { attachSelectBoxStyler, attachStylerCallback } from 'vs/platform/theme/common/styler';
|
||||
import { selectBorder } from 'vs/platform/theme/common/colorRegistry';
|
||||
|
@ -43,6 +43,7 @@ import { URI } from 'vs/base/common/uri';
|
|||
import { ColorScheme } from 'vs/platform/theme/common/theme';
|
||||
import { getColorClass, getUriClasses } from 'vs/workbench/contrib/terminal/browser/terminalIcon';
|
||||
import { terminalStrings } from 'vs/workbench/contrib/terminal/common/terminalStrings';
|
||||
import { withNullAsUndefined } from 'vs/base/common/types';
|
||||
|
||||
export class TerminalViewPane extends ViewPane {
|
||||
private _actions: IAction[] | undefined;
|
||||
|
@ -178,6 +179,26 @@ export class TerminalViewPane extends ViewPane {
|
|||
|
||||
override getActionViewItem(action: Action): IActionViewItem | undefined {
|
||||
switch (action.id) {
|
||||
case TerminalCommandId.Split: {
|
||||
// Split needs to be special cased to force splitting within the panel, not the editor
|
||||
const panelOnlySplitAction: IAction = {
|
||||
id: action.id,
|
||||
checked: action.checked,
|
||||
class: action.class,
|
||||
enabled: action.enabled,
|
||||
label: action.label,
|
||||
dispose: action.dispose.bind(action),
|
||||
tooltip: action.tooltip,
|
||||
run: () => {
|
||||
const instance = this._terminalGroupService.activeInstance;
|
||||
if (instance) {
|
||||
return this._terminalService.splitInstance(instance);
|
||||
}
|
||||
return;
|
||||
}
|
||||
};
|
||||
return new ActionViewItem(action, panelOnlySplitAction, { icon: true, label: false, keybinding: this._getKeybindingLabel(action) });
|
||||
}
|
||||
case TerminalCommandId.SwitchTerminal: {
|
||||
return this._instantiationService.createInstance(SwitchTerminalActionViewItem, action);
|
||||
}
|
||||
|
@ -200,6 +221,10 @@ export class TerminalViewPane extends ViewPane {
|
|||
return super.getActionViewItem(action);
|
||||
}
|
||||
|
||||
private _getKeybindingLabel(action: IAction): string | undefined {
|
||||
return withNullAsUndefined(this._keybindingService.lookupKeybinding(action.id)?.getLabel());
|
||||
}
|
||||
|
||||
private _updateTabActionBar(profiles: ITerminalProfile[]): void {
|
||||
const actions = this._getTabActionBarArgs(profiles);
|
||||
this._tabButtons?.update(actions.dropdownAction, actions.dropdownMenuActions);
|
||||
|
@ -218,12 +243,19 @@ export class TerminalViewPane extends ViewPane {
|
|||
const defaultProfileName = this._terminalProfileResolverService.defaultProfileName;
|
||||
for (const p of profiles) {
|
||||
const isDefault = p.profileName === defaultProfileName;
|
||||
const options: IMenuActionOptions = {
|
||||
arg: {
|
||||
config: p,
|
||||
target: TerminalLocation.TerminalView
|
||||
} as ICreateTerminalOptions,
|
||||
shouldForwardArgs: true
|
||||
};
|
||||
if (isDefault) {
|
||||
dropdownActions.unshift(new MenuItemAction({ id: TerminalCommandId.NewWithProfile, title: nls.localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService));
|
||||
submenuActions.unshift(new MenuItemAction({ id: TerminalCommandId.Split, title: nls.localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService));
|
||||
dropdownActions.unshift(new MenuItemAction({ id: TerminalCommandId.NewWithProfile, title: nls.localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, options, this._contextKeyService, this._commandService));
|
||||
submenuActions.unshift(new MenuItemAction({ id: TerminalCommandId.Split, title: nls.localize('defaultTerminalProfile', "{0} (Default)", p.profileName), category: TerminalTabContextMenuGroup.Profile }, undefined, options, this._contextKeyService, this._commandService));
|
||||
} else {
|
||||
dropdownActions.push(new MenuItemAction({ id: TerminalCommandId.NewWithProfile, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService));
|
||||
submenuActions.push(new MenuItemAction({ id: TerminalCommandId.Split, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, { arg: p, shouldForwardArgs: true }, this._contextKeyService, this._commandService));
|
||||
dropdownActions.push(new MenuItemAction({ id: TerminalCommandId.NewWithProfile, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, options, this._contextKeyService, this._commandService));
|
||||
submenuActions.push(new MenuItemAction({ id: TerminalCommandId.Split, title: p.profileName.replace(/[\n\r\t]/g, ''), category: TerminalTabContextMenuGroup.Profile }, undefined, options, this._contextKeyService, this._commandService));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,7 +290,10 @@ export class TerminalViewPane extends ViewPane {
|
|||
title: terminalStrings.split.value,
|
||||
icon: Codicon.splitHorizontal
|
||||
},
|
||||
undefined);
|
||||
{
|
||||
shouldForwardArgs: true,
|
||||
arg: { target: TerminalLocation.TerminalView } as ICreateTerminalOptions,
|
||||
});
|
||||
|
||||
const dropdownAction = new Action('refresh profiles', 'Launch Profile...', 'codicon-chevron-down', true);
|
||||
return { primaryAction, dropdownAction, dropdownMenuActions: dropdownActions, className: 'terminal-tab-actions' };
|
||||
|
@ -410,7 +445,7 @@ class SingleTerminalTabActionViewItem extends MenuEntryActionViewItem {
|
|||
|
||||
override async onClick(event: MouseEvent): Promise<void> {
|
||||
if (event.altKey && this._menuItemAction.alt) {
|
||||
this._commandService.executeCommand(this._menuItemAction.alt.id);
|
||||
this._commandService.executeCommand(this._menuItemAction.alt.id, { target: TerminalLocation.TerminalView } as ICreateTerminalOptions);
|
||||
} else {
|
||||
this._openContextMenu();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue