1
>
/*---------------------------------------------------------------------------------------------
editor.ts
2
>
* Copyright (c) Microsoft Corporation. All rights reserved.
3
>
* Licensed under the MIT License. See License.txt in the project root for license information.
4
>
*--------------------------------------------------------------------------------------------*/
5
>
6
>
import { localize } from '../../nls.js';
7
>
import { Event } from '../../base/common/event.js';
8
>
import { DeepRequiredNonNullable, assertReturnsDefined } from '../../base/common/types.js';
9
>
import { URI } from '../../base/common/uri.js';
10
>
import { Disposable, IDisposable, toDisposable } from '../../base/common/lifecycle.js';
11
>
import { ICodeEditorViewState, IDiffEditor, IDiffEditorViewState, IEditor, IEditorViewState } from '../../editor/common/editorCommon.js';
12
>
import { IEditorOptions, IResourceEditorInput, ITextResourceEditorInput, IBaseTextResourceEditorInput, IBaseUntypedEditorInput, ITextEditorOptions } from '../../platform/editor/common/editor.js';
13
>
import type { EditorInput } from './editor/editorInput.js';
14
>
import { IInstantiationService, IConstructorSignature, ServicesAccessor, BrandedService } from '../../platform/instantiation/common/instantiation.js';
15
>
import { IContextKeyService } from '../../platform/contextkey/common/contextkey.js';
16
>
import { Registry } from '../../platform/registry/common/platform.js';
17
>
import { IEncodingSupport, ILanguageSupport } from '../services/textfile/common/textfiles.js';
18
>
import { IEditorGroup } from '../services/editor/common/editorGroupsService.js';
19
>
import { ICompositeControl, IComposite } from './composite.js';
20
>
import { FileType, IFileReadLimits, IFileService } from '../../platform/files/common/files.js';
21
>
import { IPathData } from '../../platform/window/common/window.js';
22
>
import { IExtUri } from '../../base/common/resources.js';
23
>
import { Schemas } from '../../base/common/network.js';
24
>
import { IEditorService } from '../services/editor/common/editorService.js';
25
>
import { ILogService } from '../../platform/log/common/log.js';
26
>
import { IErrorWithActions, createErrorWithActions, isErrorWithActions } from '../../base/common/errorMessage.js';
27
>
import { IAction, toAction } from '../../base/common/actions.js';
28
>
import Severity from '../../base/common/severity.js';
29
>
import { IPreferencesService } from '../services/preferences/common/preferences.js';
30
>
import { IReadonlyEditorGroupModel } from './editor/editorGroupModel.js';
31
>
32
>
// Static values for editor contributions
33
>
export const EditorExtensions = {
34
>
EditorPane: 'workbench.contributions.editors',
35
>
EditorFactory: 'workbench.contributions.editor.inputFactories'
36
>
};
37
>
38
>
// Static information regarding the text editor
39
>
export const DEFAULT_EDITOR_ASSOCIATION = {
40
>
id: 'default',
41
>
displayName: localize('promptOpenWith.defaultEditor.displayName', "Text Editor"),
42
>
providerDisplayName: localize('builtinProviderDisplayName', "Built-in")
43
>
};
44
>
45
>
/**
46
>
* Side by side editor id.
47
>
*/
48
>
export const SIDE_BY_SIDE_EDITOR_ID = 'workbench.editor.sidebysideEditor';
49
>
50
>
/**
51
>
* Text diff editor id.
52
>
*/
53
>
export const TEXT_DIFF_EDITOR_ID = 'workbench.editors.textDiffEditor';
54
>
55
>
/**
56
>
* Binary diff editor id.
57
>
*/
58
>
export const BINARY_DIFF_EDITOR_ID = 'workbench.editors.binaryResourceDiffEditor';
59
>
60
>
export interface IEditorDescriptor<T extends IEditorPane> {
61
>
62
>
/**
63
>
* The unique type identifier of the editor. All instances
64
>
* of the same `IEditorPane` should have the same type
65
>
* identifier.
66
>
*/
67
>
readonly typeId: string;
68
>
69
>
/**
70
>
* The display name of the editor.
71
>
*/
72
>
readonly name: string;
73
>
74
>
/**
75
>
* Instantiates the editor pane using the provided services.
76
>
*/
77
>
instantiate(instantiationService: IInstantiationService, group: IEditorGroup): T;
78
>
79
>
/**
80
>
* Whether the descriptor is for the provided editor pane.
81
>
*/
82
>
describes(editorPane: T): boolean;
83
>
}
84
>
85
>
/**
86
>
* Declares that an editor hosts the full-width group header (rendered by the
87
>
* editor group below the tab bar, using the group's configured header menus).
88
>
*/
89
>
export interface IEditorHeaderActions {
90
>
/** Editor-scoped instantiation service so the header toolbars' `when` clauses see the editor's context. */
91
>
readonly instantiationService: IInstantiationService;
92
>
}
93
>
94
>
/**
95
>
* The editor pane is the container for workbench editors.
96
>
*/
97
>
export interface IEditorPane extends IComposite {
98
>
99
>
/**
100
>
* An event to notify when the `IEditorControl` in this
101
>
* editor pane changes.
102
>
*
103
>
* This can be used for editor panes that are a compound
104
>
* of multiple editor controls to signal that the active
105
>
* editor control has changed when the user clicks around.
106
>
*/
107
>
readonly onDidChangeControl: Event<void>;
108
>
109
>
/**
110
>
* An optional event to notify when the selection inside the editor
111
>
* pane changed in case the editor has a selection concept.
112
>
*
113
>
* For example, in a text editor pane, the selection changes whenever
114
>
* the cursor is set to a new location.
115
>
*/
116
>
readonly onDidChangeSelection?: Event<IEditorPaneSelectionChangeEvent>;
117
>
118
>
/**
119
>
* An optional event to notify when the editor inside the pane scrolled
120
>
*/
121
>
readonly onDidChangeScroll?: Event<void>;
122
>
123
>
/**
124
>
* The assigned input of this editor.
125
>
*/
126
>
readonly input: EditorInput | undefined;
127
>
128
>
/**
129
>
* The assigned options of the editor.
130
>
*/
131
>
readonly options: IEditorOptions | undefined;
132
>
133
>
/**
134
>
* The assigned group this editor is showing in.
135
>
*/
136
>
readonly group: IEditorGroup;
137
>
138
>
/**
139
>
* The minimum width of this editor.
140
>
*/
141
>
readonly minimumWidth: number;
142
>
143
>
/**
144
>
* The maximum width of this editor.
145
>
*/
146
>
readonly maximumWidth: number;
147
>
148
>
/**
149
>
* The minimum height of this editor.
150
>
*/
151
>
readonly minimumHeight: number;
152
>
153
>
/**
154
>
* The maximum height of this editor.
155
>
*/
156
>
readonly maximumHeight: number;
157
>
158
>
/**
159
>
* An event to notify whenever minimum/maximum width/height changes.
160
>
*/
161
>
readonly onDidChangeSizeConstraints: Event<{ width: number; height: number } | undefined>;
162
>
163
>
/**
164
>
* The context key service for this editor. Should be overridden by
165
>
* editors that have their own ScopedContextKeyService
166
>
*/
167
>
readonly scopedContextKeyService: IContextKeyService | undefined;
168
>
169
>
/**
170
>
* Returns the underlying control of this editor. Callers need to cast
171
>
* the control to a specific instance as needed, e.g. by using the
172
>
* `isCodeEditor` helper method to access the text code editor.
173
>
*
174
>
* Use the `onDidChangeControl` event to track whenever the control
175
>
* changes.
176
>
*/
177
>
getControl(): IEditorControl | undefined;
178
>
179
>
/**
180
>
* Returns the current view state of the editor if any.
181
>
*
182
>
* This method is optional to override for the editor pane
183
>
* and should only be overridden when the pane can deal with
184
>
* `IEditorOptions.viewState` to be applied when opening.
185
>
*/
186
>
getViewState(): object | undefined;
187
>
188
>
/**
189
>
* An optional method to declare that this editor hosts the full-width group
190
>
* header (rendered by the editor group below the tab bar using the group's
191
>
* configured header menus), providing the editor-scoped instantiation service
192
>
* so the header actions' `when` clauses evaluate in the editor's context.
193
>
* Return `undefined` for no header (the default).
194
>
*/
195
>
getHeaderActions?(): IEditorHeaderActions | undefined;
196
>
197
>
/**
198
>
* An optional method to return the current selection in
199
>
* the editor pane in case the editor pane has a selection
200
>
* concept.
201
>
*
202
>
* Clients of this method will typically react to the
203
>
* `onDidChangeSelection` event to receive the current
204
>
* selection as needed.
205
>
*/
206
>
getSelection?(): IEditorPaneSelection | undefined;
207
>
208
>
/**
209
>
* An optional method to return the current scroll position
210
>
* of an editor inside the pane.
211
>
*
212
>
* Clients of this method will typically react to the
213
>
* `onDidChangeScroll` event to receive the current
214
>
* scroll position as needed.
215
>
*/
216
>
getScrollPosition?(): IEditorPaneScrollPosition;
217
>
218
>
/**
219
>
* An optional method to set the current scroll position
220
>
* of an editor inside the pane.
221
>
*/
222
>
setScrollPosition?(scrollPosition: IEditorPaneScrollPosition): void;
223
>
224
>
/**
225
>
* Finds out if this editor is visible or not.
226
>
*/
227
>
isVisible(): boolean;
228
>
}
229
>
230
>
export interface IEditorPaneSelectionChangeEvent {
231
>
232
>
/**
233
>
* More details for how the selection was made.
234
>
*/
235
>
reason: EditorPaneSelectionChangeReason;
236
>
}
237
>
238
>
export const enum EditorPaneSelectionChangeReason {
239
>
240
>
/**
241
>
* The selection was changed as a result of a programmatic
242
>
* method invocation.
243
>
*
244
>
* For a text editor pane, this for example can be a selection
245
>
* being restored from previous view state automatically.
246
>
*/
247
>
PROGRAMMATIC = 1,
248
>
249
>
/**
250
>
* The selection was changed by the user.
251
>
*
252
>
* This typically means the user changed the selection
253
>
* with mouse or keyboard.
254
>
*/
255
>
USER,
256
>
257
>
/**
258
>
* The selection was changed as a result of editing in
259
>
* the editor pane.
260
>
*
261
>
* For a text editor pane, this for example can be typing
262
>
* in the text of the editor pane.
263
>
*/
264
>
EDIT,
265
>
266
>
/**
267
>
* The selection was changed as a result of a navigation
268
>
* action.
269
>
*
270
>
* For a text editor pane, this for example can be a result
271
>
* of selecting an entry from a text outline view.
272
>
*/
273
>
NAVIGATION,
274
>
275
>
/**
276
>
* The selection was changed as a result of a jump action
277
>
* from within the editor pane.
278
>
*
279
>
* For a text editor pane, this for example can be a result
280
>
* of invoking "Go to definition" from a symbol.
281
>
*/
282
>
JUMP
283
>
}
284
>
285
>
export interface IEditorPaneSelection {
286
>
287
>
/**
288
>
* Asks to compare this selection to another selection.
289
>
*/
290
>
compare(otherSelection: IEditorPaneSelection): EditorPaneSelectionCompareResult;
291
>
292
>
/**
293
>
* Asks to massage the provided `options` in a way
294
>
* that the selection can be restored when the editor
295
>
* is opened again.
296
>
*
297
>
* For a text editor this means to apply the selected
298
>
* line and column as text editor options.
299
>
*/
300
>
restore(options: IEditorOptions): IEditorOptions;
301
>
302
>
/**
303
>
* Only used for logging to print more info about the selection.
304
>
*/
305
>
log?(): string;
306
>
}
307
>
308
>
export const enum EditorPaneSelectionCompareResult {
309
>
310
>
/**
311
>
* The selections are identical.
312
>
*/
313
>
IDENTICAL = 1,
314
>
315
>
/**
316
>
* The selections are similar.
317
>
*
318
>
* For a text editor this can mean that the one
319
>
* selection is in close proximity to the other
320
>
* selection.
321
>
*
322
>
* Upstream clients may decide in this case to
323
>
* not treat the selection different from the
324
>
* previous one because it is not distinct enough.
325
>
*/
326
>
SIMILAR = 2,
327
>
328
>
/**
329
>
* The selections are entirely different.
330
>
*/
331
>
DIFFERENT = 3
332
>
}
333
>
334
>
export interface IEditorPaneWithSelection extends IEditorPane {
335
>
336
>
readonly onDidChangeSelection: Event<IEditorPaneSelectionChangeEvent>;
337
>
338
>
getSelection(): IEditorPaneSelection | undefined;
339
>
}
340
>
341
>
export function isEditorPaneWithSelection(editorPane: IEditorPane | undefined): editorPane is IEditorPaneWithSelection {
342
const candidate = editorPane as IEditorPaneWithSelection | undefined;
343
344
return !!candidate && typeof candidate.getSelection === 'function' && !!candidate.onDidChangeSelection;
345
}
347
>
export interface IEditorPaneWithScrolling extends IEditorPane {
348
>
349
>
readonly onDidChangeScroll: Event<void>;
350
>
351
>
getScrollPosition(): IEditorPaneScrollPosition;
352
>
353
>
setScrollPosition(position: IEditorPaneScrollPosition): void;
354
>
}
355
>
356
>
export function isEditorPaneWithScrolling(editorPane: IEditorPane | undefined): editorPane is IEditorPaneWithScrolling {
357
const candidate = editorPane as IEditorPaneWithScrolling | undefined;
358
359
return !!candidate && typeof candidate.getScrollPosition === 'function' && typeof candidate.setScrollPosition === 'function' && !!candidate.onDidChangeScroll;
360
}
362
>
/**
363
>
* Scroll position of a pane
364
>
*/
365
>
export interface IEditorPaneScrollPosition {
366
>
readonly scrollTop: number;
367
>
readonly scrollLeft?: number;
368
>
}
369
>
370
>
/**
371
>
* Try to retrieve the view state for the editor pane that
372
>
* has the provided editor input opened, if at all.
373
>
*
374
>
* This method will return `undefined` if the editor input
375
>
* is not visible in any of the opened editor panes.
376
>
*/
377
>
export function findViewStateForEditor(input: EditorInput, group: GroupIdentifier, editorService: IEditorService): object | undefined {
378
for (const editorPane of editorService.visibleEditorPanes) {
379
if (editorPane.group.id === group && input.matches(editorPane.input)) {