mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode 93309f060778f6480a7d2a13913e6e7c624e9bc7
This commit is contained in:
@@ -121,21 +121,33 @@ suite.skip('BackupRestorer', () => { // {{SQL CARBON EDIT}} TODO @anthonydresser
|
||||
const resource = editor.resource;
|
||||
if (isEqual(resource, untitledFile1)) {
|
||||
const model = await accessor.textFileService.untitled.resolve({ untitledResource: resource });
|
||||
assert.equal(model.textEditorModel.getValue(), 'untitled-1');
|
||||
if (model.textEditorModel.getValue() !== 'untitled-1') {
|
||||
const backupContents = await backupFileService.getBackupContents(untitledFile1);
|
||||
assert.fail(`Unable to restore backup for resource ${untitledFile1.toString()}. Backup contents: ${backupContents}`);
|
||||
}
|
||||
model.dispose();
|
||||
counter++;
|
||||
} else if (isEqual(resource, untitledFile2)) {
|
||||
const model = await accessor.textFileService.untitled.resolve({ untitledResource: resource });
|
||||
assert.equal(model.textEditorModel.getValue(), 'untitled-2');
|
||||
if (model.textEditorModel.getValue() !== 'untitled-2') {
|
||||
const backupContents = await backupFileService.getBackupContents(untitledFile2);
|
||||
assert.fail(`Unable to restore backup for resource ${untitledFile2.toString()}. Backup contents: ${backupContents}`);
|
||||
}
|
||||
model.dispose();
|
||||
counter++;
|
||||
} else if (isEqual(resource, fooFile)) {
|
||||
const model = await accessor.textFileService.files.get(resource!)?.load();
|
||||
assert.equal(model?.textEditorModel?.getValue(), 'fooFile');
|
||||
const model = await accessor.textFileService.files.get(fooFile!)?.load();
|
||||
if (model?.textEditorModel?.getValue() !== 'fooFile') {
|
||||
const backupContents = await backupFileService.getBackupContents(fooFile);
|
||||
assert.fail(`Unable to restore backup for resource ${fooFile.toString()}. Backup contents: ${backupContents}`);
|
||||
}
|
||||
counter++;
|
||||
} else {
|
||||
const model = await accessor.textFileService.files.get(resource!)?.load();
|
||||
assert.equal(model?.textEditorModel?.getValue(), 'barFile');
|
||||
const model = await accessor.textFileService.files.get(barFile!)?.load();
|
||||
if (model?.textEditorModel?.getValue() !== 'barFile') {
|
||||
const backupContents = await backupFileService.getBackupContents(barFile);
|
||||
assert.fail(`Unable to restore backup for resource ${barFile.toString()}. Backup contents: ${backupContents}`);
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,12 @@ class InspectEditorTokensController extends Disposable implements IEditorContrib
|
||||
this._register(this._editor.onDidChangeModel((e) => this.stop()));
|
||||
this._register(this._editor.onDidChangeModelLanguage((e) => this.stop()));
|
||||
this._register(this._editor.onKeyUp((e) => e.keyCode === KeyCode.Escape && this.stop()));
|
||||
this._register(this._themeService.onDidColorThemeChange(_ => {
|
||||
if (this._widget) {
|
||||
this.stop();
|
||||
this.launch();
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { memoize } from 'vs/base/common/decorators';
|
||||
import { Lazy } from 'vs/base/common/lazy';
|
||||
import { IReference } from 'vs/base/common/lifecycle';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { basename } from 'vs/base/common/path';
|
||||
import { isEqual } from 'vs/base/common/resources';
|
||||
import { assertIsDefined } from 'vs/base/common/types';
|
||||
@@ -99,6 +100,10 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
return this._modelRef ? this._modelRef.object.isReadonly() : false;
|
||||
}
|
||||
|
||||
public isUntitled(): boolean {
|
||||
return this.resource.scheme === Schemas.untitled;
|
||||
}
|
||||
|
||||
public isDirty(): boolean {
|
||||
if (!this._modelRef) {
|
||||
return false;
|
||||
@@ -120,8 +125,16 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
|
||||
public async save(groupId: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
|
||||
const modelRef = assertIsDefined(this._modelRef);
|
||||
const result = await modelRef.object.save(options);
|
||||
return result ? this : undefined;
|
||||
const target = await modelRef.object.saveCustomEditor(options);
|
||||
if (!target) {
|
||||
return undefined; // save cancelled
|
||||
}
|
||||
|
||||
if (!isEqual(target, this.resource)) {
|
||||
return this.customEditorService.createInput(target, this.viewType, groupId);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
public async saveAs(groupId: GroupIdentifier, options?: ISaveOptions): Promise<IEditorInput | undefined> {
|
||||
@@ -133,7 +146,7 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
return undefined; // save cancelled
|
||||
}
|
||||
|
||||
if (!await modelRef.object.saveAs(this._editorResource, target, options)) {
|
||||
if (!await modelRef.object.saveCustomEditorAs(this._editorResource, target, options)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -160,29 +173,29 @@ export class CustomEditorInput extends LazilyResolvedWebviewEditorInput {
|
||||
}
|
||||
|
||||
move(group: GroupIdentifier, newResource: URI): { editor: IEditorInput } | undefined {
|
||||
// See if we can keep using the same custom editor provider
|
||||
const editorInfo = this.customEditorService.getCustomEditor(this.viewType);
|
||||
if (editorInfo?.matches(newResource)) {
|
||||
// We can keep using the same custom editor provider
|
||||
|
||||
if (!this._moveHandler) {
|
||||
return {
|
||||
editor: this.customEditorService.createInput(newResource, this.viewType, group),
|
||||
};
|
||||
}
|
||||
|
||||
this._moveHandler(newResource);
|
||||
const newEditor = this.instantiationService.createInstance(CustomEditorInput,
|
||||
newResource,
|
||||
this.viewType,
|
||||
this.id,
|
||||
new Lazy(() => undefined!)); // this webview is replaced in the transfer call
|
||||
this.transfer(newEditor);
|
||||
newEditor.updateGroup(group);
|
||||
return { editor: newEditor };
|
||||
} else {
|
||||
// const possible = this.customEditorService.getContributedCustomEditors(newResource);
|
||||
return { editor: this.editorService.createEditorInput({ resource: newResource, forceFile: true }) };
|
||||
return { editor: this.doMove(group, newResource) };
|
||||
}
|
||||
|
||||
return { editor: this.editorService.createEditorInput({ resource: newResource, forceFile: true }) };
|
||||
}
|
||||
|
||||
private doMove(group: GroupIdentifier, newResource: URI): IEditorInput {
|
||||
if (!this._moveHandler) {
|
||||
return this.customEditorService.createInput(newResource, this.viewType, group);
|
||||
}
|
||||
|
||||
this._moveHandler(newResource);
|
||||
const newEditor = this.instantiationService.createInstance(CustomEditorInput,
|
||||
newResource,
|
||||
this.viewType,
|
||||
this.id,
|
||||
new Lazy(() => undefined!)); // this webview is replaced in the transfer call
|
||||
this.transfer(newEditor);
|
||||
newEditor.updateGroup(group);
|
||||
return newEditor;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -327,8 +327,8 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
||||
|
||||
private async handleMovedFileInOpenedFileEditors(_oldResource: URI, newResource: URI): Promise<void> {
|
||||
// See if the new resource can be opened in a custom editor
|
||||
const possibleEditors = this.getAllCustomEditors(newResource).allEditors;
|
||||
if (!possibleEditors.length) {
|
||||
const possibleEditors = this.getAllCustomEditors(newResource);
|
||||
if (!possibleEditors.allEditors.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -354,19 +354,25 @@ export class CustomEditorService extends Disposable implements ICustomEditorServ
|
||||
return;
|
||||
}
|
||||
|
||||
// If there is, show a single prompt for all editors to see if the user wants to re-open them
|
||||
//
|
||||
// TODO: instead of prompting eagerly, it'd likly be better to replace all the editors with
|
||||
// ones that would prompt when they first become visible
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
const pickedViewType = await this.showOpenWithPrompt(newResource);
|
||||
if (!pickedViewType) {
|
||||
let viewType: string | undefined;
|
||||
if (possibleEditors.defaultEditor) {
|
||||
viewType = possibleEditors.defaultEditor.id;
|
||||
} else {
|
||||
// If there is, show a single prompt for all editors to see if the user wants to re-open them
|
||||
//
|
||||
// TODO: instead of prompting eagerly, it'd likly be better to replace all the editors with
|
||||
// ones that would prompt when they first become visible
|
||||
await new Promise(resolve => setTimeout(resolve, 50));
|
||||
viewType = await this.showOpenWithPrompt(newResource);
|
||||
}
|
||||
|
||||
if (!viewType) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const [group, entries] of editorsToReplace) {
|
||||
this.editorService.replaceEditors(entries.map(editor => {
|
||||
const replacement = this.createInput(newResource, pickedViewType, group);
|
||||
const replacement = this.createInput(newResource, viewType!, group);
|
||||
return {
|
||||
editor,
|
||||
replacement,
|
||||
|
||||
@@ -26,7 +26,15 @@ interface IWebviewEditorsExtensionPoint {
|
||||
const webviewEditorsContribution: IJSONSchema = {
|
||||
description: nls.localize('contributes.customEditors', 'Contributed custom editors.'),
|
||||
type: 'array',
|
||||
defaultSnippets: [{ body: [{ viewType: '', displayName: '' }] }],
|
||||
defaultSnippets: [{
|
||||
body: [{
|
||||
[WebviewEditorContribution.viewType]: '$1',
|
||||
[WebviewEditorContribution.displayName]: '$2',
|
||||
[WebviewEditorContribution.selector]: [{
|
||||
filenamePattern: '$3'
|
||||
}],
|
||||
}]
|
||||
}],
|
||||
items: {
|
||||
type: 'object',
|
||||
required: [
|
||||
@@ -48,6 +56,11 @@ const webviewEditorsContribution: IJSONSchema = {
|
||||
description: nls.localize('contributes.selector', 'Set of globs that the custom editor is enabled for.'),
|
||||
items: {
|
||||
type: 'object',
|
||||
defaultSnippets: [{
|
||||
body: {
|
||||
filenamePattern: '$1',
|
||||
}
|
||||
}],
|
||||
properties: {
|
||||
filenamePattern: {
|
||||
type: 'string',
|
||||
@@ -64,7 +77,7 @@ const webviewEditorsContribution: IJSONSchema = {
|
||||
CustomEditorPriority.option,
|
||||
CustomEditorPriority.builtin,
|
||||
],
|
||||
enumDescriptions: [
|
||||
markdownEnumDescriptions: [
|
||||
nls.localize('contributes.priority.default', 'Editor is automatically used for a resource if no other default custom editors are registered for it.'),
|
||||
nls.localize('contributes.priority.option', 'Editor is not automatically used but can be selected by a user.'),
|
||||
nls.localize('contributes.priority.builtin', 'Editor automatically used if no other `default` or `builtin` editors are registered for the resource.'),
|
||||
|
||||
@@ -57,8 +57,8 @@ export interface ICustomEditorModel extends IDisposable {
|
||||
|
||||
revert(options?: IRevertOptions): Promise<void>;
|
||||
|
||||
save(options?: ISaveOptions): Promise<boolean>;
|
||||
saveAs(resource: URI, targetResource: URI, currentOptions?: ISaveOptions): Promise<boolean>;
|
||||
saveCustomEditor(options?: ISaveOptions): Promise<URI | undefined>;
|
||||
saveCustomEditorAs(resource: URI, targetResource: URI, currentOptions?: ISaveOptions): Promise<boolean>;
|
||||
}
|
||||
|
||||
export const enum CustomEditorPriority {
|
||||
|
||||
@@ -68,11 +68,11 @@ export class CustomTextEditorModel extends Disposable implements ICustomEditorMo
|
||||
return this.textFileService.revert(this.resource, options);
|
||||
}
|
||||
|
||||
public async save(options?: ISaveOptions): Promise<boolean> {
|
||||
return !!await this.textFileService.save(this.resource, options);
|
||||
public saveCustomEditor(options?: ISaveOptions): Promise<URI | undefined> {
|
||||
return this.textFileService.save(this.resource, options);
|
||||
}
|
||||
|
||||
public async saveAs(resource: URI, targetResource: URI, options?: ISaveOptions): Promise<boolean> {
|
||||
public async saveCustomEditorAs(resource: URI, targetResource: URI, options?: ISaveOptions): Promise<boolean> {
|
||||
return !!await this.textFileService.saveAs(resource, targetResource, options);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewE
|
||||
Registry.as<IViewsRegistry>(ViewExtensions.ViewsRegistry).registerViews([{
|
||||
id: REPL_VIEW_ID,
|
||||
name: nls.localize({ comment: ['Debug is a noun in this context, not a verb.'], key: 'debugPanel' }, 'Debug Console'),
|
||||
containerIcon: 'codicon-debug-console',
|
||||
canToggleVisibility: false,
|
||||
canMoveView: true,
|
||||
ctorDescriptor: new SyncDescriptor(Repl),
|
||||
|
||||
@@ -36,7 +36,7 @@ import { IDecorationOptions } from 'vs/editor/common/editorCommon';
|
||||
import { transparent, editorForeground } from 'vs/platform/theme/common/colorRegistry';
|
||||
import { ICodeEditorService } from 'vs/editor/browser/services/codeEditorService';
|
||||
import { FocusSessionActionViewItem } from 'vs/workbench/contrib/debug/browser/debugActionViewItems';
|
||||
import { CompletionContext, CompletionList, CompletionProviderRegistry, CompletionItem, completionKindFromString, CompletionItemKind } from 'vs/editor/common/modes';
|
||||
import { CompletionContext, CompletionList, CompletionProviderRegistry, CompletionItem, completionKindFromString, CompletionItemKind, CompletionItemInsertTextRule } from 'vs/editor/common/modes';
|
||||
import { first } from 'vs/base/common/arrays';
|
||||
import { ITreeNode, ITreeContextMenuEvent, IAsyncDataSource } from 'vs/base/browser/ui/tree/tree';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
@@ -147,13 +147,24 @@ export class Repl extends ViewPane implements IHistoryNavigationWidget {
|
||||
if (response && response.body && response.body.targets) {
|
||||
response.body.targets.forEach(item => {
|
||||
if (item && item.label) {
|
||||
let insertTextRules: CompletionItemInsertTextRule | undefined = undefined;
|
||||
let insertText = item.text || item.label;
|
||||
if (typeof item.selectionStart === 'number') {
|
||||
// If a debug completion item sets a selection we need to use snippets to make sure the selection is selected #90974
|
||||
insertTextRules = CompletionItemInsertTextRule.InsertAsSnippet;
|
||||
const selectionLength = typeof item.selectionLength === 'number' ? item.selectionLength : 0;
|
||||
const placeholder = selectionLength > 0 ? '${1:' + insertText.substr(item.selectionStart, selectionLength) + '}$0' : '$0';
|
||||
insertText = insertText.substr(0, item.selectionStart) + placeholder + insertText.substr(item.selectionStart + selectionLength);
|
||||
}
|
||||
|
||||
suggestions.push({
|
||||
label: item.label,
|
||||
insertText: item.text || item.label,
|
||||
insertText,
|
||||
kind: completionKindFromString(item.type || 'property'),
|
||||
filterText: (item.start && item.length) ? text.substr(item.start, item.length).concat(item.label) : undefined,
|
||||
range: computeRange(item.length || overwriteBefore),
|
||||
sortText: item.sortText
|
||||
sortText: item.sortText,
|
||||
insertTextRules
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -247,6 +247,9 @@ function convertPaths(msg: DebugProtocol.ProtocolMessage, fixSourcePath: (toDA:
|
||||
export function getVisibleAndSorted<T extends { presentation?: IConfigPresentation }>(array: T[]): T[] {
|
||||
return array.filter(config => !config.presentation?.hidden).sort((first, second) => {
|
||||
if (!first.presentation) {
|
||||
if (!second.presentation) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
if (!second.presentation) {
|
||||
@@ -271,6 +274,10 @@ export function getVisibleAndSorted<T extends { presentation?: IConfigPresentati
|
||||
|
||||
function compareOrders(first: number | undefined, second: number | undefined): number {
|
||||
if (typeof first !== 'number') {
|
||||
if (typeof second !== 'number') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
if (typeof second !== 'number') {
|
||||
|
||||
@@ -207,6 +207,7 @@ export class ExtensionEditor extends BaseEditor {
|
||||
const root = append(parent, $('.extension-editor'));
|
||||
root.tabIndex = 0; // this is required for the focus tracker on the editor
|
||||
root.style.outline = 'none';
|
||||
root.setAttribute('role', 'document');
|
||||
const header = append(root, $('.header'));
|
||||
|
||||
const iconContainer = append(header, $('.icon-container'));
|
||||
|
||||
@@ -32,6 +32,7 @@ import { isWindows } from 'vs/base/common/platform';
|
||||
import { Schemas } from 'vs/base/common/network';
|
||||
import { IPreferencesService } from 'vs/workbench/services/preferences/common/preferences';
|
||||
import { SaveReason } from 'vs/workbench/common/editor';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
|
||||
export const CONFLICT_RESOLUTION_CONTEXT = 'saveConflictResolutionContext';
|
||||
export const CONFLICT_RESOLUTION_SCHEME = 'conflictResolution';
|
||||
@@ -53,10 +54,14 @@ export class TextFileSaveErrorHandler extends Disposable implements ISaveErrorHa
|
||||
@IEditorService private readonly editorService: IEditorService,
|
||||
@ITextModelService textModelService: ITextModelService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IStorageService private readonly storageService: IStorageService
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
|
||||
) {
|
||||
super();
|
||||
|
||||
// opt-in to syncing
|
||||
storageKeysSyncRegistryService.registerStorageKey({ key: LEARN_MORE_DIRTY_WRITE_IGNORE_KEY, version: 1 });
|
||||
|
||||
this.messages = new ResourceMap<INotificationHandle>();
|
||||
this.conflictResolutionContext = new RawContextKey<boolean>(CONFLICT_RESOLUTION_CONTEXT, false).bindTo(contextKeyService);
|
||||
|
||||
|
||||
@@ -26,11 +26,14 @@ import { minimumTranslatedStrings } from 'vs/workbench/contrib/localizations/bro
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
import { CancellationToken } from 'vs/base/common/cancellation';
|
||||
import { ExtensionType } from 'vs/platform/extensions/common/extensions';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
|
||||
// Register action to configure locale and related settings
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(Extensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(ConfigureLocaleAction, ConfigureLocaleAction.ID, ConfigureLocaleAction.LABEL), 'Configure Display Language');
|
||||
|
||||
const LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY = 'extensionsAssistant/languagePackSuggestionIgnore';
|
||||
|
||||
export class LocalizationWorkbenchContribution extends Disposable implements IWorkbenchContribution {
|
||||
constructor(
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@@ -41,9 +44,12 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
@IExtensionManagementService private readonly extensionManagementService: IExtensionManagementService,
|
||||
@IExtensionGalleryService private readonly galleryService: IExtensionGalleryService,
|
||||
@IViewletService private readonly viewletService: IViewletService,
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService
|
||||
@ITelemetryService private readonly telemetryService: ITelemetryService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService
|
||||
) {
|
||||
super();
|
||||
|
||||
storageKeysSyncRegistryService.registerStorageKey({ key: LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, version: 1 });
|
||||
this.checkAndInstall();
|
||||
this._register(this.extensionManagementService.onDidInstallExtension(e => this.onDidInstallExtension(e)));
|
||||
}
|
||||
@@ -77,7 +83,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
private checkAndInstall(): void {
|
||||
const language = platform.language;
|
||||
const locale = platform.locale;
|
||||
const languagePackSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get('extensionsAssistant/languagePackSuggestionIgnore', StorageScope.GLOBAL, '[]'));
|
||||
const languagePackSuggestionIgnoreList = <string[]>JSON.parse(this.storageService.get(LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY, StorageScope.GLOBAL, '[]'));
|
||||
|
||||
if (!this.galleryService.isEnabled()) {
|
||||
return;
|
||||
@@ -168,7 +174,7 @@ export class LocalizationWorkbenchContribution extends Disposable implements IWo
|
||||
run: () => {
|
||||
languagePackSuggestionIgnoreList.push(language);
|
||||
this.storageService.store(
|
||||
'extensionsAssistant/languagePackSuggestionIgnore',
|
||||
LANGUAGEPACK_SUGGESTION_IGNORE_STORAGE_KEY,
|
||||
JSON.stringify(languagePackSuggestionIgnoreList),
|
||||
StorageScope.GLOBAL
|
||||
);
|
||||
|
||||
@@ -20,11 +20,11 @@ export const COPY_CELL_DOWN_COMMAND_ID = 'workbench.notebook.cell.copyDown';
|
||||
export const EXECUTE_CELL_COMMAND_ID = 'workbench.notebook.cell.execute';
|
||||
|
||||
// Cell sizing related
|
||||
export const CELL_MARGIN = 32;
|
||||
export const CELL_MARGIN = 20;
|
||||
export const CELL_RUN_GUTTER = 32; // TODO should be dynamic based on execution order width, and runnable enablement
|
||||
export const EDITOR_TOP_PADDING = 8;
|
||||
export const EDITOR_BOTTOM_PADDING = 8;
|
||||
export const EDITOR_TOOLBAR_HEIGHT = 22;
|
||||
export const RUN_BUTTON_WIDTH = 20;
|
||||
|
||||
// Cell context keys
|
||||
export const NOTEBOOK_CELL_TYPE_CONTEXT_KEY = 'notebookCellType'; // code, markdown
|
||||
|
||||
@@ -16,6 +16,7 @@ import { CellRenderTemplate, CellEditState, ICellViewModel, INotebookEditor, KEY
|
||||
import { INotebookService } from 'vs/workbench/contrib/notebook/browser/notebookService';
|
||||
import { CellKind, NOTEBOOK_EDITOR_CURSOR_BOUNDARY } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IEditorService } from 'vs/workbench/services/editor/common/editorService';
|
||||
import { EditorContextKeys } from 'vs/editor/common/editorContextKeys';
|
||||
|
||||
const enum CellToolbarOrder {
|
||||
MoveCellUp,
|
||||
@@ -709,9 +710,9 @@ registerAction2(class extends Action2 {
|
||||
id: 'workbench.action.notebook.cursorDown',
|
||||
title: 'Notebook Cursor Move Down',
|
||||
keybinding: {
|
||||
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('top'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
|
||||
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), EditorContextKeys.editorTextFocus, NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('top'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
|
||||
primary: KeyCode.DownArrow,
|
||||
weight: KeybindingWeight.WorkbenchContrib
|
||||
weight: KeybindingWeight.EditorContrib // smaller than Suggest Widget, etc
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -748,9 +749,9 @@ registerAction2(class extends Action2 {
|
||||
id: 'workbench.action.notebook.cursorUp',
|
||||
title: 'Notebook Cursor Move Up',
|
||||
keybinding: {
|
||||
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('bottom'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
|
||||
when: ContextKeyExpr.and(NOTEBOOK_EDITOR_FOCUSED, ContextKeyExpr.has(InputFocusedContextKey), EditorContextKeys.editorTextFocus, NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('bottom'), NOTEBOOK_EDITOR_CURSOR_BOUNDARY.notEqualsTo('none')),
|
||||
primary: KeyCode.UpArrow,
|
||||
weight: KeybindingWeight.WorkbenchContrib
|
||||
weight: KeybindingWeight.EditorContrib // smaller than Suggest Widget, etc
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .cell {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
@@ -87,16 +87,16 @@
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row {
|
||||
overflow: visible !important;
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:focus-within {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:focus-within {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 28px;
|
||||
@@ -107,40 +107,65 @@
|
||||
}
|
||||
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu.mouseover,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .menu {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .menu {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row:hover {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row.selected,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list .monaco-list-row.focused {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.selected,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu.mouseover,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .menu:hover {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu.mouseover,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .menu:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > .monaco-toolbar {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row > .monaco-toolbar {
|
||||
visibility: hidden;
|
||||
margin-right: 24px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row .cell .run-button-container .monaco-toolbar {
|
||||
margin-top: 8px;
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar {
|
||||
margin-top: 5px;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .cell .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.focused .cell .run-button-container .monaco-toolbar {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .monaco-toolbar .codicon-play {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .cell.runnable .run-button-container .monaco-toolbar,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .cell.runnable .run-button-container .monaco-toolbar {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row .cell .run-button-container .execution-count-label {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
font-size: 12px;
|
||||
visibility: visible;
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
padding-right: 2px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .cell .run-button-container .execution-count-label,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .cell .run-button-container .execution-count-label {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container {
|
||||
position: relative;
|
||||
}
|
||||
@@ -149,13 +174,13 @@
|
||||
top: 0px;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row.focused .monaco-toolbar,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row:hover .monaco-toolbar {
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row.focused .monaco-toolbar,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list > .monaco-scrollable-element > .monaco-list-rows > .monaco-list-row:hover .monaco-toolbar {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-tree.focused.no-focused-item:focus:before,
|
||||
.monaco-workbench .part.editor > .content .notebook-editor .monaco-list:not(.element-focused):focus:before {
|
||||
|
||||
.monaco-workbench .part.editor > .content .notebook-editor > .cell-list-container > .monaco-list:not(.element-focused):focus:before {
|
||||
outline: none !important;
|
||||
}
|
||||
|
||||
@@ -167,7 +192,7 @@
|
||||
width: 6px;
|
||||
border-left-width: 2px;
|
||||
border-left-style: solid;
|
||||
left: 28px;
|
||||
left: 20px;
|
||||
top: 22px;
|
||||
bottom: 8px;
|
||||
visibility: hidden;
|
||||
|
||||
@@ -15,7 +15,7 @@ import { FindMatch } from 'vs/editor/common/model';
|
||||
import { RawContextKey } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/output/outputRenderer';
|
||||
import { IModelDecorationsChangeAccessor, NotebookViewModel, CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { CellKind, IOutput, IRenderOutput, NotebookCellMetadata, NotebookDocumentMetadata } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { NOTEBOOK_EDITABLE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
|
||||
export const KEYBINDING_CONTEXT_NOTEBOOK_FIND_WIDGET_FOCUSED = new RawContextKey<boolean>('notebookFindWidgetFocused', false);
|
||||
@@ -72,6 +72,7 @@ export interface ICellViewModel {
|
||||
focusMode: CellFocusMode;
|
||||
getText(): string;
|
||||
metadata: NotebookCellMetadata | undefined;
|
||||
getEvaluatedMetadata(documentMetadata: NotebookDocumentMetadata | undefined): NotebookCellMetadata;
|
||||
}
|
||||
|
||||
export interface INotebookEditor {
|
||||
@@ -249,6 +250,7 @@ export interface CellRenderTemplate {
|
||||
focusIndicator?: HTMLElement;
|
||||
runToolbar?: ToolBar;
|
||||
runButtonContainer?: HTMLElement;
|
||||
executionOrderLabel?: HTMLElement;
|
||||
editingContainer?: HTMLElement;
|
||||
outputContainer?: HTMLElement;
|
||||
editor?: CodeEditorWidget;
|
||||
|
||||
@@ -14,7 +14,6 @@ import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKey, IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IStorageService } from 'vs/platform/storage/common/storage';
|
||||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
|
||||
@@ -29,7 +28,6 @@ import { OutputRenderer } from 'vs/workbench/contrib/notebook/browser/view/outpu
|
||||
import { BackLayerWebView } from 'vs/workbench/contrib/notebook/browser/view/renderers/backLayerWebView';
|
||||
import { CodeCellRenderer, MarkdownCellRenderer, NotebookCellListDelegate } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellRenderer';
|
||||
import { IOutput, CellKind, CellUri } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IWebviewService } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { getExtraColor } from 'vs/workbench/contrib/welcome/walkThrough/common/walkThroughUtils';
|
||||
import { IEditorGroup, IEditorGroupsService } from 'vs/workbench/services/editor/common/editorGroupsService';
|
||||
import { ICodeEditor } from 'vs/editor/browser/editorBrowser';
|
||||
@@ -42,7 +40,7 @@ import { NotebookViewModel, INotebookEditorViewState, IModelDecorationsChangeAcc
|
||||
import { IEditorGroupView } from 'vs/workbench/browser/parts/editor/editor';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { Range } from 'vs/editor/common/core/range';
|
||||
import { CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { Color, RGBA } from 'vs/base/common/color';
|
||||
import { NotebookEventDispatcher, NotebookLayoutChangedEvent } from 'vs/workbench/contrib/notebook/browser/viewModel/eventDispatcher';
|
||||
|
||||
@@ -113,11 +111,9 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
|
||||
@IThemeService themeService: IThemeService,
|
||||
@IInstantiationService private readonly instantiationService: IInstantiationService,
|
||||
@IStorageService storageService: IStorageService,
|
||||
@IWebviewService private webviewService: IWebviewService,
|
||||
@INotebookService private notebookService: INotebookService,
|
||||
@IEditorGroupsService editorGroupService: IEditorGroupsService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService,
|
||||
@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
|
||||
@IContextKeyService private readonly contextKeyService: IContextKeyService,
|
||||
) {
|
||||
super(NotebookEditor.ID, telemetryService, themeService, storageService);
|
||||
@@ -223,7 +219,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
|
||||
);
|
||||
|
||||
this.control = new NotebookCodeEditors(this.list, this.renderedEditors);
|
||||
this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
|
||||
this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
|
||||
this._register(this.webview.onMessage(message => {
|
||||
if (this.viewModel) {
|
||||
this.notebookService.onDidReceiveMessage(this.viewModel.viewType, this.viewModel.uri, message);
|
||||
@@ -334,7 +330,7 @@ export class NotebookEditor extends BaseEditor implements INotebookEditor {
|
||||
|
||||
private async attachModel(input: NotebookEditorInput, model: NotebookEditorModel) {
|
||||
if (!this.webview) {
|
||||
this.webview = new BackLayerWebView(this.webviewService, this.notebookService, this, this.environmentSerice);
|
||||
this.webview = this.instantiationService.createInstance(BackLayerWebView, this);
|
||||
this.list?.rowsContainer.insertAdjacentElement('afterbegin', this.webview!.element);
|
||||
}
|
||||
|
||||
@@ -798,8 +794,10 @@ registerThemingParticipant((theme, collector) => {
|
||||
}
|
||||
|
||||
// Cell Margin
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { padding: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN}px; }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN + RUN_BUTTON_WIDTH}px }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN}px; }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .output { margin: 8px ${CELL_MARGIN}px 8px ${CELL_MARGIN + CELL_RUN_GUTTER}px }`);
|
||||
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${RUN_BUTTON_WIDTH}px); }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .cell-editor-container { width: calc(100% - ${CELL_RUN_GUTTER}px); }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .monaco-list-row > div.cell.markdown { padding-left: ${CELL_RUN_GUTTER}px; }`);
|
||||
collector.addRule(`.monaco-workbench .part.editor > .content .notebook-editor .cell .run-button-container { width: ${CELL_RUN_GUTTER}px; }`);
|
||||
});
|
||||
|
||||
@@ -15,8 +15,9 @@ import { IOutput } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { IWebviewService, WebviewElement } from 'vs/workbench/contrib/webview/browser/webview';
|
||||
import { WebviewResourceScheme } from 'vs/workbench/contrib/webview/common/resourceLoader';
|
||||
import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/codeCellViewModel';
|
||||
import { CELL_MARGIN } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { Emitter, Event } from 'vs/base/common/event';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
export interface IDimentionMessage {
|
||||
__vscode_notebook_message: boolean;
|
||||
@@ -43,11 +44,13 @@ export interface ICreationRequestMessage {
|
||||
id: string;
|
||||
outputId: string;
|
||||
top: number;
|
||||
left: number;
|
||||
}
|
||||
|
||||
export interface IContentWidgetTopRequest {
|
||||
id: string;
|
||||
top: number;
|
||||
left: number;
|
||||
}
|
||||
|
||||
export interface IViewScrollTopRequestMessage {
|
||||
@@ -85,7 +88,13 @@ export class BackLayerWebView extends Disposable {
|
||||
public readonly onMessage: Event<any> = this._onMessage.event;
|
||||
|
||||
|
||||
constructor(public webviewService: IWebviewService, public notebookService: INotebookService, public notebookEditor: INotebookEditor, public environmentSerice: IEnvironmentService) {
|
||||
constructor(
|
||||
public notebookEditor: INotebookEditor,
|
||||
@IWebviewService webviewService: IWebviewService,
|
||||
@IOpenerService openerService: IOpenerService,
|
||||
@IEnvironmentService private readonly environmentSerice: IEnvironmentService,
|
||||
@INotebookService private readonly notebookService: INotebookService,
|
||||
) {
|
||||
super();
|
||||
this.element = document.createElement('div');
|
||||
|
||||
@@ -194,6 +203,7 @@ export class BackLayerWebView extends Disposable {
|
||||
let outputNode = document.createElement('div');
|
||||
outputNode.style.position = 'absolute';
|
||||
outputNode.style.top = event.data.top + 'px';
|
||||
outputNode.style.left = event.data.left + 'px';
|
||||
|
||||
outputNode.id = outputId;
|
||||
let content = event.data.content;
|
||||
@@ -258,6 +268,10 @@ export class BackLayerWebView extends Disposable {
|
||||
this.webview = this._createInset(webviewService, content);
|
||||
this.webview.mountTo(this.element);
|
||||
|
||||
this._register(this.webview.onDidClickLink(link => {
|
||||
openerService.open(link, { fromUserGesture: true });
|
||||
}));
|
||||
|
||||
this._register(this.webview.onDidWheel(e => {
|
||||
this.notebookEditor.triggerScroll(e);
|
||||
}));
|
||||
@@ -331,7 +345,8 @@ export class BackLayerWebView extends Disposable {
|
||||
|
||||
return {
|
||||
id: id,
|
||||
top: outputOffset
|
||||
top: outputOffset,
|
||||
left: CELL_RUN_GUTTER
|
||||
};
|
||||
});
|
||||
|
||||
@@ -355,7 +370,8 @@ export class BackLayerWebView extends Disposable {
|
||||
content: shadowContent,
|
||||
id: cell.id,
|
||||
outputId: outputId,
|
||||
top: initialTop
|
||||
top: initialTop,
|
||||
left: CELL_RUN_GUTTER
|
||||
};
|
||||
|
||||
this.webview.sendMessage(message);
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
import { getZoomLevel } from 'vs/base/browser/browser';
|
||||
import * as DOM from 'vs/base/browser/dom';
|
||||
import { IListRenderer, IListVirtualDelegate } from 'vs/base/browser/ui/list/list';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
import { ToolBar } from 'vs/base/browser/ui/toolbar/toolbar';
|
||||
import { IAction } from 'vs/base/common/actions';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
@@ -16,15 +17,16 @@ import { CodeEditorWidget } from 'vs/editor/browser/widget/codeEditorWidget';
|
||||
import { IEditorOptions } from 'vs/editor/common/config/editorOptions';
|
||||
import { BareFontInfo } from 'vs/editor/common/config/fontInfo';
|
||||
import { ContextAwareMenuEntryActionViewItem } from 'vs/platform/actions/browser/menuEntryActionViewItem';
|
||||
import { MenuItemAction, IMenu } from 'vs/platform/actions/common/actions';
|
||||
import { IMenu, MenuItemAction } from 'vs/platform/actions/common/actions';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IContextKeyService } from 'vs/platform/contextkey/common/contextkey';
|
||||
import { IContextMenuService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IKeybindingService } from 'vs/platform/keybinding/common/keybinding';
|
||||
import { INotificationService } from 'vs/platform/notification/common/notification';
|
||||
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellRenderTemplate, CellRunState, ICellViewModel, INotebookEditor, CellEditState } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, NOTEBOOK_CELL_TYPE_CONTEXT_KEY } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { ExecuteCellAction, INotebookCellActionContext } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions';
|
||||
import { CellEditState, CellRenderTemplate, CellRunState, ICellViewModel, INotebookEditor } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellMenus } from 'vs/workbench/contrib/notebook/browser/view/renderers/cellMenus';
|
||||
import { CodeCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/codeCell';
|
||||
import { StatefullMarkdownCell } from 'vs/workbench/contrib/notebook/browser/view/renderers/markdownCell';
|
||||
@@ -32,8 +34,6 @@ import { CodeCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewMod
|
||||
import { MarkdownCellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/markdownCellViewModel';
|
||||
import { CellViewModel } from 'vs/workbench/contrib/notebook/browser/viewModel/notebookViewModel';
|
||||
import { CellKind } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { INotebookCellActionContext, ExecuteCellAction } from 'vs/workbench/contrib/notebook/browser/contrib/notebookActions';
|
||||
import { ProgressBar } from 'vs/base/browser/ui/progressbar/progressbar';
|
||||
|
||||
const $ = DOM.$;
|
||||
|
||||
@@ -221,8 +221,8 @@ export class MarkdownCellRenderer extends AbstractCellRenderer implements IListR
|
||||
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
|
||||
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'markdown');
|
||||
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
|
||||
elementDisposable.add(element.onDidChangeMetadata((e) => {
|
||||
cellEditableKey.set(!!e?.editable);
|
||||
elementDisposable.add(element.onDidChangeMetadata(() => {
|
||||
cellEditableKey.set(!!element.metadata?.editable);
|
||||
}));
|
||||
|
||||
const editModeKey = contextKeyService.createKey(NOTEBOOK_CELL_MARKDOWN_EDIT_MODE_CONTEXT_KEY, element.editState === CellEditState.Editing);
|
||||
@@ -286,6 +286,8 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
])();
|
||||
disposables.add(runToolbar);
|
||||
|
||||
const executionOrderLabel = DOM.append(runButtonContainer, $('div.execution-count-label'));
|
||||
|
||||
const editorContainer = DOM.append(cellContainer, $('.cell-editor-container'));
|
||||
const editor = this.instantiationService.createInstance(CodeEditorWidget, editorContainer, {
|
||||
...this.editorOptions,
|
||||
@@ -314,6 +316,7 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
toolbar,
|
||||
runToolbar,
|
||||
runButtonContainer,
|
||||
executionOrderLabel,
|
||||
outputContainer,
|
||||
editor,
|
||||
disposables,
|
||||
@@ -352,21 +355,36 @@ export class CodeCellRenderer extends AbstractCellRenderer implements IListRende
|
||||
}
|
||||
}));
|
||||
|
||||
function renderExecutionOrder() {
|
||||
const executionOrdeerLabel = typeof element.metadata?.executionOrder === 'number' ? `[ ${element.metadata.executionOrder} ]` :
|
||||
'[ ]';
|
||||
templateData.executionOrderLabel!.innerText = executionOrdeerLabel;
|
||||
}
|
||||
|
||||
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
|
||||
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
|
||||
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
|
||||
|
||||
const updateForMetadata = () => {
|
||||
const metadata = element.getEvaluatedMetadata(this.notebookEditor.viewModel!.notebookDocument.metadata);
|
||||
DOM.toggleClass(templateData.cellContainer, 'runnable', !!metadata.runnable);
|
||||
renderExecutionOrder();
|
||||
cellEditableKey.set(!!metadata.editable);
|
||||
};
|
||||
|
||||
updateForMetadata();
|
||||
elementDisposable.add(element.onDidChangeMetadata(() => {
|
||||
updateForMetadata();
|
||||
}));
|
||||
|
||||
this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable);
|
||||
|
||||
const toolbarContext = <INotebookCellActionContext>{
|
||||
cell: element,
|
||||
cellTemplate: templateData,
|
||||
notebookEditor: this.notebookEditor,
|
||||
$mid: 12
|
||||
};
|
||||
|
||||
const contextKeyService = this.contextKeyService.createScoped(templateData.container);
|
||||
contextKeyService.createKey(NOTEBOOK_CELL_TYPE_CONTEXT_KEY, 'code');
|
||||
const cellEditableKey = contextKeyService.createKey(NOTEBOOK_CELL_EDITABLE_CONTEXT_KEY, !!(element.metadata?.editable));
|
||||
elementDisposable.add(element.onDidChangeMetadata((e) => {
|
||||
cellEditableKey.set(!!e?.editable);
|
||||
}));
|
||||
|
||||
this.setupCellToolbarActions(contextKeyService, templateData, elementDisposable);
|
||||
templateData.toolbar.context = toolbarContext;
|
||||
templateData.runToolbar!.context = toolbarContext;
|
||||
}
|
||||
|
||||
@@ -83,7 +83,7 @@ export class CodeCell extends Disposable {
|
||||
}));
|
||||
|
||||
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) });
|
||||
this._register(viewCell.onDidChangeMetadata((e) => {
|
||||
this._register(viewCell.onDidChangeMetadata(() => {
|
||||
templateData.editor?.updateOptions({ readOnly: !(viewCell.getEvaluatedMetadata(notebookEditor.viewModel?.metadata).editable) });
|
||||
}));
|
||||
|
||||
|
||||
@@ -32,8 +32,8 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
readonly onDidChangeEditorAttachState = this._onDidChangeEditorAttachState.event;
|
||||
protected readonly _onDidChangeCursorSelection: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onDidChangeCursorSelection: Event<void> = this._onDidChangeCursorSelection.event;
|
||||
protected readonly _onDidChangeMetadata: Emitter<NotebookCellMetadata | undefined> = this._register(new Emitter<NotebookCellMetadata | undefined>());
|
||||
public readonly onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
|
||||
protected readonly _onDidChangeMetadata: Emitter<void> = this._register(new Emitter<void>());
|
||||
public readonly onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
|
||||
protected readonly _onDidChangeLanguage: Emitter<string> = this._register(new Emitter<string>());
|
||||
public readonly onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
|
||||
get handle() {
|
||||
@@ -106,8 +106,8 @@ export abstract class BaseCellViewModel extends Disposable {
|
||||
this._onDidChangeLanguage.fire(e);
|
||||
}));
|
||||
|
||||
this._register(cell.onDidChangeMetadata((e) => {
|
||||
this._onDidChangeMetadata.fire(e);
|
||||
this._register(cell.onDidChangeMetadata(() => {
|
||||
this._onDidChangeMetadata.fire();
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import * as UUID from 'vs/base/common/uuid';
|
||||
import * as model from 'vs/editor/common/model';
|
||||
import { ITextModelService } from 'vs/editor/common/services/resolverService';
|
||||
import { PrefixSumComputer } from 'vs/editor/common/viewModel/prefixSumComputer';
|
||||
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, RUN_BUTTON_WIDTH } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { EDITOR_BOTTOM_PADDING, EDITOR_TOOLBAR_HEIGHT, EDITOR_TOP_PADDING, CELL_MARGIN, CELL_RUN_GUTTER } from 'vs/workbench/contrib/notebook/browser/constants';
|
||||
import { CellEditState, ICellViewModel, CellFindMatch, CodeCellLayoutChangeEvent, CodeCellLayoutInfo } from 'vs/workbench/contrib/notebook/browser/notebookBrowser';
|
||||
import { CellKind, ICell, NotebookCellOutputsSplice } from 'vs/workbench/contrib/notebook/common/notebookCommon';
|
||||
import { BaseCellViewModel } from './baseCellViewModel';
|
||||
@@ -72,6 +72,10 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
}));
|
||||
}
|
||||
|
||||
this._register(this.cell.onDidChangeMetadata(() => {
|
||||
this._onDidChangeMetadata.fire();
|
||||
}));
|
||||
|
||||
this._outputCollection = new Array(this.cell.outputs.length);
|
||||
this._buffer = null;
|
||||
|
||||
@@ -105,7 +109,7 @@ export class CodeCellViewModel extends BaseCellViewModel implements ICellViewMod
|
||||
? EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + 16 + outputTotalHeight
|
||||
: EDITOR_TOOLBAR_HEIGHT + this.editorHeight + EDITOR_TOP_PADDING + EDITOR_BOTTOM_PADDING + outputTotalHeight;
|
||||
const indicatorHeight = totalHeight - EDITOR_TOOLBAR_HEIGHT - 16;
|
||||
const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - RUN_BUTTON_WIDTH : 0;
|
||||
const editorWidth = state.outerWidth !== undefined ? state.outerWidth - CELL_MARGIN * 2 - CELL_RUN_GUTTER : 0;
|
||||
this._layoutInfo = {
|
||||
fontInfo: state.font || null,
|
||||
editorHeight: this._editorHeight,
|
||||
|
||||
@@ -15,8 +15,8 @@ export class NotebookCellTextModel implements ICell {
|
||||
private _onDidChangeContent = new Emitter<void>();
|
||||
onDidChangeContent: Event<void> = this._onDidChangeContent.event;
|
||||
|
||||
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata | undefined>();
|
||||
onDidChangeMetadata: Event<NotebookCellMetadata | undefined> = this._onDidChangeMetadata.event;
|
||||
private _onDidChangeMetadata = new Emitter<void>();
|
||||
onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
|
||||
|
||||
private _onDidChangeLanguage = new Emitter<string>();
|
||||
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
|
||||
@@ -44,7 +44,7 @@ export class NotebookCellTextModel implements ICell {
|
||||
|
||||
set metadata(newMetadata: NotebookCellMetadata | undefined) {
|
||||
this._metadata = newMetadata;
|
||||
this._onDidChangeMetadata.fire(this._metadata);
|
||||
this._onDidChangeMetadata.fire();
|
||||
}
|
||||
|
||||
get language() {
|
||||
|
||||
@@ -45,6 +45,7 @@ export interface NotebookDocumentMetadata {
|
||||
export interface NotebookCellMetadata {
|
||||
editable?: boolean;
|
||||
runnable?: boolean;
|
||||
executionOrder?: number;
|
||||
}
|
||||
|
||||
export interface INotebookDisplayOrder {
|
||||
@@ -135,8 +136,8 @@ export interface ICell {
|
||||
outputs: IOutput[];
|
||||
metadata?: NotebookCellMetadata;
|
||||
onDidChangeOutputs?: Event<NotebookCellOutputsSplice[]>;
|
||||
onDidChangeMetadata: Event<NotebookCellMetadata | undefined>;
|
||||
onDidChangeLanguage: Event<string>;
|
||||
onDidChangeMetadata: Event<void>;
|
||||
resolveTextBufferFactory(): PieceTreeTextBufferFactory;
|
||||
// TODO@rebornix it should be later on replaced by moving textmodel resolution into CellTextModel
|
||||
contentChange(): void;
|
||||
|
||||
@@ -83,4 +83,81 @@ suite('NotebookViewModel', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('metadata', function () {
|
||||
withTestNotebook(
|
||||
instantiationService,
|
||||
blukEditService,
|
||||
undoRedoService,
|
||||
[
|
||||
[['var a = 1;'], 'javascript', CellKind.Code, [], {}],
|
||||
[['var b = 2;'], 'javascript', CellKind.Code, [], { editable: true, runnable: true }],
|
||||
[['var c = 3;'], 'javascript', CellKind.Code, [], { editable: true, runnable: false }],
|
||||
[['var d = 4;'], 'javascript', CellKind.Code, [], { editable: false, runnable: true }],
|
||||
[['var e = 5;'], 'javascript', CellKind.Code, [], { editable: false, runnable: false }],
|
||||
],
|
||||
(editor, viewModel) => {
|
||||
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: true, cellEditable: true };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: true
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: true
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: false
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: false,
|
||||
runnable: true
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: false,
|
||||
runnable: false
|
||||
});
|
||||
|
||||
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: false, cellEditable: true };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: false
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[1].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: true
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[2].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: true,
|
||||
runnable: false
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[3].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: false,
|
||||
runnable: true
|
||||
});
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[4].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: false,
|
||||
runnable: false
|
||||
});
|
||||
|
||||
viewModel.notebookDocument.metadata = { editable: true, cellRunnable: false, cellEditable: false };
|
||||
|
||||
assert.deepEqual(viewModel.viewCells[0].getEvaluatedMetadata(viewModel.metadata), {
|
||||
editable: false,
|
||||
runnable: false
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -25,11 +25,10 @@ export class TestCell implements ICell {
|
||||
uri: URI;
|
||||
private _onDidChangeOutputs = new Emitter<NotebookCellOutputsSplice[]>();
|
||||
onDidChangeOutputs: Event<NotebookCellOutputsSplice[]> = this._onDidChangeOutputs.event;
|
||||
private _onDidChangeMetadata = new Emitter<NotebookCellMetadata>();
|
||||
onDidChangeMetadata: Event<NotebookCellMetadata> = this._onDidChangeMetadata.event;
|
||||
private _onDidChangeLanguage = new Emitter<string>();
|
||||
onDidChangeLanguage: Event<string> = this._onDidChangeLanguage.event;
|
||||
|
||||
private _onDidChangeMetadata = new Emitter<void>();
|
||||
onDidChangeMetadata: Event<void> = this._onDidChangeMetadata.event;
|
||||
private _isDirty: boolean = false;
|
||||
private _outputs: IOutput[];
|
||||
|
||||
|
||||
@@ -1,111 +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 { localize } from 'vs/nls';
|
||||
import { STATUS_BAR_PROMINENT_ITEM_BACKGROUND, STATUS_BAR_PROMINENT_ITEM_FOREGROUND } from 'vs/workbench/common/theme';
|
||||
import { themeColorFromId } from 'vs/platform/theme/common/themeService';
|
||||
import { Disposable } from 'vs/base/common/lifecycle';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkbenchContribution, IWorkbenchContributionsRegistry, Extensions as WorkbenchContributionsExtensions } from 'vs/workbench/common/contributions';
|
||||
import { StatusbarAlignment, IStatusbarService, IStatusbarEntry } from 'vs/workbench/services/statusbar/common/statusbar';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { Action } from 'vs/base/common/actions';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IWorkbenchActionRegistry, Extensions as ActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IWorkbenchEnvironmentService } from 'vs/workbench/services/environment/common/environmentService';
|
||||
import { IApplicationLink } from 'vs/workbench/workbench.web.api';
|
||||
import { IQuickInputService } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
|
||||
export class OpenInDesktopIndicator extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
constructor(
|
||||
@IStatusbarService private readonly statusbarService: IStatusbarService,
|
||||
@IWorkspaceContextService workspaceService: IWorkspaceContextService,
|
||||
@IWorkbenchEnvironmentService environmentService: IWorkbenchEnvironmentService
|
||||
) {
|
||||
super();
|
||||
|
||||
const links = environmentService.options?.applicationLinks;
|
||||
if (Array.isArray(links) && links?.length > 0) {
|
||||
this.installOpenInDesktopIndicator(links);
|
||||
}
|
||||
}
|
||||
|
||||
private installOpenInDesktopIndicator(links: readonly IApplicationLink[]): void {
|
||||
|
||||
// Register action to trigger "Open In Desktop"
|
||||
const registry = Registry.as<IWorkbenchActionRegistry>(ActionExtensions.WorkbenchActions);
|
||||
registry.registerWorkbenchAction(SyncActionDescriptor.create(OpenInDesktopAction, OpenInDesktopAction.ID, OpenInDesktopAction.LABEL), 'Open Workspace in Desktop');
|
||||
|
||||
// Show in status bar
|
||||
const properties: IStatusbarEntry = {
|
||||
backgroundColor: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_BACKGROUND),
|
||||
color: themeColorFromId(STATUS_BAR_PROMINENT_ITEM_FOREGROUND),
|
||||
text: links.length === 1 ? links[0].label : localize('openInDesktop', "Open in Desktop..."),
|
||||
command: 'workbench.web.openWorkspaceInDesktop'
|
||||
};
|
||||
|
||||
this.statusbarService.addEntry(properties, 'status.openInDesktop', properties.text, StatusbarAlignment.LEFT, Number.MAX_VALUE /* first entry */);
|
||||
}
|
||||
}
|
||||
|
||||
const workbenchContributionsRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchContributionsExtensions.Workbench);
|
||||
workbenchContributionsRegistry.registerWorkbenchContribution(OpenInDesktopIndicator, LifecyclePhase.Starting);
|
||||
|
||||
export class OpenInDesktopAction extends Action {
|
||||
static readonly ID = 'workbench.web.openWorkspaceInDesktop';
|
||||
static readonly LABEL = localize('openWorkspaceInDesktop', "Open Workspace in Desktop");
|
||||
|
||||
constructor(
|
||||
id: string,
|
||||
label: string,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService,
|
||||
@IWorkbenchEnvironmentService private readonly environmentService: IWorkbenchEnvironmentService,
|
||||
@IOpenerService private readonly openerService: IOpenerService
|
||||
) {
|
||||
super(id, label);
|
||||
}
|
||||
|
||||
async run(): Promise<boolean> {
|
||||
const links = this.environmentService.options?.applicationLinks;
|
||||
if (Array.isArray(links)) {
|
||||
if (links.length === 1) {
|
||||
return this.openApplicationLink(links[0]);
|
||||
}
|
||||
|
||||
return this.runWithPicker(links);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async runWithPicker(links: readonly IApplicationLink[]): Promise<boolean> {
|
||||
|
||||
// Show a picker with choices
|
||||
const quickPick = this.quickInputService.createQuickPick<IApplicationLink>();
|
||||
quickPick.items = links;
|
||||
quickPick.placeholder = OpenInDesktopAction.LABEL;
|
||||
quickPick.canSelectMany = false;
|
||||
quickPick.onDidAccept(() => {
|
||||
const selectedItems = quickPick.selectedItems;
|
||||
if (selectedItems.length === 1) {
|
||||
this.openApplicationLink(selectedItems[0]);
|
||||
}
|
||||
quickPick.hide();
|
||||
});
|
||||
|
||||
quickPick.show();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private async openApplicationLink(link: IApplicationLink): Promise<boolean> {
|
||||
this.openerService.open(link.uri, { openExternal: true });
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -69,6 +69,8 @@ const VIEW_CONTAINER: ViewContainer = Registry.as<IViewContainersRegistry>(ViewC
|
||||
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
|
||||
id: OUTPUT_VIEW_ID,
|
||||
name: nls.localize('output', "Output"),
|
||||
containerIcon: 'codicon-output',
|
||||
canMoveView: true,
|
||||
canToggleVisibility: false,
|
||||
ctorDescriptor: new SyncDescriptor(OutputViewPane),
|
||||
}], VIEW_CONTAINER);
|
||||
|
||||
@@ -50,6 +50,7 @@ import { IPreferencesService, ISearchResult, ISettingsEditorModel, ISettingsEdit
|
||||
import { SettingsEditor2Input } from 'vs/workbench/services/preferences/common/preferencesEditorInput';
|
||||
import { Settings2EditorModel } from 'vs/workbench/services/preferences/common/preferencesModels';
|
||||
import { IEditorModel } from 'vs/platform/editor/common/editor';
|
||||
import { IStorageKeysSyncRegistryService } from 'vs/platform/userDataSync/common/storageKeys';
|
||||
|
||||
function createGroupIterator(group: SettingsTreeGroupElement): Iterator<ITreeElement<SettingsTreeGroupChild>> {
|
||||
const groupsIt = Iterator.fromArray(group.children);
|
||||
@@ -70,6 +71,7 @@ interface IFocusEventFromScroll extends KeyboardEvent {
|
||||
fromScroll: true;
|
||||
}
|
||||
|
||||
const SETTINGS_AUTOSAVE_NOTIFIED_KEY = 'hasNotifiedOfSettingsAutosave';
|
||||
const SETTINGS_EDITOR_STATE_KEY = 'settingsEditorState';
|
||||
export class SettingsEditor2 extends BaseEditor {
|
||||
|
||||
@@ -160,7 +162,8 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@INotificationService private readonly notificationService: INotificationService,
|
||||
@IEditorGroupsService protected editorGroupService: IEditorGroupsService,
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService
|
||||
@IKeybindingService private readonly keybindingService: IKeybindingService,
|
||||
@IStorageKeysSyncRegistryService storageKeysSyncRegistryService: IStorageKeysSyncRegistryService,
|
||||
) {
|
||||
super(SettingsEditor2.ID, telemetryService, themeService, storageService);
|
||||
this.delayedFilterLogging = new Delayer<void>(1000);
|
||||
@@ -186,6 +189,8 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
this.onConfigUpdate(e.affectedKeys);
|
||||
}
|
||||
}));
|
||||
|
||||
storageKeysSyncRegistryService.registerStorageKey({ key: SETTINGS_AUTOSAVE_NOTIFIED_KEY, version: 1 });
|
||||
}
|
||||
|
||||
get minimumWidth(): number { return 375; }
|
||||
@@ -712,8 +717,8 @@ export class SettingsEditor2 extends BaseEditor {
|
||||
}
|
||||
|
||||
private notifyNoSaveNeeded() {
|
||||
if (!this.storageService.getBoolean('hasNotifiedOfSettingsAutosave', StorageScope.GLOBAL, false)) {
|
||||
this.storageService.store('hasNotifiedOfSettingsAutosave', true, StorageScope.GLOBAL);
|
||||
if (!this.storageService.getBoolean(SETTINGS_AUTOSAVE_NOTIFIED_KEY, StorageScope.GLOBAL, false)) {
|
||||
this.storageService.store(SETTINGS_AUTOSAVE_NOTIFIED_KEY, true, StorageScope.GLOBAL);
|
||||
this.notificationService.info(localize('settingsNoSaveNeeded', "Your changes are automatically saved as you edit."));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import { INotificationService } from 'vs/platform/notification/common/notificati
|
||||
import { DefaultQuickAccessFilterValue } from 'vs/platform/quickinput/common/quickAccess';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IWorkbenchQuickOpenConfiguration } from 'vs/workbench/browser/quickopen';
|
||||
import { stripCodicons } from 'vs/base/common/codicons';
|
||||
|
||||
export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAccessProvider {
|
||||
|
||||
@@ -114,7 +115,7 @@ export class CommandsQuickAccessProvider extends AbstractEditorCommandsQuickAcce
|
||||
globalCommandPicks.push({
|
||||
commandId: action.item.id,
|
||||
commandAlias,
|
||||
label
|
||||
label: stripCodicons(label)
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import 'vs/css!./media/anythingQuickAccess';
|
||||
import { IQuickPickSeparator, IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction, FastAndSlowPicksType } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { IQuickInputButton, IKeyMods, quickPickItemScorerAccessor, QuickPickItemScorerAccessor, IQuickPick } from 'vs/platform/quickinput/common/quickInput';
|
||||
import { IPickerQuickAccessItem, PickerQuickAccessProvider, TriggerAction, FastAndSlowPicks, Picks, PicksWithActive } from 'vs/platform/quickinput/browser/pickerQuickAccess';
|
||||
import { prepareQuery, IPreparedQuery, compareItemsByScore, scoreItem, ScorerCache } from 'vs/base/common/fuzzyScorer';
|
||||
import { IFileQueryBuilderOptions, QueryBuilder } from 'vs/workbench/contrib/search/common/queryBuilder';
|
||||
import { IInstantiationService } from 'vs/platform/instantiation/common/instantiation';
|
||||
@@ -88,7 +88,8 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
lastOriginalFilter: string | undefined = undefined;
|
||||
lastFilter: string | undefined = undefined;
|
||||
lastRange: IRange | undefined = undefined;
|
||||
lastActiveGlobalPick: IAnythingQuickPickItem | undefined = undefined;
|
||||
|
||||
lastGlobalPicks: PicksWithActive<IAnythingQuickPickItem> | undefined = undefined;
|
||||
|
||||
isQuickNavigating: boolean | undefined = undefined;
|
||||
|
||||
@@ -116,7 +117,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
this.lastOriginalFilter = undefined;
|
||||
this.lastFilter = undefined;
|
||||
this.lastRange = undefined;
|
||||
this.lastActiveGlobalPick = undefined;
|
||||
this.lastGlobalPicks = undefined;
|
||||
this.editorViewState = undefined;
|
||||
}
|
||||
|
||||
@@ -240,7 +241,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
return toDisposable(() => this.clearDecorations(activeEditorControl));
|
||||
}
|
||||
|
||||
protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | FastAndSlowPicksType<IAnythingQuickPickItem> | null {
|
||||
protected getPicks(originalFilter: string, disposables: DisposableStore, token: CancellationToken): Picks<IAnythingQuickPickItem> | Promise<Picks<IAnythingQuickPickItem>> | FastAndSlowPicks<IAnythingQuickPickItem> | null {
|
||||
|
||||
// Find a suitable range from the pattern looking for ":", "#" or ","
|
||||
// unless we have the `@` editor symbol character inside the filter
|
||||
@@ -269,16 +270,25 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
this.pickState.lastOriginalFilter = originalFilter;
|
||||
this.pickState.lastFilter = filter;
|
||||
|
||||
// Remember last active pick (unless editor symbol)
|
||||
// Remember our pick state before returning new picks
|
||||
// unless an editor symbol is selected. We can use this
|
||||
// state to return back to the global pick when the
|
||||
// user is narrowing back out of editor symbols.
|
||||
const picks = this.pickState.picker?.items;
|
||||
const activePick = this.pickState.picker?.activeItems[0];
|
||||
if (activePick && !isEditorSymbolQuickPickItem(activePick)) {
|
||||
this.pickState.lastActiveGlobalPick = activePick;
|
||||
if (picks && activePick) {
|
||||
if (!isEditorSymbolQuickPickItem(activePick)) {
|
||||
this.pickState.lastGlobalPicks = {
|
||||
items: picks,
|
||||
active: activePick
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return this.doGetPicks(filter, disposables, token);
|
||||
}
|
||||
|
||||
private doGetPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | FastAndSlowPicksType<IAnythingQuickPickItem> | null {
|
||||
private doGetPicks(filter: string, disposables: DisposableStore, token: CancellationToken): Picks<IAnythingQuickPickItem> | Promise<Picks<IAnythingQuickPickItem>> | FastAndSlowPicks<IAnythingQuickPickItem> | null {
|
||||
const query = prepareQuery(filter);
|
||||
|
||||
// Return early if we have editor symbol picks. We support this by:
|
||||
@@ -289,6 +299,14 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
return editorSymbolPicks;
|
||||
}
|
||||
|
||||
// If we have a known last active editor symbol pick, we try to restore
|
||||
// the last global pick to support the case of narrowing out from a
|
||||
// editor symbol search back into the global search
|
||||
const activePick = this.pickState.picker?.activeItems[0];
|
||||
if (isEditorSymbolQuickPickItem(activePick) && this.pickState.lastGlobalPicks) {
|
||||
return this.pickState.lastGlobalPicks;
|
||||
}
|
||||
|
||||
// Otherwise return normally with history and file/symbol results
|
||||
const historyEditorPicks = this.getEditorHistoryPicks(query);
|
||||
|
||||
@@ -304,7 +322,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
],
|
||||
|
||||
// Slow picks: files and symbols
|
||||
additionalPicks: (async (): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> => {
|
||||
additionalPicks: (async (): Promise<Picks<IAnythingQuickPickItem>> => {
|
||||
|
||||
// Exclude any result that is already present in editor history
|
||||
const additionalPicksExcludes = new ResourceMap<boolean>();
|
||||
@@ -636,13 +654,13 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
|
||||
private readonly editorSymbolsQuickAccess = this.instantiationService.createInstance(GotoSymbolQuickAccessProvider);
|
||||
|
||||
private getEditorSymbolPicks(query: IPreparedQuery, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> | null {
|
||||
private getEditorSymbolPicks(query: IPreparedQuery, disposables: DisposableStore, token: CancellationToken): Promise<Picks<IAnythingQuickPickItem>> | null {
|
||||
const filter = query.original.split(GotoSymbolQuickAccessProvider.PREFIX)[1]?.trim();
|
||||
if (typeof filter !== 'string') {
|
||||
return null; // we need to be searched for editor symbols via `@`
|
||||
}
|
||||
|
||||
const activeGlobalPick = this.pickState.lastActiveGlobalPick;
|
||||
const activeGlobalPick = this.pickState.lastGlobalPicks?.active;
|
||||
if (!activeGlobalPick) {
|
||||
return null; // we need an active global pick to find symbols for
|
||||
}
|
||||
@@ -655,7 +673,7 @@ export class AnythingQuickAccessProvider extends PickerQuickAccessProvider<IAnyt
|
||||
return this.doGetEditorSymbolPicks(activeGlobalPick, activeGlobalResource, filter, disposables, token);
|
||||
}
|
||||
|
||||
private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Array<IAnythingQuickPickItem | IQuickPickSeparator>> {
|
||||
private async doGetEditorSymbolPicks(activeGlobalPick: IAnythingQuickPickItem, activeGlobalResource: URI, filter: string, disposables: DisposableStore, token: CancellationToken): Promise<Picks<IAnythingQuickPickItem>> {
|
||||
|
||||
// Bring the editor to front to review symbols to go to
|
||||
try {
|
||||
|
||||
@@ -390,6 +390,7 @@ Registry.as<panel.PanelRegistry>(panel.Extensions.Panels).setDefaultPanelId(TERM
|
||||
Registry.as<IViewsRegistry>(ViewContainerExtensions.ViewsRegistry).registerViews([{
|
||||
id: TERMINAL_VIEW_ID,
|
||||
name: nls.localize('terminal', "Terminal"),
|
||||
containerIcon: 'codicon-terminal',
|
||||
canToggleVisibility: false,
|
||||
canMoveView: true,
|
||||
ctorDescriptor: new SyncDescriptor(TerminalViewPane)
|
||||
@@ -459,10 +460,7 @@ actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ManageWorkspa
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(RenameTerminalAction, RenameTerminalAction.ID, RenameTerminalAction.LABEL), 'Terminal: Rename', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Focus Find Widget', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FocusTerminalFindWidgetAction, FocusTerminalFindWidgetAction.ID, FocusTerminalFindWidgetAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.KEY_F
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Focus Find Widget', category);
|
||||
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED, KEYBINDING_CONTEXT_TERMINAL_FOCUS)), 'Terminal: Focus Find Widget', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(HideTerminalFindWidgetAction, HideTerminalFindWidgetAction.ID, HideTerminalFindWidgetAction.LABEL, {
|
||||
primary: KeyCode.Escape,
|
||||
secondary: [KeyMod.Shift | KeyCode.Escape]
|
||||
@@ -550,43 +548,25 @@ actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationMod
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Exit Navigation Mode', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusPreviousTerminalAction, NavigationModeFocusPreviousTerminalAction.ID, NavigationModeFocusPreviousTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.UpArrow
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Previous Line (Navigation Mode)', category);
|
||||
}, ContextKeyExpr.or(ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED), ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED))), 'Terminal: Focus Previous Line (Navigation Mode)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(NavigationModeFocusNextTerminalAction, NavigationModeFocusNextTerminalAction.ID, NavigationModeFocusNextTerminalAction.LABEL, {
|
||||
primary: KeyMod.CtrlCmd | KeyCode.DownArrow
|
||||
}, ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED)), 'Terminal: Focus Next Line (Navigation Mode)', category);
|
||||
}, ContextKeyExpr.or(ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_A11Y_TREE_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED), ContextKeyExpr.and(KEYBINDING_CONTEXT_TERMINAL_FOCUS, CONTEXT_ACCESSIBILITY_MODE_ENABLED))), 'Terminal: Focus Next Line (Navigation Mode)', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToPreviousLineAction, SelectToPreviousLineAction.ID, SelectToPreviousLineAction.LABEL), 'Terminal: Select To Previous Line', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(SelectToNextLineAction, SelectToNextLineAction.ID, SelectToNextLineAction.LABEL), 'Terminal: Select To Next Line', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleEscapeSequenceLoggingAction, ToggleEscapeSequenceLoggingAction.ID, ToggleEscapeSequenceLoggingAction.LABEL), 'Terminal: Toggle Escape Sequence Logging', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using regex', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleRegexCommand, ToggleRegexCommand.ID, ToggleRegexCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_R,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_R }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using regex', category);
|
||||
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using regex', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_W,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using whole word', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleWholeWordCommand, ToggleWholeWordCommand.ID, ToggleWholeWordCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_W,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_W }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using whole word', category);
|
||||
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using whole word', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_C,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED), 'Terminal: Toggle find using case sensitive', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(ToggleCaseSensitiveCommand, ToggleCaseSensitiveCommand.ID, ToggleCaseSensitiveCommand.LABEL, {
|
||||
primary: KeyMod.Alt | KeyCode.KEY_C,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyMod.Alt | KeyCode.KEY_C }
|
||||
}, KEYBINDING_CONTEXT_TERMINAL_FOCUS), 'Terminal: Toggle find using case sensitive', category);
|
||||
}, ContextKeyExpr.or(KEYBINDING_CONTEXT_TERMINAL_FOCUS, KEYBINDING_CONTEXT_TERMINAL_FIND_WIDGET_FOCUSED)), 'Terminal: Toggle find using case sensitive', category);
|
||||
actionRegistry.registerWorkbenchAction(SyncActionDescriptor.create(FindNext, FindNext.ID, FindNext.LABEL, {
|
||||
primary: KeyCode.F3,
|
||||
mac: { primary: KeyMod.CtrlCmd | KeyCode.KEY_G, secondary: [KeyCode.F3] }
|
||||
|
||||
@@ -776,12 +776,14 @@ export class TimelinePane extends ViewPane {
|
||||
// Refresh the view on focus to update the relative timestamps
|
||||
this.onDidFocus(() => this.refreshDebounced(), this, this.visibilityDisposables);
|
||||
|
||||
super.setVisible(visible);
|
||||
|
||||
this.onActiveEditorChanged();
|
||||
} else {
|
||||
this.visibilityDisposables?.dispose();
|
||||
}
|
||||
|
||||
super.setVisible(visible);
|
||||
super.setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
protected layoutBody(height: number, width: number): void {
|
||||
|
||||
@@ -53,6 +53,7 @@ import { IProductService } from 'vs/platform/product/common/productService';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IOpenerService } from 'vs/platform/opener/common/opener';
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import { distinct } from 'vs/base/common/arrays';
|
||||
|
||||
const enum AuthStatus {
|
||||
Initializing = 'Initializing',
|
||||
@@ -98,19 +99,19 @@ const getActivityTitle = (label: string, userDataSyncService: IUserDataSyncServi
|
||||
const getIdentityTitle = (label: string, authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService): string => {
|
||||
return account ? `${label} (${authenticationService.getDisplayName(authenticationProviderId)}:${account.accountName})` : label;
|
||||
};
|
||||
const turnOnSyncCommand = { id: 'workbench.userData.actions.syncStart', title: localize('turn on sync with category', "Sync: Turn on Sync") };
|
||||
const signInCommand = { id: 'workbench.userData.actions.signin', title: localize('sign in', "Sync: Sign in to sync") };
|
||||
const stopSyncCommand = { id: 'workbench.userData.actions.stopSync', title(authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService) { return getIdentityTitle(localize('stop sync', "Sync: Turn off Sync"), authenticationProviderId, account, authenticationService); } };
|
||||
const resolveSettingsConflictsCommand = { id: 'workbench.userData.actions.resolveSettingsConflicts', title: localize('showConflicts', "Sync: Show Settings Conflicts") };
|
||||
const resolveKeybindingsConflictsCommand = { id: 'workbench.userData.actions.resolveKeybindingsConflicts', title: localize('showKeybindingsConflicts', "Sync: Show Keybindings Conflicts") };
|
||||
const resolveSnippetsConflictsCommand = { id: 'workbench.userData.actions.resolveSnippetsConflicts', title: localize('showSnippetsConflicts', "Sync: Show User Snippets Conflicts") };
|
||||
const configureSyncCommand = { id: 'workbench.userData.actions.configureSync', title: localize('configure sync', "Sync: Configure") };
|
||||
const turnOnSyncCommand = { id: 'workbench.userData.actions.syncStart', title: localize('turn on sync with category', "Preferences Sync: Turn on...") };
|
||||
const signInCommand = { id: 'workbench.userData.actions.signin', title: localize('sign in', "Preferences Sync: Sign in to sync") };
|
||||
const stopSyncCommand = { id: 'workbench.userData.actions.stopSync', title(authenticationProviderId: string, account: AuthenticationSession | undefined, authenticationService: IAuthenticationService) { return getIdentityTitle(localize('stop sync', "Preferences Sync: Turn off"), authenticationProviderId, account, authenticationService); } };
|
||||
const resolveSettingsConflictsCommand = { id: 'workbench.userData.actions.resolveSettingsConflicts', title: localize('showConflicts', "Preferences Sync: Show Settings Conflicts") };
|
||||
const resolveKeybindingsConflictsCommand = { id: 'workbench.userData.actions.resolveKeybindingsConflicts', title: localize('showKeybindingsConflicts', "Preferences Sync: Show Keybindings Conflicts") };
|
||||
const resolveSnippetsConflictsCommand = { id: 'workbench.userData.actions.resolveSnippetsConflicts', title: localize('showSnippetsConflicts', "Preferences Sync: Show User Snippets Conflicts") };
|
||||
const configureSyncCommand = { id: 'workbench.userData.actions.configureSync', title: localize('configure sync', "Preferences Sync: Configure...") };
|
||||
const showSyncActivityCommand = {
|
||||
id: 'workbench.userData.actions.showSyncActivity', title(userDataSyncService: IUserDataSyncService): string {
|
||||
return getActivityTitle(localize('show sync log', "Sync: Show Log"), userDataSyncService);
|
||||
return getActivityTitle(localize('show sync log', "Preferences Sync: Show Log"), userDataSyncService);
|
||||
}
|
||||
};
|
||||
const showSyncSettingsCommand = { id: 'workbench.userData.actions.syncSettings', title: localize('sync settings', "Sync: Settings"), };
|
||||
const showSyncSettingsCommand = { id: 'workbench.userData.actions.syncSettings', title: localize('sync settings', "Preferences Sync: Show Settings"), };
|
||||
|
||||
export class UserDataSyncWorkbenchContribution extends Disposable implements IWorkbenchContribution {
|
||||
|
||||
@@ -249,9 +250,10 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
private async showSwitchAccountPicker(sessions: readonly AuthenticationSession[]): Promise<void> {
|
||||
return new Promise((resolve, _) => {
|
||||
const quickPick = this.quickInputService.createQuickPick<{ label: string, session: AuthenticationSession }>();
|
||||
quickPick.title = localize('chooseAccountTitle', "Sync: Choose Account");
|
||||
quickPick.title = localize('chooseAccountTitle', "Preferences Sync: Choose Account");
|
||||
quickPick.placeholder = localize('chooseAccount', "Choose an account you would like to use for settings sync");
|
||||
quickPick.items = sessions.map(session => {
|
||||
const dedupedSessions = distinct(sessions, (session) => session.accountName);
|
||||
quickPick.items = dedupedSessions.map(session => {
|
||||
return {
|
||||
label: session.accountName,
|
||||
session: session
|
||||
@@ -577,7 +579,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
if (this.userDataSyncService.status !== SyncStatus.Uninitialized && this.userDataSyncEnablementService.isEnabled() && this.authenticationState.get() === AuthStatus.SignedOut) {
|
||||
badge = new NumberBadge(1, () => localize('sign in to sync', "Sign in to Sync"));
|
||||
} else if (this.userDataSyncService.conflicts.length) {
|
||||
badge = new NumberBadge(this.userDataSyncService.conflicts.reduce((result, syncResourceConflict) => { return result + syncResourceConflict.conflicts.length; }, 0), () => localize('has conflicts', "Sync: Conflicts Detected"));
|
||||
badge = new NumberBadge(this.userDataSyncService.conflicts.reduce((result, syncResourceConflict) => { return result + syncResourceConflict.conflicts.length; }, 0), () => localize('has conflicts', "Preferences Sync: Conflicts Detected"));
|
||||
}
|
||||
|
||||
if (badge) {
|
||||
@@ -608,7 +610,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
const disposables: DisposableStore = new DisposableStore();
|
||||
const quickPick = this.quickInputService.createQuickPick<ConfigureSyncQuickPickItem>();
|
||||
disposables.add(quickPick);
|
||||
quickPick.title = localize('turn on title', "Sync: Turn On");
|
||||
quickPick.title = localize('turn on title', "Preferences Sync: Turn On");
|
||||
quickPick.ok = false;
|
||||
quickPick.customButton = true;
|
||||
if (this.authenticationState.get() === AuthStatus.SignedIn) {
|
||||
@@ -713,7 +715,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
const disposables: DisposableStore = new DisposableStore();
|
||||
const quickPick = this.quickInputService.createQuickPick<ConfigureSyncQuickPickItem>();
|
||||
disposables.add(quickPick);
|
||||
quickPick.title = localize('turn on sync', "Turn on Sync");
|
||||
quickPick.title = localize('configure sync', "Preferences Sync: Configure...");
|
||||
quickPick.placeholder = localize('configure sync placeholder', "Choose what to sync");
|
||||
quickPick.canSelectMany = true;
|
||||
quickPick.ignoreFocusOut = true;
|
||||
@@ -888,7 +890,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: turnOnSyncCommand.id,
|
||||
title: localize('global activity turn on sync', "Turn on Sync...")
|
||||
title: localize('global activity turn on sync', "Preferences Sync: Turn on...")
|
||||
},
|
||||
when: turnOnSyncWhenContext,
|
||||
order: 1
|
||||
@@ -901,7 +903,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: turnOnSyncCommand.id,
|
||||
title: localize('global activity turn on sync', "Turn on Sync...")
|
||||
title: localize('global activity turn on sync', "Preferences Sync: Turn on...")
|
||||
},
|
||||
when: turnOnSyncWhenContext,
|
||||
});
|
||||
@@ -913,7 +915,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
constructor() {
|
||||
super({
|
||||
id: signInCommand.id,
|
||||
title: localize('sign in 2', "Sync: Sign in to sync (1)"),
|
||||
title: localize('sign in 2', "Preferences Sync: Sign in to sync (1)"),
|
||||
menu: {
|
||||
group: '5_sync',
|
||||
id: MenuId.GlobalActivity,
|
||||
@@ -939,7 +941,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSettingsConflictsCommand.id,
|
||||
title: localize('resolveConflicts_global', "Sync: Show Settings Conflicts (1)"),
|
||||
title: localize('resolveConflicts_global', "Preferences Sync: Show Settings Conflicts (1)"),
|
||||
},
|
||||
when: resolveSettingsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -948,7 +950,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSettingsConflictsCommand.id,
|
||||
title: localize('resolveConflicts_global', "Sync: Show Settings Conflicts (1)"),
|
||||
title: localize('resolveConflicts_global', "Preferences Sync: Show Settings Conflicts (1)"),
|
||||
},
|
||||
when: resolveSettingsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -966,7 +968,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveKeybindingsConflictsCommand.id,
|
||||
title: localize('resolveKeybindingsConflicts_global', "Sync: Show Keybindings Conflicts (1)"),
|
||||
title: localize('resolveKeybindingsConflicts_global', "Preferences Sync: Show Keybindings Conflicts (1)"),
|
||||
},
|
||||
when: resolveKeybindingsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -975,7 +977,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveKeybindingsConflictsCommand.id,
|
||||
title: localize('resolveKeybindingsConflicts_global', "Sync: Show Keybindings Conflicts (1)"),
|
||||
title: localize('resolveKeybindingsConflicts_global', "Preferences Sync: Show Keybindings Conflicts (1)"),
|
||||
},
|
||||
when: resolveKeybindingsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -996,7 +998,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSnippetsConflictsCommand.id,
|
||||
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
title: localize('resolveSnippetsConflicts_global', "Preferences Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
},
|
||||
when: resolveSnippetsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -1005,7 +1007,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
group: '5_sync',
|
||||
command: {
|
||||
id: resolveSnippetsConflictsCommand.id,
|
||||
title: localize('resolveSnippetsConflicts_global', "Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
title: localize('resolveSnippetsConflicts_global', "Preferences Sync: Show User Snippets Conflicts ({0})", conflicts?.length || 1),
|
||||
},
|
||||
when: resolveSnippetsConflictsWhenContext,
|
||||
order: 2
|
||||
@@ -1023,7 +1025,7 @@ export class UserDataSyncWorkbenchContribution extends Disposable implements IWo
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.userData.actions.syncStatus',
|
||||
title: localize('sync is on', "Sync is on"),
|
||||
title: localize('sync is on', "Preferences Sync: On"),
|
||||
menu: [
|
||||
{
|
||||
id: MenuId.GlobalActivity,
|
||||
@@ -1262,8 +1264,8 @@ class AcceptChangesContribution extends Disposable implements IEditorContributio
|
||||
const result = await this.dialogService.confirm({
|
||||
type: 'info',
|
||||
title: isRemote
|
||||
? localize('Sync accept remote', "Sync: {0}", acceptRemoteLabel)
|
||||
: localize('Sync accept local', "Sync: {0}", acceptLocalLabel),
|
||||
? localize('Sync accept remote', "Preferences Sync: {0}", acceptRemoteLabel)
|
||||
: localize('Sync accept local', "Preferences Sync: {0}", acceptLocalLabel),
|
||||
message: isRemote
|
||||
? localize('confirm replace and overwrite local', "Would you like to accept remote {0} and replace local {1}?", syncAreaLabel.toLowerCase(), syncAreaLabel.toLowerCase())
|
||||
: localize('confirm replace and overwrite remote', "Would you like to accept local {0} and replace remote {1}?", syncAreaLabel.toLowerCase(), syncAreaLabel.toLowerCase()),
|
||||
|
||||
@@ -36,7 +36,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
|
||||
return Registry.as<IViewContainersRegistry>(Extensions.ViewContainersRegistry).registerViewContainer(
|
||||
{
|
||||
id: 'workbench.view.sync',
|
||||
name: localize('sync', "Sync"),
|
||||
name: localize('sync preferences', "Preferences Sync"),
|
||||
ctorDescriptor: new SyncDescriptor(
|
||||
ViewPaneContainer,
|
||||
['workbench.view.sync', `workbench.view.sync.state`, { mergeViewWithContainerWhenSingleView: true }]
|
||||
@@ -80,7 +80,7 @@ export class UserDataSyncViewContribution implements IWorkbenchContribution {
|
||||
title: remote ?
|
||||
{ value: localize('workbench.action.showSyncRemoteBackup', "Show Remote Backup"), original: `Show Remote Backup` }
|
||||
: { value: localize('workbench.action.showSyncLocalBackup', "Show Local Backup"), original: `Show Local Backup` },
|
||||
category: { value: localize('sync', "Sync"), original: `Sync` },
|
||||
category: { value: localize('sync preferences', "Preferences Sync"), original: `Preferences Sync` },
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: CONTEXT_SYNC_ENABLEMENT
|
||||
|
||||
@@ -33,7 +33,8 @@ registerAction2(class OpenSyncBackupsFolder extends Action2 {
|
||||
constructor() {
|
||||
super({
|
||||
id: 'workbench.userData.actions.openSyncBackupsFolder',
|
||||
title: localize('Open Backup folder', "Sync: Open Local Backups Folder"),
|
||||
title: { value: localize('Open Backup folder', "Open Local Backups Folder"), original: 'Open Local Backups Folder' },
|
||||
category: { value: localize('sync preferences', "Preferences Sync"), original: `Preferences Sync` },
|
||||
menu: {
|
||||
id: MenuId.CommandPalette,
|
||||
when: CONTEXT_SYNC_STATE.notEqualsTo(SyncStatus.Uninitialized),
|
||||
|
||||
@@ -233,11 +233,10 @@ export class ElectronWebviewBasedWebview extends BaseWebview<WebviewTag> impleme
|
||||
const webviewAndContents = this._register(new WebviewTagHandle(this.element!));
|
||||
const session = this._register(new WebviewSession(webviewAndContents));
|
||||
|
||||
this._protocolProvider = new WebviewProtocolProvider
|
||||
(webviewAndContents,
|
||||
() => this.extension ? this.extension.location : undefined,
|
||||
() => (this.content.options.localResourceRoots || []),
|
||||
fileService);
|
||||
this._protocolProvider = new WebviewProtocolProvider(webviewAndContents,
|
||||
() => this.extension?.location,
|
||||
() => (this.content.options.localResourceRoots || []),
|
||||
fileService);
|
||||
this._register(this._protocolProvider);
|
||||
|
||||
this._register(new WebviewPortMappingProvider(
|
||||
|
||||
@@ -8,7 +8,7 @@ import { localize } from 'vs/nls';
|
||||
|
||||
export default () => `
|
||||
<div class="welcomePageContainer">
|
||||
<div class="welcomePage">
|
||||
<div class="welcomePage" role="document">
|
||||
<div class="title">
|
||||
<h1 class="caption">${escape(localize('welcomePage.vscode', "Visual Studio Code"))}</h1>
|
||||
<p class="subtitle detail">${escape(localize({ key: 'welcomePage.editingEvolved', comment: ['Shown as subtitle on the Welcome page.'] }, "Editing evolved"))}</p>
|
||||
|
||||
Reference in New Issue
Block a user