Merge from vscode 099a7622e6e90dbcc226e428d4e35a72cb19ecbc (#9646)

* Merge from vscode 099a7622e6e90dbcc226e428d4e35a72cb19ecbc

* fix strict
This commit is contained in:
Anthony Dresser
2020-03-16 23:16:40 -07:00
committed by GitHub
parent 81e1b9a434
commit a53b78c0c8
170 changed files with 2601 additions and 2026 deletions

View File

@@ -11,15 +11,20 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { AbstractEditorCommandsQuickAccessProvider } from 'vs/editor/contrib/quickAccess/commandsQuickAccess';
import { IEditor } from 'vs/editor/common/editorCommon';
import { withNullAsUndefined } from 'vs/base/common/types';
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
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 { EditorAction, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
export class StandaloneCommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider {
get activeTextEditorControl(): IEditor | undefined { return withNullAsUndefined(this.codeEditorService.getFocusedCodeEditor()); }
protected get activeTextEditorControl(): IEditor | undefined { return withNullAsUndefined(this.codeEditorService.getFocusedCodeEditor()); }
constructor(
@IInstantiationService instantiationService: IInstantiationService,
@@ -42,3 +47,30 @@ Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessPro
prefix: StandaloneCommandsQuickAccessProvider.PREFIX,
helpEntries: [{ description: QuickCommandNLS.quickCommandHelp, needsEditor: true }]
});
export class GotoLineAction extends EditorAction {
constructor() {
super({
id: 'editor.action.quickCommand',
label: QuickCommandNLS.quickCommandActionLabel,
alias: 'Command Palette',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyCode.F1,
weight: KeybindingWeight.EditorContrib
},
contextMenuOpts: {
group: 'z_commands',
order: 1
}
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IQuickInputService).quickAccess.show(StandaloneCommandsQuickAccessProvider.PREFIX);
}
}
registerEditorAction(GotoLineAction);

View File

@@ -10,22 +10,51 @@ import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService
import { withNullAsUndefined } from 'vs/base/common/types';
import { GoToLineNLS } from 'vs/editor/common/standaloneStrings';
import { Event } from 'vs/base/common/event';
import { EditorAction, registerEditorAction, ServicesAccessor } from 'vs/editor/browser/editorExtensions';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
export class StandaloneGotoLineQuickAccessProvider extends AbstractGotoLineQuickAccessProvider {
readonly onDidActiveTextEditorControlChange = Event.None;
protected readonly onDidActiveTextEditorControlChange = Event.None;
constructor(@ICodeEditorService private readonly editorService: ICodeEditorService) {
super();
}
get activeTextEditorControl() {
protected get activeTextEditorControl() {
return withNullAsUndefined(this.editorService.getFocusedCodeEditor());
}
}
Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({
ctor: StandaloneGotoLineQuickAccessProvider,
prefix: AbstractGotoLineQuickAccessProvider.PREFIX,
prefix: StandaloneGotoLineQuickAccessProvider.PREFIX,
helpEntries: [{ description: GoToLineNLS.gotoLineActionLabel, needsEditor: true }]
});
export class GotoLineAction extends EditorAction {
constructor() {
super({
id: 'editor.action.gotoLine',
label: GoToLineNLS.gotoLineActionLabel,
alias: 'Go to Line...',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.CtrlCmd | KeyCode.KEY_G,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_G },
weight: KeybindingWeight.EditorContrib
}
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IQuickInputService).quickAccess.show(StandaloneGotoLineQuickAccessProvider.PREFIX);
}
}
registerEditorAction(GotoLineAction);

View File

@@ -0,0 +1,67 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { AbstractGotoSymbolQuickAccessProvider } from 'vs/editor/contrib/quickAccess/gotoSymbolQuickAccess';
import { Registry } from 'vs/platform/registry/common/platform';
import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/quickAccess';
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
import { withNullAsUndefined } from 'vs/base/common/types';
import { QuickOutlineNLS } from 'vs/editor/common/standaloneStrings';
import { Event } from 'vs/base/common/event';
import { EditorAction, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { KeyMod, KeyCode } from 'vs/base/common/keyCodes';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { ServicesAccessor } from 'vs/platform/instantiation/common/instantiation';
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
export class StandaloneGotoSymbolQuickAccessProvider extends AbstractGotoSymbolQuickAccessProvider {
protected readonly onDidActiveTextEditorControlChange = Event.None;
constructor(@ICodeEditorService private readonly editorService: ICodeEditorService) {
super();
}
protected get activeTextEditorControl() {
return withNullAsUndefined(this.editorService.getFocusedCodeEditor());
}
}
Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({
ctor: StandaloneGotoSymbolQuickAccessProvider,
prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX,
helpEntries: [
{ description: QuickOutlineNLS.quickOutlineActionLabel, prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX, needsEditor: true },
{ description: QuickOutlineNLS.quickOutlineByCategoryActionLabel, prefix: AbstractGotoSymbolQuickAccessProvider.PREFIX_BY_CATEGORY, needsEditor: true }
]
});
export class GotoLineAction extends EditorAction {
constructor() {
super({
id: 'editor.action.quickOutline',
label: QuickOutlineNLS.quickOutlineActionLabel,
alias: 'Go to Symbol...',
precondition: EditorContextKeys.hasDocumentSymbolProvider,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_O,
weight: KeybindingWeight.EditorContrib
},
contextMenuOpts: {
group: 'navigation',
order: 3
}
});
}
run(accessor: ServicesAccessor): void {
accessor.get(IQuickInputService).quickAccess.show(AbstractGotoSymbolQuickAccessProvider.PREFIX);
}
}
registerEditorAction(GotoLineAction);

View File

@@ -8,8 +8,8 @@ import { IQuickAccessRegistry, Extensions } from 'vs/platform/quickinput/common/
import { QuickHelpNLS } from 'vs/editor/common/standaloneStrings';
import { HelpQuickAccessProvider } from 'vs/platform/quickinput/browser/helpQuickAccess';
Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).defaultProvider = {
Registry.as<IQuickAccessRegistry>(Extensions.Quickaccess).registerQuickAccessProvider({
ctor: HelpQuickAccessProvider,
prefix: '',
helpEntries: [{ description: QuickHelpNLS.helpQuickAccessActionLabel, needsEditor: true }]
};
});

View File

@@ -1,19 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
.monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
color: #0066BF;
}
.vs-dark .monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
.vs-dark .monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
color: #0097fb;
}
.hc-black .monaco-quick-open-widget .monaco-tree .monaco-tree-row .monaco-highlighted-label .highlight,
.hc-black .monaco-quick-open-widget .monaco-list .monaco-list-row .monaco-highlighted-label .highlight {
color: #F38518;
}

