@theia/plugin-ext 1.61.0 → 1.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/common/plugin-api-rpc-model.d.ts +2 -2
- package/lib/common/plugin-api-rpc-model.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.d.ts +3 -2
- package/lib/common/plugin-api-rpc.d.ts.map +1 -1
- package/lib/common/plugin-api-rpc.js.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.d.ts +64 -15
- package/lib/main/browser/comments/comment-thread-widget.d.ts.map +1 -1
- package/lib/main/browser/comments/comment-thread-widget.js +93 -49
- package/lib/main/browser/comments/comment-thread-widget.js.map +1 -1
- package/lib/main/browser/comments/{comments-context-key-service.d.ts → comments-context.d.ts} +2 -7
- package/lib/main/browser/comments/comments-context.d.ts.map +1 -0
- package/lib/main/browser/comments/{comments-context-key-service.js → comments-context.js} +8 -25
- package/lib/main/browser/comments/comments-context.js.map +1 -0
- package/lib/main/browser/comments/comments-contribution.d.ts +2 -2
- package/lib/main/browser/comments/comments-contribution.d.ts.map +1 -1
- package/lib/main/browser/comments/comments-contribution.js +8 -8
- package/lib/main/browser/comments/comments-contribution.js.map +1 -1
- package/lib/main/browser/comments/comments-main.d.ts +28 -3
- package/lib/main/browser/comments/comments-main.d.ts.map +1 -1
- package/lib/main/browser/comments/comments-main.js.map +1 -1
- package/lib/main/browser/custom-editors/custom-editor-opener.d.ts.map +1 -1
- package/lib/main/browser/custom-editors/custom-editor-opener.js +6 -1
- package/lib/main/browser/custom-editors/custom-editor-opener.js.map +1 -1
- package/lib/main/browser/documents-main.d.ts +2 -1
- package/lib/main/browser/documents-main.d.ts.map +1 -1
- package/lib/main/browser/documents-main.js +13 -9
- package/lib/main/browser/documents-main.js.map +1 -1
- package/lib/main/browser/main-context.d.ts.map +1 -1
- package/lib/main/browser/main-context.js +3 -1
- package/lib/main/browser/main-context.js.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.d.ts +7 -13
- package/lib/main/browser/menus/menus-contribution-handler.d.ts.map +1 -1
- package/lib/main/browser/menus/menus-contribution-handler.js +64 -51
- package/lib/main/browser/menus/menus-contribution-handler.js.map +1 -1
- package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts +5 -30
- package/lib/main/browser/menus/plugin-menu-command-adapter.d.ts.map +1 -1
- package/lib/main/browser/menus/plugin-menu-command-adapter.js +7 -110
- package/lib/main/browser/menus/plugin-menu-command-adapter.js.map +1 -1
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts +4 -4
- package/lib/main/browser/menus/vscode-theia-menu-mappings.d.ts.map +1 -1
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js +7 -10
- package/lib/main/browser/menus/vscode-theia-menu-mappings.js.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.d.ts.map +1 -1
- package/lib/main/browser/plugin-ext-frontend-module.js +2 -4
- package/lib/main/browser/plugin-ext-frontend-module.js.map +1 -1
- package/lib/main/browser/terminal-main.d.ts.map +1 -1
- package/lib/main/browser/terminal-main.js +4 -1
- package/lib/main/browser/terminal-main.js.map +1 -1
- package/lib/main/browser/text-editor-model-service.d.ts +1 -3
- package/lib/main/browser/text-editor-model-service.d.ts.map +1 -1
- package/lib/main/browser/text-editor-model-service.js +0 -5
- package/lib/main/browser/text-editor-model-service.js.map +1 -1
- package/lib/main/browser/view/tree-view-widget.d.ts +2 -2
- package/lib/main/browser/view/tree-view-widget.d.ts.map +1 -1
- package/lib/main/browser/view/tree-view-widget.js +5 -4
- package/lib/main/browser/view/tree-view-widget.js.map +1 -1
- package/lib/plugin/comments.d.ts +2 -2
- package/lib/plugin/comments.d.ts.map +1 -1
- package/lib/plugin/comments.js.map +1 -1
- package/lib/plugin/terminal-ext.d.ts +2 -1
- package/lib/plugin/terminal-ext.d.ts.map +1 -1
- package/lib/plugin/terminal-ext.js +13 -3
- package/lib/plugin/terminal-ext.js.map +1 -1
- package/package.json +29 -29
- package/src/common/plugin-api-rpc-model.ts +2 -2
- package/src/common/plugin-api-rpc.ts +3 -2
- package/src/main/browser/comments/comment-thread-widget.tsx +177 -85
- package/src/main/browser/comments/{comments-context-key-service.ts → comments-context.ts} +1 -20
- package/src/main/browser/comments/comments-contribution.ts +5 -5
- package/src/main/browser/comments/comments-main.ts +5 -4
- package/src/main/browser/custom-editors/custom-editor-opener.tsx +5 -1
- package/src/main/browser/documents-main.ts +19 -10
- package/src/main/browser/main-context.ts +3 -1
- package/src/main/browser/menus/menus-contribution-handler.ts +68 -49
- package/src/main/browser/menus/plugin-menu-command-adapter.ts +13 -120
- package/src/main/browser/menus/vscode-theia-menu-mappings.ts +4 -6
- package/src/main/browser/plugin-ext-frontend-module.ts +2 -4
- package/src/main/browser/style/comments.css +9 -1
- package/src/main/browser/terminal-main.ts +4 -1
- package/src/main/browser/text-editor-model-service.ts +1 -6
- package/src/main/browser/view/tree-view-widget.tsx +7 -6
- package/src/plugin/comments.ts +4 -4
- package/src/plugin/terminal-ext.ts +14 -3
- package/lib/main/browser/comments/comments-context-key-service.d.ts.map +0 -1
- package/lib/main/browser/comments/comments-context-key-service.js.map +0 -1
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
import { DocumentsMain, MAIN_RPC_CONTEXT, DocumentsExt } from '../../common/plugin-api-rpc';
|
|
17
17
|
import { UriComponents } from '../../common/uri-components';
|
|
18
18
|
import { EditorsAndDocumentsMain } from './editors-and-documents-main';
|
|
19
|
-
import { DisposableCollection, Disposable, UntitledResourceResolver } from '@theia/core';
|
|
19
|
+
import { DisposableCollection, Disposable, UntitledResourceResolver, CancellationToken } from '@theia/core';
|
|
20
20
|
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
|
|
21
21
|
import { RPCProtocol } from '../../common/rpc-protocol';
|
|
22
22
|
import { EditorModelService } from './text-editor-model-service';
|
|
23
23
|
import { EditorOpenerOptions } from '@theia/editor/lib/browser';
|
|
24
24
|
import URI from '@theia/core/lib/common/uri';
|
|
25
25
|
import { URI as CodeURI } from '@theia/core/shared/vscode-uri';
|
|
26
|
-
import { ApplicationShell } from '@theia/core/lib/browser';
|
|
26
|
+
import { ApplicationShell, SaveOptions, SaveReason } from '@theia/core/lib/browser';
|
|
27
27
|
import { TextDocumentShowOptions } from '../../common/plugin-api-rpc-model';
|
|
28
28
|
import { Range } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
29
29
|
import { OpenerService } from '@theia/core/lib/browser/opener-service';
|
|
@@ -33,6 +33,8 @@ import { MonacoLanguages } from '@theia/monaco/lib/browser/monaco-languages';
|
|
|
33
33
|
import * as monaco from '@theia/monaco-editor-core';
|
|
34
34
|
import { TextDocumentChangeReason } from '../../plugin/types-impl';
|
|
35
35
|
import { NotebookDocumentsMainImpl } from './notebooks/notebook-documents-main';
|
|
36
|
+
import { MonacoEditorProvider, SAVE_PARTICIPANT_DEFAULT_ORDER } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
37
|
+
import { MonacoEditor } from '@theia/monaco/lib/browser/monaco-editor';
|
|
36
38
|
|
|
37
39
|
/*---------------------------------------------------------------------------------------------
|
|
38
40
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
@@ -98,6 +100,7 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
|
|
|
98
100
|
private shell: ApplicationShell,
|
|
99
101
|
private untitledResourceResolver: UntitledResourceResolver,
|
|
100
102
|
private languageService: MonacoLanguages,
|
|
103
|
+
monacoEditorProvider: MonacoEditorProvider
|
|
101
104
|
) {
|
|
102
105
|
this.proxy = rpc.getProxy(MAIN_RPC_CONTEXT.DOCUMENTS_EXT);
|
|
103
106
|
|
|
@@ -111,10 +114,16 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
|
|
|
111
114
|
this.toDispose.push(modelService.onModelSaved(m => {
|
|
112
115
|
this.proxy.$acceptModelSaved(m.textEditorModel.uri);
|
|
113
116
|
}));
|
|
114
|
-
this.toDispose.push(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
117
|
+
this.toDispose.push(monacoEditorProvider.registerSaveParticipant(({
|
|
118
|
+
order: SAVE_PARTICIPANT_DEFAULT_ORDER,
|
|
119
|
+
applyChangesOnSave: async (
|
|
120
|
+
editor: MonacoEditor,
|
|
121
|
+
cancellationToken: CancellationToken,
|
|
122
|
+
options: SaveOptions): Promise<void> => {
|
|
123
|
+
|
|
124
|
+
const saveReason = options.saveReason ?? SaveReason.Manual;
|
|
125
|
+
|
|
126
|
+
const edits = await this.proxy.$acceptModelWillSave(editor.uri.toComponents(), saveReason.valueOf(), this.saveTimeout);
|
|
118
127
|
const editOperations: monaco.editor.IIdentifiedSingleEditOperation[] = [];
|
|
119
128
|
for (const edit of edits) {
|
|
120
129
|
const { range, text } = edit;
|
|
@@ -126,15 +135,15 @@ export class DocumentsMainImpl implements DocumentsMain, Disposable {
|
|
|
126
135
|
}
|
|
127
136
|
|
|
128
137
|
editOperations.push({
|
|
129
|
-
range: range ? monaco.Range.lift(range) :
|
|
138
|
+
range: range ? monaco.Range.lift(range) : editor.document.textEditorModel.getFullModelRange(),
|
|
130
139
|
/* eslint-disable-next-line no-null/no-null */
|
|
131
140
|
text: text || null,
|
|
132
141
|
forceMoveMarkers: edit.forceMoveMarkers
|
|
133
142
|
});
|
|
134
143
|
}
|
|
135
|
-
|
|
136
|
-
}
|
|
137
|
-
}));
|
|
144
|
+
editor.document.textEditorModel.applyEdits(editOperations);
|
|
145
|
+
}
|
|
146
|
+
})));
|
|
138
147
|
this.toDispose.push(modelService.onModelDirtyChanged(m => {
|
|
139
148
|
this.proxy.$acceptDirtyStateChanged(m.textEditorModel.uri, m.dirty);
|
|
140
149
|
}));
|
|
@@ -66,6 +66,7 @@ import { NotebooksAndEditorsMain } from './notebooks/notebook-documents-and-edit
|
|
|
66
66
|
import { TestingMainImpl } from './test-main';
|
|
67
67
|
import { UriMainImpl } from './uri-main';
|
|
68
68
|
import { LoggerMainImpl } from './logger-main';
|
|
69
|
+
import { MonacoEditorProvider } from '@theia/monaco/lib/browser/monaco-editor-provider';
|
|
69
70
|
|
|
70
71
|
export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container): void {
|
|
71
72
|
const loggerMain = new LoggerMainImpl(container);
|
|
@@ -105,8 +106,9 @@ export function setUpPluginApi(rpc: RPCProtocol, container: interfaces.Container
|
|
|
105
106
|
const shell = container.get(ApplicationShell);
|
|
106
107
|
const untitledResourceResolver = container.get(UntitledResourceResolver);
|
|
107
108
|
const languageService = container.get(MonacoLanguages);
|
|
109
|
+
const monacoEditorProvider = container.get(MonacoEditorProvider);
|
|
108
110
|
const documentsMain = new DocumentsMainImpl(editorsAndDocuments, notebookDocumentsMain, modelService, rpc,
|
|
109
|
-
openerService, shell, untitledResourceResolver, languageService);
|
|
111
|
+
openerService, shell, untitledResourceResolver, languageService, monacoEditorProvider);
|
|
110
112
|
rpc.set(PLUGIN_RPC_CONTEXT.DOCUMENTS_MAIN, documentsMain);
|
|
111
113
|
|
|
112
114
|
rpc.set(PLUGIN_RPC_CONTEXT.NOTEBOOKS_MAIN, new NotebooksMainImpl(rpc, container, commandRegistryMain));
|
|
@@ -17,18 +17,17 @@
|
|
|
17
17
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
18
18
|
|
|
19
19
|
import { inject, injectable, optional } from '@theia/core/shared/inversify';
|
|
20
|
-
import { MenuPath, CommandRegistry, Disposable, DisposableCollection,
|
|
20
|
+
import { MenuPath, CommandRegistry, Disposable, DisposableCollection, nls, CommandMenu, AcceleratorSource, ContextExpressionMatcher } from '@theia/core';
|
|
21
21
|
import { MenuModelRegistry } from '@theia/core/lib/common';
|
|
22
22
|
import { TabBarToolbarRegistry } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
23
23
|
import { DeployedPlugin, IconUrl, Menu } from '../../../common';
|
|
24
24
|
import { ScmWidget } from '@theia/scm/lib/browser/scm-widget';
|
|
25
|
-
import { QuickCommandService } from '@theia/core/lib/browser';
|
|
25
|
+
import { KeybindingRegistry, QuickCommandService } from '@theia/core/lib/browser';
|
|
26
26
|
import {
|
|
27
27
|
CodeEditorWidgetUtil, codeToTheiaMappings, ContributionPoint,
|
|
28
28
|
PLUGIN_EDITOR_TITLE_MENU, PLUGIN_EDITOR_TITLE_RUN_MENU, PLUGIN_SCM_TITLE_MENU, PLUGIN_VIEW_TITLE_MENU
|
|
29
29
|
} from './vscode-theia-menu-mappings';
|
|
30
|
-
import { PluginMenuCommandAdapter
|
|
31
|
-
import { ContextKeyExpr } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
|
|
30
|
+
import { PluginMenuCommandAdapter } from './plugin-menu-command-adapter';
|
|
32
31
|
import { ContextKeyService } from '@theia/core/lib/browser/context-key-service';
|
|
33
32
|
import { PluginSharedStyle } from '../plugin-shared-style';
|
|
34
33
|
import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themables';
|
|
@@ -37,40 +36,35 @@ import { ThemeIcon } from '@theia/monaco-editor-core/esm/vs/base/common/themable
|
|
|
37
36
|
export class MenusContributionPointHandler {
|
|
38
37
|
|
|
39
38
|
@inject(MenuModelRegistry) private readonly menuRegistry: MenuModelRegistry;
|
|
40
|
-
@inject(CommandRegistry) private readonly
|
|
39
|
+
@inject(CommandRegistry) private readonly commandRegistry: CommandRegistry;
|
|
41
40
|
@inject(TabBarToolbarRegistry) private readonly tabBarToolbar: TabBarToolbarRegistry;
|
|
42
|
-
@inject(
|
|
43
|
-
@inject(PluginMenuCommandAdapter) protected readonly commandAdapter: PluginMenuCommandAdapter;
|
|
44
|
-
@inject(MenuCommandAdapterRegistry) protected readonly commandAdapterRegistry: MenuCommandAdapterRegistry;
|
|
41
|
+
@inject(PluginMenuCommandAdapter) pluginMenuCommandAdapter: PluginMenuCommandAdapter;
|
|
45
42
|
@inject(ContextKeyService) protected readonly contextKeyService: ContextKeyService;
|
|
46
43
|
@inject(PluginSharedStyle) protected readonly style: PluginSharedStyle;
|
|
44
|
+
@inject(KeybindingRegistry) keybindingRegistry: KeybindingRegistry;
|
|
45
|
+
|
|
47
46
|
@inject(QuickCommandService) @optional()
|
|
48
47
|
private readonly quickCommandService: QuickCommandService;
|
|
49
48
|
|
|
50
|
-
protected readonly titleContributionContextKeys = new ReferenceCountingSet();
|
|
51
|
-
protected readonly onDidChangeTitleContributionEmitter = new Emitter<void>();
|
|
52
|
-
|
|
53
49
|
private initialized = false;
|
|
54
50
|
private initialize(): void {
|
|
55
51
|
this.initialized = true;
|
|
56
|
-
this.
|
|
57
|
-
this.
|
|
52
|
+
this.tabBarToolbar.registerMenuDelegate(PLUGIN_EDITOR_TITLE_MENU, widget => CodeEditorWidgetUtil.is(widget));
|
|
53
|
+
this.menuRegistry.registerSubmenu(PLUGIN_EDITOR_TITLE_RUN_MENU, 'EditorTitleRunMenu');
|
|
58
54
|
this.tabBarToolbar.registerItem({
|
|
59
|
-
id: this.tabBarToolbar.toElementId(PLUGIN_EDITOR_TITLE_RUN_MENU),
|
|
60
|
-
|
|
61
|
-
|
|
55
|
+
id: this.tabBarToolbar.toElementId(PLUGIN_EDITOR_TITLE_RUN_MENU),
|
|
56
|
+
menuPath: PLUGIN_EDITOR_TITLE_RUN_MENU,
|
|
57
|
+
icon: 'debug-alt',
|
|
58
|
+
text: nls.localizeByDefault('Run or Debug...'),
|
|
59
|
+
command: '',
|
|
60
|
+
group: 'navigation',
|
|
61
|
+
isVisible: widget => CodeEditorWidgetUtil.is(widget)
|
|
62
62
|
});
|
|
63
63
|
this.tabBarToolbar.registerMenuDelegate(PLUGIN_SCM_TITLE_MENU, widget => widget instanceof ScmWidget);
|
|
64
|
-
this.tabBarToolbar.registerMenuDelegate(PLUGIN_VIEW_TITLE_MENU, widget => !
|
|
65
|
-
this.tabBarToolbar.registerItem({ id: 'plugin-menu-contribution-title-contribution', command: '_never_', onDidChange: this.onDidChangeTitleContributionEmitter.event });
|
|
66
|
-
this.contextKeyService.onDidChange(event => {
|
|
67
|
-
if (event.affects(this.titleContributionContextKeys)) {
|
|
68
|
-
this.onDidChangeTitleContributionEmitter.fire();
|
|
69
|
-
}
|
|
70
|
-
});
|
|
64
|
+
this.tabBarToolbar.registerMenuDelegate(PLUGIN_VIEW_TITLE_MENU, widget => !CodeEditorWidgetUtil.is(widget));
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
private
|
|
67
|
+
private getMatchingTheiaMenuPaths(contributionPoint: string): MenuPath[] | undefined {
|
|
74
68
|
return codeToTheiaMappings.get(contributionPoint);
|
|
75
69
|
}
|
|
76
70
|
|
|
@@ -86,7 +80,7 @@ export class MenusContributionPointHandler {
|
|
|
86
80
|
const submenus = plugin.contributes?.submenus ?? [];
|
|
87
81
|
for (const submenu of submenus) {
|
|
88
82
|
const iconClass = submenu.icon && this.toIconClass(submenu.icon, toDispose);
|
|
89
|
-
this.menuRegistry.
|
|
83
|
+
this.menuRegistry.registerSubmenu([submenu.id], submenu.label, { icon: iconClass });
|
|
90
84
|
}
|
|
91
85
|
|
|
92
86
|
for (const [contributionPoint, items] of Object.entries(allMenus)) {
|
|
@@ -95,8 +89,10 @@ export class MenusContributionPointHandler {
|
|
|
95
89
|
if (contributionPoint === 'commandPalette') {
|
|
96
90
|
toDispose.push(this.registerCommandPaletteAction(item));
|
|
97
91
|
} else {
|
|
98
|
-
this.
|
|
99
|
-
|
|
92
|
+
let targets = this.getMatchingTheiaMenuPaths(contributionPoint as ContributionPoint);
|
|
93
|
+
if (!targets) {
|
|
94
|
+
targets = [[contributionPoint]];
|
|
95
|
+
}
|
|
100
96
|
const { group, order } = this.parseGroup(item.group);
|
|
101
97
|
const { submenu, command } = item;
|
|
102
98
|
if (submenu && command) {
|
|
@@ -105,19 +101,55 @@ export class MenusContributionPointHandler {
|
|
|
105
101
|
);
|
|
106
102
|
}
|
|
107
103
|
if (command) {
|
|
108
|
-
|
|
104
|
+
|
|
109
105
|
targets.forEach(target => {
|
|
106
|
+
const menuPath = group ? [...target, group] : target;
|
|
110
107
|
|
|
111
|
-
const
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
}
|
|
116
|
-
const
|
|
117
|
-
|
|
108
|
+
const cmd = this.commandRegistry.getCommand(command);
|
|
109
|
+
if (!cmd) {
|
|
110
|
+
console.debug(`No label for action menu node: No command "${command}" exists.`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const label = cmd.label || cmd.id;
|
|
114
|
+
const icon = cmd.iconClass;
|
|
115
|
+
const action: CommandMenu & AcceleratorSource = {
|
|
116
|
+
id: command,
|
|
117
|
+
sortString: order || '',
|
|
118
|
+
isVisible: <T>(effectiveMenuPath: MenuPath, contextMatcher: ContextExpressionMatcher<T>, context: T | undefined, ...args: any[]): boolean => {
|
|
119
|
+
if (item.when && !contextMatcher.match(item.when, context)) {
|
|
120
|
+
return false;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
return this.commandRegistry.isVisible(command, ...this.pluginMenuCommandAdapter.getArgumentAdapter(contributionPoint)(...args));
|
|
124
|
+
},
|
|
125
|
+
icon: icon,
|
|
126
|
+
label: label,
|
|
127
|
+
isEnabled: (effeciveMenuPath: MenuPath, ...args: any[]): boolean =>
|
|
128
|
+
this.commandRegistry.isEnabled(command, ...this.pluginMenuCommandAdapter.getArgumentAdapter(contributionPoint)(...args)),
|
|
129
|
+
run: (effeciveMenuPath: MenuPath, ...args: any[]): Promise<void> =>
|
|
130
|
+
this.commandRegistry.executeCommand(command, ...this.pluginMenuCommandAdapter.getArgumentAdapter(contributionPoint)(...args)),
|
|
131
|
+
isToggled: (effectiveMenuPath: MenuPath) => false,
|
|
132
|
+
getAccelerator: (context: HTMLElement | undefined): string[] => {
|
|
133
|
+
const bindings = this.keybindingRegistry.getKeybindingsForCommand(command);
|
|
134
|
+
// Only consider the first active keybinding.
|
|
135
|
+
if (bindings.length) {
|
|
136
|
+
const binding = bindings.find(b => this.keybindingRegistry.isEnabledInScope(b, context));
|
|
137
|
+
if (binding) {
|
|
138
|
+
return this.keybindingRegistry.acceleratorFor(binding, '+', true);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
toDispose.push(this.menuRegistry.registerCommandMenu(menuPath, action));
|
|
118
145
|
});
|
|
119
146
|
} else if (submenu) {
|
|
120
|
-
targets.forEach(target => toDispose.push(this.menuRegistry.
|
|
147
|
+
targets.forEach(target => toDispose.push(this.menuRegistry.linkCompoundMenuNode({
|
|
148
|
+
newParentPath: group ? [...target, group] : target,
|
|
149
|
+
submenuPath: [submenu!],
|
|
150
|
+
order: order,
|
|
151
|
+
when: item.when
|
|
152
|
+
})));
|
|
121
153
|
}
|
|
122
154
|
}
|
|
123
155
|
} catch (error) {
|
|
@@ -146,19 +178,6 @@ export class MenusContributionPointHandler {
|
|
|
146
178
|
return Disposable.NULL;
|
|
147
179
|
}
|
|
148
180
|
|
|
149
|
-
protected checkTitleContribution(contributionPoint: ContributionPoint | string, contribution: { when?: string }, toDispose: DisposableCollection): void {
|
|
150
|
-
if (contribution.when && contributionPoint.endsWith('title')) {
|
|
151
|
-
const expression = ContextKeyExpr.deserialize(contribution.when);
|
|
152
|
-
if (expression) {
|
|
153
|
-
for (const key of expression.keys()) {
|
|
154
|
-
this.titleContributionContextKeys.add(key);
|
|
155
|
-
toDispose.push(Disposable.create(() => this.titleContributionContextKeys.delete(key)));
|
|
156
|
-
}
|
|
157
|
-
toDispose.push(Disposable.create(() => this.onDidChangeTitleContributionEmitter.fire()));
|
|
158
|
-
}
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
181
|
protected toIconClass(url: IconUrl, toDispose: DisposableCollection): string | undefined {
|
|
163
182
|
if (typeof url === 'string') {
|
|
164
183
|
const asThemeIcon = ThemeIcon.fromString(url);
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
|
|
17
|
-
import {
|
|
17
|
+
import { SelectionService, UriSelection } from '@theia/core';
|
|
18
18
|
import { ResourceContextKey } from '@theia/core/lib/browser/resource-context-key';
|
|
19
19
|
import { inject, injectable, postConstruct } from '@theia/core/shared/inversify';
|
|
20
20
|
import { URI as CodeUri } from '@theia/core/shared/vscode-uri';
|
|
@@ -29,57 +29,20 @@ import { ScmCommandArg, TimelineCommandArg, TreeViewItemReference } from '../../
|
|
|
29
29
|
import { TestItemReference, TestMessageArg } from '../../../common/test-types';
|
|
30
30
|
import { PluginScmProvider, PluginScmResource, PluginScmResourceGroup } from '../scm-main';
|
|
31
31
|
import { TreeViewWidget } from '../view/tree-view-widget';
|
|
32
|
-
import { CodeEditorWidgetUtil,
|
|
33
|
-
import { TAB_BAR_TOOLBAR_CONTEXT_MENU } from '@theia/core/lib/browser/shell/tab-bar-toolbar';
|
|
32
|
+
import { CodeEditorWidgetUtil, ContributionPoint } from './vscode-theia-menu-mappings';
|
|
34
33
|
import { TestItem, TestMessage } from '@theia/test/lib/browser/test-service';
|
|
35
34
|
|
|
36
35
|
export type ArgumentAdapter = (...args: unknown[]) => unknown[];
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
protected readonly references: Map<T, number>;
|
|
40
|
-
constructor(initialMembers?: Iterable<T>) {
|
|
41
|
-
this.references = new Map();
|
|
42
|
-
if (initialMembers) {
|
|
43
|
-
for (const member of initialMembers) {
|
|
44
|
-
this.add(member);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
add(newMember: T): ReferenceCountingSet<T> {
|
|
50
|
-
const value = this.references.get(newMember) ?? 0;
|
|
51
|
-
this.references.set(newMember, value + 1);
|
|
52
|
-
return this;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/** @returns true if the deletion results in the removal of the element from the set */
|
|
56
|
-
delete(member: T): boolean {
|
|
57
|
-
const value = this.references.get(member);
|
|
58
|
-
if (value === undefined) { } else if (value <= 1) {
|
|
59
|
-
this.references.delete(member);
|
|
60
|
-
return true;
|
|
61
|
-
} else {
|
|
62
|
-
this.references.set(member, value - 1);
|
|
63
|
-
}
|
|
64
|
-
return false;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
has(maybeMember: T): boolean {
|
|
68
|
-
return this.references.has(maybeMember);
|
|
69
|
-
}
|
|
36
|
+
function identity(...args: unknown[]): unknown[] {
|
|
37
|
+
return args;
|
|
70
38
|
}
|
|
71
|
-
|
|
72
39
|
@injectable()
|
|
73
|
-
export class PluginMenuCommandAdapter
|
|
74
|
-
@inject(
|
|
75
|
-
@inject(
|
|
76
|
-
@inject(
|
|
77
|
-
@inject(SelectionService) protected readonly selectionService: SelectionService;
|
|
78
|
-
@inject(ResourceContextKey) protected readonly resourceContextKey: ResourceContextKey;
|
|
40
|
+
export class PluginMenuCommandAdapter {
|
|
41
|
+
@inject(ScmService) private readonly scmService: ScmService;
|
|
42
|
+
@inject(SelectionService) private readonly selectionService: SelectionService;
|
|
43
|
+
@inject(ResourceContextKey) private readonly resourceContextKey: ResourceContextKey;
|
|
79
44
|
|
|
80
|
-
protected readonly commands = new ReferenceCountingSet<string>();
|
|
81
45
|
protected readonly argumentAdapters = new Map<string, ArgumentAdapter>();
|
|
82
|
-
protected readonly separator = ':)(:';
|
|
83
46
|
|
|
84
47
|
@postConstruct()
|
|
85
48
|
protected init(): void {
|
|
@@ -89,8 +52,8 @@ export class PluginMenuCommandAdapter implements MenuCommandAdapter {
|
|
|
89
52
|
const noArgs: ArgumentAdapter = () => [];
|
|
90
53
|
const toScmArgs: ArgumentAdapter = (...args) => this.toScmArgs(...args);
|
|
91
54
|
const selectedResource = () => this.getSelectedResources();
|
|
92
|
-
const widgetURI: ArgumentAdapter = widget =>
|
|
93
|
-
(<Array<[ContributionPoint, ArgumentAdapter
|
|
55
|
+
const widgetURI: ArgumentAdapter = widget => CodeEditorWidgetUtil.is(widget) ? [CodeEditorWidgetUtil.getResourceUri(widget)] : [];
|
|
56
|
+
(<Array<[ContributionPoint, ArgumentAdapter]>>[
|
|
94
57
|
['comments/comment/context', toCommentArgs],
|
|
95
58
|
['comments/comment/title', toCommentArgs],
|
|
96
59
|
['comments/commentThread/context', toCommentArgs],
|
|
@@ -117,82 +80,12 @@ export class PluginMenuCommandAdapter implements MenuCommandAdapter {
|
|
|
117
80
|
['terminal/context', noArgs],
|
|
118
81
|
['terminal/title/context', noArgs],
|
|
119
82
|
]).forEach(([contributionPoint, adapter]) => {
|
|
120
|
-
|
|
121
|
-
const paths = codeToTheiaMappings.get(contributionPoint);
|
|
122
|
-
if (paths) {
|
|
123
|
-
paths.forEach(path => this.addArgumentAdapter(path, adapter));
|
|
124
|
-
}
|
|
125
|
-
}
|
|
83
|
+
this.argumentAdapters.set(contributionPoint, adapter);
|
|
126
84
|
});
|
|
127
|
-
this.addArgumentAdapter(TAB_BAR_TOOLBAR_CONTEXT_MENU, widgetURI);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
canHandle(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): number {
|
|
131
|
-
if (this.commands.has(command) && this.getArgumentAdapterForMenu(menuPath)) {
|
|
132
|
-
return 500;
|
|
133
|
-
}
|
|
134
|
-
return -1;
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
executeCommand(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): Promise<unknown> {
|
|
138
|
-
const argumentAdapter = this.getAdapterOrThrow(menuPath);
|
|
139
|
-
return this.commandRegistry.executeCommand(command, ...argumentAdapter(...commandArgs));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
isVisible(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
|
|
143
|
-
const argumentAdapter = this.getAdapterOrThrow(menuPath);
|
|
144
|
-
return this.commandRegistry.isVisible(command, ...argumentAdapter(...commandArgs));
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
isEnabled(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
|
|
148
|
-
const argumentAdapter = this.getAdapterOrThrow(menuPath);
|
|
149
|
-
return this.commandRegistry.isEnabled(command, ...argumentAdapter(...commandArgs));
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
isToggled(menuPath: MenuPath, command: string, ...commandArgs: unknown[]): boolean {
|
|
153
|
-
const argumentAdapter = this.getAdapterOrThrow(menuPath);
|
|
154
|
-
return this.commandRegistry.isToggled(command, ...argumentAdapter(...commandArgs));
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
protected getAdapterOrThrow(menuPath: MenuPath): ArgumentAdapter {
|
|
158
|
-
const argumentAdapter = this.getArgumentAdapterForMenu(menuPath);
|
|
159
|
-
if (!argumentAdapter) {
|
|
160
|
-
throw new Error('PluginMenuCommandAdapter attempted to execute command for unregistered menu: ' + JSON.stringify(menuPath));
|
|
161
|
-
}
|
|
162
|
-
return argumentAdapter;
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
addCommand(commandId: string): Disposable {
|
|
166
|
-
this.commands.add(commandId);
|
|
167
|
-
return Disposable.create(() => this.commands.delete(commandId));
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
protected getArgumentAdapterForMenu(menuPath: MenuPath): ArgumentAdapter | undefined {
|
|
171
|
-
let result;
|
|
172
|
-
let length = 0;
|
|
173
|
-
for (const [key, value] of this.argumentAdapters.entries()) {
|
|
174
|
-
const candidate = key.split(this.separator);
|
|
175
|
-
if (this.isPrefixOf(candidate, menuPath) && candidate.length > length) {
|
|
176
|
-
result = value;
|
|
177
|
-
length = candidate.length;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return result;
|
|
181
|
-
}
|
|
182
|
-
isPrefixOf(candidate: string[], menuPath: MenuPath): boolean {
|
|
183
|
-
if (candidate.length > menuPath.length) {
|
|
184
|
-
return false;
|
|
185
|
-
}
|
|
186
|
-
for (let i = 0; i < candidate.length; i++) {
|
|
187
|
-
if (candidate[i] !== menuPath[i]) {
|
|
188
|
-
return false;
|
|
189
|
-
}
|
|
190
|
-
}
|
|
191
|
-
return true;
|
|
192
85
|
}
|
|
193
86
|
|
|
194
|
-
|
|
195
|
-
this.argumentAdapters.
|
|
87
|
+
getArgumentAdapter(contributionPoint: string): ArgumentAdapter {
|
|
88
|
+
return this.argumentAdapters.get(contributionPoint) || identity;
|
|
196
89
|
}
|
|
197
90
|
|
|
198
91
|
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
@@ -17,7 +17,6 @@
|
|
|
17
17
|
import { MenuPath } from '@theia/core';
|
|
18
18
|
import { SHELL_TABBAR_CONTEXT_MENU } from '@theia/core/lib/browser';
|
|
19
19
|
import { Navigatable } from '@theia/core/lib/browser/navigatable';
|
|
20
|
-
import { injectable } from '@theia/core/shared/inversify';
|
|
21
20
|
import { URI as CodeUri } from '@theia/core/shared/vscode-uri';
|
|
22
21
|
import { DebugStackFramesWidget } from '@theia/debug/lib/browser/view/debug-stack-frames-widget';
|
|
23
22
|
import { DebugThreadsWidget } from '@theia/debug/lib/browser/view/debug-threads-widget';
|
|
@@ -74,7 +73,7 @@ export const implementedVSCodeContributionPoints = [
|
|
|
74
73
|
export type ContributionPoint = (typeof implementedVSCodeContributionPoints)[number];
|
|
75
74
|
|
|
76
75
|
/** The values are menu paths to which the VSCode contribution points correspond */
|
|
77
|
-
export const codeToTheiaMappings = new Map<
|
|
76
|
+
export const codeToTheiaMappings = new Map<string, MenuPath[]>([
|
|
78
77
|
['comments/comment/context', [COMMENT_CONTEXT]],
|
|
79
78
|
['comments/comment/title', [COMMENT_TITLE]],
|
|
80
79
|
['comments/commentThread/context', [COMMENT_THREAD_CONTEXT]],
|
|
@@ -106,12 +105,11 @@ export const codeToTheiaMappings = new Map<ContributionPoint, MenuPath[]>([
|
|
|
106
105
|
]);
|
|
107
106
|
|
|
108
107
|
type CodeEditorWidget = EditorWidget | WebviewWidget;
|
|
109
|
-
|
|
110
|
-
export
|
|
111
|
-
is(arg: unknown): arg is CodeEditorWidget {
|
|
108
|
+
export namespace CodeEditorWidgetUtil {
|
|
109
|
+
export function is(arg: unknown): arg is CodeEditorWidget {
|
|
112
110
|
return arg instanceof EditorWidget || arg instanceof WebviewWidget;
|
|
113
111
|
}
|
|
114
|
-
getResourceUri(editor: CodeEditorWidget): CodeUri | undefined {
|
|
112
|
+
export function getResourceUri(editor: CodeEditorWidget): CodeUri | undefined {
|
|
115
113
|
const resourceUri = Navigatable.is(editor) && editor.getResourceUri();
|
|
116
114
|
return resourceUri ? resourceUri['codeUri'] : undefined;
|
|
117
115
|
}
|
|
@@ -68,7 +68,7 @@ import { WebviewWidgetFactory } from './webview/webview-widget-factory';
|
|
|
68
68
|
import { CommentsService, PluginCommentService } from './comments/comments-service';
|
|
69
69
|
import { CommentingRangeDecorator } from './comments/comments-decorator';
|
|
70
70
|
import { CommentsContribution } from './comments/comments-contribution';
|
|
71
|
-
import {
|
|
71
|
+
import { CommentsContext } from './comments/comments-context';
|
|
72
72
|
import { PluginCustomEditorRegistry } from './custom-editors/plugin-custom-editor-registry';
|
|
73
73
|
import { CustomEditorWidgetFactory } from '../browser/custom-editors/custom-editor-widget-factory';
|
|
74
74
|
import { CustomEditorWidget } from './custom-editors/custom-editor-widget';
|
|
@@ -77,7 +77,6 @@ import { WebviewFrontendSecurityWarnings } from './webview/webview-frontend-secu
|
|
|
77
77
|
import { PluginAuthenticationServiceImpl } from './plugin-authentication-service';
|
|
78
78
|
import { AuthenticationService } from '@theia/core/lib/browser/authentication-service';
|
|
79
79
|
import { bindTreeViewDecoratorUtilities, TreeViewDecoratorService } from './view/tree-view-decorator-service';
|
|
80
|
-
import { CodeEditorWidgetUtil } from './menus/vscode-theia-menu-mappings';
|
|
81
80
|
import { PluginMenuCommandAdapter } from './menus/plugin-menu-command-adapter';
|
|
82
81
|
import './theme-icon-override';
|
|
83
82
|
import { PluginIconService } from './plugin-icon-service';
|
|
@@ -250,7 +249,6 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
250
249
|
|
|
251
250
|
bind(MenusContributionPointHandler).toSelf().inSingletonScope();
|
|
252
251
|
bind(PluginMenuCommandAdapter).toSelf().inSingletonScope();
|
|
253
|
-
bind(CodeEditorWidgetUtil).toSelf().inSingletonScope();
|
|
254
252
|
bind(KeybindingsContributionPointHandler).toSelf().inSingletonScope();
|
|
255
253
|
bind(PluginContributionHandler).toSelf().inSingletonScope();
|
|
256
254
|
|
|
@@ -266,7 +264,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
266
264
|
bind(CommentsService).to(PluginCommentService).inSingletonScope();
|
|
267
265
|
bind(CommentingRangeDecorator).toSelf().inSingletonScope();
|
|
268
266
|
bind(CommentsContribution).toSelf().inSingletonScope();
|
|
269
|
-
bind(
|
|
267
|
+
bind(CommentsContext).toSelf().inSingletonScope();
|
|
270
268
|
|
|
271
269
|
bind(WebviewFrontendSecurityWarnings).toSelf().inSingletonScope();
|
|
272
270
|
bind(FrontendApplicationContribution).toService(WebviewFrontendSecurityWarnings);
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
margin-left: 5px;
|
|
9
9
|
cursor: pointer;
|
|
10
10
|
}
|
|
11
|
+
|
|
11
12
|
.comment-range-glyph:before {
|
|
12
13
|
position: absolute;
|
|
13
14
|
content: '';
|
|
@@ -36,6 +37,7 @@
|
|
|
36
37
|
border-left: 3px solid var(--theia-editorGutter-commentRangeForeground);
|
|
37
38
|
transition: opacity 0.5s;
|
|
38
39
|
}
|
|
40
|
+
|
|
39
41
|
.monaco-editor .comment-diff-added:before {
|
|
40
42
|
background: var(--theia-editorGutter-commentRangeForeground);
|
|
41
43
|
}
|
|
@@ -123,6 +125,7 @@
|
|
|
123
125
|
}
|
|
124
126
|
|
|
125
127
|
.monaco-editor .review-widget .body .review-comment .avatar-container {
|
|
128
|
+
margin-right: 8px !important;
|
|
126
129
|
margin-top: 4px !important;
|
|
127
130
|
}
|
|
128
131
|
|
|
@@ -138,7 +141,6 @@
|
|
|
138
141
|
}
|
|
139
142
|
|
|
140
143
|
.monaco-editor .review-widget .body .review-comment .review-comment-contents {
|
|
141
|
-
padding-left: 20px;
|
|
142
144
|
user-select: text;
|
|
143
145
|
-webkit-user-select: text;
|
|
144
146
|
width: 100%;
|
|
@@ -255,6 +257,12 @@
|
|
|
255
257
|
max-width: 100%;
|
|
256
258
|
}
|
|
257
259
|
|
|
260
|
+
.monaco-editor .review-widget .body .comment-form {
|
|
261
|
+
flex: 1;
|
|
262
|
+
margin: 0px;
|
|
263
|
+
/* Reset margin as it's handled by container */
|
|
264
|
+
}
|
|
265
|
+
|
|
258
266
|
.monaco-editor .review-widget .body .comment-form .form-actions {
|
|
259
267
|
display: none;
|
|
260
268
|
}
|
|
@@ -130,9 +130,12 @@ export class TerminalServiceMainImpl implements TerminalServiceMain, TerminalLin
|
|
|
130
130
|
}));
|
|
131
131
|
this.toDispose.push(terminal.onData(data => {
|
|
132
132
|
this.extProxy.$terminalOnInput(terminal.id, data);
|
|
133
|
-
this.extProxy.$
|
|
133
|
+
this.extProxy.$terminalOnInteraction(terminal.id);
|
|
134
134
|
}));
|
|
135
135
|
|
|
136
|
+
this.toDispose.push(terminal.onShellTypeChanged(shellType => {
|
|
137
|
+
this.extProxy.$terminalShellTypeChanged(terminal.id, shellType);
|
|
138
|
+
}));
|
|
136
139
|
this.observers.forEach((observer, id) => this.observeTerminal(id, terminal, observer));
|
|
137
140
|
}
|
|
138
141
|
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
|
|
15
15
|
// *****************************************************************************
|
|
16
16
|
import { Event, Emitter } from '@theia/core';
|
|
17
|
-
import { MonacoEditorModel
|
|
17
|
+
import { MonacoEditorModel } from '@theia/monaco/lib/browser/monaco-editor-model';
|
|
18
18
|
import { injectable, inject } from '@theia/core/shared/inversify';
|
|
19
19
|
import { MonacoTextModelService } from '@theia/monaco/lib/browser/monaco-text-model-service';
|
|
20
20
|
import { MonacoWorkspace } from '@theia/monaco/lib/browser/monaco-workspace';
|
|
@@ -30,13 +30,11 @@ export class EditorModelService {
|
|
|
30
30
|
private onModelRemovedEmitter = new Emitter<MonacoEditorModel>();
|
|
31
31
|
private modelDirtyEmitter = new Emitter<MonacoEditorModel>();
|
|
32
32
|
private modelSavedEmitter = new Emitter<MonacoEditorModel>();
|
|
33
|
-
private onModelWillSavedEmitter = new Emitter<WillSaveMonacoModelEvent>();
|
|
34
33
|
|
|
35
34
|
readonly onModelDirtyChanged = this.modelDirtyEmitter.event;
|
|
36
35
|
readonly onModelSaved = this.modelSavedEmitter.event;
|
|
37
36
|
readonly onModelModeChanged = this.modelModeChangedEmitter.event;
|
|
38
37
|
readonly onModelRemoved = this.onModelRemovedEmitter.event;
|
|
39
|
-
readonly onModelWillSave = this.onModelWillSavedEmitter.event;
|
|
40
38
|
|
|
41
39
|
constructor(@inject(MonacoTextModelService) monacoModelService: MonacoTextModelService,
|
|
42
40
|
@inject(MonacoWorkspace) monacoWorkspace: MonacoWorkspace) {
|
|
@@ -63,9 +61,6 @@ export class EditorModelService {
|
|
|
63
61
|
model.onDirtyChanged(_ => {
|
|
64
62
|
this.modelDirtyEmitter.fire(model);
|
|
65
63
|
});
|
|
66
|
-
model.onWillSaveModel(willSaveModelEvent => {
|
|
67
|
-
this.onModelWillSavedEmitter.fire(willSaveModelEvent);
|
|
68
|
-
});
|
|
69
64
|
}
|
|
70
65
|
|
|
71
66
|
get onModelAdded(): Event<MonacoEditorModel> {
|