Merge commit 'be3e8236086165e5e45a5a10783823874b3f3ebd' as 'lib/vscode'

This commit is contained in:
Joe Previte
2020-12-15 15:52:33 -07:00
4649 changed files with 1311795 additions and 0 deletions

View File

@@ -0,0 +1,184 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { ICommandQuickPick, CommandsHistory } from 'vs/platform/quickinput/browser/commandsQuickAccess';
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
import { IMenuService, MenuId, MenuItemAction, SubmenuItemAction, Action2 } from 'vs/platform/actions/common/actions';
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
import { CancellationToken } from 'vs/base/common/cancellation';
import { timeout } from 'vs/base/common/async';
import { DisposableStore, toDisposable, dispose } from 'vs/base/common/lifecycle';
import { AbstractEditorCommandsQuickAccessProvider } from 'vs/editor/contrib/quickAccess/commandsQuickAccess';
import { IEditor } from 'vs/editor/common/editorCommon';
import { Language } from 'vs/base/common/platform';
import { IInstantiationService, ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { ICommandService } from 'vs/platform/commands/common/commands';
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { INotificationService } from 'vs/platform/notification/common/notification';
import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess';
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
import { IWorkbenchQuickAccessConfiguration } from 'vs/workbench/browser/quickaccess';
import { stripCodicons } from 'vs/base/common/codicons';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
import { IStorageService } from 'vs/platform/storage/common/storage';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider {
// If extensions are not yet registered, we wait for a little moment to give them
// a chance to register so that the complete set of commands shows up as result
// We do not want to delay functionality beyond that time though to keep the commands
// functional.
private readonly extensionRegistrationRace = Promise.race([
timeout(800),
this.extensionService.whenInstalledExtensionsRegistered()
]);
protected get activeTextEditorControl(): IEditor | undefined { return this.editorService.activeTextEditorControl; }
get defaultFilterValue(): DefaultQuickAccessFilterValue | undefined {
if (this.configuration.preserveInput) {
return DefaultQuickAccessFilterValue.LAST;
}
return undefined;
}
constructor(
@IEditorService private readonly editorService: IEditorService,
@IMenuService private readonly menuService: IMenuService,
@IExtensionService private readonly extensionService: IExtensionService,
@IInstantiationService instantiationService: IInstantiationService,
@IKeybindingService keybindingService: IKeybindingService,
@ICommandService commandService: ICommandService,
@ITelemetryService telemetryService: ITelemetryService,
@INotificationService notificationService: INotificationService,
@IConfigurationService private readonly configurationService: IConfigurationService,
@IEditorGroupsService private readonly editorGroupService: IEditorGroupsService
) {
super({
showAlias: !Language.isDefaultVariant(),
noResultsPick: {
label: localize('noCommandResults', "No matching commands"),
commandId: ''
}
}, instantiationService, keybindingService, commandService, telemetryService, notificationService);
}
private get configuration() {
const commandPaletteConfig = this.configurationService.getValue<IWorkbenchQuickAccessConfiguration>().workbench.commandPalette;
return {
preserveInput: commandPaletteConfig.preserveInput
};
}
protected async getCommandPicks(disposables: DisposableStore, token: CancellationToken): Promise<Array<ICommandQuickPick>> {
// wait for extensions registration or 800ms once
await this.extensionRegistrationRace;
if (token.isCancellationRequested) {
return [];
}
return [
...this.getCodeEditorCommandPicks(),
...this.getGlobalCommandPicks(disposables)
];
}
private getGlobalCommandPicks(disposables: DisposableStore): ICommandQuickPick[] {
const globalCommandPicks: ICommandQuickPick[] = [];
const scopedContextKeyService = this.editorService.activeEditorPane?.scopedContextKeyService || this.editorGroupService.activeGroup.scopedContextKeyService;
const globalCommandsMenu = this.menuService.createMenu(MenuId.CommandPalette, scopedContextKeyService);
const globalCommandsMenuActions = globalCommandsMenu.getActions()
.reduce((r, [, actions]) => [...r, ...actions], <Array<MenuItemAction | SubmenuItemAction | string>>[])
.filter(action => action instanceof MenuItemAction) as MenuItemAction[];
for (const action of globalCommandsMenuActions) {
// Label
let label = (typeof action.item.title === 'string' ? action.item.title : action.item.title.value) || action.item.id;
// Category
const category = typeof action.item.category === 'string' ? action.item.category : action.item.category?.value;
if (category) {
label = localize('commandWithCategory', "{0}: {1}", category, label);
}
// Alias
const aliasLabel = typeof action.item.title !== 'string' ? action.item.title.original : undefined;
const aliasCategory = (category && action.item.category && typeof action.item.category !== 'string') ? action.item.category.original : undefined;
const commandAlias = (aliasLabel && category) ?
aliasCategory ? `${aliasCategory}: ${aliasLabel}` : `${category}: ${aliasLabel}` :
aliasLabel;
globalCommandPicks.push({
commandId: action.item.id,
commandAlias,
label: stripCodicons(label)
});
}
// Cleanup
globalCommandsMenu.dispose();
disposables.add(toDisposable(() => dispose(globalCommandsMenuActions)));
return globalCommandPicks;
}
}
//#region Actions
export class ShowAllCommandsAction extends Action2 {
static readonly ID = 'workbench.action.showCommands';
constructor() {
super({
id: ShowAllCommandsAction.ID,
title: { value: localize('showTriggerActions', "Show All Commands"), original: 'Show All Commands' },
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_P,
secondary: [KeyCode.F1]
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
accessor.get(IQuickInputService).quickAccess.show(CommandsQuickAccessProvider.PREFIX);
}
}
export class ClearCommandHistoryAction extends Action2 {
constructor() {
super({
id: 'workbench.action.clearCommandHistory',
title: { value: localize('clearCommandHistory', "Clear Command History"), original: 'Clear Command History' },
f1: true
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const configurationService = accessor.get(IConfigurationService);
const storageService = accessor.get(IStorageService);
const commandHistoryLength = CommandsHistory.getConfiguredCommandHistoryLength(configurationService);
if (commandHistoryLength > 0) {
CommandsHistory.clearHistory(configurationService, storageService);
}
}
}
//#endregion

View File

@@ -0,0 +1,144 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess';
import { Registry } from 'vs/platform/registry/common/platform';
import { HelpQuickAccessProvider } from 'vs/platform/quickinput/browser/helpQuickAccess';
import { ViewQuickAccessProvider, OpenViewPickerAction, QuickAccessViewPickerAction } from 'vs/workbench/contrib/quickaccess/browser/viewQuickAccess';
import { CommandsQuickAccessProvider, ShowAllCommandsAction, ClearCommandHistoryAction } from 'vs/workbench/contrib/quickaccess/browser/commandsQuickAccess';
import { MenuRegistry, MenuId, registerAction2 } from 'vs/platform/actions/common/actions';
import { KeyMod } from 'vs/base/common/keyCodes';
import { ContextKeyExpr } from 'vs/platform/contextkey/common/contextkey';
import { inQuickPickContext, getQuickNavigateHandler } from 'vs/workbench/browser/quickaccess';
import { KeybindingsRegistry, KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
//#region Quick Access Proviers
const quickAccessRegistry = Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess);
quickAccessRegistry.registerQuickAccessProvider({
ctor: HelpQuickAccessProvider,
prefix: HelpQuickAccessProvider.PREFIX,
placeholder: localize('helpQuickAccessPlaceholder', "Type '{0}' to get help on the actions you can take from here.", HelpQuickAccessProvider.PREFIX),
helpEntries: [{ description: localize('helpQuickAccess', "Show all Quick Access Providers"), needsEditor: false }]
});
quickAccessRegistry.registerQuickAccessProvider({
ctor: ViewQuickAccessProvider,
prefix: ViewQuickAccessProvider.PREFIX,
contextKey: 'inViewsPicker',
placeholder: localize('viewQuickAccessPlaceholder', "Type the name of a view, output channel or terminal to open."),
helpEntries: [{ description: localize('viewQuickAccess', "Open View"), needsEditor: false }]
});
quickAccessRegistry.registerQuickAccessProvider({
ctor: CommandsQuickAccessProvider,
prefix: CommandsQuickAccessProvider.PREFIX,
contextKey: 'inCommandsPicker',
placeholder: localize('commandsQuickAccessPlaceholder', "Type the name of a command to run."),
helpEntries: [{ description: localize('commandsQuickAccess', "Show and Run Commands"), needsEditor: false }]
});
//#endregion
//#region Menu contributions
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
group: '1_open',
command: {
id: ShowAllCommandsAction.ID,
title: localize({ key: 'miCommandPalette', comment: ['&& denotes a mnemonic'] }, "&&Command Palette...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarViewMenu, {
group: '1_open',
command: {
id: OpenViewPickerAction.ID,
title: localize({ key: 'miOpenView', comment: ['&& denotes a mnemonic'] }, "&&Open View...")
},
order: 2
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '4_symbol_nav',
command: {
id: 'workbench.action.gotoSymbol',
title: localize({ key: 'miGotoSymbolInEditor', comment: ['&& denotes a mnemonic'] }, "Go to &&Symbol in Editor...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.MenubarGoMenu, {
group: '5_infile_nav',
command: {
id: 'workbench.action.gotoLine',
title: localize({ key: 'miGotoLine', comment: ['&& denotes a mnemonic'] }, "Go to &&Line/Column...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.GlobalActivity, {
group: '1_command',
command: {
id: ShowAllCommandsAction.ID,
title: localize('commandPalette', "Command Palette...")
},
order: 1
});
MenuRegistry.appendMenuItem(MenuId.EditorContext, {
group: 'z_commands',
when: EditorContextKeys.editorSimpleInput.toNegated(),
command: {
id: ShowAllCommandsAction.ID,
title: localize('commandPalette', "Command Palette..."),
},
order: 1
});
//#endregion
//#region Workbench actions and commands
registerAction2(ClearCommandHistoryAction);
registerAction2(ShowAllCommandsAction);
registerAction2(OpenViewPickerAction);
registerAction2(QuickAccessViewPickerAction);
const inViewsPickerContextKey = 'inViewsPicker';
const inViewsPickerContext = ContextKeyExpr.and(inQuickPickContext, ContextKeyExpr.has(inViewsPickerContextKey));
const viewPickerKeybinding = QuickAccessViewPickerAction.KEYBINDING;
const quickAccessNavigateNextInViewPickerId = 'workbench.action.quickOpenNavigateNextInViewPicker';
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: quickAccessNavigateNextInViewPickerId,
weight: KeybindingWeight.WorkbenchContrib + 50,
handler: getQuickNavigateHandler(quickAccessNavigateNextInViewPickerId, true),
when: inViewsPickerContext,
primary: viewPickerKeybinding.primary,
linux: viewPickerKeybinding.linux,
mac: viewPickerKeybinding.mac
});
const quickAccessNavigatePreviousInViewPickerId = 'workbench.action.quickOpenNavigatePreviousInViewPicker';
KeybindingsRegistry.registerCommandAndKeybindingRule({
id: quickAccessNavigatePreviousInViewPickerId,
weight: KeybindingWeight.WorkbenchContrib + 50,
handler: getQuickNavigateHandler(quickAccessNavigatePreviousInViewPickerId, false),
when: inViewsPickerContext,
primary: viewPickerKeybinding.primary | KeyMod.Shift,
linux: viewPickerKeybinding.linux,
mac: {
primary: viewPickerKeybinding.mac.primary | KeyMod.Shift
}
});
//#endregion

View File

@@ -0,0 +1,243 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
import { IQuickPickSeparator, IQuickInputService, ItemActivation } from 'vs/platform/quickinput/common/quickInput';
import { IPickerQuickAccessItem, PickerQuickAccessProvider } from 'vs/platform/quickinput/browser/pickerQuickAccess';
import { IViewletService } from 'vs/workbench/services/viewlet/browser/viewlet';
import { IViewDescriptorService, IViewsService, ViewContainer } from 'vs/workbench/common/views';
import { IOutputService } from 'vs/workbench/contrib/output/common/output';
import { ITerminalService } from 'vs/workbench/contrib/terminal/browser/terminal';
import { IPanelService, IPanelIdentifier } from 'vs/workbench/services/panel/common/panelService';
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
import { ViewletDescriptor } from 'vs/workbench/browser/viewlet';
import { matchesFuzzy } from 'vs/base/common/filters';
import { fuzzyContains } from 'vs/base/common/strings';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { Action2 } from 'vs/platform/actions/common/actions';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { CATEGORIES } from 'vs/workbench/common/actions';
interface IViewQuickPickItem extends IPickerQuickAccessItem {
containerLabel: string;
}
export class ViewQuickAccessProvider extends PickerQuickAccessProvider<IViewQuickPickItem> {
static PREFIX = 'view ';
constructor(
@IViewletService private readonly viewletService: IViewletService,
@IViewDescriptorService private readonly viewDescriptorService: IViewDescriptorService,
@IViewsService private readonly viewsService: IViewsService,
@IOutputService private readonly outputService: IOutputService,
@ITerminalService private readonly terminalService: ITerminalService,
@IPanelService private readonly panelService: IPanelService,
@IContextKeyService private readonly contextKeyService: IContextKeyService
) {
super(ViewQuickAccessProvider.PREFIX, {
noResultsPick: {
label: localize('noViewResults', "No matching views"),
containerLabel: ''
}
});
}
protected getPicks(filter: string): Array<IViewQuickPickItem | IQuickPickSeparator> {
const filteredViewEntries = this.doGetViewPickItems().filter(entry => {
if (!filter) {
return true;
}
// Match fuzzy on label
entry.highlights = { label: withNullAsUndefined(matchesFuzzy(filter, entry.label, true)) };
// Return if we have a match on label or container
return entry.highlights.label || fuzzyContains(entry.containerLabel, filter);
});
// Map entries to container labels
const mapEntryToContainer = new Map<string, string>();
for (const entry of filteredViewEntries) {
if (!mapEntryToContainer.has(entry.label)) {
mapEntryToContainer.set(entry.label, entry.containerLabel);
}
}
// Add separators for containers
const filteredViewEntriesWithSeparators: Array<IViewQuickPickItem | IQuickPickSeparator> = [];
let lastContainer: string | undefined = undefined;
for (const entry of filteredViewEntries) {
if (lastContainer !== entry.containerLabel) {
lastContainer = entry.containerLabel;
// When the entry container has a parent container, set container
// label as Parent / Child. For example, `Views / Explorer`.
let separatorLabel: string;
if (mapEntryToContainer.has(lastContainer)) {
separatorLabel = `${mapEntryToContainer.get(lastContainer)} / ${lastContainer}`;
} else {
separatorLabel = lastContainer;
}
filteredViewEntriesWithSeparators.push({ type: 'separator', label: separatorLabel });
}
filteredViewEntriesWithSeparators.push(entry);
}
return filteredViewEntriesWithSeparators;
}
private doGetViewPickItems(): Array<IViewQuickPickItem> {
const viewEntries: Array<IViewQuickPickItem> = [];
const getViewEntriesForViewlet = (viewlet: ViewletDescriptor, viewContainer: ViewContainer): IViewQuickPickItem[] => {
const viewContainerModel = this.viewDescriptorService.getViewContainerModel(viewContainer);
const result: IViewQuickPickItem[] = [];
for (const view of viewContainerModel.allViewDescriptors) {
if (this.contextKeyService.contextMatchesRules(view.when)) {
result.push({
label: view.name,
containerLabel: viewlet.name,
accept: () => this.viewsService.openView(view.id, true)
});
}
}
return result;
};
// Viewlets
const viewlets = this.viewletService.getViewlets();
for (const viewlet of viewlets) {
if (this.includeViewContainer(viewlet)) {
viewEntries.push({
label: viewlet.name,
containerLabel: localize('views', "Side Bar"),
accept: () => this.viewletService.openViewlet(viewlet.id, true)
});
}
}
// Panels
const panels = this.panelService.getPanels();
for (const panel of panels) {
if (this.includeViewContainer(panel)) {
viewEntries.push({
label: panel.name,
containerLabel: localize('panels', "Panel"),
accept: () => this.panelService.openPanel(panel.id, true)
});
}
}
// Viewlet Views
for (const viewlet of viewlets) {
const viewContainer = this.viewDescriptorService.getViewContainerById(viewlet.id);
if (viewContainer) {
viewEntries.push(...getViewEntriesForViewlet(viewlet, viewContainer));
}
}
// Terminals
this.terminalService.terminalTabs.forEach((tab, tabIndex) => {
tab.terminalInstances.forEach((terminal, terminalIndex) => {
const label = localize('terminalTitle', "{0}: {1}", `${tabIndex + 1}.${terminalIndex + 1}`, terminal.title);
viewEntries.push({
label,
containerLabel: localize('terminals', "Terminal"),
accept: async () => {
await this.terminalService.showPanel(true);
this.terminalService.setActiveInstance(terminal);
}
});
});
});
// Output Channels
const channels = this.outputService.getChannelDescriptors();
for (const channel of channels) {
const label = channel.log ? localize('logChannel', "Log ({0})", channel.label) : channel.label;
viewEntries.push({
label,
containerLabel: localize('channels', "Output"),
accept: () => this.outputService.showChannel(channel.id)
});
}
return viewEntries;
}
private includeViewContainer(container: ViewletDescriptor | IPanelIdentifier): boolean {
const viewContainer = this.viewDescriptorService.getViewContainerById(container.id);
if (viewContainer?.hideIfEmpty) {
return this.viewDescriptorService.getViewContainerModel(viewContainer).activeViewDescriptors.length > 0;
}
return true;
}
}
//#region Actions
export class OpenViewPickerAction extends Action2 {
static readonly ID = 'workbench.action.openView';
constructor() {
super({
id: OpenViewPickerAction.ID,
title: { value: localize('openView', "Open View"), original: 'Open View' },
category: CATEGORIES.View,
f1: true
});
}
async run(accessor: ServicesAccessor): Promise<void> {
accessor.get(IQuickInputService).quickAccess.show(ViewQuickAccessProvider.PREFIX);
}
}
export class QuickAccessViewPickerAction extends Action2 {
static readonly ID = 'workbench.action.quickOpenView';
static readonly KEYBINDING = {
primary: KeyMod.CtrlCmd | KeyCode.KEY_Q,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_Q },
linux: { primary: 0 }
};
constructor() {
super({
id: QuickAccessViewPickerAction.ID,
title: { value: localize('quickOpenView', "Quick Open View"), original: 'Quick Open View' },
category: CATEGORIES.View,
f1: true,
keybinding: {
weight: KeybindingWeight.WorkbenchContrib,
when: undefined,
...QuickAccessViewPickerAction.KEYBINDING
}
});
}
async run(accessor: ServicesAccessor): Promise<void> {
const keybindingService = accessor.get(IKeybindingService);
const quickInputService = accessor.get(IQuickInputService);
const keys = keybindingService.lookupKeybindings(QuickAccessViewPickerAction.ID);
quickInputService.quickAccess.show(ViewQuickAccessProvider.PREFIX, { quickNavigateConfiguration: { keybindings: keys }, itemActivation: ItemActivation.FIRST });
}
}
//#endregion