View File

@@ -1,172 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./editorQuickOpen';
import { QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { EditorAction, IActionOptions, registerEditorContribution } from 'vs/editor/browser/editorExtensions';
import { Range } from 'vs/editor/common/core/range';
import { Selection } from 'vs/editor/common/core/selection';
import { IEditorContribution, ScrollType, IEditor } from 'vs/editor/common/editorCommon';
import { IModelDeltaDecoration } from 'vs/editor/common/model';
import { ModelDecorationOptions } from 'vs/editor/common/model/textModel';
import { QuickOpenEditorWidget } from 'vs/editor/standalone/browser/quickOpen/quickOpenEditorWidget';
import { IThemeService } from 'vs/platform/theme/common/themeService';
export interface IQuickOpenControllerOpts {
inputAriaLabel: string;
getModel(value: string): QuickOpenModel;
getAutoFocus(searchValue: string): IAutoFocus;
}
export class QuickOpenController implements IEditorContribution, IDecorator {
public static readonly ID = 'editor.controller.quickOpenController';
public static get(editor: ICodeEditor): QuickOpenController {
return editor.getContribution<QuickOpenController>(QuickOpenController.ID);
}
private readonly editor: ICodeEditor;
private widget: QuickOpenEditorWidget | null = null;
private rangeHighlightDecorationId: string | null = null;
private lastKnownEditorSelection: Selection | null = null;
constructor(editor: ICodeEditor, @IThemeService private readonly themeService: IThemeService) {
this.editor = editor;
}
public dispose(): void {
// Dispose widget
if (this.widget) {
this.widget.destroy();
this.widget = null;
}
}
public run(opts: IQuickOpenControllerOpts): void {
if (this.widget) {
this.widget.destroy();
this.widget = null;
}
// Create goto line widget
let onClose = (canceled: boolean) => {
// Clear Highlight Decorations if present
this.clearDecorations();
// Restore selection if canceled
if (canceled && this.lastKnownEditorSelection) {
this.editor.setSelection(this.lastKnownEditorSelection);
this.editor.revealRangeInCenterIfOutsideViewport(this.lastKnownEditorSelection, ScrollType.Smooth);
}
this.lastKnownEditorSelection = null;
// Return focus to the editor if
// - focus is back on the <body> element because no other focusable element was clicked
// - a command was picked from the picker which indicates the editor should get focused
if (document.activeElement === document.body || !canceled) {
this.editor.focus();
}
};
this.widget = new QuickOpenEditorWidget(
this.editor,
() => onClose(false),
() => onClose(true),
(value: string) => {
this.widget!.setInput(opts.getModel(value), opts.getAutoFocus(value));
},
{
inputAriaLabel: opts.inputAriaLabel
},
this.themeService
);
// Remember selection to be able to restore on cancel
if (!this.lastKnownEditorSelection) {
this.lastKnownEditorSelection = this.editor.getSelection();
}
// Show
this.widget.show('');
}
private static readonly _RANGE_HIGHLIGHT_DECORATION = ModelDecorationOptions.register({
className: 'rangeHighlight',
isWholeLine: true
});
public decorateLine(range: Range, editor: ICodeEditor): void {
const oldDecorations: string[] = [];
if (this.rangeHighlightDecorationId) {
oldDecorations.push(this.rangeHighlightDecorationId);
this.rangeHighlightDecorationId = null;
}
const newDecorations: IModelDeltaDecoration[] = [
{
range: range,
options: QuickOpenController._RANGE_HIGHLIGHT_DECORATION
}
];
const decorations = editor.deltaDecorations(oldDecorations, newDecorations);
this.rangeHighlightDecorationId = decorations[0];
}
public clearDecorations(): void {
if (this.rangeHighlightDecorationId) {
this.editor.deltaDecorations([this.rangeHighlightDecorationId], []);
this.rangeHighlightDecorationId = null;
}
}
}
export interface IQuickOpenOpts {
/**
* provide the quick open model for the given search value.
*/
getModel(value: string): QuickOpenModel;
/**
* provide the quick open auto focus mode for the given search value.
*/
getAutoFocus(searchValue: string): IAutoFocus;
}
/**
* Base class for providing quick open in the editor.
*/
export abstract class BaseEditorQuickOpenAction extends EditorAction {
private readonly _inputAriaLabel: string;
constructor(inputAriaLabel: string, opts: IActionOptions) {
super(opts);
this._inputAriaLabel = inputAriaLabel;
}
protected getController(editor: ICodeEditor): QuickOpenController {
return QuickOpenController.get(editor);
}
protected _show(controller: QuickOpenController, opts: IQuickOpenOpts): void {
controller.run({
inputAriaLabel: this._inputAriaLabel,
getModel: (value: string): QuickOpenModel => opts.getModel(value),
getAutoFocus: (searchValue: string): IAutoFocus => opts.getAutoFocus(searchValue)
});
}
}
export interface IDecorator {
decorateLine(range: Range, editor: IEditor): void;
clearDecorations(): void;
}
registerEditorContribution(QuickOpenController.ID, QuickOpenController);

View File

@@ -1,8 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-quick-open-widget {
font-size: 13px;
}

View File

@@ -1,177 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./gotoLine';
import * as strings from 'vs/base/common/strings';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import { QuickOpenEntry, QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IAutoFocus, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import { ICodeEditor, IDiffEditor, isCodeEditor } from 'vs/editor/browser/editorBrowser';
import { ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { Position } from 'vs/editor/common/core/position';
import { Range } from 'vs/editor/common/core/range';
import { IEditor, ScrollType } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { ITextModel } from 'vs/editor/common/model';
import { BaseEditorQuickOpenAction, IDecorator } from 'vs/editor/standalone/browser/quickOpen/editorQuickOpen';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { GoToLineNLS } from 'vs/editor/common/standaloneStrings';
interface ParseResult {
position: Position;
isValid: boolean;
label: string;
}
export class GotoLineEntry extends QuickOpenEntry {
private readonly parseResult: ParseResult;
private readonly decorator: IDecorator;
private readonly editor: IEditor;
constructor(line: string, editor: IEditor, decorator: IDecorator) {
super();
this.editor = editor;
this.decorator = decorator;
this.parseResult = this.parseInput(line);
}
private parseInput(line: string): ParseResult {
const numbers = line.split(',').map(part => parseInt(part, 10)).filter(part => !isNaN(part));
let position: Position;
if (numbers.length === 0) {
position = new Position(-1, -1);
} else if (numbers.length === 1) {
position = new Position(numbers[0], 1);
} else {
position = new Position(numbers[0], numbers[1]);
}
let model: ITextModel | null;
if (isCodeEditor(this.editor)) {
model = this.editor.getModel();
} else {
const diffModel = (<IDiffEditor>this.editor).getModel();
model = diffModel ? diffModel.modified : null;
}
const isValid = model ? model.validatePosition(position).equals(position) : false;
let label: string;
if (isValid) {
if (position.column && position.column > 1) {
label = strings.format(GoToLineNLS.gotoLineLabelValidLineAndColumn, position.lineNumber, position.column);
} else {
label = strings.format(GoToLineNLS.gotoLineLabelValidLine, position.lineNumber);
}
} else if (position.lineNumber < 1 || position.lineNumber > (model ? model.getLineCount() : 0)) {
label = strings.format(GoToLineNLS.gotoLineLabelEmptyWithLineLimit, model ? model.getLineCount() : 0);
} else {
label = strings.format(GoToLineNLS.gotoLineLabelEmptyWithLineAndColumnLimit, model ? model.getLineMaxColumn(position.lineNumber) : 0);
}
return {
position: position,
isValid: isValid,
label: label
};
}
getLabel(): string {
return this.parseResult.label;
}
getAriaLabel(): string {
const position = this.editor.getPosition();
const currentLine = position ? position.lineNumber : 0;
return strings.format(GoToLineNLS.gotoLineAriaLabel, currentLine, this.parseResult.label);
}
run(mode: Mode, _context: IEntryRunContext): boolean {
if (mode === Mode.OPEN) {
return this.runOpen();
}
return this.runPreview();
}
runOpen(): boolean {
// No-op if range is not valid
if (!this.parseResult.isValid) {
return false;
}
// Apply selection and focus
const range = this.toSelection();
(<ICodeEditor>this.editor).setSelection(range);
(<ICodeEditor>this.editor).revealRangeInCenter(range, ScrollType.Smooth);
this.editor.focus();
return true;
}
runPreview(): boolean {
// No-op if range is not valid
if (!this.parseResult.isValid) {
this.decorator.clearDecorations();
return false;
}
// Select Line Position
const range = this.toSelection();
this.editor.revealRangeInCenter(range, ScrollType.Smooth);
// Decorate if possible
this.decorator.decorateLine(range, this.editor);
return false;
}
private toSelection(): Range {
return new Range(
this.parseResult.position.lineNumber,
this.parseResult.position.column,
this.parseResult.position.lineNumber,
this.parseResult.position.column
);
}
}
export class GotoLineAction extends BaseEditorQuickOpenAction {
constructor() {
super(GoToLineNLS.gotoLineActionInput, {
id: 'editor.action.gotoLine',
label: GoToLineNLS.gotoLineActionLabel,
alias: 'Go to Line...',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.CtrlCmd | KeyCode.KEY_G,
mac: { primary: KeyMod.WinCtrl | KeyCode.KEY_G },
weight: KeybindingWeight.EditorContrib
}
});
}
run(accessor: ServicesAccessor, editor: ICodeEditor): void {
this._show(this.getController(editor), {
getModel: (value: string): QuickOpenModel => {
return new QuickOpenModel([new GotoLineEntry(value, editor, this.getController(editor))]);
},
getAutoFocus: (searchValue: string): IAutoFocus => {
return {
autoFocusFirstEntry: searchValue.length > 0
};
}
});
}
}
registerEditorAction(GotoLineAction);

View File

@@ -1,144 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as strings from 'vs/base/common/strings';
import { onUnexpectedError } from 'vs/base/common/errors';
import { matchesFuzzy } from 'vs/base/common/filters';
import { KeyCode } from 'vs/base/common/keyCodes';
import { IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IAutoFocus, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { IEditor, IEditorAction } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { BaseEditorQuickOpenAction } from 'vs/editor/standalone/browser/quickOpen/editorQuickOpen';
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { QuickCommandNLS } from 'vs/editor/common/standaloneStrings';
export class EditorActionCommandEntry extends QuickOpenEntryGroup {
private readonly key: string;
private readonly action: IEditorAction;
private readonly editor: IEditor;
private readonly keyAriaLabel: string;
constructor(key: string, keyAriaLabel: string, highlights: IHighlight[], action: IEditorAction, editor: IEditor) {
super();
this.key = key;
this.keyAriaLabel = keyAriaLabel;
this.setHighlights(highlights);
this.action = action;
this.editor = editor;
}
public getLabel(): string {
return this.action.label;
}
public getAriaLabel(): string {
if (this.keyAriaLabel) {
return strings.format(QuickCommandNLS.ariaLabelEntryWithKey, this.getLabel(), this.keyAriaLabel);
}
return strings.format(QuickCommandNLS.ariaLabelEntry, this.getLabel());
}
public getGroupLabel(): string {
return this.key;
}
public run(mode: Mode, context: IEntryRunContext): boolean {
if (mode === Mode.OPEN) {
// Use a timeout to give the quick open widget a chance to close itself first
setTimeout(() => {
// Some actions are enabled only when editor has focus
this.editor.focus();
try {
let promise = this.action.run() || Promise.resolve();
promise.then(undefined, onUnexpectedError);
} catch (error) {
onUnexpectedError(error);
}
}, 50);
return true;
}
return false;
}
}
export class QuickCommandAction extends BaseEditorQuickOpenAction {
constructor() {
super(QuickCommandNLS.quickCommandActionInput, {
id: 'editor.action.quickCommand',
label: QuickCommandNLS.quickCommandActionLabel,
alias: 'Command Palette',
precondition: undefined,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyCode.F1,
weight: KeybindingWeight.EditorContrib
},
contextMenuOpts: {
group: 'z_commands',
order: 1
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor): void {
const keybindingService = accessor.get(IKeybindingService);
this._show(this.getController(editor), {
getModel: (value: string): QuickOpenModel => {
return new QuickOpenModel(this._editorActionsToEntries(keybindingService, editor, value));
},
getAutoFocus: (searchValue: string): IAutoFocus => {
return {
autoFocusFirstEntry: true,
autoFocusPrefixMatch: searchValue
};
}
});
}
private _sort(elementA: QuickOpenEntryGroup, elementB: QuickOpenEntryGroup): number {
let elementAName = (elementA.getLabel() || '').toLowerCase();
let elementBName = (elementB.getLabel() || '').toLowerCase();
return elementAName.localeCompare(elementBName);
}
private _editorActionsToEntries(keybindingService: IKeybindingService, editor: ICodeEditor, searchValue: string): EditorActionCommandEntry[] {
let actions: IEditorAction[] = editor.getSupportedActions();
let entries: EditorActionCommandEntry[] = [];
for (const action of actions) {
let keybinding = keybindingService.lookupKeybinding(action.id);
if (action.label) {
let highlights = matchesFuzzy(searchValue, action.label);
if (highlights) {
entries.push(new EditorActionCommandEntry(keybinding ? keybinding.getLabel() || '' : '', keybinding ? keybinding.getAriaLabel() || '' : '', highlights, action, editor));
}
}
}
// Sort by name
entries = entries.sort(this._sort);
return entries;
}
}
registerEditorAction(QuickCommandAction);

View File

@@ -1,107 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { Dimension } from 'vs/base/browser/dom';
import { IDisposable } from 'vs/base/common/lifecycle';
import { QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { QuickOpenWidget } from 'vs/base/parts/quickopen/browser/quickOpenWidget';
import { IAutoFocus } from 'vs/base/parts/quickopen/common/quickOpen';
import { ICodeEditor, IOverlayWidget, IOverlayWidgetPosition, OverlayWidgetPositionPreference } from 'vs/editor/browser/editorBrowser';
import { foreground } from 'vs/platform/theme/common/colorRegistry';
import { attachQuickOpenStyler } from 'vs/platform/theme/common/styler';
import { IThemeService } from 'vs/platform/theme/common/themeService';
export interface IQuickOpenEditorWidgetOptions {
inputAriaLabel: string;
}
export class QuickOpenEditorWidget implements IOverlayWidget {
private static readonly ID = 'editor.contrib.quickOpenEditorWidget';
private readonly codeEditor: ICodeEditor;
private readonly themeService: IThemeService;
private visible: boolean | undefined;
private quickOpenWidget: QuickOpenWidget;
private domNode: HTMLElement;
private styler: IDisposable;
constructor(codeEditor: ICodeEditor, onOk: () => void, onCancel: () => void, onType: (value: string) => void, configuration: IQuickOpenEditorWidgetOptions, themeService: IThemeService) {
this.codeEditor = codeEditor;
this.themeService = themeService;
this.visible = false;
this.domNode = document.createElement('div');
this.quickOpenWidget = new QuickOpenWidget(
this.domNode,
{
onOk: onOk,
onCancel: onCancel,
onType: onType
}, {
inputPlaceHolder: undefined,
inputAriaLabel: configuration.inputAriaLabel,
keyboardSupport: true
}
);
this.styler = attachQuickOpenStyler(this.quickOpenWidget, this.themeService, {
pickerGroupForeground: foreground
});
this.quickOpenWidget.create();
this.codeEditor.addOverlayWidget(this);
}
setInput(model: QuickOpenModel, focus: IAutoFocus): void {
this.quickOpenWidget.setInput(model, focus);
}
getId(): string {
return QuickOpenEditorWidget.ID;
}
getDomNode(): HTMLElement {
return this.domNode;
}
destroy(): void {
this.codeEditor.removeOverlayWidget(this);
this.quickOpenWidget.dispose();
this.styler.dispose();
}
isVisible(): boolean {
return !!this.visible;
}
show(value: string): void {
this.visible = true;
const editorLayout = this.codeEditor.getLayoutInfo();
if (editorLayout) {
this.quickOpenWidget.layout(new Dimension(editorLayout.width, editorLayout.height));
}
this.quickOpenWidget.show(value);
this.codeEditor.layoutOverlayWidget(this);
}
hide(): void {
this.visible = false;
this.quickOpenWidget.hide();
this.codeEditor.layoutOverlayWidget(this);
}
getPosition(): IOverlayWidgetPosition | null {
if (this.visible) {
return {
preference: OverlayWidgetPositionPreference.TOP_CENTER
};
}
return null;
}
}

View File

@@ -1,8 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
.monaco-quick-open-widget {
font-size: 13px;
}

View File

@@ -1,325 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import 'vs/css!./quickOutline';
import 'vs/base/browser/ui/codiconLabel/codiconLabel'; // The codicon symbol styles are defined here and must be loaded
import 'vs/editor/contrib/documentSymbols/outlineTree'; // The codicon symbol colors are defined here and must be loaded
import { CancellationToken } from 'vs/base/common/cancellation';
import { matchesFuzzy } from 'vs/base/common/filters';
import { KeyCode, KeyMod } from 'vs/base/common/keyCodes';
import * as strings from 'vs/base/common/strings';
import { IHighlight, QuickOpenEntryGroup, QuickOpenModel } from 'vs/base/parts/quickopen/browser/quickOpenModel';
import { IAutoFocus, Mode, IEntryRunContext } from 'vs/base/parts/quickopen/common/quickOpen';
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
import { ServicesAccessor, registerEditorAction } from 'vs/editor/browser/editorExtensions';
import { IRange, Range } from 'vs/editor/common/core/range';
import { ScrollType } from 'vs/editor/common/editorCommon';
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
import { DocumentSymbol, DocumentSymbolProviderRegistry, SymbolKinds } from 'vs/editor/common/modes';
import { getDocumentSymbols } from 'vs/editor/contrib/quickOpen/quickOpen';
import { BaseEditorQuickOpenAction, IDecorator } from 'vs/editor/standalone/browser/quickOpen/editorQuickOpen';
import { KeybindingWeight } from 'vs/platform/keybinding/common/keybindingsRegistry';
import { QuickOutlineNLS } from 'vs/editor/common/standaloneStrings';
let SCOPE_PREFIX = ':';
export class SymbolEntry extends QuickOpenEntryGroup {
private readonly name: string;
private readonly type: string;
private readonly description: string | undefined;
private readonly range: Range;
private readonly editor: ICodeEditor;
private readonly decorator: IDecorator;
constructor(name: string, type: string, description: string | undefined, range: Range, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator) {
super();
this.name = name;
this.type = type;
this.description = description;
this.range = range;
this.setHighlights(highlights);
this.editor = editor;
this.decorator = decorator;
}
public getLabel(): string {
return this.name;
}
public getAriaLabel(): string {
return strings.format(QuickOutlineNLS.entryAriaLabel, this.name);
}
public getIcon(): string {
return this.type;
}
public getDescription(): string | undefined {
return this.description;
}
public getType(): string {
return this.type;
}
public getRange(): Range {
return this.range;
}
public run(mode: Mode, context: IEntryRunContext): boolean {
if (mode === Mode.OPEN) {
return this.runOpen(context);
}
return this.runPreview();
}
private runOpen(_context: IEntryRunContext): boolean {
// Apply selection and focus
let range = this.toSelection();
this.editor.setSelection(range);
this.editor.revealRangeInCenter(range, ScrollType.Smooth);
this.editor.focus();
return true;
}
private runPreview(): boolean {
// Select Outline Position
let range = this.toSelection();
this.editor.revealRangeInCenter(range, ScrollType.Smooth);
// Decorate if possible
this.decorator.decorateLine(this.range, this.editor);
return false;
}
private toSelection(): Range {
return new Range(
this.range.startLineNumber,
this.range.startColumn || 1,
this.range.startLineNumber,
this.range.startColumn || 1
);
}
}
export class QuickOutlineAction extends BaseEditorQuickOpenAction {
constructor() {
super(QuickOutlineNLS.quickOutlineActionInput, {
id: 'editor.action.quickOutline',
label: QuickOutlineNLS.quickOutlineActionLabel,
alias: 'Go to Symbol...',
precondition: EditorContextKeys.hasDocumentSymbolProvider,
kbOpts: {
kbExpr: EditorContextKeys.focus,
primary: KeyMod.CtrlCmd | KeyMod.Shift | KeyCode.KEY_O,
weight: KeybindingWeight.EditorContrib
},
contextMenuOpts: {
group: 'navigation',
order: 3
}
});
}
public run(accessor: ServicesAccessor, editor: ICodeEditor) {
if (!editor.hasModel()) {
return undefined;
}
const model = editor.getModel();
if (!DocumentSymbolProviderRegistry.has(model)) {
return undefined;
}
// Resolve outline
return getDocumentSymbols(model, true, CancellationToken.None).then((result: DocumentSymbol[]) => {
if (result.length === 0) {
return;
}
this._run(editor, result);
});
}
private _run(editor: ICodeEditor, result: DocumentSymbol[]): void {
this._show(this.getController(editor), {
getModel: (value: string): QuickOpenModel => {
return new QuickOpenModel(this.toQuickOpenEntries(editor, result, value));
},
getAutoFocus: (searchValue: string): IAutoFocus => {
// Remove any type pattern (:) from search value as needed
if (searchValue.indexOf(SCOPE_PREFIX) === 0) {
searchValue = searchValue.substr(SCOPE_PREFIX.length);
}
return {
autoFocusPrefixMatch: searchValue,
autoFocusFirstEntry: !!searchValue
};
}
});
}
private symbolEntry(name: string, type: string, description: string | undefined, range: IRange, highlights: IHighlight[], editor: ICodeEditor, decorator: IDecorator): SymbolEntry {
return new SymbolEntry(name, type, description, Range.lift(range), highlights, editor, decorator);
}
private toQuickOpenEntries(editor: ICodeEditor, flattened: DocumentSymbol[], searchValue: string): SymbolEntry[] {
const controller = this.getController(editor);
let results: SymbolEntry[] = [];
// Convert to Entries
let normalizedSearchValue = searchValue;
if (searchValue.indexOf(SCOPE_PREFIX) === 0) {
normalizedSearchValue = normalizedSearchValue.substr(SCOPE_PREFIX.length);
}
for (const element of flattened) {
let label = strings.trim(element.name);
// Check for meatch
let highlights = matchesFuzzy(normalizedSearchValue, label);
if (highlights) {
// Show parent scope as description
let description: string | undefined = undefined;
if (element.containerName) {
description = element.containerName;
}
// Add
results.push(this.symbolEntry(label, SymbolKinds.toCssClassName(element.kind), description, element.range, highlights, editor, controller));
}
}
// Sort properly if actually searching
if (searchValue) {
if (searchValue.indexOf(SCOPE_PREFIX) === 0) {
results = results.sort(this.sortScoped.bind(this, searchValue.toLowerCase()));
} else {
results = results.sort(this.sortNormal.bind(this, searchValue.toLowerCase()));
}
}
// Mark all type groups
if (results.length > 0 && searchValue.indexOf(SCOPE_PREFIX) === 0) {
let currentType: string | null = null;
let currentResult: SymbolEntry | null = null;
let typeCounter = 0;
for (let i = 0; i < results.length; i++) {
let result = results[i];
// Found new type
if (currentType !== result.getType()) {
// Update previous result with count
if (currentResult) {
currentResult.setGroupLabel(this.typeToLabel(currentType || '', typeCounter));
}
currentType = result.getType();
currentResult = result;
typeCounter = 1;
result.setShowBorder(i > 0);
}
// Existing type, keep counting
else {
typeCounter++;
}
}
// Update previous result with count
if (currentResult) {
currentResult.setGroupLabel(this.typeToLabel(currentType || '', typeCounter));
}
}
// Mark first entry as outline
else if (results.length > 0) {
results[0].setGroupLabel(strings.format(QuickOutlineNLS._symbols_, results.length));
}
return results;
}
private typeToLabel(type: string, count: number): string {
switch (type) {
case 'module': return strings.format(QuickOutlineNLS._modules_, count);
case 'class': return strings.format(QuickOutlineNLS._class_, count);
case 'interface': return strings.format(QuickOutlineNLS._interface_, count);
case 'method': return strings.format(QuickOutlineNLS._method_, count);
case 'function': return strings.format(QuickOutlineNLS._function_, count);
case 'property': return strings.format(QuickOutlineNLS._property_, count);
case 'variable': return strings.format(QuickOutlineNLS._variable_, count);
case 'var': return strings.format(QuickOutlineNLS._variable2_, count);
case 'constructor': return strings.format(QuickOutlineNLS._constructor_, count);
case 'call': return strings.format(QuickOutlineNLS._call_, count);
}
return type;
}
private sortNormal(searchValue: string, elementA: SymbolEntry, elementB: SymbolEntry): number {
let elementAName = elementA.getLabel().toLowerCase();
let elementBName = elementB.getLabel().toLowerCase();
// Compare by name
let r = elementAName.localeCompare(elementBName);
if (r !== 0) {
return r;
}
// If name identical sort by range instead
let elementARange = elementA.getRange();
let elementBRange = elementB.getRange();
return elementARange.startLineNumber - elementBRange.startLineNumber;
}
private sortScoped(searchValue: string, elementA: SymbolEntry, elementB: SymbolEntry): number {
// Remove scope char
searchValue = searchValue.substr(SCOPE_PREFIX.length);
// Sort by type first if scoped search
let elementAType = elementA.getType();
let elementBType = elementB.getType();
let r = elementAType.localeCompare(elementBType);
if (r !== 0) {
return r;
}
// Special sort when searching in scoped mode
if (searchValue) {
let elementAName = elementA.getLabel().toLowerCase();
let elementBName = elementB.getLabel().toLowerCase();
// Compare by name
let r = elementAName.localeCompare(elementBName);
if (r !== 0) {
return r;
}
}
// Default to sort by range
let elementARange = elementA.getRange();
let elementBRange = elementB.getRange();
return elementARange.startLineNumber - elementBRange.startLineNumber;
}
}
registerEditorAction(QuickOutlineAction);

View File

@@ -138,6 +138,8 @@ class StandaloneTheme implements IStandaloneTheme {
public get tokenColorMap(): string[] {
return [];
}
public readonly semanticHighlighting = false;
}
function isBuiltinTheme(themeName: string): themeName is BuiltinTheme {