chrome-devtools-frontend 1.0.945884 → 1.0.946351
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/config/gni/all_devtools_files.gni +0 -5
- package/config/gni/devtools_grd_files.gni +0 -33
- package/front_end/core/host/UserMetrics.ts +0 -1
- package/front_end/core/i18n/locales/en-US.json +3 -12
- package/front_end/core/i18n/locales/en-XL.json +3 -12
- package/front_end/core/root/Runtime.ts +0 -1
- package/front_end/core/sdk/CSSProperty.ts +16 -9
- package/front_end/devtools_compatibility.js +0 -7
- package/front_end/entrypoints/devtools_app/devtools_app.js +3 -0
- package/front_end/entrypoints/devtools_app/devtools_app.json +1 -2
- package/front_end/entrypoints/formatter_worker/CSSFormatter.ts +1 -3
- package/front_end/entrypoints/formatter_worker/FormatterActions.ts +0 -2
- package/front_end/entrypoints/formatter_worker/FormatterWorker.ts +0 -120
- package/front_end/entrypoints/formatter_worker/formatter_worker-entrypoint.ts +1 -11
- package/front_end/entrypoints/formatter_worker/formatter_worker.ts +5 -0
- package/front_end/entrypoints/js_app/js_app.js +3 -0
- package/front_end/entrypoints/js_app/js_app.json +1 -2
- package/front_end/entrypoints/main/MainImpl.ts +0 -6
- package/front_end/entrypoints/ndb_app/ndb_app.js +3 -0
- package/front_end/entrypoints/ndb_app/ndb_app.json +1 -2
- package/front_end/entrypoints/node_app/node_app.js +3 -0
- package/front_end/entrypoints/node_app/node_app.json +1 -2
- package/front_end/entrypoints/shell/shell.js +18 -1
- package/front_end/entrypoints/worker_app/worker_app.js +3 -0
- package/front_end/entrypoints/worker_app/worker_app.json +1 -2
- package/front_end/legacy_test_runner/sources_test_runner/sources_test_runner.js +0 -1
- package/front_end/models/bindings/DebuggerWorkspaceBinding.ts +1 -1
- package/front_end/models/bindings/ResourceMapping.ts +1 -1
- package/front_end/models/formatter/FormatterWorkerPool.ts +0 -18
- package/front_end/models/text_utils/CodeMirrorUtils.ts +6 -51
- package/front_end/models/text_utils/TextUtils.ts +1 -2
- package/front_end/models/text_utils/text_utils-legacy.ts +0 -5
- package/front_end/panels/application/ApplicationPanelSidebar.ts +2 -4
- package/front_end/panels/elements/elementsTreeOutline.css +0 -13
- package/front_end/panels/network/NetworkConfigView.ts +10 -0
- package/front_end/panels/network/NetworkItemView.ts +3 -0
- package/front_end/panels/network/networkConfigView.css +5 -0
- package/front_end/panels/profiler/profilesPanel.css +1 -1
- package/front_end/panels/settings/emulation/components/UserAgentClientHintsForm.ts +6 -4
- package/front_end/panels/settings/emulation/components/userAgentClientHintsForm.css +0 -12
- package/front_end/panels/sources/DebuggerPlugin.ts +6 -2
- package/front_end/panels/sources/sourcesView.css +0 -130
- package/front_end/third_party/codemirror/codemirror-tsconfig.json +1 -25
- package/front_end/ui/components/text_editor/config.ts +3 -3
- package/front_end/ui/components/text_editor/javascript.ts +21 -3
- package/front_end/ui/components/text_editor/theme.ts +1 -0
- package/front_end/ui/legacy/components/object_ui/ObjectPropertiesSection.ts +2 -3
- package/front_end/ui/legacy/components/object_ui/objectPropertiesSection.css +0 -1
- package/front_end/ui/legacy/components/object_ui/object_ui-legacy.ts +0 -8
- package/front_end/ui/legacy/components/object_ui/object_ui.ts +0 -4
- package/front_end/ui/legacy/components/source_frame/SourceFrame.ts +3 -0
- package/front_end/ui/legacy/inspectorSyntaxHighlight.css +0 -211
- package/front_end/ui/legacy/legacy-legacy.ts +0 -6
- package/front_end/ui/legacy/legacy.ts +0 -2
- package/front_end/ui/legacy/tabbedPane.css +1 -1
- package/inspector_overlay/main.ts +12 -2
- package/package.json +1 -1
- package/scripts/check_gn.js +1 -1
- package/scripts/hosted_mode/server.js +17 -2
- package/front_end/entrypoints/shell/shell-meta-files.ts +0 -22
- package/front_end/entrypoints/shell/shell.json +0 -5
- package/front_end/ui/legacy/TextEditor.ts +0 -82
- package/front_end/ui/legacy/components/object_ui/JavaScriptAutocomplete.ts +0 -836
- package/front_end/ui/legacy/components/text_editor/CodeMirrorTextEditor.ts +0 -1676
- package/front_end/ui/legacy/components/text_editor/TextEditorAutocompleteController.ts +0 -586
- package/front_end/ui/legacy/components/text_editor/autocompleteTooltip.css +0 -20
- package/front_end/ui/legacy/components/text_editor/cm_modes.ts +0 -23
- package/front_end/ui/legacy/components/text_editor/cmdevtools.css +0 -995
- package/front_end/ui/legacy/components/text_editor/module.json +0 -7
- package/front_end/ui/legacy/components/text_editor/text_editor-legacy.ts +0 -33
- package/front_end/ui/legacy/components/text_editor/text_editor.ts +0 -13
|
@@ -1,1676 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
* Copyright (C) 2012 Google Inc. All rights reserved.
|
|
3
|
-
*
|
|
4
|
-
* Redistribution and use in source and binary forms, with or without
|
|
5
|
-
* modification, are permitted provided that the following conditions are
|
|
6
|
-
* met:
|
|
7
|
-
*
|
|
8
|
-
* * Redistributions of source code must retain the above copyright
|
|
9
|
-
* notice, this list of conditions and the following disclaimer.
|
|
10
|
-
* * Redistributions in binary form must reproduce the above
|
|
11
|
-
* copyright notice, this list of conditions and the following disclaimer
|
|
12
|
-
* in the documentation and/or other materials provided with the
|
|
13
|
-
* distribution.
|
|
14
|
-
* * Neither the name of Google Inc. nor the names of its
|
|
15
|
-
* contributors may be used to endorse or promote products derived from
|
|
16
|
-
* this software without specific prior written permission.
|
|
17
|
-
*
|
|
18
|
-
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
19
|
-
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
20
|
-
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
21
|
-
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
22
|
-
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
23
|
-
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
24
|
-
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
25
|
-
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
26
|
-
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
27
|
-
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
28
|
-
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
32
|
-
/* eslint-disable @typescript-eslint/naming-convention */
|
|
33
|
-
|
|
34
|
-
import * as Common from '../../../../core/common/common.js';
|
|
35
|
-
import * as Host from '../../../../core/host/host.js';
|
|
36
|
-
import * as i18n from '../../../../core/i18n/i18n.js';
|
|
37
|
-
import * as Platform from '../../../../core/platform/platform.js';
|
|
38
|
-
import * as TextUtils from '../../../../models/text_utils/text_utils.js';
|
|
39
|
-
import * as UI from '../../legacy.js';
|
|
40
|
-
|
|
41
|
-
import {TextEditorAutocompleteController} from './TextEditorAutocompleteController.js';
|
|
42
|
-
|
|
43
|
-
const UIStrings = {
|
|
44
|
-
/**
|
|
45
|
-
*@description Text in Code Mirror Text Editor of the CodeMirror text editor
|
|
46
|
-
*/
|
|
47
|
-
codeEditor: 'Code editor',
|
|
48
|
-
};
|
|
49
|
-
const str_ = i18n.i18n.registerUIStrings('ui/legacy/components/text_editor/CodeMirrorTextEditor.ts', UIStrings);
|
|
50
|
-
const i18nString = i18n.i18n.getLocalizedString.bind(undefined, str_);
|
|
51
|
-
|
|
52
|
-
export interface Token {
|
|
53
|
-
startColumn: number;
|
|
54
|
-
endColumn: number;
|
|
55
|
-
type: string;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export interface Coordinates {
|
|
59
|
-
x: number;
|
|
60
|
-
y: number;
|
|
61
|
-
height: number;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
65
|
-
const editorToDevtoolsWrapper = new WeakMap<any, CodeMirrorTextEditor>();
|
|
66
|
-
|
|
67
|
-
export class CodeMirrorTextEditor extends
|
|
68
|
-
Common.ObjectWrapper.eventMixin<UI.TextEditor.EventTypes, typeof UI.Widget.VBox>(UI.Widget.VBox)
|
|
69
|
-
implements UI.TextEditor.TextEditor {
|
|
70
|
-
private options: UI.TextEditor.Options;
|
|
71
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
72
|
-
private codeMirrorInternal: any;
|
|
73
|
-
private readonly codeMirrorElement: HTMLElement;
|
|
74
|
-
private shouldClearHistory: boolean;
|
|
75
|
-
private lineSeparator: string;
|
|
76
|
-
private hasOneLine!: boolean;
|
|
77
|
-
// https://crbug.com/1151919 * = CodeMirror.TextMarker
|
|
78
|
-
private readonly bookmarkForMarker: WeakMap<any, TextEditorBookMark>;
|
|
79
|
-
private readonly selectNextOccurrenceController: SelectNextOccurrenceController;
|
|
80
|
-
private readonly decorations: Platform.MapUtilities.Multimap<number, Decoration>;
|
|
81
|
-
private needsRefresh: boolean;
|
|
82
|
-
private readOnlyInternal: boolean;
|
|
83
|
-
private mimeTypeInternal: string;
|
|
84
|
-
private placeholderElement: HTMLPreElement|null;
|
|
85
|
-
autocompleteController?: TextEditorAutocompleteController;
|
|
86
|
-
private highlightedLine?: any;
|
|
87
|
-
private clearHighlightTimeout?: number;
|
|
88
|
-
private editorSizeInSync?: boolean;
|
|
89
|
-
private lastSelectionInternal?: TextUtils.TextRange.TextRange;
|
|
90
|
-
private selectionSetScheduled?: boolean;
|
|
91
|
-
|
|
92
|
-
constructor(options: UI.TextEditor.Options) {
|
|
93
|
-
super();
|
|
94
|
-
this.options = options;
|
|
95
|
-
|
|
96
|
-
// eslint-disable-next-line no-restricted-syntax -- Should import styles https://crbug.com/1106746
|
|
97
|
-
this.registerRequiredCSS('third_party/codemirror/codemirror.css');
|
|
98
|
-
// eslint-disable-next-line no-restricted-syntax -- Should import styles https://crbug.com/1106746
|
|
99
|
-
this.registerRequiredCSS('ui/legacy/components/text_editor/cmdevtools.css');
|
|
100
|
-
|
|
101
|
-
const {indentWithTabs, indentUnit} = CodeMirrorTextEditor.getIndentation(
|
|
102
|
-
Common.Settings.Settings.instance().moduleSetting('textEditorIndent').get());
|
|
103
|
-
// @ts-ignore TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
|
|
104
|
-
this.codeMirrorInternal = new CodeMirror(this.element, {
|
|
105
|
-
screenReaderLabel: options.devtoolsAccessibleName || i18nString(UIStrings.codeEditor),
|
|
106
|
-
lineNumbers: options.lineNumbers,
|
|
107
|
-
smartIndent: true,
|
|
108
|
-
electricChars: true,
|
|
109
|
-
indentUnit,
|
|
110
|
-
indentWithTabs,
|
|
111
|
-
lineWrapping: options.lineWrapping,
|
|
112
|
-
lineWiseCopyCut: options.lineWiseCopyCut || false,
|
|
113
|
-
pollInterval: Math.pow(2, 31) - 1,
|
|
114
|
-
matchBrackets: true,
|
|
115
|
-
inputStyle: (options.inputStyle || 'devToolsAccessibleTextArea') as unknown as undefined,
|
|
116
|
-
styleSelectedText: true,
|
|
117
|
-
styleActiveLine: true,
|
|
118
|
-
tabIndex: 0,
|
|
119
|
-
});
|
|
120
|
-
this.codeMirrorElement = this.element.lastElementChild as HTMLElement;
|
|
121
|
-
|
|
122
|
-
editorToDevtoolsWrapper.set(this.codeMirrorInternal, this);
|
|
123
|
-
|
|
124
|
-
Common.Settings.Settings.instance()
|
|
125
|
-
.moduleSetting('textEditorIndent')
|
|
126
|
-
.addChangeListener(this.updateIndentSize.bind(this));
|
|
127
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
128
|
-
CodeMirror.keyMap['devtools-common'] = {
|
|
129
|
-
'Left': 'goCharLeft',
|
|
130
|
-
'Right': 'goCharRight',
|
|
131
|
-
'Up': 'goLineUp',
|
|
132
|
-
'Down': 'goLineDown',
|
|
133
|
-
'End': 'goLineEnd',
|
|
134
|
-
'Home': 'goLineStartSmart',
|
|
135
|
-
'PageUp': 'goSmartPageUp',
|
|
136
|
-
'PageDown': 'goSmartPageDown',
|
|
137
|
-
'Delete': 'delCharAfter',
|
|
138
|
-
'Backspace': 'delCharBefore',
|
|
139
|
-
'Tab': 'UserIndent',
|
|
140
|
-
'Shift-Tab': 'indentLessOrPass',
|
|
141
|
-
'Enter': 'newlineAndIndent',
|
|
142
|
-
'Ctrl-Space': 'autocomplete',
|
|
143
|
-
'Esc': 'dismiss',
|
|
144
|
-
'Ctrl-M': 'gotoMatchingBracket',
|
|
145
|
-
};
|
|
146
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
147
|
-
CodeMirror.keyMap['devtools-pc'] = {
|
|
148
|
-
'Ctrl-A': 'selectAll',
|
|
149
|
-
'Ctrl-Z': 'undoAndReveal',
|
|
150
|
-
'Shift-Ctrl-Z': 'redoAndReveal',
|
|
151
|
-
'Ctrl-Y': 'redo',
|
|
152
|
-
'Ctrl-Home': 'goDocStart',
|
|
153
|
-
'Ctrl-Up': 'goDocStart',
|
|
154
|
-
'Ctrl-End': 'goDocEnd',
|
|
155
|
-
'Ctrl-Down': 'goDocEnd',
|
|
156
|
-
'Ctrl-Left': 'goGroupLeft',
|
|
157
|
-
'Ctrl-Right': 'goGroupRight',
|
|
158
|
-
'Alt-Left': 'moveCamelLeft',
|
|
159
|
-
'Alt-Right': 'moveCamelRight',
|
|
160
|
-
'Shift-Alt-Left': 'selectCamelLeft',
|
|
161
|
-
'Shift-Alt-Right': 'selectCamelRight',
|
|
162
|
-
'Ctrl-Backspace': 'delGroupBefore',
|
|
163
|
-
'Ctrl-Delete': 'delGroupAfter',
|
|
164
|
-
'Ctrl-/': 'toggleComment',
|
|
165
|
-
'Ctrl-D': 'selectNextOccurrence',
|
|
166
|
-
'Ctrl-U': 'undoLastSelection',
|
|
167
|
-
fallthrough: 'devtools-common',
|
|
168
|
-
};
|
|
169
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
170
|
-
CodeMirror.keyMap['devtools-mac'] = {
|
|
171
|
-
'Cmd-A': 'selectAll',
|
|
172
|
-
'Cmd-Z': 'undoAndReveal',
|
|
173
|
-
'Shift-Cmd-Z': 'redoAndReveal',
|
|
174
|
-
'Cmd-Up': 'goDocStart',
|
|
175
|
-
'Cmd-Down': 'goDocEnd',
|
|
176
|
-
'Alt-Left': 'goGroupLeft',
|
|
177
|
-
'Alt-Right': 'goGroupRight',
|
|
178
|
-
'Ctrl-Left': 'moveCamelLeft',
|
|
179
|
-
'Ctrl-Right': 'moveCamelRight',
|
|
180
|
-
'Ctrl-A': 'goLineLeft',
|
|
181
|
-
'Ctrl-E': 'goLineRight',
|
|
182
|
-
'Ctrl-B': 'goCharLeft',
|
|
183
|
-
'Ctrl-F': 'goCharRight',
|
|
184
|
-
'Ctrl-Alt-B': 'goGroupLeft',
|
|
185
|
-
'Ctrl-Alt-F': 'goGroupRight',
|
|
186
|
-
'Ctrl-H': 'delCharBefore',
|
|
187
|
-
'Ctrl-D': 'delCharAfter',
|
|
188
|
-
'Ctrl-K': 'killLine',
|
|
189
|
-
'Ctrl-T': 'transposeChars',
|
|
190
|
-
'Ctrl-P': 'goLineUp',
|
|
191
|
-
'Ctrl-N': 'goLineDown',
|
|
192
|
-
'Shift-Ctrl-Left': 'selectCamelLeft',
|
|
193
|
-
'Shift-Ctrl-Right': 'selectCamelRight',
|
|
194
|
-
'Cmd-Left': 'goLineStartSmart',
|
|
195
|
-
'Cmd-Right': 'goLineEnd',
|
|
196
|
-
'Cmd-Backspace': 'delLineLeft',
|
|
197
|
-
'Alt-Backspace': 'delGroupBefore',
|
|
198
|
-
'Alt-Delete': 'delGroupAfter',
|
|
199
|
-
'Cmd-/': 'toggleComment',
|
|
200
|
-
'Cmd-D': 'selectNextOccurrence',
|
|
201
|
-
'Cmd-U': 'undoLastSelection',
|
|
202
|
-
fallthrough: 'devtools-common',
|
|
203
|
-
};
|
|
204
|
-
|
|
205
|
-
if (options.bracketMatchingSetting) {
|
|
206
|
-
options.bracketMatchingSetting.addChangeListener(this.enableBracketMatchingIfNeeded, this);
|
|
207
|
-
}
|
|
208
|
-
this.enableBracketMatchingIfNeeded();
|
|
209
|
-
|
|
210
|
-
this.codeMirrorInternal.setOption('keyMap', Host.Platform.isMac() ? 'devtools-mac' : 'devtools-pc');
|
|
211
|
-
|
|
212
|
-
this.codeMirrorInternal.setOption('flattenSpans', false);
|
|
213
|
-
|
|
214
|
-
let maxHighlightLength = options.maxHighlightLength;
|
|
215
|
-
if (typeof maxHighlightLength !== 'number') {
|
|
216
|
-
maxHighlightLength = CodeMirrorTextEditor.maxHighlightLength;
|
|
217
|
-
}
|
|
218
|
-
this.codeMirrorInternal.setOption('maxHighlightLength', maxHighlightLength);
|
|
219
|
-
this.codeMirrorInternal.setOption('mode', null);
|
|
220
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
221
|
-
this.codeMirrorInternal.setOption('crudeMeasuringFrom', 1000);
|
|
222
|
-
|
|
223
|
-
this.shouldClearHistory = true;
|
|
224
|
-
this.lineSeparator = '\n';
|
|
225
|
-
|
|
226
|
-
this.bookmarkForMarker = new WeakMap();
|
|
227
|
-
|
|
228
|
-
CodeMirrorTextEditor.fixWordMovement(this.codeMirrorInternal);
|
|
229
|
-
|
|
230
|
-
this.selectNextOccurrenceController = new SelectNextOccurrenceController(this, this.codeMirrorInternal);
|
|
231
|
-
|
|
232
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
233
|
-
this.codeMirrorInternal.on('changes', this.changes.bind(this));
|
|
234
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
235
|
-
this.codeMirrorInternal.on('beforeSelectionChange', this.beforeSelectionChange.bind(this));
|
|
236
|
-
this.codeMirrorInternal.on('cursorActivity', () => {
|
|
237
|
-
this.dispatchEventToListeners(UI.TextEditor.Events.CursorChanged);
|
|
238
|
-
});
|
|
239
|
-
|
|
240
|
-
this.element.style.overflow = 'hidden';
|
|
241
|
-
this.codeMirrorElement.classList.add('source-code');
|
|
242
|
-
this.codeMirrorElement.classList.add('fill');
|
|
243
|
-
|
|
244
|
-
this.decorations = new Platform.MapUtilities.Multimap();
|
|
245
|
-
|
|
246
|
-
this.element.addEventListener('keydown', this.handleKeyDown.bind(this), true);
|
|
247
|
-
this.element.addEventListener('keydown', this.handlePostKeyDown.bind(this), false);
|
|
248
|
-
|
|
249
|
-
this.needsRefresh = true;
|
|
250
|
-
|
|
251
|
-
this.readOnlyInternal = false;
|
|
252
|
-
|
|
253
|
-
this.mimeTypeInternal = '';
|
|
254
|
-
if (options.mimeType) {
|
|
255
|
-
this.setMimeType(options.mimeType);
|
|
256
|
-
}
|
|
257
|
-
if (options.autoHeight) {
|
|
258
|
-
this.codeMirrorInternal.setSize(null, 'auto');
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
this.placeholderElement = null;
|
|
262
|
-
if (options.placeholder) {
|
|
263
|
-
this.placeholderElement = document.createElement('pre');
|
|
264
|
-
this.placeholderElement.classList.add('placeholder-text');
|
|
265
|
-
this.placeholderElement.classList.add('CodeMirror-line-like');
|
|
266
|
-
this.placeholderElement.textContent = options.placeholder;
|
|
267
|
-
this.updatePlaceholder();
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
272
|
-
static getForCodeMirror(codeMirrorEditor: any): CodeMirrorTextEditor {
|
|
273
|
-
const wrapper = editorToDevtoolsWrapper.get(codeMirrorEditor);
|
|
274
|
-
if (!wrapper) {
|
|
275
|
-
throw new Error('CodeMirrorTextEditor not found');
|
|
276
|
-
}
|
|
277
|
-
return wrapper;
|
|
278
|
-
}
|
|
279
|
-
|
|
280
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
281
|
-
static autocompleteCommand(codeMirror: any): void {
|
|
282
|
-
const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codeMirror).autocompleteController;
|
|
283
|
-
if (autocompleteController) {
|
|
284
|
-
autocompleteController.autocomplete(true);
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
289
|
-
static undoLastSelectionCommand(codeMirror: any): void {
|
|
290
|
-
CodeMirrorTextEditor.getForCodeMirror(codeMirror).selectNextOccurrenceController.undoLastSelection();
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
294
|
-
static selectNextOccurrenceCommand(codeMirror: any): void {
|
|
295
|
-
CodeMirrorTextEditor.getForCodeMirror(codeMirror).selectNextOccurrenceController.selectNextOccurrence();
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
299
|
-
static moveCamelLeftCommand(shift: boolean, codeMirror: any): void {
|
|
300
|
-
CodeMirrorTextEditor.getForCodeMirror(codeMirror).doCamelCaseMovement(-1, shift);
|
|
301
|
-
}
|
|
302
|
-
|
|
303
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
304
|
-
static moveCamelRightCommand(shift: boolean, codeMirror: any): void {
|
|
305
|
-
CodeMirrorTextEditor.getForCodeMirror(codeMirror).doCamelCaseMovement(1, shift);
|
|
306
|
-
}
|
|
307
|
-
|
|
308
|
-
private static getIndentation(indentationValue: string): {
|
|
309
|
-
indentWithTabs: boolean,
|
|
310
|
-
indentUnit: number,
|
|
311
|
-
} {
|
|
312
|
-
const indentWithTabs = /\t/.test(indentationValue);
|
|
313
|
-
const indentUnit = indentWithTabs ? 4 : indentationValue.length;
|
|
314
|
-
return {indentWithTabs, indentUnit};
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
static overrideModeWithPrefixedTokens(modeName: string, tokenPrefix: string): void {
|
|
318
|
-
const oldModeName = modeName + '-old';
|
|
319
|
-
if (CodeMirror.modes[oldModeName]) {
|
|
320
|
-
return;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
CodeMirror.defineMode(oldModeName, CodeMirror.modes[modeName]);
|
|
324
|
-
CodeMirror.defineMode(modeName, modeConstructor);
|
|
325
|
-
|
|
326
|
-
// @ts-ignore TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
|
|
327
|
-
function modeConstructor(config: any, parserConfig: any): any {
|
|
328
|
-
// TODO(crbug.com/1172300) Properly type this after jsdoc to ts migration
|
|
329
|
-
const innerConfig: any = {};
|
|
330
|
-
for (const i in parserConfig) {
|
|
331
|
-
innerConfig[i] = parserConfig[i];
|
|
332
|
-
}
|
|
333
|
-
innerConfig.name = oldModeName;
|
|
334
|
-
const codeMirrorMode = CodeMirror.getMode(config, innerConfig);
|
|
335
|
-
codeMirrorMode.name = modeName;
|
|
336
|
-
if (typeof codeMirrorMode.token === 'undefined') {
|
|
337
|
-
throw new Error('codeMirrorMode.token was unexpectedly undefined');
|
|
338
|
-
}
|
|
339
|
-
codeMirrorMode.token = getTokenFunction(codeMirrorMode.token);
|
|
340
|
-
return codeMirrorMode;
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
function getTokenFunction(superToken: (arg0: any, arg1: any) => string | null): (stream: any, state: any) =>
|
|
344
|
-
string | null {
|
|
345
|
-
function childFunc(stream: any, state: any): string|null {
|
|
346
|
-
return tokenOverride(superToken, stream, state);
|
|
347
|
-
}
|
|
348
|
-
|
|
349
|
-
return childFunc;
|
|
350
|
-
}
|
|
351
|
-
function tokenOverride(superToken: (arg0: any, arg1: any) => string | null, stream: any, state: any): string|null {
|
|
352
|
-
const token = superToken(stream, state);
|
|
353
|
-
return token ? tokenPrefix + token.split(/ +/).join(' ' + tokenPrefix) : token;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
|
|
357
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
358
|
-
private static fixWordMovement(codeMirror: any): void {
|
|
359
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
360
|
-
function moveLeft(shift: boolean, codeMirror: any): void {
|
|
361
|
-
codeMirror.setExtending(shift);
|
|
362
|
-
const cursor = codeMirror.getCursor('head');
|
|
363
|
-
codeMirror.execCommand('goGroupLeft');
|
|
364
|
-
const newCursor = codeMirror.getCursor('head');
|
|
365
|
-
if (newCursor.ch === 0 && newCursor.line !== 0) {
|
|
366
|
-
codeMirror.setExtending(false);
|
|
367
|
-
return;
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
const skippedText = codeMirror.getRange(newCursor, cursor, '#');
|
|
371
|
-
if (/^\s+$/.test(skippedText)) {
|
|
372
|
-
codeMirror.execCommand('goGroupLeft');
|
|
373
|
-
}
|
|
374
|
-
codeMirror.setExtending(false);
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
378
|
-
function moveRight(shift: boolean, codeMirror: any): void {
|
|
379
|
-
codeMirror.setExtending(shift);
|
|
380
|
-
const cursor = codeMirror.getCursor('head');
|
|
381
|
-
codeMirror.execCommand('goGroupRight');
|
|
382
|
-
const newCursor = codeMirror.getCursor('head');
|
|
383
|
-
if (newCursor.ch === 0 && newCursor.line !== 0) {
|
|
384
|
-
codeMirror.setExtending(false);
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
const skippedText = codeMirror.getRange(cursor, newCursor, '#');
|
|
389
|
-
if (/^\s+$/.test(skippedText)) {
|
|
390
|
-
codeMirror.execCommand('goGroupRight');
|
|
391
|
-
}
|
|
392
|
-
codeMirror.setExtending(false);
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
const modifierKey = Host.Platform.isMac() ? 'Alt' : 'Ctrl';
|
|
396
|
-
const leftKey = modifierKey + '-Left';
|
|
397
|
-
const rightKey = modifierKey + '-Right';
|
|
398
|
-
const keyMap: {[key: string]: Function} = {};
|
|
399
|
-
keyMap[leftKey] = moveLeft.bind(null, false);
|
|
400
|
-
keyMap[rightKey] = moveRight.bind(null, false);
|
|
401
|
-
keyMap['Shift-' + leftKey] = moveLeft.bind(null, true);
|
|
402
|
-
keyMap['Shift-' + rightKey] = moveRight.bind(null, true);
|
|
403
|
-
codeMirror.addKeyMap(keyMap);
|
|
404
|
-
}
|
|
405
|
-
|
|
406
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
407
|
-
codeMirror(): any {
|
|
408
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
409
|
-
return /** @type {*} */ this.codeMirrorInternal as any;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
widget(): UI.Widget.Widget {
|
|
413
|
-
return this;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
setPlaceholder(placeholder: string): void {
|
|
417
|
-
if (!this.placeholderElement) {
|
|
418
|
-
this.placeholderElement = document.createElement('pre');
|
|
419
|
-
this.placeholderElement.classList.add('placeholder-text');
|
|
420
|
-
this.placeholderElement.classList.add('CodeMirror-line-like');
|
|
421
|
-
}
|
|
422
|
-
this.placeholderElement.textContent = placeholder || '';
|
|
423
|
-
this.updatePlaceholder();
|
|
424
|
-
}
|
|
425
|
-
|
|
426
|
-
private normalizePositionForOverlappingColumn(lineNumber: number, lineLength: number, charNumber: number): {
|
|
427
|
-
lineNumber: number,
|
|
428
|
-
columnNumber: number,
|
|
429
|
-
} {
|
|
430
|
-
const linesCount = this.codeMirrorInternal.lineCount();
|
|
431
|
-
let columnNumber: number|0 = charNumber;
|
|
432
|
-
if (charNumber < 0 && lineNumber > 0) {
|
|
433
|
-
--lineNumber;
|
|
434
|
-
columnNumber = this.line(lineNumber).length;
|
|
435
|
-
} else if (charNumber >= lineLength && lineNumber < linesCount - 1) {
|
|
436
|
-
++lineNumber;
|
|
437
|
-
columnNumber = 0;
|
|
438
|
-
} else {
|
|
439
|
-
columnNumber = Platform.NumberUtilities.clamp(charNumber, 0, lineLength);
|
|
440
|
-
}
|
|
441
|
-
return {lineNumber: lineNumber, columnNumber: columnNumber};
|
|
442
|
-
}
|
|
443
|
-
|
|
444
|
-
private camelCaseMoveFromPosition(lineNumber: number, columnNumber: number, direction: number): {
|
|
445
|
-
lineNumber: number,
|
|
446
|
-
columnNumber: number,
|
|
447
|
-
} {
|
|
448
|
-
function valid(charNumber: number, length: number): boolean {
|
|
449
|
-
return charNumber >= 0 && charNumber < length;
|
|
450
|
-
}
|
|
451
|
-
|
|
452
|
-
function isWordStart(text: string, charNumber: number): boolean {
|
|
453
|
-
const position = charNumber;
|
|
454
|
-
const nextPosition = charNumber + 1;
|
|
455
|
-
return valid(position, text.length) && valid(nextPosition, text.length) &&
|
|
456
|
-
TextUtils.TextUtils.Utils.isWordChar(text[position]) &&
|
|
457
|
-
TextUtils.TextUtils.Utils.isWordChar(text[nextPosition]) &&
|
|
458
|
-
TextUtils.TextUtils.Utils.isUpperCase(text[position]) &&
|
|
459
|
-
TextUtils.TextUtils.Utils.isLowerCase(text[nextPosition]);
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
function isWordEnd(text: string, charNumber: number): boolean {
|
|
463
|
-
const position = charNumber;
|
|
464
|
-
const prevPosition = charNumber - 1;
|
|
465
|
-
return valid(position, text.length) && valid(prevPosition, text.length) &&
|
|
466
|
-
TextUtils.TextUtils.Utils.isWordChar(text[position]) &&
|
|
467
|
-
TextUtils.TextUtils.Utils.isWordChar(text[prevPosition]) &&
|
|
468
|
-
TextUtils.TextUtils.Utils.isUpperCase(text[position]) &&
|
|
469
|
-
TextUtils.TextUtils.Utils.isLowerCase(text[prevPosition]);
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
function constrainPosition(lineNumber: number, lineLength: number, columnNumber: number): {
|
|
473
|
-
lineNumber: number,
|
|
474
|
-
columnNumber: number,
|
|
475
|
-
} {
|
|
476
|
-
return {lineNumber: lineNumber, columnNumber: Platform.NumberUtilities.clamp(columnNumber, 0, lineLength)};
|
|
477
|
-
}
|
|
478
|
-
|
|
479
|
-
const text = this.line(lineNumber);
|
|
480
|
-
const length = text.length;
|
|
481
|
-
|
|
482
|
-
if ((columnNumber === length && direction === 1) || (columnNumber === 0 && direction === -1)) {
|
|
483
|
-
return this.normalizePositionForOverlappingColumn(lineNumber, length, columnNumber + direction);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
let charNumber = direction === 1 ? columnNumber : columnNumber - 1;
|
|
487
|
-
|
|
488
|
-
// Move through initial spaces if any.
|
|
489
|
-
while (valid(charNumber, length) && TextUtils.TextUtils.Utils.isSpaceChar(text[charNumber])) {
|
|
490
|
-
charNumber += direction;
|
|
491
|
-
}
|
|
492
|
-
if (!valid(charNumber, length)) {
|
|
493
|
-
return constrainPosition(lineNumber, length, charNumber);
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
if (TextUtils.TextUtils.Utils.isStopChar(text[charNumber])) {
|
|
497
|
-
while (valid(charNumber, length) && TextUtils.TextUtils.Utils.isStopChar(text[charNumber])) {
|
|
498
|
-
charNumber += direction;
|
|
499
|
-
}
|
|
500
|
-
if (!valid(charNumber, length)) {
|
|
501
|
-
return constrainPosition(lineNumber, length, charNumber);
|
|
502
|
-
}
|
|
503
|
-
return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
|
|
504
|
-
}
|
|
505
|
-
|
|
506
|
-
charNumber += direction;
|
|
507
|
-
while (valid(charNumber, length) && !isWordStart(text, charNumber) && !isWordEnd(text, charNumber) &&
|
|
508
|
-
TextUtils.TextUtils.Utils.isWordChar(text[charNumber])) {
|
|
509
|
-
charNumber += direction;
|
|
510
|
-
}
|
|
511
|
-
|
|
512
|
-
if (!valid(charNumber, length)) {
|
|
513
|
-
return constrainPosition(lineNumber, length, charNumber);
|
|
514
|
-
}
|
|
515
|
-
if (isWordStart(text, charNumber) || isWordEnd(text, charNumber)) {
|
|
516
|
-
return {lineNumber: lineNumber, columnNumber: charNumber};
|
|
517
|
-
}
|
|
518
|
-
|
|
519
|
-
return {lineNumber: lineNumber, columnNumber: direction === -1 ? charNumber + 1 : charNumber};
|
|
520
|
-
}
|
|
521
|
-
|
|
522
|
-
private doCamelCaseMovement(direction: number, shift: boolean): void {
|
|
523
|
-
const selections = this.selections();
|
|
524
|
-
for (let i = 0; i < selections.length; ++i) {
|
|
525
|
-
const selection = selections[i];
|
|
526
|
-
const move = this.camelCaseMoveFromPosition(selection.endLine, selection.endColumn, direction);
|
|
527
|
-
selection.endLine = move.lineNumber;
|
|
528
|
-
selection.endColumn = move.columnNumber;
|
|
529
|
-
if (!shift) {
|
|
530
|
-
selections[i] = selection.collapseToEnd();
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
this.setSelections(selections);
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
dispose(): void {
|
|
537
|
-
if (this.options.bracketMatchingSetting) {
|
|
538
|
-
this.options.bracketMatchingSetting.removeChangeListener(this.enableBracketMatchingIfNeeded, this);
|
|
539
|
-
}
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
private enableBracketMatchingIfNeeded(): void {
|
|
543
|
-
this.codeMirrorInternal.setOption(
|
|
544
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
545
|
-
'autoCloseBrackets',
|
|
546
|
-
(this.options.bracketMatchingSetting && this.options.bracketMatchingSetting.get()) ? {explode: false} : false);
|
|
547
|
-
}
|
|
548
|
-
|
|
549
|
-
wasShown(): void {
|
|
550
|
-
if (this.needsRefresh) {
|
|
551
|
-
this.refresh();
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
protected refresh(): void {
|
|
556
|
-
if (this.isShowing()) {
|
|
557
|
-
this.codeMirrorInternal.refresh();
|
|
558
|
-
this.needsRefresh = false;
|
|
559
|
-
return;
|
|
560
|
-
}
|
|
561
|
-
this.needsRefresh = true;
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
willHide(): void {
|
|
565
|
-
delete this.editorSizeInSync;
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
undo(): void {
|
|
569
|
-
this.codeMirrorInternal.undo();
|
|
570
|
-
}
|
|
571
|
-
|
|
572
|
-
redo(): void {
|
|
573
|
-
this.codeMirrorInternal.redo();
|
|
574
|
-
}
|
|
575
|
-
|
|
576
|
-
private handleKeyDown(e: Event): void {
|
|
577
|
-
const keyboardEvent = e as KeyboardEvent;
|
|
578
|
-
if (keyboardEvent.key === 'Tab' &&
|
|
579
|
-
Common.Settings.Settings.instance().moduleSetting('textEditorTabMovesFocus').get()) {
|
|
580
|
-
keyboardEvent.consume(false);
|
|
581
|
-
return;
|
|
582
|
-
}
|
|
583
|
-
if (this.autocompleteController && this.autocompleteController.keyDown(keyboardEvent)) {
|
|
584
|
-
keyboardEvent.consume(true);
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
private handlePostKeyDown(e: Event): void {
|
|
589
|
-
if (e.defaultPrevented) {
|
|
590
|
-
e.consume(true);
|
|
591
|
-
}
|
|
592
|
-
}
|
|
593
|
-
|
|
594
|
-
configureAutocomplete(config: UI.TextEditor.AutocompleteConfig|null): void {
|
|
595
|
-
if (this.autocompleteController) {
|
|
596
|
-
this.autocompleteController.dispose();
|
|
597
|
-
delete this.autocompleteController;
|
|
598
|
-
}
|
|
599
|
-
|
|
600
|
-
if (config) {
|
|
601
|
-
this.autocompleteController = new TextEditorAutocompleteController(this, this.codeMirrorInternal, config);
|
|
602
|
-
}
|
|
603
|
-
}
|
|
604
|
-
|
|
605
|
-
cursorPositionToCoordinates(lineNumber: number, column: number): Coordinates|null {
|
|
606
|
-
if (lineNumber >= this.codeMirrorInternal.lineCount() || lineNumber < 0 || column < 0 ||
|
|
607
|
-
column > this.codeMirrorInternal.getLine(lineNumber).length) {
|
|
608
|
-
return null;
|
|
609
|
-
}
|
|
610
|
-
const metrics = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, column));
|
|
611
|
-
return {x: metrics.left, y: metrics.top, height: metrics.bottom - metrics.top};
|
|
612
|
-
}
|
|
613
|
-
|
|
614
|
-
coordinatesToCursorPosition(x: number, y: number): TextUtils.TextRange.TextRange|null {
|
|
615
|
-
const element = this.element.ownerDocument.elementFromPoint(x, y);
|
|
616
|
-
if (!element || !element.isSelfOrDescendant(this.codeMirrorInternal.getWrapperElement())) {
|
|
617
|
-
return null;
|
|
618
|
-
}
|
|
619
|
-
const gutterBox = this.codeMirrorInternal.getGutterElement().boxInWindow();
|
|
620
|
-
if (x >= gutterBox.x && x <= gutterBox.x + gutterBox.width && y >= gutterBox.y &&
|
|
621
|
-
y <= gutterBox.y + gutterBox.height) {
|
|
622
|
-
return null;
|
|
623
|
-
}
|
|
624
|
-
const coords = this.codeMirrorInternal.coordsChar({left: x, top: y});
|
|
625
|
-
return TextUtils.CodeMirrorUtils.toRange(coords, coords);
|
|
626
|
-
}
|
|
627
|
-
|
|
628
|
-
visualCoordinates(lineNumber: number, columnNumber: number): {
|
|
629
|
-
x: number,
|
|
630
|
-
y: number,
|
|
631
|
-
} {
|
|
632
|
-
const metrics = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, columnNumber));
|
|
633
|
-
return {x: metrics.left, y: metrics.top};
|
|
634
|
-
}
|
|
635
|
-
|
|
636
|
-
tokenAtTextPosition(lineNumber: number, columnNumber: number): Token|null {
|
|
637
|
-
if (lineNumber < 0 || lineNumber >= this.codeMirrorInternal.lineCount()) {
|
|
638
|
-
return null;
|
|
639
|
-
}
|
|
640
|
-
const token = this.codeMirrorInternal.getTokenAt(new CodeMirror.Pos(lineNumber, (columnNumber || 0) + 1));
|
|
641
|
-
if (!token) {
|
|
642
|
-
return null;
|
|
643
|
-
}
|
|
644
|
-
return {startColumn: token.start, endColumn: token.end, type: token.type as string};
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
isClean(generation: number): boolean {
|
|
648
|
-
return this.codeMirrorInternal.isClean(generation);
|
|
649
|
-
}
|
|
650
|
-
|
|
651
|
-
markClean(): number {
|
|
652
|
-
return this.codeMirrorInternal.changeGeneration(true);
|
|
653
|
-
}
|
|
654
|
-
|
|
655
|
-
private hasLongLines(): boolean {
|
|
656
|
-
function lineIterator(lineHandle: {
|
|
657
|
-
text: string,
|
|
658
|
-
}): boolean {
|
|
659
|
-
if (lineHandle.text.length > CodeMirrorTextEditor.LongLineModeLineLengthThreshold) {
|
|
660
|
-
hasLongLines = true;
|
|
661
|
-
}
|
|
662
|
-
return hasLongLines;
|
|
663
|
-
}
|
|
664
|
-
let hasLongLines = false;
|
|
665
|
-
this.codeMirrorInternal.eachLine(lineIterator);
|
|
666
|
-
return hasLongLines;
|
|
667
|
-
}
|
|
668
|
-
|
|
669
|
-
private enableLongLinesMode(): void {
|
|
670
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
671
|
-
this.codeMirrorInternal.setOption('styleSelectedText', false);
|
|
672
|
-
}
|
|
673
|
-
|
|
674
|
-
private disableLongLinesMode(): void {
|
|
675
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
676
|
-
this.codeMirrorInternal.setOption('styleSelectedText', true);
|
|
677
|
-
}
|
|
678
|
-
|
|
679
|
-
private updateIndentSize(updatedValue: {
|
|
680
|
-
data: any,
|
|
681
|
-
}): void {
|
|
682
|
-
const {indentWithTabs, indentUnit} = CodeMirrorTextEditor.getIndentation(updatedValue.data as string);
|
|
683
|
-
|
|
684
|
-
this.codeMirrorInternal.setOption('indentUnit', indentUnit);
|
|
685
|
-
this.codeMirrorInternal.setOption('indentWithTabs', indentWithTabs);
|
|
686
|
-
}
|
|
687
|
-
|
|
688
|
-
setMimeType(mimeType: string): void {
|
|
689
|
-
this.mimeTypeInternal = mimeType;
|
|
690
|
-
|
|
691
|
-
const rewrittenMimeType = this.rewriteMimeType(mimeType);
|
|
692
|
-
const modeOption = this.codeMirrorInternal.getOption('mode');
|
|
693
|
-
if (modeOption !== rewrittenMimeType) {
|
|
694
|
-
this.codeMirrorInternal.setOption('mode', rewrittenMimeType);
|
|
695
|
-
}
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
setHighlightMode(mode: Object): void {
|
|
699
|
-
this.mimeTypeInternal = '';
|
|
700
|
-
this.codeMirrorInternal.setOption('mode', mode);
|
|
701
|
-
}
|
|
702
|
-
|
|
703
|
-
protected rewriteMimeType(mimeType: string): string {
|
|
704
|
-
// Overridden in SourcesTextEditor
|
|
705
|
-
return mimeType;
|
|
706
|
-
}
|
|
707
|
-
|
|
708
|
-
protected mimeType(): string {
|
|
709
|
-
return this.mimeTypeInternal;
|
|
710
|
-
}
|
|
711
|
-
|
|
712
|
-
setReadOnly(readOnly: boolean): void {
|
|
713
|
-
if (this.readOnlyInternal === readOnly) {
|
|
714
|
-
return;
|
|
715
|
-
}
|
|
716
|
-
this.clearPositionHighlight();
|
|
717
|
-
this.readOnlyInternal = readOnly;
|
|
718
|
-
this.element.classList.toggle('CodeMirror-readonly', readOnly);
|
|
719
|
-
this.codeMirrorInternal.setOption('readOnly', readOnly);
|
|
720
|
-
}
|
|
721
|
-
|
|
722
|
-
readOnly(): boolean {
|
|
723
|
-
return Boolean(this.codeMirrorInternal.getOption('readOnly'));
|
|
724
|
-
}
|
|
725
|
-
|
|
726
|
-
setLineNumberFormatter(formatter: (arg0: number) => string): void {
|
|
727
|
-
this.codeMirrorInternal.setOption('lineNumberFormatter', formatter);
|
|
728
|
-
}
|
|
729
|
-
|
|
730
|
-
addKeyDownHandler(handler: (arg0: KeyboardEvent) => void): void {
|
|
731
|
-
this.codeMirrorInternal.on(
|
|
732
|
-
'keydown', /**
|
|
733
|
-
* @param {*} CodeMirror
|
|
734
|
-
* @param {!KeyboardEvent} event
|
|
735
|
-
*/
|
|
736
|
-
(CodeMirror: any, event: KeyboardEvent) => handler(event));
|
|
737
|
-
}
|
|
738
|
-
|
|
739
|
-
addBookmark(lineNumber: number, columnNumber: number, element: HTMLElement, type: symbol, insertBefore?: boolean):
|
|
740
|
-
TextEditorBookMark {
|
|
741
|
-
const marker = this.codeMirrorInternal.setBookmark(
|
|
742
|
-
new CodeMirror.Pos(lineNumber, columnNumber), {widget: element, insertLeft: insertBefore});
|
|
743
|
-
|
|
744
|
-
const bookmark = new TextEditorBookMark(marker, type, this);
|
|
745
|
-
this.bookmarkForMarker.set(marker, bookmark);
|
|
746
|
-
this.updateDecorations(lineNumber);
|
|
747
|
-
return bookmark;
|
|
748
|
-
}
|
|
749
|
-
|
|
750
|
-
bookmarks(range: TextUtils.TextRange.TextRange, type?: symbol): TextEditorBookMark[] {
|
|
751
|
-
const pos = TextUtils.CodeMirrorUtils.toPos(range);
|
|
752
|
-
let markers = this.codeMirrorInternal.findMarksAt(pos.start);
|
|
753
|
-
if (!range.isEmpty()) {
|
|
754
|
-
const middleMarkers = this.codeMirrorInternal.findMarks(pos.start, pos.end);
|
|
755
|
-
const endMarkers = this.codeMirrorInternal.findMarksAt(pos.end);
|
|
756
|
-
markers = markers.concat(middleMarkers, endMarkers);
|
|
757
|
-
}
|
|
758
|
-
const bookmarks: TextEditorBookMark[] = [];
|
|
759
|
-
for (let i = 0; i < markers.length; i++) {
|
|
760
|
-
const marker = markers[i];
|
|
761
|
-
const bookmark = this.bookmarkForMarker.get(marker);
|
|
762
|
-
if (bookmark && (!type || bookmark.type() === type)) {
|
|
763
|
-
bookmarks.push(bookmark);
|
|
764
|
-
}
|
|
765
|
-
}
|
|
766
|
-
return bookmarks;
|
|
767
|
-
}
|
|
768
|
-
|
|
769
|
-
focus(): void {
|
|
770
|
-
this.codeMirrorInternal.focus();
|
|
771
|
-
}
|
|
772
|
-
|
|
773
|
-
hasFocus(): boolean {
|
|
774
|
-
return this.codeMirrorInternal.hasFocus();
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
operation(operation: () => any): void {
|
|
778
|
-
this.codeMirrorInternal.operation(operation);
|
|
779
|
-
}
|
|
780
|
-
|
|
781
|
-
scrollLineIntoView(lineNumber: number): void {
|
|
782
|
-
this.innerRevealLine(lineNumber, this.codeMirrorInternal.getScrollInfo());
|
|
783
|
-
}
|
|
784
|
-
|
|
785
|
-
innerRevealLine(lineNumber: number, scrollInfo: {
|
|
786
|
-
left: number,
|
|
787
|
-
top: number,
|
|
788
|
-
width: number,
|
|
789
|
-
height: number,
|
|
790
|
-
clientWidth: number,
|
|
791
|
-
clientHeight: number,
|
|
792
|
-
}): void {
|
|
793
|
-
const topLine = this.codeMirrorInternal.lineAtHeight(scrollInfo.top, 'local');
|
|
794
|
-
const bottomLine = this.codeMirrorInternal.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
|
|
795
|
-
const linesPerScreen = bottomLine - topLine + 1;
|
|
796
|
-
if (lineNumber < topLine) {
|
|
797
|
-
const topLineToReveal = Math.max(lineNumber - (linesPerScreen / 2) + 1, 0) | 0;
|
|
798
|
-
this.codeMirrorInternal.scrollIntoView(new CodeMirror.Pos(topLineToReveal, 0));
|
|
799
|
-
} else if (lineNumber > bottomLine) {
|
|
800
|
-
const bottomLineToReveal = Math.min(lineNumber + (linesPerScreen / 2) - 1, this.linesCount - 1) | 0;
|
|
801
|
-
this.codeMirrorInternal.scrollIntoView(new CodeMirror.Pos(bottomLineToReveal, 0));
|
|
802
|
-
}
|
|
803
|
-
}
|
|
804
|
-
|
|
805
|
-
addDecoration(element: HTMLElement, lineNumber: number, startColumn?: number, endColumn?: number): void {
|
|
806
|
-
const widget = this.codeMirrorInternal.addLineWidget(lineNumber, element);
|
|
807
|
-
let update: (() => void)|null = null;
|
|
808
|
-
if (typeof startColumn !== 'undefined') {
|
|
809
|
-
if (typeof endColumn === 'undefined') {
|
|
810
|
-
endColumn = Infinity;
|
|
811
|
-
}
|
|
812
|
-
update = this.updateFloatingDecoration.bind(this, element, lineNumber, startColumn, endColumn);
|
|
813
|
-
update();
|
|
814
|
-
}
|
|
815
|
-
|
|
816
|
-
this.decorations.set(lineNumber, {element: element, update: update, widget: widget});
|
|
817
|
-
}
|
|
818
|
-
|
|
819
|
-
private updateFloatingDecoration(element: HTMLElement, lineNumber: number, startColumn: number, endColumn: number):
|
|
820
|
-
void {
|
|
821
|
-
const base = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, 0), 'page');
|
|
822
|
-
const start = this.codeMirrorInternal.cursorCoords(new CodeMirror.Pos(lineNumber, startColumn), 'page');
|
|
823
|
-
const end = this.codeMirrorInternal.charCoords(new CodeMirror.Pos(lineNumber, endColumn), 'page');
|
|
824
|
-
element.style.width = (end.right - start.left) + 'px';
|
|
825
|
-
element.style.left = (start.left - base.left) + 'px';
|
|
826
|
-
}
|
|
827
|
-
|
|
828
|
-
updateDecorations(lineNumber: number): void {
|
|
829
|
-
this.decorations.get(lineNumber).forEach(innerUpdateDecorations);
|
|
830
|
-
|
|
831
|
-
function innerUpdateDecorations(decoration: Decoration): void {
|
|
832
|
-
if (decoration.update) {
|
|
833
|
-
decoration.update();
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
removeDecoration(element: Element, lineNumber: number): void {
|
|
839
|
-
this.decorations.get(lineNumber).forEach(innerRemoveDecoration.bind(this));
|
|
840
|
-
|
|
841
|
-
function innerRemoveDecoration(this: CodeMirrorTextEditor, decoration: Decoration): void {
|
|
842
|
-
if (decoration.element !== element) {
|
|
843
|
-
return;
|
|
844
|
-
}
|
|
845
|
-
this.codeMirrorInternal.removeLineWidget(decoration.widget);
|
|
846
|
-
this.decorations.delete(lineNumber, decoration);
|
|
847
|
-
}
|
|
848
|
-
}
|
|
849
|
-
|
|
850
|
-
revealPosition(lineNumber: number, columnNumber?: number, shouldHighlight?: boolean): void {
|
|
851
|
-
lineNumber = Platform.NumberUtilities.clamp(lineNumber, 0, this.codeMirrorInternal.lineCount() - 1);
|
|
852
|
-
if (typeof columnNumber !== 'number') {
|
|
853
|
-
columnNumber = 0;
|
|
854
|
-
}
|
|
855
|
-
columnNumber = Platform.NumberUtilities.clamp(columnNumber, 0, this.codeMirrorInternal.getLine(lineNumber).length);
|
|
856
|
-
|
|
857
|
-
this.clearPositionHighlight();
|
|
858
|
-
this.highlightedLine = this.codeMirrorInternal.getLineHandle(lineNumber);
|
|
859
|
-
if (!this.highlightedLine) {
|
|
860
|
-
return;
|
|
861
|
-
}
|
|
862
|
-
this.scrollLineIntoView(lineNumber);
|
|
863
|
-
if (shouldHighlight) {
|
|
864
|
-
this.codeMirrorInternal.addLineClass(
|
|
865
|
-
this.highlightedLine, null, this.readOnlyInternal ? 'cm-readonly-highlight' : 'cm-highlight');
|
|
866
|
-
if (!this.readOnlyInternal) {
|
|
867
|
-
this.clearHighlightTimeout = window.setTimeout(this.clearPositionHighlight.bind(this), 2000);
|
|
868
|
-
}
|
|
869
|
-
}
|
|
870
|
-
this.setSelection(TextUtils.TextRange.TextRange.createFromLocation(lineNumber, columnNumber));
|
|
871
|
-
}
|
|
872
|
-
|
|
873
|
-
clearPositionHighlight(): void {
|
|
874
|
-
if (this.clearHighlightTimeout) {
|
|
875
|
-
clearTimeout(this.clearHighlightTimeout);
|
|
876
|
-
}
|
|
877
|
-
delete this.clearHighlightTimeout;
|
|
878
|
-
|
|
879
|
-
if (this.highlightedLine) {
|
|
880
|
-
this.codeMirrorInternal.removeLineClass(
|
|
881
|
-
// @ts-ignore the `null` argument should be a string?
|
|
882
|
-
this.highlightedLine, null, this.readOnlyInternal ? 'cm-readonly-highlight' : 'cm-highlight');
|
|
883
|
-
}
|
|
884
|
-
delete this.highlightedLine;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
|
-
elementsToRestoreScrollPositionsFor(): Element[] {
|
|
888
|
-
return [];
|
|
889
|
-
}
|
|
890
|
-
|
|
891
|
-
private updatePaddingBottom(width: number, height: number): void {
|
|
892
|
-
let newPaddingBottom = 0;
|
|
893
|
-
const linesElement = this.codeMirrorElement.getElementsByClassName('CodeMirror-lines')[0] as HTMLElement;
|
|
894
|
-
|
|
895
|
-
if (this.options.padBottom) {
|
|
896
|
-
const scrollInfo = this.codeMirrorInternal.getScrollInfo();
|
|
897
|
-
const lineCount = this.codeMirrorInternal.lineCount();
|
|
898
|
-
if (lineCount > 1) {
|
|
899
|
-
newPaddingBottom =
|
|
900
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
901
|
-
Math.max(
|
|
902
|
-
scrollInfo.clientHeight -
|
|
903
|
-
this.codeMirrorInternal.getLineHandle(this.codeMirrorInternal.lastLine()).height,
|
|
904
|
-
0);
|
|
905
|
-
}
|
|
906
|
-
}
|
|
907
|
-
const stringPaddingBottomValue = String(newPaddingBottom) + 'px';
|
|
908
|
-
if (linesElement.style.paddingBottom !== stringPaddingBottomValue) {
|
|
909
|
-
linesElement.style.paddingBottom = stringPaddingBottomValue;
|
|
910
|
-
this.codeMirrorInternal.setSize(width, height);
|
|
911
|
-
}
|
|
912
|
-
}
|
|
913
|
-
|
|
914
|
-
toggleScrollPastEof(enableScrolling: boolean): void {
|
|
915
|
-
if (this.options.padBottom === enableScrolling) {
|
|
916
|
-
return;
|
|
917
|
-
}
|
|
918
|
-
|
|
919
|
-
this.options.padBottom = enableScrolling;
|
|
920
|
-
this.resizeEditor();
|
|
921
|
-
}
|
|
922
|
-
|
|
923
|
-
private resizeEditor(): void {
|
|
924
|
-
const parentElement = this.element.parentElement;
|
|
925
|
-
if (!parentElement || !this.isShowing()) {
|
|
926
|
-
return;
|
|
927
|
-
}
|
|
928
|
-
this.codeMirrorInternal.operation(() => {
|
|
929
|
-
const scrollLeft = this.codeMirrorInternal.doc.scrollLeft;
|
|
930
|
-
const scrollTop = this.codeMirrorInternal.doc.scrollTop;
|
|
931
|
-
const width = parentElement.offsetWidth;
|
|
932
|
-
const height = parentElement.offsetHeight - this.element.offsetTop;
|
|
933
|
-
if (this.options.autoHeight) {
|
|
934
|
-
this.codeMirrorInternal.setSize(width, 'auto');
|
|
935
|
-
} else {
|
|
936
|
-
this.codeMirrorInternal.setSize(width, height);
|
|
937
|
-
this.updatePaddingBottom(width, height);
|
|
938
|
-
}
|
|
939
|
-
this.codeMirrorInternal.scrollTo(scrollLeft, scrollTop);
|
|
940
|
-
});
|
|
941
|
-
}
|
|
942
|
-
|
|
943
|
-
onResize(): void {
|
|
944
|
-
if (this.autocompleteController) {
|
|
945
|
-
this.autocompleteController.clearAutocomplete();
|
|
946
|
-
}
|
|
947
|
-
this.resizeEditor();
|
|
948
|
-
this.editorSizeInSync = true;
|
|
949
|
-
if (this.selectionSetScheduled) {
|
|
950
|
-
delete this.selectionSetScheduled;
|
|
951
|
-
if (this.lastSelectionInternal) {
|
|
952
|
-
this.setSelection(this.lastSelectionInternal);
|
|
953
|
-
}
|
|
954
|
-
}
|
|
955
|
-
}
|
|
956
|
-
|
|
957
|
-
editRange(range: TextUtils.TextRange.TextRange, text: string, origin?: string): TextUtils.TextRange.TextRange {
|
|
958
|
-
const pos = TextUtils.CodeMirrorUtils.toPos(range);
|
|
959
|
-
this.codeMirrorInternal.replaceRange(text, pos.start, pos.end, origin);
|
|
960
|
-
const newRange = TextUtils.CodeMirrorUtils.toRange(
|
|
961
|
-
pos.start, this.codeMirrorInternal.posFromIndex(this.codeMirrorInternal.indexFromPos(pos.start) + text.length));
|
|
962
|
-
this.dispatchEventToListeners(UI.TextEditor.Events.TextChanged, {oldRange: range, newRange: newRange});
|
|
963
|
-
return newRange;
|
|
964
|
-
}
|
|
965
|
-
|
|
966
|
-
clearAutocomplete(): void {
|
|
967
|
-
if (this.autocompleteController) {
|
|
968
|
-
this.autocompleteController.clearAutocomplete();
|
|
969
|
-
}
|
|
970
|
-
}
|
|
971
|
-
|
|
972
|
-
wordRangeForCursorPosition(lineNumber: number, column: number, isWordChar: (arg0: string) => boolean):
|
|
973
|
-
TextUtils.TextRange.TextRange {
|
|
974
|
-
const line = this.line(lineNumber);
|
|
975
|
-
let wordStart: number = column;
|
|
976
|
-
if (column !== 0 && isWordChar(line.charAt(column - 1))) {
|
|
977
|
-
wordStart = column - 1;
|
|
978
|
-
while (wordStart > 0 && isWordChar(line.charAt(wordStart - 1))) {
|
|
979
|
-
--wordStart;
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
let wordEnd = column;
|
|
983
|
-
while (wordEnd < line.length && isWordChar(line.charAt(wordEnd))) {
|
|
984
|
-
++wordEnd;
|
|
985
|
-
}
|
|
986
|
-
return new TextUtils.TextRange.TextRange(lineNumber, wordStart, lineNumber, wordEnd);
|
|
987
|
-
}
|
|
988
|
-
|
|
989
|
-
// https://crbug.com/1151919 first * = CodeMirror.Editor, second * = CodeMirror.EditorChangeLinkedList
|
|
990
|
-
private changes(codeMirror: any, changes: any): void {
|
|
991
|
-
if (!changes.length) {
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
|
|
995
|
-
this.updatePlaceholder();
|
|
996
|
-
|
|
997
|
-
// We do not show "scroll beyond end of file" span for one line documents, so we need to check if "document has one line" changed.
|
|
998
|
-
const hasOneLine = this.codeMirrorInternal.lineCount() === 1;
|
|
999
|
-
if (hasOneLine !== this.hasOneLine) {
|
|
1000
|
-
this.resizeEditor();
|
|
1001
|
-
}
|
|
1002
|
-
this.hasOneLine = hasOneLine;
|
|
1003
|
-
|
|
1004
|
-
this.decorations.valuesArray().forEach(decoration => this.codeMirrorInternal.removeLineWidget(decoration.widget));
|
|
1005
|
-
this.decorations.clear();
|
|
1006
|
-
|
|
1007
|
-
const edits = [];
|
|
1008
|
-
let currentEdit;
|
|
1009
|
-
|
|
1010
|
-
for (let changeIndex = 0; changeIndex < changes.length; ++changeIndex) {
|
|
1011
|
-
const changeObject = changes[changeIndex];
|
|
1012
|
-
const edit = TextUtils.CodeMirrorUtils.changeObjectToEditOperation(changeObject);
|
|
1013
|
-
if (currentEdit && edit.oldRange.equal(currentEdit.newRange)) {
|
|
1014
|
-
currentEdit.newRange = edit.newRange;
|
|
1015
|
-
} else {
|
|
1016
|
-
currentEdit = edit;
|
|
1017
|
-
edits.push(currentEdit);
|
|
1018
|
-
}
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
for (let i = 0; i < edits.length; i++) {
|
|
1022
|
-
this.dispatchEventToListeners(
|
|
1023
|
-
UI.TextEditor.Events.TextChanged, {oldRange: edits[i].oldRange, newRange: edits[i].newRange});
|
|
1024
|
-
}
|
|
1025
|
-
}
|
|
1026
|
-
|
|
1027
|
-
// https://crbug.com/1151919 first * = CodeMirror.Editor, second and third * = CodeMirror.Pos
|
|
1028
|
-
private beforeSelectionChange(_codeMirror: any, _selection: {
|
|
1029
|
-
ranges: Array<{
|
|
1030
|
-
head: any,
|
|
1031
|
-
anchor: any,
|
|
1032
|
-
}>,
|
|
1033
|
-
}): void {
|
|
1034
|
-
this.selectNextOccurrenceController.selectionWillChange();
|
|
1035
|
-
}
|
|
1036
|
-
|
|
1037
|
-
scrollToLine(lineNumber: number): void {
|
|
1038
|
-
const pos = new CodeMirror.Pos(lineNumber, 0);
|
|
1039
|
-
const coords = this.codeMirrorInternal.charCoords(pos, 'local');
|
|
1040
|
-
this.codeMirrorInternal.scrollTo(0, coords.top);
|
|
1041
|
-
}
|
|
1042
|
-
|
|
1043
|
-
firstVisibleLine(): number {
|
|
1044
|
-
return this.codeMirrorInternal.lineAtHeight(this.codeMirrorInternal.getScrollInfo().top, 'local');
|
|
1045
|
-
}
|
|
1046
|
-
|
|
1047
|
-
scrollTop(): number {
|
|
1048
|
-
return this.codeMirrorInternal.getScrollInfo().top;
|
|
1049
|
-
}
|
|
1050
|
-
|
|
1051
|
-
setScrollTop(scrollTop: number): void {
|
|
1052
|
-
this.codeMirrorInternal.scrollTo(0, scrollTop);
|
|
1053
|
-
}
|
|
1054
|
-
|
|
1055
|
-
lastVisibleLine(): number {
|
|
1056
|
-
const scrollInfo = this.codeMirrorInternal.getScrollInfo();
|
|
1057
|
-
return this.codeMirrorInternal.lineAtHeight(scrollInfo.top + scrollInfo.clientHeight, 'local');
|
|
1058
|
-
}
|
|
1059
|
-
|
|
1060
|
-
selection(): TextUtils.TextRange.TextRange {
|
|
1061
|
-
const start = this.codeMirrorInternal.getCursor('anchor');
|
|
1062
|
-
const end = this.codeMirrorInternal.getCursor('head');
|
|
1063
|
-
|
|
1064
|
-
return TextUtils.CodeMirrorUtils.toRange(start, end);
|
|
1065
|
-
}
|
|
1066
|
-
|
|
1067
|
-
selections(): TextUtils.TextRange.TextRange[] {
|
|
1068
|
-
const selectionList = this.codeMirrorInternal.listSelections();
|
|
1069
|
-
const result = [];
|
|
1070
|
-
for (let i = 0; i < selectionList.length; ++i) {
|
|
1071
|
-
const selection = selectionList[i];
|
|
1072
|
-
result.push(TextUtils.CodeMirrorUtils.toRange(selection.anchor, selection.head));
|
|
1073
|
-
}
|
|
1074
|
-
return result;
|
|
1075
|
-
}
|
|
1076
|
-
|
|
1077
|
-
lastSelection(): TextUtils.TextRange.TextRange|null {
|
|
1078
|
-
return this.lastSelectionInternal || null;
|
|
1079
|
-
}
|
|
1080
|
-
|
|
1081
|
-
setSelection(textRange: TextUtils.TextRange.TextRange, dontScroll?: boolean): void {
|
|
1082
|
-
this.lastSelectionInternal = textRange;
|
|
1083
|
-
if (!this.editorSizeInSync) {
|
|
1084
|
-
this.selectionSetScheduled = true;
|
|
1085
|
-
return;
|
|
1086
|
-
}
|
|
1087
|
-
const pos = TextUtils.CodeMirrorUtils.toPos(textRange);
|
|
1088
|
-
// https://crbug.com/1151919 both * = CodeMirror.Position
|
|
1089
|
-
const startAsPosition = (pos.start as any);
|
|
1090
|
-
const endAsPosition = (pos.end as any);
|
|
1091
|
-
const scroll = !dontScroll;
|
|
1092
|
-
this.codeMirrorInternal.setSelection(startAsPosition, endAsPosition, {scroll});
|
|
1093
|
-
}
|
|
1094
|
-
|
|
1095
|
-
setSelections(ranges: TextUtils.TextRange.TextRange[], primarySelectionIndex?: number): void {
|
|
1096
|
-
const selections = [];
|
|
1097
|
-
for (let i = 0; i < ranges.length; ++i) {
|
|
1098
|
-
const selection = TextUtils.CodeMirrorUtils.toPos(ranges[i]);
|
|
1099
|
-
selections.push({anchor: selection.start, head: selection.end});
|
|
1100
|
-
}
|
|
1101
|
-
primarySelectionIndex = primarySelectionIndex || 0;
|
|
1102
|
-
this.codeMirrorInternal.setSelections(selections, primarySelectionIndex, {scroll: false});
|
|
1103
|
-
}
|
|
1104
|
-
|
|
1105
|
-
private detectLineSeparator(text: string): void {
|
|
1106
|
-
this.lineSeparator = text.indexOf('\r\n') >= 0 ? '\r\n' : '\n';
|
|
1107
|
-
}
|
|
1108
|
-
|
|
1109
|
-
setText(text: string): void {
|
|
1110
|
-
if (text.length > CodeMirrorTextEditor.MaxEditableTextSize) {
|
|
1111
|
-
this.configureAutocomplete(null);
|
|
1112
|
-
this.setReadOnly(true);
|
|
1113
|
-
}
|
|
1114
|
-
this.codeMirrorInternal.setValue(text);
|
|
1115
|
-
if (this.shouldClearHistory) {
|
|
1116
|
-
this.codeMirrorInternal.clearHistory();
|
|
1117
|
-
this.shouldClearHistory = false;
|
|
1118
|
-
}
|
|
1119
|
-
this.detectLineSeparator(text);
|
|
1120
|
-
|
|
1121
|
-
if (this.hasLongLines()) {
|
|
1122
|
-
this.enableLongLinesMode();
|
|
1123
|
-
} else {
|
|
1124
|
-
this.disableLongLinesMode();
|
|
1125
|
-
}
|
|
1126
|
-
|
|
1127
|
-
if (!this.isShowing()) {
|
|
1128
|
-
this.refresh();
|
|
1129
|
-
}
|
|
1130
|
-
}
|
|
1131
|
-
|
|
1132
|
-
text(textRange?: TextUtils.TextRange.TextRange): string {
|
|
1133
|
-
if (!textRange) {
|
|
1134
|
-
return this.codeMirrorInternal.getValue(this.lineSeparator);
|
|
1135
|
-
}
|
|
1136
|
-
const pos = TextUtils.CodeMirrorUtils.toPos(textRange.normalize());
|
|
1137
|
-
return this.codeMirrorInternal.getRange(pos.start, pos.end, this.lineSeparator);
|
|
1138
|
-
}
|
|
1139
|
-
|
|
1140
|
-
textWithCurrentSuggestion(): string {
|
|
1141
|
-
if (!this.autocompleteController) {
|
|
1142
|
-
return this.text();
|
|
1143
|
-
}
|
|
1144
|
-
return this.autocompleteController.textWithCurrentSuggestion();
|
|
1145
|
-
}
|
|
1146
|
-
|
|
1147
|
-
fullRange(): TextUtils.TextRange.TextRange {
|
|
1148
|
-
const lineCount = this.linesCount;
|
|
1149
|
-
const lastLine = this.codeMirrorInternal.getLine(lineCount - 1);
|
|
1150
|
-
return TextUtils.CodeMirrorUtils.toRange(
|
|
1151
|
-
new CodeMirror.Pos(0, 0), new CodeMirror.Pos(lineCount - 1, lastLine.length));
|
|
1152
|
-
}
|
|
1153
|
-
|
|
1154
|
-
currentLineNumber(): number {
|
|
1155
|
-
return this.codeMirrorInternal.getCursor().line;
|
|
1156
|
-
}
|
|
1157
|
-
|
|
1158
|
-
line(lineNumber: number): string {
|
|
1159
|
-
return this.codeMirrorInternal.getLine(lineNumber);
|
|
1160
|
-
}
|
|
1161
|
-
|
|
1162
|
-
get linesCount(): number {
|
|
1163
|
-
return this.codeMirrorInternal.lineCount();
|
|
1164
|
-
}
|
|
1165
|
-
|
|
1166
|
-
newlineAndIndent(): void {
|
|
1167
|
-
this.codeMirrorInternal.execCommand('newlineAndIndent');
|
|
1168
|
-
}
|
|
1169
|
-
|
|
1170
|
-
textEditorPositionHandle(lineNumber: number, columnNumber: number): TextEditorPositionHandle {
|
|
1171
|
-
return new CodeMirrorPositionHandle(this.codeMirrorInternal, new CodeMirror.Pos(lineNumber, columnNumber));
|
|
1172
|
-
}
|
|
1173
|
-
|
|
1174
|
-
private updatePlaceholder(): void {
|
|
1175
|
-
if (!this.placeholderElement) {
|
|
1176
|
-
return;
|
|
1177
|
-
}
|
|
1178
|
-
|
|
1179
|
-
this.placeholderElement.remove();
|
|
1180
|
-
|
|
1181
|
-
if (this.linesCount === 1 && !this.line(0)) {
|
|
1182
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1183
|
-
this.codeMirrorInternal.display.lineSpace.insertBefore(
|
|
1184
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1185
|
-
this.placeholderElement, this.codeMirrorInternal.display.lineSpace.firstChild);
|
|
1186
|
-
}
|
|
1187
|
-
}
|
|
1188
|
-
|
|
1189
|
-
static readonly maxHighlightLength = 1000;
|
|
1190
|
-
static readonly LongLineModeLineLengthThreshold = 2000;
|
|
1191
|
-
static readonly MaxEditableTextSize = 1024 * 1024 * 10;
|
|
1192
|
-
}
|
|
1193
|
-
|
|
1194
|
-
CodeMirrorTextEditor.overrideModeWithPrefixedTokens('css', 'css-');
|
|
1195
|
-
CodeMirrorTextEditor.overrideModeWithPrefixedTokens('javascript', 'js-');
|
|
1196
|
-
CodeMirrorTextEditor.overrideModeWithPrefixedTokens('xml', 'xml-');
|
|
1197
|
-
|
|
1198
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1199
|
-
CodeMirror.commands.autocomplete = CodeMirrorTextEditor.autocompleteCommand;
|
|
1200
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1201
|
-
CodeMirror.commands.undoLastSelection = CodeMirrorTextEditor.undoLastSelectionCommand;
|
|
1202
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1203
|
-
CodeMirror.commands.selectNextOccurrence = CodeMirrorTextEditor.selectNextOccurrenceCommand;
|
|
1204
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1205
|
-
CodeMirror.commands.moveCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, false);
|
|
1206
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1207
|
-
CodeMirror.commands.selectCamelLeft = CodeMirrorTextEditor.moveCamelLeftCommand.bind(null, true);
|
|
1208
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1209
|
-
CodeMirror.commands.moveCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, false);
|
|
1210
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1211
|
-
CodeMirror.commands.selectCamelRight = CodeMirrorTextEditor.moveCamelRightCommand.bind(null, true);
|
|
1212
|
-
|
|
1213
|
-
// @ts-ignore https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1214
|
-
CodeMirror.commands.UserIndent = function(codeMirror: any): void {
|
|
1215
|
-
const ranges = codeMirror.listSelections();
|
|
1216
|
-
if (ranges.length === 0) {
|
|
1217
|
-
return;
|
|
1218
|
-
}
|
|
1219
|
-
|
|
1220
|
-
if (codeMirror.somethingSelected()) {
|
|
1221
|
-
codeMirror.indentSelection('add');
|
|
1222
|
-
return;
|
|
1223
|
-
}
|
|
1224
|
-
|
|
1225
|
-
const indentation = Common.Settings.Settings.instance().moduleSetting('textEditorIndent').get();
|
|
1226
|
-
codeMirror.replaceSelection(indentation);
|
|
1227
|
-
};
|
|
1228
|
-
|
|
1229
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1230
|
-
// @ts-ignore TS doesn't find the property even though it's defined in codemirror-legacy.d.ts
|
|
1231
|
-
CodeMirror.commands.indentLessOrPass = function(codeMirror: any): Object|undefined {
|
|
1232
|
-
const selections = codeMirror.listSelections();
|
|
1233
|
-
if (selections.length === 1) {
|
|
1234
|
-
const range = TextUtils.CodeMirrorUtils.toRange(selections[0].anchor, selections[0].head);
|
|
1235
|
-
if (range.isEmpty() && !/^\s/.test(codeMirror.getLine(range.startLine))) {
|
|
1236
|
-
return CodeMirror.Pass;
|
|
1237
|
-
}
|
|
1238
|
-
}
|
|
1239
|
-
codeMirror.execCommand('indentLess');
|
|
1240
|
-
return undefined;
|
|
1241
|
-
};
|
|
1242
|
-
|
|
1243
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1244
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1245
|
-
CodeMirror.commands.gotoMatchingBracket = function(codeMirror: any): void {
|
|
1246
|
-
const updatedSelections = [];
|
|
1247
|
-
const selections = codeMirror.listSelections();
|
|
1248
|
-
for (let i = 0; i < selections.length; ++i) {
|
|
1249
|
-
const selection = selections[i];
|
|
1250
|
-
const cursor = selection.head;
|
|
1251
|
-
// @ts-ignore findMatchingBracket types are incorrect
|
|
1252
|
-
const matchingBracket = codeMirror.findMatchingBracket(cursor, false, {maxScanLines: 10000});
|
|
1253
|
-
let updatedHead = cursor;
|
|
1254
|
-
if (matchingBracket && matchingBracket.match) {
|
|
1255
|
-
const columnCorrection = CodeMirror.cmpPos(matchingBracket.from, cursor) === 0 ? 1 : 0;
|
|
1256
|
-
updatedHead = new CodeMirror.Pos(matchingBracket.to.line, matchingBracket.to.ch + columnCorrection);
|
|
1257
|
-
}
|
|
1258
|
-
updatedSelections.push({anchor: updatedHead, head: updatedHead});
|
|
1259
|
-
}
|
|
1260
|
-
codeMirror.setSelections(updatedSelections);
|
|
1261
|
-
};
|
|
1262
|
-
|
|
1263
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1264
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1265
|
-
CodeMirror.commands.undoAndReveal = function(codemirror: any): void {
|
|
1266
|
-
const scrollInfo = codemirror.getScrollInfo();
|
|
1267
|
-
codemirror.execCommand('undo');
|
|
1268
|
-
const cursor = codemirror.getCursor('start');
|
|
1269
|
-
CodeMirrorTextEditor.getForCodeMirror(codemirror).innerRevealLine(cursor.line, scrollInfo);
|
|
1270
|
-
const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codemirror).autocompleteController;
|
|
1271
|
-
if (autocompleteController) {
|
|
1272
|
-
autocompleteController.clearAutocomplete();
|
|
1273
|
-
}
|
|
1274
|
-
};
|
|
1275
|
-
|
|
1276
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1277
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1278
|
-
CodeMirror.commands.redoAndReveal = function(codemirror: any): void {
|
|
1279
|
-
const scrollInfo = codemirror.getScrollInfo();
|
|
1280
|
-
codemirror.execCommand('redo');
|
|
1281
|
-
const cursor = codemirror.getCursor('start');
|
|
1282
|
-
CodeMirrorTextEditor.getForCodeMirror(codemirror).innerRevealLine(cursor.line, scrollInfo);
|
|
1283
|
-
const autocompleteController = CodeMirrorTextEditor.getForCodeMirror(codemirror).autocompleteController;
|
|
1284
|
-
if (autocompleteController) {
|
|
1285
|
-
autocompleteController.clearAutocomplete();
|
|
1286
|
-
}
|
|
1287
|
-
};
|
|
1288
|
-
|
|
1289
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1290
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1291
|
-
CodeMirror.commands.dismiss = function(codemirror: any): Object|undefined {
|
|
1292
|
-
const selections = codemirror.listSelections();
|
|
1293
|
-
const selection = selections[0];
|
|
1294
|
-
if (selections.length === 1) {
|
|
1295
|
-
if (TextUtils.CodeMirrorUtils.toRange(selection.anchor, selection.head).isEmpty()) {
|
|
1296
|
-
return CodeMirror.Pass;
|
|
1297
|
-
}
|
|
1298
|
-
codemirror.setSelection(selection.anchor, selection.anchor, {scroll: false});
|
|
1299
|
-
CodeMirrorTextEditor.getForCodeMirror(codemirror).scrollLineIntoView(selection.anchor.line);
|
|
1300
|
-
return;
|
|
1301
|
-
}
|
|
1302
|
-
|
|
1303
|
-
codemirror.setSelection(selection.anchor, selection.head, {scroll: false});
|
|
1304
|
-
CodeMirrorTextEditor.getForCodeMirror(codemirror).scrollLineIntoView(selection.anchor.line);
|
|
1305
|
-
return undefined;
|
|
1306
|
-
};
|
|
1307
|
-
|
|
1308
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1309
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1310
|
-
CodeMirror.commands.goSmartPageUp = function(codemirror: any): Object|undefined {
|
|
1311
|
-
if (CodeMirrorTextEditor.getForCodeMirror(codemirror)
|
|
1312
|
-
.selection()
|
|
1313
|
-
.equal(TextUtils.TextRange.TextRange.createFromLocation(0, 0))) {
|
|
1314
|
-
return CodeMirror.Pass;
|
|
1315
|
-
}
|
|
1316
|
-
codemirror.execCommand('goPageUp');
|
|
1317
|
-
return undefined;
|
|
1318
|
-
};
|
|
1319
|
-
|
|
1320
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1321
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1322
|
-
CodeMirror.commands.goSmartPageDown = function(codemirror: any): Object|undefined {
|
|
1323
|
-
if (CodeMirrorTextEditor.getForCodeMirror(codemirror)
|
|
1324
|
-
.selection()
|
|
1325
|
-
.equal(CodeMirrorTextEditor.getForCodeMirror(codemirror).fullRange().collapseToEnd())) {
|
|
1326
|
-
return CodeMirror.Pass;
|
|
1327
|
-
}
|
|
1328
|
-
codemirror.execCommand('goPageDown');
|
|
1329
|
-
return undefined;
|
|
1330
|
-
};
|
|
1331
|
-
|
|
1332
|
-
export class CodeMirrorPositionHandle implements TextEditorPositionHandle {
|
|
1333
|
-
private readonly codeMirror: any;
|
|
1334
|
-
private readonly lineHandle: any;
|
|
1335
|
-
private readonly columnNumber: any;
|
|
1336
|
-
// https://crbug.com/1151919 first * = CodeMirror.Editor, second * = CodeMirror.Pos
|
|
1337
|
-
constructor(codeMirror: any, pos: any) {
|
|
1338
|
-
this.codeMirror = codeMirror;
|
|
1339
|
-
this.lineHandle = codeMirror.getLineHandle(pos.line);
|
|
1340
|
-
this.columnNumber = pos.ch;
|
|
1341
|
-
}
|
|
1342
|
-
|
|
1343
|
-
resolve(): {
|
|
1344
|
-
lineNumber: number,
|
|
1345
|
-
columnNumber: number,
|
|
1346
|
-
}|null {
|
|
1347
|
-
const lineNumber = this.lineHandle ? this.codeMirror.getLineNumber(this.lineHandle) : null;
|
|
1348
|
-
if (typeof lineNumber !== 'number') {
|
|
1349
|
-
return null;
|
|
1350
|
-
}
|
|
1351
|
-
return {lineNumber: lineNumber, columnNumber: this.columnNumber};
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
equal(argPositionHandle: TextEditorPositionHandle): boolean {
|
|
1355
|
-
const positionHandle = argPositionHandle as CodeMirrorPositionHandle;
|
|
1356
|
-
return positionHandle.lineHandle === this.lineHandle && positionHandle.columnNumber === this.columnNumber &&
|
|
1357
|
-
positionHandle.codeMirror === this.codeMirror;
|
|
1358
|
-
}
|
|
1359
|
-
}
|
|
1360
|
-
|
|
1361
|
-
export class SelectNextOccurrenceController {
|
|
1362
|
-
private readonly textEditor: CodeMirrorTextEditor;
|
|
1363
|
-
private readonly codeMirror: any;
|
|
1364
|
-
private muteSelectionListener?: boolean;
|
|
1365
|
-
private fullWordSelection?: boolean;
|
|
1366
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1367
|
-
constructor(textEditor: CodeMirrorTextEditor, codeMirror: any) {
|
|
1368
|
-
this.textEditor = textEditor;
|
|
1369
|
-
this.codeMirror = codeMirror;
|
|
1370
|
-
}
|
|
1371
|
-
|
|
1372
|
-
selectionWillChange(): void {
|
|
1373
|
-
if (!this.muteSelectionListener) {
|
|
1374
|
-
delete this.fullWordSelection;
|
|
1375
|
-
}
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
private findRange(selections: TextUtils.TextRange.TextRange[], range: TextUtils.TextRange.TextRange): boolean {
|
|
1379
|
-
for (let i = 0; i < selections.length; ++i) {
|
|
1380
|
-
if (range.equal(selections[i])) {
|
|
1381
|
-
return true;
|
|
1382
|
-
}
|
|
1383
|
-
}
|
|
1384
|
-
return false;
|
|
1385
|
-
}
|
|
1386
|
-
|
|
1387
|
-
undoLastSelection(): void {
|
|
1388
|
-
this.muteSelectionListener = true;
|
|
1389
|
-
this.codeMirror.execCommand('undoSelection');
|
|
1390
|
-
this.muteSelectionListener = false;
|
|
1391
|
-
}
|
|
1392
|
-
|
|
1393
|
-
selectNextOccurrence(): void {
|
|
1394
|
-
const selections = this.textEditor.selections();
|
|
1395
|
-
let anyEmptySelection = false;
|
|
1396
|
-
for (let i = 0; i < selections.length; ++i) {
|
|
1397
|
-
const selection = selections[i];
|
|
1398
|
-
anyEmptySelection = anyEmptySelection || selection.isEmpty();
|
|
1399
|
-
if (selection.startLine !== selection.endLine) {
|
|
1400
|
-
return;
|
|
1401
|
-
}
|
|
1402
|
-
}
|
|
1403
|
-
if (anyEmptySelection) {
|
|
1404
|
-
this.expandSelectionsToWords(selections);
|
|
1405
|
-
return;
|
|
1406
|
-
}
|
|
1407
|
-
|
|
1408
|
-
const last = selections[selections.length - 1];
|
|
1409
|
-
let next: (TextUtils.TextRange.TextRange|null)|TextUtils.TextRange.TextRange = last;
|
|
1410
|
-
do {
|
|
1411
|
-
next = next ? this.findNextOccurrence(next, Boolean(this.fullWordSelection)) : null;
|
|
1412
|
-
} while (next && this.findRange(selections, next) && !next.equal(last));
|
|
1413
|
-
|
|
1414
|
-
if (!next) {
|
|
1415
|
-
return;
|
|
1416
|
-
}
|
|
1417
|
-
selections.push(next);
|
|
1418
|
-
|
|
1419
|
-
this.muteSelectionListener = true;
|
|
1420
|
-
this.textEditor.setSelections(selections, selections.length - 1);
|
|
1421
|
-
delete this.muteSelectionListener;
|
|
1422
|
-
|
|
1423
|
-
this.textEditor.scrollLineIntoView(next.startLine);
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
private expandSelectionsToWords(selections: TextUtils.TextRange.TextRange[]): void {
|
|
1427
|
-
const newSelections = [];
|
|
1428
|
-
for (let i = 0; i < selections.length; ++i) {
|
|
1429
|
-
const selection = selections[i];
|
|
1430
|
-
const startRangeWord = this.textEditor.wordRangeForCursorPosition(
|
|
1431
|
-
selection.startLine, selection.startColumn, TextUtils.TextUtils.Utils.isWordChar) ||
|
|
1432
|
-
TextUtils.TextRange.TextRange.createFromLocation(selection.startLine, selection.startColumn);
|
|
1433
|
-
const endRangeWord = this.textEditor.wordRangeForCursorPosition(
|
|
1434
|
-
selection.endLine, selection.endColumn, TextUtils.TextUtils.Utils.isWordChar) ||
|
|
1435
|
-
TextUtils.TextRange.TextRange.createFromLocation(selection.endLine, selection.endColumn);
|
|
1436
|
-
const newSelection = new TextUtils.TextRange.TextRange(
|
|
1437
|
-
startRangeWord.startLine, startRangeWord.startColumn, endRangeWord.endLine, endRangeWord.endColumn);
|
|
1438
|
-
newSelections.push(newSelection);
|
|
1439
|
-
}
|
|
1440
|
-
this.textEditor.setSelections(newSelections, newSelections.length - 1);
|
|
1441
|
-
this.fullWordSelection = true;
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
|
-
private findNextOccurrence(range: TextUtils.TextRange.TextRange, fullWord: boolean): TextUtils.TextRange.TextRange
|
|
1445
|
-
|null {
|
|
1446
|
-
range = range.normalize();
|
|
1447
|
-
let matchedLineNumber: number|undefined = undefined;
|
|
1448
|
-
let matchedColumnNumber: number|undefined = undefined;
|
|
1449
|
-
const textToFind = this.textEditor.text(range);
|
|
1450
|
-
function findWordInLine(
|
|
1451
|
-
wordRegex: RegExp, lineNumber: number, lineText: string, from: number, to: number): boolean {
|
|
1452
|
-
if (typeof matchedLineNumber === 'number') {
|
|
1453
|
-
return true;
|
|
1454
|
-
}
|
|
1455
|
-
wordRegex.lastIndex = from;
|
|
1456
|
-
const result = wordRegex.exec(lineText);
|
|
1457
|
-
if (!result || result.index + textToFind.length > to) {
|
|
1458
|
-
return false;
|
|
1459
|
-
}
|
|
1460
|
-
matchedLineNumber = lineNumber;
|
|
1461
|
-
matchedColumnNumber = result.index;
|
|
1462
|
-
return true;
|
|
1463
|
-
}
|
|
1464
|
-
|
|
1465
|
-
let iteratedLineNumber: number;
|
|
1466
|
-
// https://crbug.com/1151919 * = CodeMirror.LineHandle
|
|
1467
|
-
function lineIterator(regex: RegExp, lineHandle: any): true|undefined {
|
|
1468
|
-
if (findWordInLine(regex, iteratedLineNumber++, lineHandle.text, 0, lineHandle.text.length)) {
|
|
1469
|
-
return true;
|
|
1470
|
-
}
|
|
1471
|
-
return undefined;
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
let regexSource = Platform.StringUtilities.escapeForRegExp(textToFind);
|
|
1475
|
-
if (fullWord) {
|
|
1476
|
-
regexSource = '\\b' + regexSource + '\\b';
|
|
1477
|
-
}
|
|
1478
|
-
const wordRegex = new RegExp(regexSource, 'g');
|
|
1479
|
-
const currentLineText = this.codeMirror.getLine(range.startLine);
|
|
1480
|
-
|
|
1481
|
-
findWordInLine(wordRegex, range.startLine, currentLineText, range.endColumn, currentLineText.length);
|
|
1482
|
-
iteratedLineNumber = range.startLine + 1;
|
|
1483
|
-
this.codeMirror.eachLine(range.startLine + 1, this.codeMirror.lineCount(), lineIterator.bind(null, wordRegex));
|
|
1484
|
-
iteratedLineNumber = 0;
|
|
1485
|
-
this.codeMirror.eachLine(0, range.startLine, lineIterator.bind(null, wordRegex));
|
|
1486
|
-
findWordInLine(wordRegex, range.startLine, currentLineText, 0, range.startColumn);
|
|
1487
|
-
|
|
1488
|
-
if (typeof matchedLineNumber !== 'number' || typeof matchedColumnNumber !== 'number') {
|
|
1489
|
-
return null;
|
|
1490
|
-
}
|
|
1491
|
-
const textToFindLength = textToFind ? textToFind.length : 0;
|
|
1492
|
-
return new TextUtils.TextRange.TextRange(
|
|
1493
|
-
matchedLineNumber as number, matchedColumnNumber as number, matchedLineNumber as number,
|
|
1494
|
-
matchedColumnNumber + textToFindLength);
|
|
1495
|
-
}
|
|
1496
|
-
}
|
|
1497
|
-
|
|
1498
|
-
/**
|
|
1499
|
-
* @interface
|
|
1500
|
-
*/
|
|
1501
|
-
export interface TextEditorPositionHandle {
|
|
1502
|
-
resolve(): {
|
|
1503
|
-
lineNumber: number,
|
|
1504
|
-
columnNumber: number,
|
|
1505
|
-
}|null;
|
|
1506
|
-
|
|
1507
|
-
equal(positionHandle: TextEditorPositionHandle): boolean;
|
|
1508
|
-
}
|
|
1509
|
-
|
|
1510
|
-
export class TextEditorBookMark {
|
|
1511
|
-
private readonly marker: any;
|
|
1512
|
-
private readonly typeInternal: symbol;
|
|
1513
|
-
private readonly editor: CodeMirrorTextEditor;
|
|
1514
|
-
// https://crbug.com/1151919 * = CodeMirror.TextMarker
|
|
1515
|
-
constructor(marker: any, type: symbol, editor: CodeMirrorTextEditor) {
|
|
1516
|
-
this.marker = marker;
|
|
1517
|
-
this.typeInternal = type;
|
|
1518
|
-
this.editor = editor;
|
|
1519
|
-
}
|
|
1520
|
-
|
|
1521
|
-
clear(): void {
|
|
1522
|
-
const position = this.marker.find();
|
|
1523
|
-
this.marker.clear();
|
|
1524
|
-
if (position) {
|
|
1525
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1526
|
-
this.editor.updateDecorations(position.line);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
|
|
1530
|
-
refresh(): void {
|
|
1531
|
-
this.marker.changed();
|
|
1532
|
-
const position = this.marker.find();
|
|
1533
|
-
if (position) {
|
|
1534
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1535
|
-
this.editor.updateDecorations(position.line);
|
|
1536
|
-
}
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
type(): symbol {
|
|
1540
|
-
return this.typeInternal;
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
position(): TextUtils.TextRange.TextRange|null {
|
|
1544
|
-
const pos = this.marker.find();
|
|
1545
|
-
// @ts-ignore https://crbug.com/1151919 CodeMirror types are incorrect
|
|
1546
|
-
return pos ? TextUtils.TextRange.TextRange.createFromLocation(pos.line, pos.ch) : null;
|
|
1547
|
-
}
|
|
1548
|
-
}
|
|
1549
|
-
let codeMirrorTextEditorFactoryInstance: CodeMirrorTextEditorFactory;
|
|
1550
|
-
|
|
1551
|
-
export class CodeMirrorTextEditorFactory implements UI.TextEditor.TextEditorFactory {
|
|
1552
|
-
static instance(opts: {forceNew: boolean|null} = {forceNew: null}): CodeMirrorTextEditorFactory {
|
|
1553
|
-
const {forceNew} = opts;
|
|
1554
|
-
if (!codeMirrorTextEditorFactoryInstance || forceNew) {
|
|
1555
|
-
codeMirrorTextEditorFactoryInstance = new CodeMirrorTextEditorFactory();
|
|
1556
|
-
}
|
|
1557
|
-
|
|
1558
|
-
return codeMirrorTextEditorFactoryInstance;
|
|
1559
|
-
}
|
|
1560
|
-
createEditor(options: UI.TextEditor.Options): CodeMirrorTextEditor {
|
|
1561
|
-
return new CodeMirrorTextEditor(options);
|
|
1562
|
-
}
|
|
1563
|
-
}
|
|
1564
|
-
|
|
1565
|
-
// CodeMirror uses an offscreen <textarea> to detect input. Due to inconsistencies in the many browsers it supports,
|
|
1566
|
-
// it simplifies things by regularly checking if something is in the textarea, adding those characters to the document,
|
|
1567
|
-
// and then clearing the textarea. This breaks assistive technology that wants to read from CodeMirror, because the
|
|
1568
|
-
// <textarea> that they interact with is constantly empty.
|
|
1569
|
-
// Because we target up-to-date Chrome, we can guarantee consistent input events. This lets us leave the current
|
|
1570
|
-
// line from the editor in our <textarea>. CodeMirror still expects a mostly empty <textarea>, so we pass CodeMirror a
|
|
1571
|
-
// fake <textarea> that only contains the users input.
|
|
1572
|
-
// @ts-ignore
|
|
1573
|
-
export class DevToolsAccessibleTextArea extends CodeMirror.inputStyles.textarea {
|
|
1574
|
-
textarea!: HTMLTextAreaElement;
|
|
1575
|
-
contextMenuPending: boolean;
|
|
1576
|
-
composing: boolean;
|
|
1577
|
-
cm: any;
|
|
1578
|
-
prevInput!: string;
|
|
1579
|
-
|
|
1580
|
-
// https://crbug.com/1151919 * = CodeMirror.Editor
|
|
1581
|
-
constructor(codeMirror: any) {
|
|
1582
|
-
super(codeMirror);
|
|
1583
|
-
this.cm = codeMirror;
|
|
1584
|
-
this.contextMenuPending = false;
|
|
1585
|
-
this.composing = false;
|
|
1586
|
-
}
|
|
1587
|
-
|
|
1588
|
-
init(display: Object): void {
|
|
1589
|
-
super.init(display);
|
|
1590
|
-
this.textarea.addEventListener('compositionstart', this.onCompositionStart.bind(this));
|
|
1591
|
-
}
|
|
1592
|
-
|
|
1593
|
-
private onCompositionStart(): void {
|
|
1594
|
-
if (this.textarea.selectionEnd === this.textarea.value.length) {
|
|
1595
|
-
return;
|
|
1596
|
-
}
|
|
1597
|
-
// CodeMirror always expects the caret to be at the end of the textarea
|
|
1598
|
-
// When in IME composition mode, clip the textarea to how CodeMirror expects it,
|
|
1599
|
-
// and then let CodeMirror do it's thing.
|
|
1600
|
-
this.textarea.value = this.textarea.value.substring(0, this.textarea.selectionEnd);
|
|
1601
|
-
this.textarea.setSelectionRange(this.textarea.value.length, this.textarea.value.length);
|
|
1602
|
-
this.prevInput = this.textarea.value;
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
reset(typing?: boolean): void {
|
|
1606
|
-
if (this.textAreaBusy(Boolean(typing))) {
|
|
1607
|
-
super.reset(typing);
|
|
1608
|
-
return;
|
|
1609
|
-
}
|
|
1610
|
-
|
|
1611
|
-
// When navigating around the document, keep the current visual line in the textarea.
|
|
1612
|
-
const cursor = this.cm.getCursor();
|
|
1613
|
-
let start, end;
|
|
1614
|
-
if (this.cm.getOption('lineWrapping')) {
|
|
1615
|
-
// To get the visual line, compute the leftmost and rightmost character positions.
|
|
1616
|
-
const top = this.cm.charCoords(cursor, 'page').top;
|
|
1617
|
-
start = this.cm.coordsChar({left: -Infinity, top});
|
|
1618
|
-
end = this.cm.coordsChar({left: Infinity, top});
|
|
1619
|
-
} else {
|
|
1620
|
-
// Limit the line to 1000 characters to prevent lag.
|
|
1621
|
-
const offset = Math.floor(cursor.ch / 1000) * 1000;
|
|
1622
|
-
start = {ch: offset, line: cursor.line};
|
|
1623
|
-
end = {ch: offset + 1000, line: cursor.line};
|
|
1624
|
-
}
|
|
1625
|
-
this.textarea.value = this.cm.getRange(start, end);
|
|
1626
|
-
const caretPosition = cursor.ch - start.ch;
|
|
1627
|
-
this.textarea.setSelectionRange(caretPosition, caretPosition);
|
|
1628
|
-
this.prevInput = this.textarea.value;
|
|
1629
|
-
}
|
|
1630
|
-
|
|
1631
|
-
/**
|
|
1632
|
-
* If the user is currently typing into the textarea or otherwise
|
|
1633
|
-
* modifying it, we don't want to clobber their work.
|
|
1634
|
-
*/
|
|
1635
|
-
protected textAreaBusy(typing: boolean): boolean {
|
|
1636
|
-
return typing || this.contextMenuPending || this.composing || this.cm.somethingSelected();
|
|
1637
|
-
}
|
|
1638
|
-
|
|
1639
|
-
poll(): boolean {
|
|
1640
|
-
if (this.contextMenuPending || this.composing) {
|
|
1641
|
-
return super.poll();
|
|
1642
|
-
}
|
|
1643
|
-
const text = this.textarea.value;
|
|
1644
|
-
let start = 0;
|
|
1645
|
-
const length = Math.min(this.prevInput.length, text.length);
|
|
1646
|
-
while (start < length && this.prevInput[start] === text[start]) {
|
|
1647
|
-
++start;
|
|
1648
|
-
}
|
|
1649
|
-
let end = 0;
|
|
1650
|
-
while (end < length - start && this.prevInput[this.prevInput.length - end - 1] === text[text.length - end - 1]) {
|
|
1651
|
-
++end;
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
|
-
// CodeMirror expects the user to be typing into a blank <textarea>.
|
|
1655
|
-
// Pass a fake textarea into super.poll that only contains the users input.
|
|
1656
|
-
const placeholder = this.textarea;
|
|
1657
|
-
this.textarea = document.createElement('textarea');
|
|
1658
|
-
this.textarea.value = text.substring(start, text.length - end);
|
|
1659
|
-
this.textarea.setSelectionRange(placeholder.selectionStart - start, placeholder.selectionEnd - start);
|
|
1660
|
-
this.prevInput = '';
|
|
1661
|
-
const result = super.poll();
|
|
1662
|
-
this.prevInput = text;
|
|
1663
|
-
this.textarea = placeholder;
|
|
1664
|
-
return result;
|
|
1665
|
-
}
|
|
1666
|
-
}
|
|
1667
|
-
|
|
1668
|
-
// @ts-ignore
|
|
1669
|
-
CodeMirror.inputStyles.devToolsAccessibleTextArea = DevToolsAccessibleTextArea;
|
|
1670
|
-
|
|
1671
|
-
export interface Decoration {
|
|
1672
|
-
element: Element;
|
|
1673
|
-
// https://crbug.com/1151919 * = CodeMirror.LineWidget
|
|
1674
|
-
widget: any;
|
|
1675
|
-
update: (() => void)|null;
|
|
1676
|
-
}
|