@difizen/libro-codemirror 0.1.1 → 0.1.2
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/es/auto-complete/filter.d.ts.map +1 -1
- package/es/auto-complete/filter.js +1 -7
- package/es/auto-complete/index.d.ts.map +1 -1
- package/es/auto-complete/index.js +5 -9
- package/es/auto-complete/snippet.d.ts.map +1 -1
- package/es/auto-complete/snippet.js +2 -2
- package/es/auto-complete/state.d.ts.map +1 -1
- package/es/auto-complete/state.js +5 -16
- package/es/auto-complete/view.d.ts +5 -0
- package/es/auto-complete/view.d.ts.map +1 -1
- package/es/auto-complete/view.js +2 -13
- package/es/completion.js +1 -1
- package/es/config.d.ts +15 -10
- package/es/config.d.ts.map +1 -1
- package/es/config.js +15 -6
- package/es/editor-contribution.d.ts +8 -0
- package/es/editor-contribution.d.ts.map +1 -0
- package/es/editor-contribution.js +30 -0
- package/es/editor.d.ts +40 -10
- package/es/editor.d.ts.map +1 -1
- package/es/editor.js +241 -45
- package/es/indentation-markers/map.d.ts +9 -9
- package/es/indentation-markers/map.d.ts.map +1 -1
- package/es/index.d.ts +3 -1
- package/es/index.d.ts.map +1 -1
- package/es/index.js +3 -1
- package/es/libro-icon.d.ts +2 -2
- package/es/libro-icon.d.ts.map +1 -1
- package/es/libro-icon.js +2 -2
- package/es/lsp/completion.d.ts +5 -0
- package/es/lsp/completion.d.ts.map +1 -0
- package/es/lsp/completion.js +245 -0
- package/es/lsp/format.d.ts +7 -0
- package/es/lsp/format.d.ts.map +1 -0
- package/es/lsp/format.js +193 -0
- package/es/lsp/index.d.ts +7 -0
- package/es/lsp/index.d.ts.map +1 -0
- package/es/lsp/index.js +6 -0
- package/es/lsp/lint.d.ts +3 -0
- package/es/lsp/lint.d.ts.map +1 -0
- package/es/lsp/lint.js +114 -0
- package/es/lsp/protocol.d.ts +7 -0
- package/es/lsp/protocol.d.ts.map +1 -0
- package/es/lsp/protocol.js +1 -0
- package/es/lsp/tooltip.d.ts +3 -0
- package/es/lsp/tooltip.d.ts.map +1 -0
- package/es/lsp/tooltip.js +113 -0
- package/es/lsp/util.d.ts +15 -0
- package/es/lsp/util.d.ts.map +1 -0
- package/es/lsp/util.js +58 -0
- package/es/mode.d.ts.map +1 -1
- package/es/module.d.ts +3 -0
- package/es/module.d.ts.map +1 -0
- package/es/module.js +4 -0
- package/es/theme.js +4 -5
- package/es/tooltip.d.ts.map +1 -1
- package/es/tooltip.js +2 -4
- package/package.json +7 -5
- package/src/auto-complete/filter.ts +5 -7
- package/src/auto-complete/index.ts +6 -7
- package/src/auto-complete/snippet.ts +8 -2
- package/src/auto-complete/state.ts +13 -18
- package/src/auto-complete/view.ts +7 -13
- package/src/completion.ts +2 -2
- package/src/config.ts +40 -28
- package/src/editor-contribution.ts +17 -0
- package/src/editor.ts +226 -50
- package/src/hyperlink.ts +1 -1
- package/src/indentation-markers/index.ts +3 -3
- package/src/indentation-markers/map.ts +9 -9
- package/src/index.ts +4 -1
- package/src/libro-icon.tsx +4 -0
- package/src/lsp/completion.ts +175 -0
- package/src/lsp/format.ts +144 -0
- package/src/lsp/index.ts +6 -0
- package/src/lsp/lint.ts +125 -0
- package/src/lsp/protocol.ts +8 -0
- package/src/lsp/tooltip.ts +76 -0
- package/src/lsp/util.ts +69 -0
- package/src/mode.ts +1 -1
- package/src/module.ts +8 -0
- package/src/theme.ts +4 -4
- package/src/tooltip.ts +2 -4
- package/src/libro-icon.ts +0 -4
package/src/config.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defaultKeymap,
|
|
1
|
+
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
|
2
2
|
import { pythonLanguage } from '@codemirror/lang-python';
|
|
3
3
|
import {
|
|
4
4
|
bracketMatching,
|
|
@@ -17,23 +17,23 @@ import { Compartment, EditorState, StateEffect } from '@codemirror/state';
|
|
|
17
17
|
import type { KeyBinding } from '@codemirror/view';
|
|
18
18
|
import {
|
|
19
19
|
crosshairCursor,
|
|
20
|
-
rectangularSelection,
|
|
21
|
-
dropCursor,
|
|
22
20
|
drawSelection,
|
|
23
|
-
|
|
24
|
-
highlightActiveLineGutter,
|
|
21
|
+
dropCursor,
|
|
25
22
|
EditorView,
|
|
26
23
|
highlightActiveLine,
|
|
24
|
+
highlightActiveLineGutter,
|
|
25
|
+
highlightSpecialChars,
|
|
27
26
|
keymap,
|
|
28
27
|
lineNumbers,
|
|
29
28
|
placeholder,
|
|
29
|
+
rectangularSelection,
|
|
30
30
|
} from '@codemirror/view';
|
|
31
31
|
import type { IEditorConfig } from '@difizen/libro-code-editor';
|
|
32
32
|
|
|
33
33
|
import {
|
|
34
|
+
autocompletion,
|
|
34
35
|
closeBrackets,
|
|
35
36
|
closeBracketsKeymap,
|
|
36
|
-
autocompletion,
|
|
37
37
|
completionKeymap,
|
|
38
38
|
} from './auto-complete/index.js';
|
|
39
39
|
import { kernelCompletions } from './completion.js';
|
|
@@ -41,6 +41,9 @@ import type { IOptions } from './editor.js';
|
|
|
41
41
|
import { hyperLink } from './hyperlink.js';
|
|
42
42
|
import { indentationMarkers } from './indentation-markers/index.js';
|
|
43
43
|
import { FoldIcon, UnFoldIcon } from './libro-icon.js';
|
|
44
|
+
import { lspPythonCompletion } from './lsp/completion.js';
|
|
45
|
+
import { formatKeymap } from './lsp/format.js';
|
|
46
|
+
import { lspLint, lspTooltip } from './lsp/index.js';
|
|
44
47
|
import { ensure } from './mode.js';
|
|
45
48
|
import { getTheme, defaultTheme } from './theme.js';
|
|
46
49
|
import { tabTooltip, tooltipKeymap } from './tooltip.js';
|
|
@@ -59,12 +62,6 @@ export interface CodeMirrorConfig extends IEditorConfig {
|
|
|
59
62
|
*/
|
|
60
63
|
mimetype?: string;
|
|
61
64
|
|
|
62
|
-
/**
|
|
63
|
-
* The theme to style the editor with. see editortheme.ts for an example
|
|
64
|
-
* of how to design a theme for CodeMirror 6.
|
|
65
|
-
*/
|
|
66
|
-
theme?: string;
|
|
67
|
-
|
|
68
65
|
// FIXME-TRANS: Handle theme localizable names
|
|
69
66
|
// themeDisplayName?: string
|
|
70
67
|
|
|
@@ -257,7 +254,7 @@ class FacetWrapper<T, U> extends ExtensionBuilder<T> {
|
|
|
257
254
|
return this._facet.of(value);
|
|
258
255
|
}
|
|
259
256
|
|
|
260
|
-
|
|
257
|
+
protected _facet: Facet<T, U>;
|
|
261
258
|
}
|
|
262
259
|
/**
|
|
263
260
|
* Extension builder that provides an extension depending
|
|
@@ -274,8 +271,8 @@ class ConditionalExtension extends ExtensionBuilder<boolean> {
|
|
|
274
271
|
return value ? this._truthy : this._falsy;
|
|
275
272
|
}
|
|
276
273
|
|
|
277
|
-
|
|
278
|
-
|
|
274
|
+
protected _truthy: Extension;
|
|
275
|
+
protected _falsy: Extension;
|
|
279
276
|
}
|
|
280
277
|
|
|
281
278
|
/**
|
|
@@ -293,8 +290,8 @@ class GenConditionalExtension<T> extends ExtensionBuilder<T> {
|
|
|
293
290
|
return this._builder.of(this._fn(value));
|
|
294
291
|
}
|
|
295
292
|
|
|
296
|
-
|
|
297
|
-
|
|
293
|
+
protected _fn: (a: T) => boolean;
|
|
294
|
+
protected _builder: ConditionalExtension;
|
|
298
295
|
}
|
|
299
296
|
|
|
300
297
|
/**
|
|
@@ -325,8 +322,8 @@ class ConfigurableBuilder implements IConfigurableBuilder {
|
|
|
325
322
|
);
|
|
326
323
|
}
|
|
327
324
|
|
|
328
|
-
|
|
329
|
-
|
|
325
|
+
protected _compartment: Compartment;
|
|
326
|
+
protected _builder: IExtensionBuilder;
|
|
330
327
|
}
|
|
331
328
|
|
|
332
329
|
/*
|
|
@@ -348,7 +345,7 @@ class ThemeBuilder implements IConfigurableBuilder {
|
|
|
348
345
|
return this._compartment.reconfigure(getTheme(v));
|
|
349
346
|
}
|
|
350
347
|
|
|
351
|
-
|
|
348
|
+
protected _compartment: Compartment;
|
|
352
349
|
}
|
|
353
350
|
|
|
354
351
|
/*
|
|
@@ -370,7 +367,7 @@ class PlaceHolderBuilder implements IConfigurableBuilder {
|
|
|
370
367
|
return this._compartment.reconfigure(placeholder(v));
|
|
371
368
|
}
|
|
372
369
|
|
|
373
|
-
|
|
370
|
+
protected _compartment: Compartment;
|
|
374
371
|
}
|
|
375
372
|
|
|
376
373
|
/**
|
|
@@ -508,17 +505,31 @@ export class EditorConfiguration {
|
|
|
508
505
|
'jupyterKernelCompletion',
|
|
509
506
|
createConditionalBuilder(
|
|
510
507
|
pythonLanguage.data.of({
|
|
511
|
-
autocomplete: kernelCompletions(options
|
|
508
|
+
autocomplete: kernelCompletions(options.completionProvider),
|
|
512
509
|
}),
|
|
513
510
|
),
|
|
514
511
|
],
|
|
515
512
|
[
|
|
516
513
|
'jupyterKernelTooltip',
|
|
517
|
-
createConditionalBuilder(tabTooltip(options
|
|
514
|
+
createConditionalBuilder(tabTooltip(options.tooltipProvider)),
|
|
518
515
|
],
|
|
519
516
|
['indentationMarkers', createConditionalBuilder(indentationMarkers())],
|
|
520
517
|
['hyperLink', createConditionalBuilder(hyperLink)],
|
|
521
518
|
['placeholder', createPlaceHolderBuilder()],
|
|
519
|
+
[
|
|
520
|
+
'lspTooltip',
|
|
521
|
+
createConditionalBuilder(lspTooltip({ lspProvider: options.lspProvider })),
|
|
522
|
+
],
|
|
523
|
+
[
|
|
524
|
+
'lspLint',
|
|
525
|
+
createConditionalBuilder(lspLint({ lspProvider: options.lspProvider })),
|
|
526
|
+
],
|
|
527
|
+
[
|
|
528
|
+
'lspCompletion',
|
|
529
|
+
createConditionalBuilder(
|
|
530
|
+
lspPythonCompletion({ lspProvider: options.lspProvider }),
|
|
531
|
+
),
|
|
532
|
+
],
|
|
522
533
|
]);
|
|
523
534
|
this._themeOverloaderSpec = { '&': {}, '.cm-line': {} };
|
|
524
535
|
this._themeOverloader = new Compartment();
|
|
@@ -607,6 +618,7 @@ export class EditorConfiguration {
|
|
|
607
618
|
...completionKeymap,
|
|
608
619
|
...lintKeymap,
|
|
609
620
|
...tooltipKeymap,
|
|
621
|
+
...formatKeymap,
|
|
610
622
|
];
|
|
611
623
|
|
|
612
624
|
const keymapExt = builder!.of(
|
|
@@ -635,7 +647,7 @@ export class EditorConfiguration {
|
|
|
635
647
|
return extensions;
|
|
636
648
|
}
|
|
637
649
|
|
|
638
|
-
|
|
650
|
+
protected updateThemeOverload(
|
|
639
651
|
config: Partial<CodeMirrorConfig> | Record<string, any>,
|
|
640
652
|
): Extension {
|
|
641
653
|
const { fontFamily, fontSize, lineHeight, lineWrap, wordWrapColumn } = config;
|
|
@@ -679,11 +691,11 @@ export class EditorConfiguration {
|
|
|
679
691
|
return EditorView.theme(this._themeOverloaderSpec);
|
|
680
692
|
}
|
|
681
693
|
|
|
682
|
-
|
|
694
|
+
protected get(key: string): IConfigurableBuilder | undefined {
|
|
683
695
|
return this._configurableBuilderMap.get(key);
|
|
684
696
|
}
|
|
685
697
|
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
698
|
+
protected _configurableBuilderMap: Map<string, IConfigurableBuilder>;
|
|
699
|
+
protected _themeOverloaderSpec: Record<string, Record<string, string>>;
|
|
700
|
+
protected _themeOverloader: Compartment;
|
|
689
701
|
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { CodeEditorFactory } from '@difizen/libro-code-editor';
|
|
2
|
+
import { CodeEditorContribution } from '@difizen/libro-code-editor';
|
|
3
|
+
import { singleton } from '@difizen/mana-app';
|
|
4
|
+
|
|
5
|
+
import { codeMirrorDefaultConfig } from './editor.js';
|
|
6
|
+
import { codeMirrorEditorFactory } from './factory.js';
|
|
7
|
+
|
|
8
|
+
@singleton({ contrib: [CodeEditorContribution] })
|
|
9
|
+
export class CodeMirrorEditorContribution implements CodeEditorContribution {
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
11
|
+
canHandle(mime: string): number {
|
|
12
|
+
// default editor
|
|
13
|
+
return 50;
|
|
14
|
+
}
|
|
15
|
+
factory: CodeEditorFactory = codeMirrorEditorFactory;
|
|
16
|
+
defaultConfig = codeMirrorDefaultConfig;
|
|
17
|
+
}
|
package/src/editor.ts
CHANGED
|
@@ -4,34 +4,36 @@ import type {
|
|
|
4
4
|
ChangeSet,
|
|
5
5
|
Extension,
|
|
6
6
|
Range,
|
|
7
|
-
StateEffectType,
|
|
8
7
|
StateCommand,
|
|
8
|
+
StateEffectType,
|
|
9
9
|
Text,
|
|
10
10
|
} from '@codemirror/state';
|
|
11
11
|
import {
|
|
12
|
-
Prec,
|
|
13
|
-
EditorState,
|
|
14
12
|
EditorSelection,
|
|
13
|
+
EditorState,
|
|
14
|
+
Prec,
|
|
15
15
|
StateEffect,
|
|
16
16
|
StateField,
|
|
17
17
|
} from '@codemirror/state';
|
|
18
|
-
import { Decoration, EditorView } from '@codemirror/view';
|
|
19
18
|
import type { Command, DecorationSet, ViewUpdate } from '@codemirror/view';
|
|
19
|
+
import { Decoration, EditorView } from '@codemirror/view';
|
|
20
|
+
import { defaultConfig, defaultSelectionStyle } from '@difizen/libro-code-editor';
|
|
20
21
|
import type {
|
|
22
|
+
ICoordinate,
|
|
21
23
|
IEditor,
|
|
22
24
|
IEditorConfig,
|
|
23
|
-
IEditorSelectionStyle,
|
|
24
|
-
KeydownHandler,
|
|
25
25
|
IEditorOptions,
|
|
26
|
+
IEditorSelectionStyle,
|
|
26
27
|
IModel,
|
|
27
28
|
IPosition,
|
|
28
29
|
IRange,
|
|
29
|
-
ICoordinate,
|
|
30
30
|
ITextSelection,
|
|
31
31
|
IToken,
|
|
32
|
+
KeydownHandler,
|
|
33
|
+
SearchMatch,
|
|
32
34
|
} from '@difizen/libro-code-editor';
|
|
33
|
-
import { defaultSelectionStyle, defaultConfig } from '@difizen/libro-code-editor';
|
|
34
35
|
import { findFirstArrayIndex, removeAllWhereFromArray } from '@difizen/libro-common';
|
|
36
|
+
import type { LSPProvider } from '@difizen/libro-lsp';
|
|
35
37
|
import { Disposable, Emitter } from '@difizen/mana-app';
|
|
36
38
|
import { getOrigin, watch } from '@difizen/mana-app';
|
|
37
39
|
import type { SyntaxNodeRef } from '@lezer/common';
|
|
@@ -90,7 +92,7 @@ export const codeMirrorDefaultConfig: Required<CodeMirrorConfig> = {
|
|
|
90
92
|
...defaultConfig,
|
|
91
93
|
mode: 'null',
|
|
92
94
|
mimetype: 'text/x-python',
|
|
93
|
-
theme: 'jupyter',
|
|
95
|
+
theme: { light: 'jupyter', dark: 'jupyter', hc: 'jupyter' },
|
|
94
96
|
smartIndent: true,
|
|
95
97
|
electricChars: true,
|
|
96
98
|
keyMap: 'default',
|
|
@@ -108,7 +110,7 @@ export const codeMirrorDefaultConfig: Required<CodeMirrorConfig> = {
|
|
|
108
110
|
styleSelectedText: true,
|
|
109
111
|
selectionPointer: false,
|
|
110
112
|
handlePaste: true,
|
|
111
|
-
|
|
113
|
+
scrollBarHeight: 8,
|
|
112
114
|
|
|
113
115
|
//
|
|
114
116
|
highlightActiveLineGutter: false,
|
|
@@ -135,12 +137,21 @@ export const codeMirrorDefaultConfig: Required<CodeMirrorConfig> = {
|
|
|
135
137
|
};
|
|
136
138
|
|
|
137
139
|
export class CodeMirrorEditor implements IEditor {
|
|
140
|
+
// highlight
|
|
141
|
+
protected highlightEffect: StateEffectType<{
|
|
142
|
+
matches: SearchMatch[];
|
|
143
|
+
currentIndex: number | undefined;
|
|
144
|
+
}>;
|
|
145
|
+
protected highlightMark: Decoration;
|
|
146
|
+
protected selectedMatchMark: Decoration;
|
|
147
|
+
protected highlightField: StateField<DecorationSet>;
|
|
148
|
+
|
|
138
149
|
/**
|
|
139
150
|
* Construct a CodeMirror editor.
|
|
140
151
|
*/
|
|
141
152
|
constructor(options: IOptions) {
|
|
142
153
|
this._editorConfig = new EditorConfiguration(options);
|
|
143
|
-
const host = (this.host = options
|
|
154
|
+
const host = (this.host = options.host);
|
|
144
155
|
|
|
145
156
|
host.classList.add(EDITOR_CLASS);
|
|
146
157
|
host.classList.add('jp-Editor');
|
|
@@ -148,7 +159,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
148
159
|
host.addEventListener('blur', this, true);
|
|
149
160
|
host.addEventListener('scroll', this, true);
|
|
150
161
|
|
|
151
|
-
this._uuid = options
|
|
162
|
+
this._uuid = options.uuid || v4();
|
|
152
163
|
|
|
153
164
|
// State and effects for handling the selection marks
|
|
154
165
|
this._addMark = StateEffect.define<ICollabSelectionText>();
|
|
@@ -186,20 +197,84 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
186
197
|
provide: (f) => EditorView.decorations.from(f),
|
|
187
198
|
});
|
|
188
199
|
|
|
200
|
+
// handle highlight
|
|
201
|
+
this.highlightEffect = StateEffect.define<{
|
|
202
|
+
matches: SearchMatch[];
|
|
203
|
+
currentIndex: number | undefined;
|
|
204
|
+
}>({
|
|
205
|
+
map: (value, mapping) => ({
|
|
206
|
+
matches: value.matches.map((v) => ({
|
|
207
|
+
text: v.text,
|
|
208
|
+
position: mapping.mapPos(v.position),
|
|
209
|
+
})),
|
|
210
|
+
currentIndex: value.currentIndex,
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
this.highlightMark = Decoration.mark({ class: 'cm-searchMatch' });
|
|
214
|
+
this.selectedMatchMark = Decoration.mark({
|
|
215
|
+
class: 'cm-searchMatch cm-searchMatch-selected libro-selectedtext',
|
|
216
|
+
});
|
|
217
|
+
this.highlightField = StateField.define<DecorationSet>({
|
|
218
|
+
create: () => {
|
|
219
|
+
return Decoration.none;
|
|
220
|
+
},
|
|
221
|
+
update: (highlights, transaction) => {
|
|
222
|
+
// eslint-disable-next-line no-param-reassign
|
|
223
|
+
highlights = highlights.map(transaction.changes);
|
|
224
|
+
for (const ef of transaction.effects) {
|
|
225
|
+
if (ef.is(this.highlightEffect)) {
|
|
226
|
+
const e = ef as StateEffect<{
|
|
227
|
+
matches: SearchMatch[];
|
|
228
|
+
currentIndex: number | undefined;
|
|
229
|
+
}>;
|
|
230
|
+
if (e.value.matches.length) {
|
|
231
|
+
// eslint-disable-next-line no-param-reassign
|
|
232
|
+
highlights = highlights.update({
|
|
233
|
+
add: e.value.matches.map((m, index) => {
|
|
234
|
+
if (index === e.value.currentIndex) {
|
|
235
|
+
return this.selectedMatchMark.range(
|
|
236
|
+
m.position,
|
|
237
|
+
m.position + m.text.length,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
return this.highlightMark.range(
|
|
241
|
+
m.position,
|
|
242
|
+
m.position + m.text.length,
|
|
243
|
+
);
|
|
244
|
+
}),
|
|
245
|
+
filter: (from, to) => {
|
|
246
|
+
return (
|
|
247
|
+
!e.value.matches.some(
|
|
248
|
+
(m) => m.position >= from && m.position + m.text.length <= to,
|
|
249
|
+
) || from === to
|
|
250
|
+
);
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
} else {
|
|
254
|
+
// eslint-disable-next-line no-param-reassign
|
|
255
|
+
highlights = Decoration.none;
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
return highlights;
|
|
260
|
+
},
|
|
261
|
+
provide: (f) => EditorView.decorations.from(f),
|
|
262
|
+
});
|
|
263
|
+
|
|
189
264
|
// Handle selection style.
|
|
190
|
-
const style = options
|
|
265
|
+
const style = options.selectionStyle || {};
|
|
191
266
|
this._selectionStyle = {
|
|
192
267
|
...defaultSelectionStyle,
|
|
193
268
|
...(style as IEditorSelectionStyle),
|
|
194
269
|
};
|
|
195
270
|
|
|
196
|
-
const model = (this._model = options
|
|
271
|
+
const model = (this._model = options.model);
|
|
197
272
|
|
|
198
273
|
const config = options.config || {};
|
|
199
274
|
const fullConfig = (this._config = {
|
|
200
275
|
...codeMirrorDefaultConfig,
|
|
201
276
|
...config,
|
|
202
|
-
mimetype: options
|
|
277
|
+
mimetype: options.model.mimeType,
|
|
203
278
|
});
|
|
204
279
|
|
|
205
280
|
// this._initializeEditorBinding();
|
|
@@ -207,16 +282,13 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
207
282
|
// Extension for handling DOM events
|
|
208
283
|
const domEventHandlers = EditorView.domEventHandlers({
|
|
209
284
|
keydown: (event: KeyboardEvent) => {
|
|
210
|
-
const index = findFirstArrayIndex(
|
|
211
|
-
this
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
return false;
|
|
218
|
-
},
|
|
219
|
-
);
|
|
285
|
+
const index = findFirstArrayIndex(this._keydownHandlers, (handler) => {
|
|
286
|
+
if (handler(this, event) === true) {
|
|
287
|
+
event.preventDefault();
|
|
288
|
+
return true;
|
|
289
|
+
}
|
|
290
|
+
return false;
|
|
291
|
+
});
|
|
220
292
|
if (index === -1) {
|
|
221
293
|
return this.onKeydown(event);
|
|
222
294
|
}
|
|
@@ -261,10 +333,6 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
261
333
|
watch(model, 'mimeType', this._onMimeTypeChanged);
|
|
262
334
|
}
|
|
263
335
|
|
|
264
|
-
handleTooltipChange = (val: boolean) => {
|
|
265
|
-
this.modalChangeEmitter.fire(val);
|
|
266
|
-
};
|
|
267
|
-
|
|
268
336
|
/**
|
|
269
337
|
* Initialize the editor binding.
|
|
270
338
|
*/
|
|
@@ -277,9 +345,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
277
345
|
// };
|
|
278
346
|
// }
|
|
279
347
|
|
|
280
|
-
save: () => void
|
|
281
|
-
//
|
|
282
|
-
};
|
|
348
|
+
save: () => void;
|
|
283
349
|
/**
|
|
284
350
|
* A signal emitted when either the top or bottom edge is requested.
|
|
285
351
|
*/
|
|
@@ -360,7 +426,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
360
426
|
/**
|
|
361
427
|
* Tests whether the editor is disposed.
|
|
362
428
|
*/
|
|
363
|
-
get
|
|
429
|
+
get disposed(): boolean {
|
|
364
430
|
return this._isDisposed;
|
|
365
431
|
}
|
|
366
432
|
|
|
@@ -368,7 +434,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
368
434
|
* Dispose of the resources held by the widget.
|
|
369
435
|
*/
|
|
370
436
|
dispose(): void {
|
|
371
|
-
if (this.
|
|
437
|
+
if (this.disposed) {
|
|
372
438
|
return;
|
|
373
439
|
}
|
|
374
440
|
this._isDisposed = true;
|
|
@@ -394,7 +460,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
394
460
|
// Don't bother setting the option if it is already the same.
|
|
395
461
|
if (this._config[option] !== value) {
|
|
396
462
|
this._config[option] = value;
|
|
397
|
-
this._editorConfig.reconfigureExtension(this._editor, option
|
|
463
|
+
this._editorConfig.reconfigureExtension(this._editor, option, value);
|
|
398
464
|
}
|
|
399
465
|
|
|
400
466
|
if (option === 'readOnly') {
|
|
@@ -427,8 +493,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
427
493
|
*/
|
|
428
494
|
getLine(line: number): string | undefined {
|
|
429
495
|
// TODO: CM6 remove +1 when CM6 first line number has propagated
|
|
430
|
-
|
|
431
|
-
return _line <= this.doc.lines ? this.doc.line(_line).text : undefined;
|
|
496
|
+
return line <= this.doc.lines ? this.doc.line(line).text : undefined;
|
|
432
497
|
}
|
|
433
498
|
|
|
434
499
|
/**
|
|
@@ -436,7 +501,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
436
501
|
*/
|
|
437
502
|
getOffsetAt(position: IPosition): number {
|
|
438
503
|
// TODO: CM6 remove +1 when CM6 first line number has propagated
|
|
439
|
-
return this.doc.line(position.line
|
|
504
|
+
return this.doc.line(position.line).from + position.column - 1;
|
|
440
505
|
}
|
|
441
506
|
|
|
442
507
|
/**
|
|
@@ -537,6 +602,16 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
537
602
|
return this.state.sliceDoc(fromOffset, toOffset);
|
|
538
603
|
}
|
|
539
604
|
|
|
605
|
+
getSelectionValue(range?: IRange) {
|
|
606
|
+
const fromOffset = range
|
|
607
|
+
? this.getOffsetAt(range.start)
|
|
608
|
+
: this.editor.state.selection.main.from;
|
|
609
|
+
const toOffset = range
|
|
610
|
+
? this.getOffsetAt(range.end)
|
|
611
|
+
: this.editor.state.selection.main.to;
|
|
612
|
+
return this.state.sliceDoc(fromOffset, toOffset);
|
|
613
|
+
}
|
|
614
|
+
|
|
540
615
|
/**
|
|
541
616
|
* Add a keydown handler to the editor.
|
|
542
617
|
*
|
|
@@ -547,10 +622,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
547
622
|
addKeydownHandler(handler: KeydownHandler): Disposable {
|
|
548
623
|
this._keydownHandlers.push(handler);
|
|
549
624
|
return Disposable.create(() => {
|
|
550
|
-
removeAllWhereFromArray(
|
|
551
|
-
this._keydownHandlers,
|
|
552
|
-
(val: KeydownHandler) => val === handler,
|
|
553
|
-
);
|
|
625
|
+
removeAllWhereFromArray(this._keydownHandlers, (val) => val === handler);
|
|
554
626
|
});
|
|
555
627
|
}
|
|
556
628
|
|
|
@@ -682,10 +754,41 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
682
754
|
*
|
|
683
755
|
* @param text The text to be inserted.
|
|
684
756
|
*/
|
|
685
|
-
replaceSelection(text: string): void {
|
|
686
|
-
this.editor.dispatch(
|
|
757
|
+
replaceSelection(text: string, range: IRange): void {
|
|
758
|
+
this.editor.dispatch({
|
|
759
|
+
changes: {
|
|
760
|
+
from: this.getOffsetAt(range.start),
|
|
761
|
+
to: this.getOffsetAt(range.end),
|
|
762
|
+
insert: text,
|
|
763
|
+
},
|
|
764
|
+
});
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
replaceSelections(edits: { text: string; range: IRange }[]): void {
|
|
768
|
+
// const trans = this.state.replaceSelection(text);
|
|
769
|
+
this.editor.dispatch({
|
|
770
|
+
changes: edits.map((item) => ({
|
|
771
|
+
from: this.getOffsetAt(item.range.start),
|
|
772
|
+
to: this.getOffsetAt(item.range.end),
|
|
773
|
+
insert: item.text,
|
|
774
|
+
})),
|
|
775
|
+
});
|
|
687
776
|
}
|
|
688
777
|
|
|
778
|
+
highlightMatches(matches: SearchMatch[], currentIndex: number | undefined) {
|
|
779
|
+
const effects: StateEffect<unknown>[] = [
|
|
780
|
+
this.highlightEffect.of({ matches: matches, currentIndex: currentIndex }),
|
|
781
|
+
];
|
|
782
|
+
if (!this.state.field(this.highlightField, false)) {
|
|
783
|
+
effects.push(StateEffect.appendConfig.of([this.highlightField]));
|
|
784
|
+
}
|
|
785
|
+
this.editor.dispatch({ effects });
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
handleTooltipChange = (val: boolean) => {
|
|
789
|
+
this.modalChangeEmitter.fire(val);
|
|
790
|
+
};
|
|
791
|
+
|
|
689
792
|
/**
|
|
690
793
|
* Get a list of tokens for the current editor text content.
|
|
691
794
|
*/
|
|
@@ -806,10 +909,36 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
806
909
|
});
|
|
807
910
|
}
|
|
808
911
|
|
|
912
|
+
/**
|
|
913
|
+
* Handles a selections change.
|
|
914
|
+
*/
|
|
915
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
916
|
+
protected _onSelectionsChanged(args: ITextSelection[]): void {
|
|
917
|
+
// const uuid = args.key;
|
|
918
|
+
// if (uuid !== this.uuid) {
|
|
919
|
+
// this._cleanSelections(uuid);
|
|
920
|
+
// if (args.type !== 'remove' && args.newValue) {
|
|
921
|
+
// this._markSelections(uuid, args.newValue);
|
|
922
|
+
// }
|
|
923
|
+
// }
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
/**
|
|
927
|
+
* Clean selections for the given uuid.
|
|
928
|
+
*/
|
|
929
|
+
protected _cleanSelections(uuid: string) {
|
|
930
|
+
this.editor.dispatch({
|
|
931
|
+
effects: this._removeMark.of({
|
|
932
|
+
uuid: uuid,
|
|
933
|
+
decorations: this._selectionMarkers[uuid],
|
|
934
|
+
}),
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
|
|
809
938
|
protected _buildMarkDecoration(
|
|
810
939
|
uuid: string,
|
|
811
940
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
812
|
-
|
|
941
|
+
selections: ISelectionText[],
|
|
813
942
|
) {
|
|
814
943
|
const decorations: Range<Decoration>[] = [];
|
|
815
944
|
|
|
@@ -886,6 +1015,20 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
886
1015
|
// });
|
|
887
1016
|
// }
|
|
888
1017
|
|
|
1018
|
+
/**
|
|
1019
|
+
* Marks selections.
|
|
1020
|
+
*/
|
|
1021
|
+
protected _markSelections(uuid: string, selections: ITextSelection[]) {
|
|
1022
|
+
const sel = selections.map((selection) => ({
|
|
1023
|
+
from: this.getOffsetAt(selection.start),
|
|
1024
|
+
to: this.getOffsetAt(selection.end),
|
|
1025
|
+
style: selection.style,
|
|
1026
|
+
}));
|
|
1027
|
+
this.editor.dispatch({
|
|
1028
|
+
effects: this._addMark.of({ uuid: uuid, selections: sel }),
|
|
1029
|
+
});
|
|
1030
|
+
}
|
|
1031
|
+
|
|
889
1032
|
/**
|
|
890
1033
|
* Handles a cursor activity event.
|
|
891
1034
|
*/
|
|
@@ -943,7 +1086,6 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
943
1086
|
if (update.docChanged) {
|
|
944
1087
|
this._lastChange = update.changes;
|
|
945
1088
|
}
|
|
946
|
-
|
|
947
1089
|
this.model.value = update.state.doc.toJSON().join('\n');
|
|
948
1090
|
}
|
|
949
1091
|
/**
|
|
@@ -1013,13 +1155,47 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
1013
1155
|
this._caretHover = null;
|
|
1014
1156
|
}
|
|
1015
1157
|
}
|
|
1158
|
+
/**
|
|
1159
|
+
* Check for an out of sync editor.
|
|
1160
|
+
*/
|
|
1161
|
+
protected _checkSync(): void {
|
|
1162
|
+
const change = this._lastChange;
|
|
1163
|
+
if (!change) {
|
|
1164
|
+
return;
|
|
1165
|
+
}
|
|
1166
|
+
this._lastChange = null;
|
|
1167
|
+
const doc = this.doc;
|
|
1168
|
+
if (doc.toString() === this._model.value) {
|
|
1169
|
+
return;
|
|
1170
|
+
}
|
|
1171
|
+
|
|
1172
|
+
// void showDialog({
|
|
1173
|
+
// title: this._trans.__('Code Editor out of Sync'),
|
|
1174
|
+
// body: this._trans.__(
|
|
1175
|
+
// 'Please open your browser JavaScript console for bug report instructions',
|
|
1176
|
+
// ),
|
|
1177
|
+
// });
|
|
1178
|
+
console.warn(
|
|
1179
|
+
'If you are able and willing to publicly share the text or code in your editor, you can help us debug the "Code Editor out of Sync" message by pasting the following to the public issue at https://github.com/jupyterlab/jupyterlab/issues/2951. Please note that the data below includes the text/code in your editor.',
|
|
1180
|
+
);
|
|
1181
|
+
console.warn(
|
|
1182
|
+
JSON.stringify({
|
|
1183
|
+
model: this._model.value,
|
|
1184
|
+
view: doc.toString(),
|
|
1185
|
+
selections: this.getSelections(),
|
|
1186
|
+
cursor: this.getCursorPosition(),
|
|
1187
|
+
lineSep: this.state.facet(EditorState.lineSeparator),
|
|
1188
|
+
change,
|
|
1189
|
+
}),
|
|
1190
|
+
);
|
|
1191
|
+
}
|
|
1016
1192
|
protected _model: IModel;
|
|
1017
1193
|
protected _editor: EditorView;
|
|
1018
1194
|
protected _selectionMarkers: Record<string, Range<Decoration>[]> = {};
|
|
1019
|
-
protected _caretHover: HTMLElement | null
|
|
1195
|
+
protected _caretHover: HTMLElement | null;
|
|
1020
1196
|
protected _config: IConfig;
|
|
1021
|
-
protected _hoverTimeout: number
|
|
1022
|
-
protected _hoverId: string
|
|
1197
|
+
protected _hoverTimeout: number;
|
|
1198
|
+
protected _hoverId: string;
|
|
1023
1199
|
protected _keydownHandlers = new Array<KeydownHandler>();
|
|
1024
1200
|
protected _selectionStyle: IEditorSelectionStyle;
|
|
1025
1201
|
protected _uuid = '';
|
|
@@ -1036,7 +1212,7 @@ export class CodeMirrorEditor implements IEditor {
|
|
|
1036
1212
|
export type IConfig = CodeMirrorConfig;
|
|
1037
1213
|
|
|
1038
1214
|
export interface IOptions extends IEditorOptions {
|
|
1039
|
-
|
|
1215
|
+
lspProvider?: LSPProvider;
|
|
1040
1216
|
/**
|
|
1041
1217
|
* The configuration options for the editor.
|
|
1042
1218
|
*/
|
package/src/hyperlink.ts
CHANGED
|
@@ -117,8 +117,8 @@ class IndentMarkersClass implements PluginValue {
|
|
|
117
117
|
view: EditorView;
|
|
118
118
|
decorations!: DecorationSet;
|
|
119
119
|
|
|
120
|
-
|
|
121
|
-
|
|
120
|
+
protected unitWidth: number;
|
|
121
|
+
protected currentLineNumber: number;
|
|
122
122
|
|
|
123
123
|
constructor(view: EditorView) {
|
|
124
124
|
this.view = view;
|
|
@@ -149,7 +149,7 @@ class IndentMarkersClass implements PluginValue {
|
|
|
149
149
|
}
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
protected generate(state: EditorState) {
|
|
153
153
|
const builder = new RangeSetBuilder<Decoration>();
|
|
154
154
|
|
|
155
155
|
const lines = getVisibleLines(this.view, state);
|