@theia/monaco 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/browser/monaco-code-action-save-participant.d.ts +14 -0
- package/lib/browser/monaco-code-action-save-participant.d.ts.map +1 -0
- package/lib/browser/monaco-code-action-save-participant.js +129 -0
- package/lib/browser/monaco-code-action-save-participant.js.map +1 -0
- package/lib/browser/monaco-editor-model.d.ts +8 -13
- package/lib/browser/monaco-editor-model.d.ts.map +1 -1
- package/lib/browser/monaco-editor-model.js +21 -57
- package/lib/browser/monaco-editor-model.js.map +1 -1
- package/lib/browser/monaco-editor-provider.d.ts +18 -7
- package/lib/browser/monaco-editor-provider.d.ts.map +1 -1
- package/lib/browser/monaco-editor-provider.js +98 -51
- package/lib/browser/monaco-editor-provider.js.map +1 -1
- package/lib/browser/monaco-editor-service.d.ts +10 -2
- package/lib/browser/monaco-editor-service.d.ts.map +1 -1
- package/lib/browser/monaco-editor-service.js +21 -2
- package/lib/browser/monaco-editor-service.js.map +1 -1
- package/lib/browser/monaco-frontend-module.d.ts.map +1 -1
- package/lib/browser/monaco-frontend-module.js +5 -0
- package/lib/browser/monaco-frontend-module.js.map +1 -1
- package/lib/browser/monaco-menu.d.ts.map +1 -1
- package/lib/browser/monaco-menu.js +5 -4
- package/lib/browser/monaco-menu.js.map +1 -1
- package/lib/browser/monaco-workspace.d.ts +1 -4
- package/lib/browser/monaco-workspace.d.ts.map +1 -1
- package/lib/browser/monaco-workspace.js +0 -6
- package/lib/browser/monaco-workspace.js.map +1 -1
- package/package.json +9 -9
- package/src/browser/monaco-code-action-save-participant.ts +143 -0
- package/src/browser/monaco-editor-model.ts +25 -74
- package/src/browser/monaco-editor-provider.ts +115 -55
- package/src/browser/monaco-editor-service.ts +24 -3
- package/src/browser/monaco-frontend-module.ts +8 -2
- package/src/browser/monaco-menu.ts +5 -4
- package/src/browser/monaco-workspace.ts +1 -9
|
@@ -18,26 +18,23 @@
|
|
|
18
18
|
import URI from '@theia/core/lib/common/uri';
|
|
19
19
|
import { EditorPreferenceChange, EditorPreferences, TextEditor, DiffNavigator } from '@theia/editor/lib/browser';
|
|
20
20
|
import { DiffUris } from '@theia/core/lib/browser/diff-uris';
|
|
21
|
-
import { inject, injectable, named } from '@theia/core/shared/inversify';
|
|
22
|
-
import { DisposableCollection, deepClone, Disposable } from '@theia/core/lib/common';
|
|
23
|
-
import { TextDocumentSaveReason } from '@theia/core/shared/vscode-languageserver-protocol';
|
|
21
|
+
import { inject, injectable, named, postConstruct } from '@theia/core/shared/inversify';
|
|
22
|
+
import { DisposableCollection, deepClone, Disposable, CancellationToken } from '@theia/core/lib/common';
|
|
24
23
|
import { MonacoDiffEditor } from './monaco-diff-editor';
|
|
25
24
|
import { MonacoDiffNavigatorFactory } from './monaco-diff-navigator-factory';
|
|
26
25
|
import { EditorServiceOverrides, MonacoEditor, MonacoEditorServices } from './monaco-editor';
|
|
27
|
-
import { MonacoEditorModel,
|
|
26
|
+
import { MonacoEditorModel, TextDocumentSaveReason } from './monaco-editor-model';
|
|
28
27
|
import { MonacoWorkspace } from './monaco-workspace';
|
|
29
28
|
import { ContributionProvider } from '@theia/core';
|
|
30
|
-
import { KeybindingRegistry, OpenerService, open, WidgetOpenerOptions, FormatType } from '@theia/core/lib/browser';
|
|
29
|
+
import { KeybindingRegistry, OpenerService, open, WidgetOpenerOptions, SaveOptions, FormatType } from '@theia/core/lib/browser';
|
|
31
30
|
import { MonacoResolvedKeybinding } from './monaco-resolved-keybinding';
|
|
32
31
|
import { HttpOpenHandlerOptions } from '@theia/core/lib/browser/http-open-handler';
|
|
33
32
|
import { MonacoToProtocolConverter } from './monaco-to-protocol-converter';
|
|
34
33
|
import { ProtocolToMonacoConverter } from './protocol-to-monaco-converter';
|
|
35
|
-
import { FileSystemPreferences } from '@theia/filesystem/lib/browser';
|
|
36
34
|
import * as monaco from '@theia/monaco-editor-core';
|
|
37
35
|
import { StandaloneServices } from '@theia/monaco-editor-core/esm/vs/editor/standalone/browser/standaloneServices';
|
|
38
36
|
import { IOpenerService, OpenExternalOptions, OpenInternalOptions } from '@theia/monaco-editor-core/esm/vs/platform/opener/common/opener';
|
|
39
37
|
import { IKeybindingService } from '@theia/monaco-editor-core/esm/vs/platform/keybinding/common/keybinding';
|
|
40
|
-
import { timeoutReject } from '@theia/core/lib/common/promise-util';
|
|
41
38
|
import { IContextMenuService } from '@theia/monaco-editor-core/esm/vs/platform/contextview/browser/contextView';
|
|
42
39
|
import { KeyCodeChord } from '@theia/monaco-editor-core/esm/vs/base/common/keybindings';
|
|
43
40
|
import { IContextKeyService } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
|
|
@@ -46,6 +43,8 @@ import { IReference } from '@theia/monaco-editor-core/esm/vs/base/common/lifecyc
|
|
|
46
43
|
import { MarkdownString } from '@theia/core/lib/common/markdown-rendering';
|
|
47
44
|
import { SimpleMonacoEditor } from './simple-monaco-editor';
|
|
48
45
|
import { ICodeEditorWidgetOptions } from '@theia/monaco-editor-core/esm/vs/editor/browser/widget/codeEditor/codeEditorWidget';
|
|
46
|
+
import { timeoutReject } from '@theia/core/lib/common/promise-util';
|
|
47
|
+
import { FileSystemPreferences } from '@theia/filesystem/lib/browser';
|
|
49
48
|
|
|
50
49
|
export const MonacoEditorFactory = Symbol('MonacoEditorFactory');
|
|
51
50
|
export interface MonacoEditorFactory {
|
|
@@ -53,6 +52,17 @@ export interface MonacoEditorFactory {
|
|
|
53
52
|
create(model: MonacoEditorModel, defaultOptions: MonacoEditor.IOptions, defaultOverrides: EditorServiceOverrides): Promise<MonacoEditor>;
|
|
54
53
|
}
|
|
55
54
|
|
|
55
|
+
export const SaveParticipant = Symbol('SaveParticipant');
|
|
56
|
+
|
|
57
|
+
export interface SaveParticipant {
|
|
58
|
+
readonly order: number;
|
|
59
|
+
applyChangesOnSave(
|
|
60
|
+
editor: MonacoEditor,
|
|
61
|
+
cancellationToken: CancellationToken,
|
|
62
|
+
options?: SaveOptions): Promise<void>;
|
|
63
|
+
}
|
|
64
|
+
export const SAVE_PARTICIPANT_DEFAULT_ORDER = 0;
|
|
65
|
+
|
|
56
66
|
@injectable()
|
|
57
67
|
export class MonacoEditorProvider {
|
|
58
68
|
|
|
@@ -68,9 +78,13 @@ export class MonacoEditorProvider {
|
|
|
68
78
|
|
|
69
79
|
@inject(OpenerService)
|
|
70
80
|
protected readonly openerService: OpenerService;
|
|
81
|
+
@inject(ContributionProvider)
|
|
82
|
+
@named(SaveParticipant)
|
|
83
|
+
protected readonly saveProviderContributions: ContributionProvider<SaveParticipant>;
|
|
71
84
|
|
|
72
85
|
@inject(FileSystemPreferences)
|
|
73
86
|
protected readonly filePreferences: FileSystemPreferences;
|
|
87
|
+
protected saveParticipants: SaveParticipant[];
|
|
74
88
|
|
|
75
89
|
protected _current: MonacoEditor | undefined;
|
|
76
90
|
/**
|
|
@@ -210,7 +224,7 @@ export class MonacoEditorProvider {
|
|
|
210
224
|
}));
|
|
211
225
|
toDispose.push(editor.onLanguageChanged(() => this.updateMonacoEditorOptions(editor)));
|
|
212
226
|
toDispose.push(editor.onDidChangeReadOnly(() => this.updateReadOnlyMessage(options, model.readOnly)));
|
|
213
|
-
editor.document.
|
|
227
|
+
toDispose.push(editor.document.registerWillSaveModelListener((_, token, o) => this.runSaveParticipants(editor, token, o)));
|
|
214
228
|
return editor;
|
|
215
229
|
}
|
|
216
230
|
|
|
@@ -239,46 +253,6 @@ export class MonacoEditorProvider {
|
|
|
239
253
|
}
|
|
240
254
|
}
|
|
241
255
|
|
|
242
|
-
protected shouldFormat(editor: MonacoEditor, event: WillSaveMonacoModelEvent): boolean {
|
|
243
|
-
if (event.reason !== TextDocumentSaveReason.Manual) {
|
|
244
|
-
return false;
|
|
245
|
-
}
|
|
246
|
-
if (event.options?.formatType) {
|
|
247
|
-
switch (event.options.formatType) {
|
|
248
|
-
case FormatType.ON: return true;
|
|
249
|
-
case FormatType.OFF: return false;
|
|
250
|
-
case FormatType.DIRTY: return editor.document.dirty;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
protected async formatOnSave(editor: MonacoEditor, event: WillSaveMonacoModelEvent): Promise<monaco.editor.IIdentifiedSingleEditOperation[]> {
|
|
257
|
-
if (!this.shouldFormat(editor, event)) {
|
|
258
|
-
return [];
|
|
259
|
-
}
|
|
260
|
-
const edits: monaco.editor.IIdentifiedSingleEditOperation[] = [];
|
|
261
|
-
const overrideIdentifier = editor.document.languageId;
|
|
262
|
-
const uri = editor.uri.toString();
|
|
263
|
-
const formatOnSave = this.editorPreferences.get({ preferenceName: 'editor.formatOnSave', overrideIdentifier }, undefined, uri);
|
|
264
|
-
if (formatOnSave) {
|
|
265
|
-
const formatOnSaveTimeout = this.editorPreferences.get({ preferenceName: 'editor.formatOnSaveTimeout', overrideIdentifier }, undefined, uri)!;
|
|
266
|
-
await Promise.race([
|
|
267
|
-
timeoutReject(formatOnSaveTimeout, `Aborted format on save after ${formatOnSaveTimeout}ms`),
|
|
268
|
-
editor.runAction('editor.action.formatDocument')
|
|
269
|
-
]);
|
|
270
|
-
}
|
|
271
|
-
const shouldRemoveWhiteSpace = this.filePreferences.get({ preferenceName: 'files.trimTrailingWhitespace', overrideIdentifier }, undefined, uri);
|
|
272
|
-
if (shouldRemoveWhiteSpace) {
|
|
273
|
-
await editor.runAction('editor.action.trimTrailingWhitespace');
|
|
274
|
-
}
|
|
275
|
-
const insertFinalNewline = this.filePreferences.get({ preferenceName: 'files.insertFinalNewline', overrideIdentifier }, undefined, uri);
|
|
276
|
-
if (insertFinalNewline) {
|
|
277
|
-
edits.push(...this.insertFinalNewline(editor));
|
|
278
|
-
}
|
|
279
|
-
return edits;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
256
|
protected get diffPreferencePrefixes(): string[] {
|
|
283
257
|
return [...this.preferencePrefixes, 'diffEditor.'];
|
|
284
258
|
}
|
|
@@ -497,20 +471,106 @@ export class MonacoEditorProvider {
|
|
|
497
471
|
);
|
|
498
472
|
}
|
|
499
473
|
|
|
500
|
-
|
|
501
|
-
|
|
474
|
+
@postConstruct()
|
|
475
|
+
init(): void {
|
|
476
|
+
this.saveParticipants = this.saveProviderContributions.getContributions().slice().sort((left, right) => left.order - right.order);
|
|
477
|
+
this.registerSaveParticipant({
|
|
478
|
+
order: 1000,
|
|
479
|
+
applyChangesOnSave: (
|
|
480
|
+
editor: MonacoEditor,
|
|
481
|
+
cancellationToken: monaco.CancellationToken,
|
|
482
|
+
options: SaveOptions): Promise<void> => this.formatOnSave(editor, editor.document, cancellationToken, options)
|
|
483
|
+
});
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
registerSaveParticipant(saveParticipant: SaveParticipant): Disposable {
|
|
487
|
+
if (this.saveParticipants.find(value => value === saveParticipant)) {
|
|
488
|
+
throw new Error('Save participant already registered');
|
|
489
|
+
}
|
|
490
|
+
this.saveParticipants.push(saveParticipant);
|
|
491
|
+
this.saveParticipants.sort((left, right) => left.order - right.order);
|
|
492
|
+
return Disposable.create(() => {
|
|
493
|
+
const index = this.saveParticipants.indexOf(saveParticipant);
|
|
494
|
+
if (index >= 0) {
|
|
495
|
+
this.saveParticipants.splice(index, 1);
|
|
496
|
+
}
|
|
497
|
+
});
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
protected shouldFormat(model: MonacoEditorModel, options: SaveOptions): boolean {
|
|
501
|
+
if (options.saveReason !== TextDocumentSaveReason.Manual) {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
switch (options.formatType) {
|
|
505
|
+
case FormatType.ON: return true;
|
|
506
|
+
case FormatType.OFF: return false;
|
|
507
|
+
case FormatType.DIRTY: return model.dirty;
|
|
508
|
+
}
|
|
509
|
+
return true;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
async runSaveParticipants(editor: MonacoEditor, cancellationToken: CancellationToken, options?: SaveOptions): Promise<void> {
|
|
513
|
+
const initialState = editor.document.createSnapshot();
|
|
514
|
+
for (const participant of this.saveParticipants) {
|
|
515
|
+
if (cancellationToken.isCancellationRequested) {
|
|
516
|
+
break;
|
|
517
|
+
}
|
|
518
|
+
const snapshot = editor.document.createSnapshot();
|
|
519
|
+
try {
|
|
520
|
+
await participant.applyChangesOnSave(editor, cancellationToken, options);
|
|
521
|
+
} catch (e) {
|
|
522
|
+
console.error(e);
|
|
523
|
+
editor.document.applySnapshot(snapshot);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
if (cancellationToken.isCancellationRequested) {
|
|
527
|
+
editor.document.applySnapshot(initialState);
|
|
528
|
+
}
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
protected async formatOnSave(
|
|
532
|
+
editor: MonacoEditor,
|
|
533
|
+
model: MonacoEditorModel,
|
|
534
|
+
cancellationToken: CancellationToken,
|
|
535
|
+
options: SaveOptions): Promise<void> {
|
|
536
|
+
if (!this.shouldFormat(model, options)) {
|
|
537
|
+
return;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
const overrideIdentifier = model.languageId;
|
|
541
|
+
const uri = model.uri.toString();
|
|
542
|
+
const formatOnSave = this.editorPreferences.get({ preferenceName: 'editor.formatOnSave', overrideIdentifier }, undefined, uri);
|
|
543
|
+
if (formatOnSave) {
|
|
544
|
+
const formatOnSaveTimeout = this.editorPreferences.get({ preferenceName: 'editor.formatOnSaveTimeout', overrideIdentifier }, undefined, uri)!;
|
|
545
|
+
await Promise.race([
|
|
546
|
+
timeoutReject(formatOnSaveTimeout, `Aborted format on save after ${formatOnSaveTimeout}ms`),
|
|
547
|
+
await editor.runAction('editor.action.formatDocument')
|
|
548
|
+
]);
|
|
549
|
+
}
|
|
550
|
+
const shouldRemoveWhiteSpace = this.filePreferences.get({ preferenceName: 'files.trimTrailingWhitespace', overrideIdentifier }, undefined, uri);
|
|
551
|
+
if (shouldRemoveWhiteSpace) {
|
|
552
|
+
await editor.runAction('editor.action.trimTrailingWhitespace');
|
|
553
|
+
}
|
|
554
|
+
const insertFinalNewline = this.filePreferences.get({ preferenceName: 'files.insertFinalNewline', overrideIdentifier }, undefined, uri);
|
|
555
|
+
if (insertFinalNewline) {
|
|
556
|
+
this.insertFinalNewline(model);
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
protected insertFinalNewline(editorModel: MonacoEditorModel): void {
|
|
561
|
+
const model = editorModel.textEditorModel;
|
|
502
562
|
if (!model) {
|
|
503
|
-
return
|
|
563
|
+
return;
|
|
504
564
|
}
|
|
505
565
|
|
|
506
566
|
const lines = model?.getLineCount();
|
|
507
567
|
if (lines === 0) {
|
|
508
|
-
return
|
|
568
|
+
return;
|
|
509
569
|
}
|
|
510
570
|
|
|
511
571
|
const lastLine = model?.getLineContent(lines);
|
|
512
572
|
if (lastLine.trim() === '') {
|
|
513
|
-
return
|
|
573
|
+
return;
|
|
514
574
|
}
|
|
515
575
|
|
|
516
576
|
const lastLineMaxColumn = model?.getLineMaxColumn(lines);
|
|
@@ -520,9 +580,9 @@ export class MonacoEditorProvider {
|
|
|
520
580
|
endLineNumber: lines,
|
|
521
581
|
endColumn: lastLineMaxColumn
|
|
522
582
|
};
|
|
523
|
-
|
|
583
|
+
model.applyEdits([{
|
|
524
584
|
range,
|
|
525
585
|
text: model?.getEOL()
|
|
526
|
-
}];
|
|
586
|
+
}]);
|
|
527
587
|
}
|
|
528
588
|
}
|
|
@@ -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 { injectable, inject, decorate } from '@theia/core/shared/inversify';
|
|
17
|
+
import { injectable, inject, decorate, named } from '@theia/core/shared/inversify';
|
|
18
18
|
import URI from '@theia/core/lib/common/uri';
|
|
19
19
|
import { OpenerService, open, WidgetOpenMode, ApplicationShell, PreferenceService } from '@theia/core/lib/browser';
|
|
20
20
|
import { EditorWidget, EditorOpenerOptions, EditorManager, CustomEditorWidget } from '@theia/editor/lib/browser';
|
|
@@ -27,6 +27,7 @@ import { StandaloneCodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/st
|
|
|
27
27
|
import { ICodeEditor } from '@theia/monaco-editor-core/esm/vs/editor/browser/editorBrowser';
|
|
28
28
|
import { IContextKeyService } from '@theia/monaco-editor-core/esm/vs/platform/contextkey/common/contextkey';
|
|
29
29
|
import { IThemeService } from '@theia/monaco-editor-core/esm/vs/platform/theme/common/themeService';
|
|
30
|
+
import { ContributionProvider } from '@theia/core';
|
|
30
31
|
|
|
31
32
|
decorate(injectable(), StandaloneCodeEditorService);
|
|
32
33
|
|
|
@@ -36,6 +37,14 @@ export const VSCodeThemeService = Symbol('VSCodeThemeService');
|
|
|
36
37
|
export const MonacoEditorServiceFactory = Symbol('MonacoEditorServiceFactory');
|
|
37
38
|
export type MonacoEditorServiceFactoryType = (contextKeyService: IContextKeyService, themeService: IThemeService) => MonacoEditorService;
|
|
38
39
|
|
|
40
|
+
/**
|
|
41
|
+
* contribution provider to extend the active editor handling to other editor types than just standalone editor widgets.
|
|
42
|
+
*/
|
|
43
|
+
export const ActiveMonacoEditorContribution = Symbol('ActiveMonacoEditorContribution');
|
|
44
|
+
export interface ActiveMonacoEditorContribution {
|
|
45
|
+
getActiveEditor(): ICodeEditor | undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
39
48
|
@injectable()
|
|
40
49
|
export class MonacoEditorService extends StandaloneCodeEditorService {
|
|
41
50
|
|
|
@@ -56,6 +65,9 @@ export class MonacoEditorService extends StandaloneCodeEditorService {
|
|
|
56
65
|
@inject(PreferenceService)
|
|
57
66
|
protected readonly preferencesService: PreferenceService;
|
|
58
67
|
|
|
68
|
+
@inject(ContributionProvider) @named(ActiveMonacoEditorContribution)
|
|
69
|
+
protected readonly activeMonacoEditorContribution: ContributionProvider<ActiveMonacoEditorContribution>;
|
|
70
|
+
|
|
59
71
|
constructor(@inject(VSCodeContextKeyService) contextKeyService: IContextKeyService, @inject(VSCodeThemeService) themeService: IThemeService) {
|
|
60
72
|
super(contextKeyService, themeService);
|
|
61
73
|
}
|
|
@@ -63,7 +75,7 @@ export class MonacoEditorService extends StandaloneCodeEditorService {
|
|
|
63
75
|
/**
|
|
64
76
|
* Monaco active editor is either focused or last focused editor.
|
|
65
77
|
*/
|
|
66
|
-
override getActiveCodeEditor():
|
|
78
|
+
override getActiveCodeEditor(): ICodeEditor | null {
|
|
67
79
|
let editor = MonacoEditor.getCurrent(this.editors);
|
|
68
80
|
if (!editor && CustomEditorWidget.is(this.shell.activeWidget)) {
|
|
69
81
|
const model = this.shell.activeWidget.modelRef.object;
|
|
@@ -73,8 +85,17 @@ export class MonacoEditorService extends StandaloneCodeEditorService {
|
|
|
73
85
|
}
|
|
74
86
|
const candidate = editor?.getControl();
|
|
75
87
|
// Since we extend a private super class, we have to check that the thing that matches the public interface also matches the private expectations the superclass.
|
|
88
|
+
if (candidate instanceof StandaloneCodeEditor) {
|
|
89
|
+
return candidate;
|
|
90
|
+
}
|
|
91
|
+
for (const activeEditorProvider of this.activeMonacoEditorContribution.getContributions()) {
|
|
92
|
+
const activeEditor = activeEditorProvider.getActiveEditor();
|
|
93
|
+
if (activeEditor) {
|
|
94
|
+
return activeEditor;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
76
97
|
/* eslint-disable-next-line no-null/no-null */
|
|
77
|
-
return
|
|
98
|
+
return null;
|
|
78
99
|
}
|
|
79
100
|
|
|
80
101
|
override async openCodeEditor(input: IResourceEditorInput, source: ICodeEditor | null, sideBySide?: boolean): Promise<ICodeEditor | null> {
|
|
@@ -25,13 +25,13 @@ import {
|
|
|
25
25
|
WidgetStatusBarContribution
|
|
26
26
|
} from '@theia/core/lib/browser';
|
|
27
27
|
import { TextEditorProvider, DiffNavigatorProvider, TextEditor } from '@theia/editor/lib/browser';
|
|
28
|
-
import { MonacoEditorProvider, MonacoEditorFactory } from './monaco-editor-provider';
|
|
28
|
+
import { MonacoEditorProvider, MonacoEditorFactory, SaveParticipant } from './monaco-editor-provider';
|
|
29
29
|
import { MonacoEditorMenuContribution } from './monaco-menu';
|
|
30
30
|
import { MonacoEditorCommandHandlers } from './monaco-command';
|
|
31
31
|
import { MonacoKeybindingContribution } from './monaco-keybinding';
|
|
32
32
|
import { MonacoLanguages } from './monaco-languages';
|
|
33
33
|
import { MonacoWorkspace } from './monaco-workspace';
|
|
34
|
-
import { MonacoEditorService, MonacoEditorServiceFactory, VSCodeContextKeyService, VSCodeThemeService } from './monaco-editor-service';
|
|
34
|
+
import { ActiveMonacoEditorContribution, MonacoEditorService, MonacoEditorServiceFactory, VSCodeContextKeyService, VSCodeThemeService } from './monaco-editor-service';
|
|
35
35
|
import { MonacoTextModelService, MonacoEditorModelFactory, MonacoEditorModelFilter } from './monaco-text-model-service';
|
|
36
36
|
import { MonacoContextMenuService } from './monaco-context-menu';
|
|
37
37
|
import { MonacoOutlineContribution } from './monaco-outline-contribution';
|
|
@@ -79,6 +79,7 @@ import { ActiveMonacoUndoRedoHandler, FocusedMonacoUndoRedoHandler } from './mon
|
|
|
79
79
|
import { ILogService } from '@theia/monaco-editor-core/esm/vs/platform/log/common/log';
|
|
80
80
|
import { DefaultContentHoverWidgetPatcher } from './default-content-hover-widget-patcher';
|
|
81
81
|
import { MonacoWorkspaceContextService } from './monaco-workspace-context-service';
|
|
82
|
+
import { MonacoCodeActionSaveParticipant } from './monaco-code-action-save-participant';
|
|
82
83
|
|
|
83
84
|
export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
84
85
|
bind(MonacoThemingService).toSelf().inSingletonScope();
|
|
@@ -91,6 +92,9 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
91
92
|
bind(FrontendApplicationContribution).toService(MonacoFrontendApplicationContribution);
|
|
92
93
|
bind(StylingParticipant).toService(MonacoFrontendApplicationContribution);
|
|
93
94
|
|
|
95
|
+
bind(MonacoCodeActionSaveParticipant).toSelf().inSingletonScope();
|
|
96
|
+
bind(SaveParticipant).toService(MonacoCodeActionSaveParticipant);
|
|
97
|
+
|
|
94
98
|
bind(MonacoToProtocolConverter).toSelf().inSingletonScope();
|
|
95
99
|
bind(ProtocolToMonacoConverter).toSelf().inSingletonScope();
|
|
96
100
|
|
|
@@ -107,6 +111,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
107
111
|
bind(MonacoConfigurationService).toDynamicValue(({ container }) => createMonacoConfigurationService(container)).inSingletonScope();
|
|
108
112
|
|
|
109
113
|
bind(MonacoBulkEditService).toSelf().inSingletonScope();
|
|
114
|
+
bindContributionProvider(bind, ActiveMonacoEditorContribution);
|
|
110
115
|
bind(MonacoEditorServiceFactory).toFactory((context: interfaces.Context) => (contextKeyService: IContextKeyService, themeService: IThemeService) => {
|
|
111
116
|
const child = context.container.createChild();
|
|
112
117
|
child.bind(VSCodeContextKeyService).toConstantValue(contextKeyService);
|
|
@@ -121,6 +126,7 @@ export default new ContainerModule((bind, unbind, isBound, rebind) => {
|
|
|
121
126
|
bindContributionProvider(bind, MonacoEditorFactory);
|
|
122
127
|
bindContributionProvider(bind, MonacoEditorModelFactory);
|
|
123
128
|
bindContributionProvider(bind, MonacoEditorModelFilter);
|
|
129
|
+
bindContributionProvider(bind, SaveParticipant);
|
|
124
130
|
bind(MonacoCommandService).toSelf().inTransientScope();
|
|
125
131
|
|
|
126
132
|
bind(TextEditorProvider).toProvider(context =>
|
|
@@ -40,16 +40,17 @@ export class MonacoEditorMenuContribution implements MenuContribution {
|
|
|
40
40
|
) { }
|
|
41
41
|
|
|
42
42
|
registerMenus(registry: MenuModelRegistry): void {
|
|
43
|
+
registry.registerSubmenu(EDITOR_CONTEXT_MENU, 'Editor Context Menu');
|
|
43
44
|
for (const item of MenuRegistry.getMenuItems(MenuId.EditorContext)) {
|
|
44
45
|
if (!isIMenuItem(item)) {
|
|
45
46
|
continue;
|
|
46
47
|
}
|
|
47
48
|
const commandId = this.commands.validate(item.command.id);
|
|
48
49
|
if (commandId) {
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
if (
|
|
52
|
-
// Don't add additional actions if the item is already registered
|
|
50
|
+
const nodeId = MonacoCommands.COMMON_ACTIONS.get(commandId) || commandId;
|
|
51
|
+
const menuPath = item.group ? [...EDITOR_CONTEXT_MENU, item.group] : EDITOR_CONTEXT_MENU;
|
|
52
|
+
if (registry.getMenuNode([...menuPath, nodeId])) {
|
|
53
|
+
// Don't add additional actions if the item is already registered.
|
|
53
54
|
registry.registerMenuAction(menuPath, this.buildMenuAction(commandId, item));
|
|
54
55
|
}
|
|
55
56
|
}
|
|
@@ -23,7 +23,7 @@ import { Emitter } from '@theia/core/lib/common/event';
|
|
|
23
23
|
import { FileSystemPreferences } from '@theia/filesystem/lib/browser';
|
|
24
24
|
import { EditorManager, EditorPreferences } from '@theia/editor/lib/browser';
|
|
25
25
|
import { MonacoTextModelService } from './monaco-text-model-service';
|
|
26
|
-
import {
|
|
26
|
+
import { MonacoEditorModel, MonacoModelContentChangedEvent } from './monaco-editor-model';
|
|
27
27
|
import { MonacoEditor } from './monaco-editor';
|
|
28
28
|
import { ProblemManager } from '@theia/markers/lib/browser';
|
|
29
29
|
import { ArrayUtils } from '@theia/core/lib/common/types';
|
|
@@ -101,9 +101,6 @@ export class MonacoWorkspace {
|
|
|
101
101
|
protected readonly onDidChangeTextDocumentEmitter = new Emitter<MonacoModelContentChangedEvent>();
|
|
102
102
|
readonly onDidChangeTextDocument = this.onDidChangeTextDocumentEmitter.event;
|
|
103
103
|
|
|
104
|
-
protected readonly onWillSaveTextDocumentEmitter = new Emitter<WillSaveMonacoModelEvent>();
|
|
105
|
-
readonly onWillSaveTextDocument = this.onWillSaveTextDocumentEmitter.event;
|
|
106
|
-
|
|
107
104
|
protected readonly onDidSaveTextDocumentEmitter = new Emitter<MonacoEditorModel>();
|
|
108
105
|
readonly onDidSaveTextDocument = this.onDidSaveTextDocumentEmitter.event;
|
|
109
106
|
|
|
@@ -160,7 +157,6 @@ export class MonacoWorkspace {
|
|
|
160
157
|
});
|
|
161
158
|
model.onDidChangeContent(event => this.fireDidChangeContent(event));
|
|
162
159
|
model.onDidSaveModel(() => this.fireDidSave(model));
|
|
163
|
-
model.onWillSaveModel(event => this.fireWillSave(event));
|
|
164
160
|
model.onDirtyChanged(() => this.openEditorIfDirty(model));
|
|
165
161
|
model.onDispose(() => this.fireDidClose(model));
|
|
166
162
|
}
|
|
@@ -177,10 +173,6 @@ export class MonacoWorkspace {
|
|
|
177
173
|
this.onDidChangeTextDocumentEmitter.fire(event);
|
|
178
174
|
}
|
|
179
175
|
|
|
180
|
-
protected fireWillSave(event: WillSaveMonacoModelEvent): void {
|
|
181
|
-
this.onWillSaveTextDocumentEmitter.fire(event);
|
|
182
|
-
}
|
|
183
|
-
|
|
184
176
|
protected fireDidSave(model: MonacoEditorModel): void {
|
|
185
177
|
this.onDidSaveTextDocumentEmitter.fire(model);
|
|
186
178
|
}
|