@adecore/editor 0.42.0 → 0.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controller.d.ts +9 -2
- package/dist/controller.js +82 -8
- package/dist/editor.css +13 -0
- package/dist/engine.js +44 -3
- package/dist/fake.d.ts +23 -2
- package/dist/fake.js +80 -4
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/keymap-table.d.ts +25 -1
- package/dist/keymap-table.js +30 -3
- package/dist/keymap.js +14 -0
- package/dist/layout.d.ts +2 -0
- package/dist/layout.js +6 -1
- package/dist/outline.d.ts +1 -0
- package/dist/outline.js +10 -0
- package/dist/paint.js +12 -2
- package/dist/text-queries.d.ts +10 -0
- package/dist/text-queries.js +24 -0
- package/dist/types.d.ts +41 -3
- package/dist/view.d.ts +11 -0
- package/dist/view.js +73 -8
- package/package.json +2 -2
- package/src/controller.ts +110 -9
- package/src/editor.css +13 -0
- package/src/engine.ts +60 -3
- package/src/fake.ts +109 -4
- package/src/index.ts +8 -0
- package/src/keymap-table.ts +55 -4
- package/src/keymap.ts +14 -0
- package/src/layout.ts +9 -1
- package/src/outline.ts +13 -0
- package/src/paint.ts +11 -2
- package/src/text-queries.ts +45 -0
- package/src/types.ts +77 -3
- package/src/view.ts +95 -9
package/dist/keymap-table.js
CHANGED
|
@@ -15,10 +15,15 @@ export const KEYMAP = {
|
|
|
15
15
|
deleteLine: bind('Mod+Backspace', 'Mod+Y'),
|
|
16
16
|
moveLineUp: bind('Alt+Shift+ArrowUp'),
|
|
17
17
|
moveLineDown: bind('Alt+Shift+ArrowDown'),
|
|
18
|
+
moveStatementUp: bind('Mod+Shift+ArrowUp'),
|
|
19
|
+
moveStatementDown: bind('Mod+Shift+ArrowDown'),
|
|
18
20
|
toggleLineComment: bind('Mod+/'),
|
|
19
21
|
toggleBlockComment: bind('Mod+Alt+/', 'Mod+Shift+/'),
|
|
20
22
|
joinLines: bind('Ctrl+Shift+J'),
|
|
21
23
|
startNewLine: bind('Shift+Enter'),
|
|
24
|
+
completeCurrentStatement: bind('Mod+Shift+Enter'),
|
|
25
|
+
hippieCompletion: bind('Alt+/'),
|
|
26
|
+
hippieBackwardCompletion: bind('Alt+Shift+/'),
|
|
22
27
|
startNewLineBefore: bind('Mod+Alt+Enter'),
|
|
23
28
|
splitLine: bind('Mod+Enter'),
|
|
24
29
|
toggleCase: bind('Mod+Shift+U'),
|
|
@@ -30,8 +35,21 @@ export const KEYMAP = {
|
|
|
30
35
|
convertIndentsToSpaces: bind(null),
|
|
31
36
|
convertIndentsToTabs: bind(null),
|
|
32
37
|
expandSelection: bind('Alt+ArrowUp', 'Ctrl+W'),
|
|
33
|
-
|
|
38
|
+
// Off macOS Alt+ArrowDown is Next Method, as in IntelliJ, so Shrink Selection takes its own chord there.
|
|
39
|
+
shrinkSelection: bind('Alt+ArrowDown', 'Ctrl+Shift+W'),
|
|
34
40
|
matchBrace: bind('Ctrl+M', 'Ctrl+Shift+M'),
|
|
41
|
+
methodUp: bind('Ctrl+Shift+ArrowUp', 'Alt+ArrowUp'),
|
|
42
|
+
methodDown: bind('Ctrl+Shift+ArrowDown', 'Alt+ArrowDown'),
|
|
43
|
+
lastEditLocation: bind('Mod+Shift+Backspace'),
|
|
44
|
+
nextEditLocation: bind(null),
|
|
45
|
+
pasteFromHistory: bind('Mod+Shift+V'),
|
|
46
|
+
pasteAsPlainText: bind('Mod+Alt+Shift+V'),
|
|
47
|
+
nextChange: bind('Ctrl+Alt+Shift+ArrowDown'),
|
|
48
|
+
previousChange: bind('Ctrl+Alt+Shift+ArrowUp'),
|
|
49
|
+
codeBlockStart: bind('Mod+Alt+[', 'Ctrl+['),
|
|
50
|
+
codeBlockEnd: bind('Mod+Alt+]', 'Ctrl+]'),
|
|
51
|
+
codeBlockStartWithSelection: bind('Mod+Alt+Shift+[', 'Ctrl+Shift+['),
|
|
52
|
+
codeBlockEndWithSelection: bind('Mod+Alt+Shift+]', 'Ctrl+Shift+]'),
|
|
35
53
|
selectNextOccurrence: bind('Ctrl+G', 'Alt+J'),
|
|
36
54
|
unselectOccurrence: bind('Ctrl+Shift+G', 'Alt+Shift+J'),
|
|
37
55
|
selectAllOccurrences: bind('Meta+Ctrl+G', 'Ctrl+Alt+Shift+J'),
|
|
@@ -51,9 +69,10 @@ export const KEYMAP = {
|
|
|
51
69
|
smartEnd: bind('Meta+ArrowRight', null),
|
|
52
70
|
selectSmartEnd: bind('Meta+Shift+ArrowRight', null),
|
|
53
71
|
textStart: bind('Meta+ArrowUp', null),
|
|
54
|
-
|
|
72
|
+
// IntelliJ binds Cmd+Shift+ArrowUp and ArrowDown to Move Statement on macOS, where Cmd+Shift+Home and End still select to the text edges.
|
|
73
|
+
selectTextStart: bind(null),
|
|
55
74
|
textEnd: bind('Meta+ArrowDown', null),
|
|
56
|
-
selectTextEnd: bind(
|
|
75
|
+
selectTextEnd: bind(null),
|
|
57
76
|
collapse: bind('Mod+-'),
|
|
58
77
|
expand: bind('Mod+='),
|
|
59
78
|
collapseAll: bind('Mod+Shift+-'),
|
|
@@ -81,6 +100,13 @@ export const KEYMAP = {
|
|
|
81
100
|
renameSymbol: bind('Shift+F6'),
|
|
82
101
|
organizeImports: bind('Ctrl+Alt+O'),
|
|
83
102
|
formatDocument: bind('Mod+Alt+L'),
|
|
103
|
+
insertLiveTemplate: bind('Mod+J'),
|
|
104
|
+
surroundWith: bind('Mod+Alt+T'),
|
|
105
|
+
surroundWithLiveTemplate: bind('Mod+Alt+J'),
|
|
106
|
+
unwrap: bind('Mod+Shift+Delete'),
|
|
107
|
+
saveAsLiveTemplate: bind(null),
|
|
108
|
+
// Surround with Emmet has no chord of its own: it is a row of Surround with Live Template, which has this one.
|
|
109
|
+
wrapWithAbbreviation: bind(null),
|
|
84
110
|
selectionToChat: bind(null),
|
|
85
111
|
inlineEdit: bind(null),
|
|
86
112
|
suggestInline: bind(null),
|
|
@@ -92,6 +118,7 @@ export const KEYMAP = {
|
|
|
92
118
|
peekDefinition: bind('Alt+Space', 'Ctrl+Shift+I'),
|
|
93
119
|
peekReferences: bind('Alt+F7'),
|
|
94
120
|
callHierarchy: bind('Ctrl+Alt+H'),
|
|
121
|
+
typeHierarchy: bind('Ctrl+H'),
|
|
95
122
|
toggleRenderedDocs: bind('Ctrl+Alt+Q'),
|
|
96
123
|
historyBack: bind('Mod+[', 'Ctrl+Alt+ArrowLeft'),
|
|
97
124
|
historyForward: bind('Mod+]', 'Ctrl+Alt+ArrowRight'),
|
package/dist/keymap.js
CHANGED
|
@@ -16,10 +16,15 @@ const ACTIONS = {
|
|
|
16
16
|
deleteLine: command('deleteLine'),
|
|
17
17
|
moveLineUp: command('moveLineUp'),
|
|
18
18
|
moveLineDown: command('moveLineDown'),
|
|
19
|
+
moveStatementUp: command('moveStatementUp'),
|
|
20
|
+
moveStatementDown: command('moveStatementDown'),
|
|
19
21
|
toggleLineComment: command('toggleLineComment'),
|
|
20
22
|
toggleBlockComment: command('toggleBlockComment'),
|
|
21
23
|
joinLines: command('joinLines'),
|
|
22
24
|
startNewLine: command('startNewLine'),
|
|
25
|
+
completeCurrentStatement: command('completeCurrentStatement'),
|
|
26
|
+
hippieCompletion: command('hippieCompletion'),
|
|
27
|
+
hippieBackwardCompletion: command('hippieBackwardCompletion'),
|
|
23
28
|
startNewLineBefore: command('startNewLineBefore'),
|
|
24
29
|
splitLine: command('splitLine'),
|
|
25
30
|
toggleCase: command('toggleCase'),
|
|
@@ -32,6 +37,15 @@ const ACTIONS = {
|
|
|
32
37
|
expandSelection: command('expandSelection'),
|
|
33
38
|
shrinkSelection: command('shrinkSelection'),
|
|
34
39
|
matchBrace: { type: 'bracket' },
|
|
40
|
+
methodUp: view('methodUp'),
|
|
41
|
+
methodDown: view('methodDown'),
|
|
42
|
+
pasteAsPlainText: view('pasteAsPlainText'),
|
|
43
|
+
nextChange: view('nextChange'),
|
|
44
|
+
previousChange: view('previousChange'),
|
|
45
|
+
codeBlockStart: command('codeBlockStart'),
|
|
46
|
+
codeBlockEnd: command('codeBlockEnd'),
|
|
47
|
+
codeBlockStartWithSelection: command('codeBlockStartWithSelection'),
|
|
48
|
+
codeBlockEndWithSelection: command('codeBlockEndWithSelection'),
|
|
35
49
|
selectNextOccurrence: command('selectNextOccurrence'),
|
|
36
50
|
unselectOccurrence: command('unselectOccurrence'),
|
|
37
51
|
selectAllOccurrences: command('selectAllOccurrences'),
|
package/dist/layout.d.ts
CHANGED
package/dist/layout.js
CHANGED
|
@@ -11,6 +11,8 @@ export function subRowBand(top, subRows, lineHeight, window, block = 1) {
|
|
|
11
11
|
last: Math.min(subRows - 1, Math.ceil((last + 1) / block) * block - 1)
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
+
/* The side of a swatch in pixels, without its gaps. */
|
|
15
|
+
export const SWATCH_SIZE = 12;
|
|
14
16
|
export const TEXT_PADDING = 0;
|
|
15
17
|
export const BOTTOM_PADDING = 8;
|
|
16
18
|
export const RIGHT_PADDING = 16;
|
|
@@ -154,9 +156,12 @@ export function scanDenseLine(line, metrics, limit, lineInlays) {
|
|
|
154
156
|
flushRun(offset);
|
|
155
157
|
const inlay = lineInlays[nextInlay++];
|
|
156
158
|
const shown = visibleBidi(inlay.text);
|
|
159
|
+
const gaps = (inlay.gapLeft ?? 0) + (inlay.gapRight ?? 0);
|
|
157
160
|
const width = inlay.composition || inlay.ghost
|
|
158
161
|
? metrics.measureText(shown)
|
|
159
|
-
:
|
|
162
|
+
: inlay.swatch !== undefined
|
|
163
|
+
? SWATCH_SIZE + gaps
|
|
164
|
+
: Math.max(8, metrics.measureInlay(shown) + 12) + gaps;
|
|
160
165
|
geometry.inlays.push({ inlay, x, width, subRow: row });
|
|
161
166
|
x += width;
|
|
162
167
|
}
|
package/dist/outline.d.ts
CHANGED
|
@@ -37,6 +37,7 @@ export declare class Outline {
|
|
|
37
37
|
setStructure(entries: OutlineEntry[]): void;
|
|
38
38
|
setProvided(blocks: readonly EditorBlock[] | null, document: OutlineDocument): void;
|
|
39
39
|
edited(batches: readonly (readonly DocumentChange[])[]): void;
|
|
40
|
+
declarationStops(document: OutlineDocument): number[];
|
|
40
41
|
blocks(document: OutlineDocument): readonly OutlineBlock[];
|
|
41
42
|
}
|
|
42
43
|
export interface StickyRows {
|
package/dist/outline.js
CHANGED
|
@@ -140,6 +140,16 @@ export class Outline {
|
|
|
140
140
|
this.provided = this.provided === null ? null : move(this.provided);
|
|
141
141
|
this.version++;
|
|
142
142
|
}
|
|
143
|
+
/* Where the named blocks of the structure declare their name, in no order: the stops of Method Up and Down. */
|
|
144
|
+
declarationStops(document) {
|
|
145
|
+
return this.structure.flatMap((entry) => {
|
|
146
|
+
if (entry.name === undefined) {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
const header = document.getLine(document.positionAt(entry.from).line);
|
|
150
|
+
return [header.start + Math.max(0, header.text.indexOf(entry.name))];
|
|
151
|
+
});
|
|
152
|
+
}
|
|
143
153
|
/* Outermost first. Of two blocks that start on one line, only the larger one. */
|
|
144
154
|
blocks(document) {
|
|
145
155
|
if (this.cache?.version !== this.version) {
|
package/dist/paint.js
CHANGED
|
@@ -102,10 +102,20 @@ export function lineElement(document, geometry, tokens, lineHeight, band, whites
|
|
|
102
102
|
continue;
|
|
103
103
|
}
|
|
104
104
|
const span = document.createElement('span');
|
|
105
|
-
span.className = box.inlay.ghost
|
|
105
|
+
span.className = box.inlay.ghost
|
|
106
|
+
? 'se-ghost'
|
|
107
|
+
: box.inlay.composition
|
|
108
|
+
? 'se-composition'
|
|
109
|
+
: box.inlay.swatch !== undefined
|
|
110
|
+
? 'se-inlay se-swatch'
|
|
111
|
+
: 'se-inlay';
|
|
106
112
|
span.dataset.inlayId = box.inlay.id;
|
|
107
113
|
const { parts } = box.inlay;
|
|
108
|
-
if (
|
|
114
|
+
if (box.inlay.swatch !== undefined) {
|
|
115
|
+
span.style.backgroundColor = box.inlay.swatch;
|
|
116
|
+
span.setAttribute('aria-label', box.inlay.text);
|
|
117
|
+
}
|
|
118
|
+
else if (parts === undefined) {
|
|
109
119
|
span.textContent = visibleBidi(box.inlay.text);
|
|
110
120
|
}
|
|
111
121
|
else {
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { DocumentModel } from '@adecore/editor-core';
|
|
2
|
+
import type { EditorPosition, EditorPostfixOperand, EditorRange, EditorSurroundShape, EditorTextPlace, EditorUnwrapTarget } from './types.ts';
|
|
3
|
+
export interface Coordinates {
|
|
4
|
+
positionAt(offset: number): EditorPosition;
|
|
5
|
+
offsetAt(position: EditorPosition): number;
|
|
6
|
+
}
|
|
7
|
+
export declare function placeAt(model: DocumentModel, coordinates: Coordinates, position: EditorPosition, language: string): EditorTextPlace;
|
|
8
|
+
export declare function postfixOperands(model: DocumentModel, coordinates: Coordinates, dot: EditorPosition, language: string): EditorPostfixOperand[];
|
|
9
|
+
export declare function surroundShape(model: DocumentModel, coordinates: Coordinates, range: EditorRange, language: string): EditorSurroundShape | null;
|
|
10
|
+
export declare function unwrapTargets(model: DocumentModel, coordinates: Coordinates, position: EditorPosition, language: string, indentUnit: string): EditorUnwrapTarget[];
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
function rangeOf(coordinates, from, to) {
|
|
2
|
+
return { start: coordinates.positionAt(from), end: coordinates.positionAt(to) };
|
|
3
|
+
}
|
|
4
|
+
export function placeAt(model, coordinates, position, language) {
|
|
5
|
+
return model.placeAt(coordinates.offsetAt(position), language);
|
|
6
|
+
}
|
|
7
|
+
export function postfixOperands(model, coordinates, dot, language) {
|
|
8
|
+
const at = coordinates.offsetAt(dot);
|
|
9
|
+
return model.postfixOperands(at, language).map((operand) => ({
|
|
10
|
+
range: rangeOf(coordinates, operand.from, operand.from + model.slice(operand.from, at).trimEnd().length),
|
|
11
|
+
statement: operand.statement
|
|
12
|
+
}));
|
|
13
|
+
}
|
|
14
|
+
export function surroundShape(model, coordinates, range, language) {
|
|
15
|
+
const shape = model.surroundShape(coordinates.offsetAt(range.start), coordinates.offsetAt(range.end), language);
|
|
16
|
+
return shape === null ? null : { range: rangeOf(coordinates, shape.from, shape.to), statements: shape.statements, expression: shape.expression };
|
|
17
|
+
}
|
|
18
|
+
export function unwrapTargets(model, coordinates, position, language, indentUnit) {
|
|
19
|
+
return model.unwrapTargets(coordinates.offsetAt(position), language, indentUnit).map((target) => ({
|
|
20
|
+
kind: target.kind,
|
|
21
|
+
range: rangeOf(coordinates, target.range.from, target.range.to),
|
|
22
|
+
edits: target.edits.map((edit) => ({ range: rangeOf(coordinates, edit.from, edit.to), text: edit.text }))
|
|
23
|
+
}));
|
|
24
|
+
}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { EditorSearchClientOptions } from './search-client.ts';
|
|
2
2
|
import type { Keymap } from './keymap-table.ts';
|
|
3
|
-
import type { EditorCommand, FoldRole, WhitespaceCleanupOptions } from '@adecore/editor-core';
|
|
3
|
+
import type { EditorCommand, FoldRole, TextPlaceKind, UnwrapKind, WhitespaceCleanupOptions } from '@adecore/editor-core';
|
|
4
4
|
export type { EditorCommand, FoldRole };
|
|
5
5
|
export type EditorWhitespaceCleanup = WhitespaceCleanupOptions;
|
|
6
6
|
export type EditorFoldOutline = 'off' | 'hover' | 'always';
|
|
7
|
-
export type EditorViewCommand = 'collapseRegion' | 'expandRegion' | 'collapseAllRegions' | 'expandAllRegions' | 'collapseRegionRecursively' | 'expandRegionRecursively' | 'foldSelection' | 'collapseDocComments' | 'expandDocComments' | 'expandAllToLevel1' | 'expandAllToLevel2' | 'expandAllToLevel3' | 'expandAllToLevel4' | 'expandAllToLevel5' | 'toggleColumnMode' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize';
|
|
7
|
+
export type EditorViewCommand = 'collapseRegion' | 'expandRegion' | 'collapseAllRegions' | 'expandAllRegions' | 'collapseRegionRecursively' | 'expandRegionRecursively' | 'foldSelection' | 'collapseDocComments' | 'expandDocComments' | 'expandAllToLevel1' | 'expandAllToLevel2' | 'expandAllToLevel3' | 'expandAllToLevel4' | 'expandAllToLevel5' | 'toggleColumnMode' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize' | 'methodUp' | 'methodDown' | 'nextChange' | 'previousChange' | 'pasteAsPlainText';
|
|
8
8
|
export interface EditorZoom {
|
|
9
9
|
readonly min?: number;
|
|
10
10
|
readonly max?: number;
|
|
@@ -139,6 +139,33 @@ export interface EditorContentChange {
|
|
|
139
139
|
readonly range: EditorRange;
|
|
140
140
|
readonly text: string;
|
|
141
141
|
}
|
|
142
|
+
export interface EditorTextPlace {
|
|
143
|
+
readonly language: string;
|
|
144
|
+
readonly kind: TextPlaceKind;
|
|
145
|
+
}
|
|
146
|
+
export interface EditorPostfixOperand {
|
|
147
|
+
readonly range: EditorRange;
|
|
148
|
+
readonly statement: boolean;
|
|
149
|
+
}
|
|
150
|
+
export interface EditorSurroundShape {
|
|
151
|
+
readonly range: EditorRange;
|
|
152
|
+
readonly statements: boolean;
|
|
153
|
+
readonly expression: boolean;
|
|
154
|
+
}
|
|
155
|
+
export interface EditorUnwrapTarget {
|
|
156
|
+
readonly kind: UnwrapKind;
|
|
157
|
+
readonly range: EditorRange;
|
|
158
|
+
readonly edits: readonly EditorContentChange[];
|
|
159
|
+
}
|
|
160
|
+
export interface EditorCopy {
|
|
161
|
+
readonly text: string;
|
|
162
|
+
readonly wholeLines: boolean;
|
|
163
|
+
readonly cut: boolean;
|
|
164
|
+
}
|
|
165
|
+
export interface EditorPasteOptions {
|
|
166
|
+
readonly wholeLines?: boolean;
|
|
167
|
+
readonly reindent?: boolean;
|
|
168
|
+
}
|
|
142
169
|
export interface EditorApplyEditsOptions {
|
|
143
170
|
readonly mapSelections?: (range: EditorRange) => EditorRange;
|
|
144
171
|
readonly mergeUndo?: boolean;
|
|
@@ -240,6 +267,7 @@ export interface EditorInlayHint {
|
|
|
240
267
|
readonly parts?: readonly string[];
|
|
241
268
|
readonly paddingLeft?: boolean;
|
|
242
269
|
readonly paddingRight?: boolean;
|
|
270
|
+
readonly swatch?: string;
|
|
243
271
|
}
|
|
244
272
|
export interface EditorInlayTarget {
|
|
245
273
|
readonly id: string;
|
|
@@ -336,6 +364,12 @@ export interface Editor {
|
|
|
336
364
|
setTodoWords?(words: readonly string[]): void;
|
|
337
365
|
setLabel(label: string): void;
|
|
338
366
|
setFoldHints(hints: EditorFoldHints | null): void;
|
|
367
|
+
setDeclarations?(positions: readonly EditorPosition[] | null): void;
|
|
368
|
+
onNavigate?(listener: (from: EditorPosition) => void): () => void;
|
|
369
|
+
hasFocus?(): boolean;
|
|
370
|
+
setWordSources?(source: (() => readonly string[]) | null): void;
|
|
371
|
+
onCopy?(listener: (copy: EditorCopy) => void): () => void;
|
|
372
|
+
paste?(text: string, options?: EditorPasteOptions): boolean;
|
|
339
373
|
setChangeMarks(marks: readonly EditorChangeMark[], layer?: string): void;
|
|
340
374
|
setBlocks(blocks: readonly EditorBlock[] | null): void;
|
|
341
375
|
onScope(listener: (scope: readonly EditorBlock[]) => void): () => void;
|
|
@@ -351,7 +385,7 @@ export interface Editor {
|
|
|
351
385
|
setHighlights(highlights: readonly EditorHighlight[]): void;
|
|
352
386
|
setLink(range: EditorRange | null): void;
|
|
353
387
|
setSemanticTokens(tokens: readonly EditorSemanticToken[] | null): void;
|
|
354
|
-
setInlayHints(hints: readonly EditorInlayHint[]): void;
|
|
388
|
+
setInlayHints(hints: readonly EditorInlayHint[], owner?: string): void;
|
|
355
389
|
onInlayHover?(listener: (target: EditorInlayTarget | null) => void): () => void;
|
|
356
390
|
onInlayClick?(handler: EditorInlayClickHandler): () => void;
|
|
357
391
|
setInlayLink?(target: {
|
|
@@ -404,6 +438,10 @@ export interface Editor {
|
|
|
404
438
|
onFontSizeChange?(listener: (size: number | null) => void): () => void;
|
|
405
439
|
setReadOnly(readOnly: boolean, reason?: string): void;
|
|
406
440
|
isReadOnly?(): boolean;
|
|
441
|
+
placeAt?(position: EditorPosition): EditorTextPlace;
|
|
442
|
+
postfixOperands?(dot: EditorPosition): readonly EditorPostfixOperand[];
|
|
443
|
+
surroundShape?(range: EditorRange): EditorSurroundShape | null;
|
|
444
|
+
unwrapTargets?(position: EditorPosition): readonly EditorUnwrapTarget[];
|
|
407
445
|
runCommand(command: EditorRunCommand): boolean;
|
|
408
446
|
focus(): void;
|
|
409
447
|
dispose(): void;
|
package/dist/view.d.ts
CHANGED
|
@@ -143,6 +143,7 @@ export declare class EditorView {
|
|
|
143
143
|
private lenses;
|
|
144
144
|
private readonly replacements;
|
|
145
145
|
private occurrences;
|
|
146
|
+
private hippieSource;
|
|
146
147
|
private replacePreview;
|
|
147
148
|
private dropCaret;
|
|
148
149
|
private activeGuideCache;
|
|
@@ -157,6 +158,7 @@ export declare class EditorView {
|
|
|
157
158
|
private customFolds;
|
|
158
159
|
private collapsed;
|
|
159
160
|
private foldHints;
|
|
161
|
+
private declarations;
|
|
160
162
|
private defaultRoles;
|
|
161
163
|
private settled;
|
|
162
164
|
private foldTimer;
|
|
@@ -188,6 +190,10 @@ export declare class EditorView {
|
|
|
188
190
|
setLenses(lenses: readonly BlockWidget[]): void;
|
|
189
191
|
private allBlocks;
|
|
190
192
|
setOccurrences(occurrences: readonly Occurrence[]): void;
|
|
193
|
+
setHippieSource(range: {
|
|
194
|
+
from: number;
|
|
195
|
+
to: number;
|
|
196
|
+
} | null): void;
|
|
191
197
|
setLink(link: {
|
|
192
198
|
from: number;
|
|
193
199
|
to: number;
|
|
@@ -239,6 +245,7 @@ export declare class EditorView {
|
|
|
239
245
|
private foldStates;
|
|
240
246
|
private scheduleFolds;
|
|
241
247
|
refreshFolds(): void;
|
|
248
|
+
structureRanges(): FoldingRange[];
|
|
242
249
|
private withCustomFolds;
|
|
243
250
|
private closerOf;
|
|
244
251
|
private foldAt;
|
|
@@ -274,6 +281,10 @@ export declare class EditorView {
|
|
|
274
281
|
endLine: number;
|
|
275
282
|
}[];
|
|
276
283
|
} | null, defaults?: readonly FoldRole[]): void;
|
|
284
|
+
setDeclarations(offsets: readonly number[] | null): void;
|
|
285
|
+
private methodStops;
|
|
286
|
+
goToChange(direction: -1 | 1): boolean;
|
|
287
|
+
goToMethod(direction: -1 | 1): boolean;
|
|
277
288
|
setFoldHints(hints: FoldHints | null): void;
|
|
278
289
|
private applyFoldDefaults;
|
|
279
290
|
foldRole(role: FoldRole, collapse: boolean): void;
|
package/dist/view.js
CHANGED
|
@@ -168,6 +168,7 @@ export class EditorView {
|
|
|
168
168
|
lenses = [];
|
|
169
169
|
replacements = new Map();
|
|
170
170
|
occurrences = [];
|
|
171
|
+
hippieSource = null;
|
|
171
172
|
replacePreview = null;
|
|
172
173
|
dropCaret = null;
|
|
173
174
|
activeGuideCache;
|
|
@@ -186,6 +187,7 @@ export class EditorView {
|
|
|
186
187
|
collapsed = new Set();
|
|
187
188
|
/* What a language server said about the folds, in offsets that follow the text through edits. */
|
|
188
189
|
foldHints = null;
|
|
190
|
+
declarations = null;
|
|
189
191
|
/* The roles that fold by themselves while the file is as it was opened; null once a person edited or the file opened with folds of its own. */
|
|
190
192
|
defaultRoles = null;
|
|
191
193
|
/* The folds somebody already decided on, a person or the defaults, so a later answer of a server leaves them as they are. */
|
|
@@ -427,6 +429,14 @@ export class EditorView {
|
|
|
427
429
|
this.occurrences = [...occurrences];
|
|
428
430
|
this.render();
|
|
429
431
|
}
|
|
432
|
+
/* The word Hippie completion took from this document, shown until the next key or edit; null takes the mark away. */
|
|
433
|
+
setHippieSource(range) {
|
|
434
|
+
if (range === null && this.hippieSource === null) {
|
|
435
|
+
return;
|
|
436
|
+
}
|
|
437
|
+
this.hippieSource = range;
|
|
438
|
+
this.render();
|
|
439
|
+
}
|
|
430
440
|
/* A name underlined as a link a press follows, with the pointer to match; null takes it away. */
|
|
431
441
|
setLink(link) {
|
|
432
442
|
this.link = link;
|
|
@@ -621,6 +631,7 @@ export class EditorView {
|
|
|
621
631
|
this.markerVersion++;
|
|
622
632
|
const anchor = this.topAnchor;
|
|
623
633
|
this.occurrences = [];
|
|
634
|
+
this.hippieSource = null;
|
|
624
635
|
this.link = null;
|
|
625
636
|
this.content.classList.remove('se-content-link');
|
|
626
637
|
this.outline.edited(batches);
|
|
@@ -668,6 +679,9 @@ export class EditorView {
|
|
|
668
679
|
if (this.foldHints !== null) {
|
|
669
680
|
this.foldHints = mapFoldHints(this.foldHints, map);
|
|
670
681
|
}
|
|
682
|
+
if (this.declarations !== null) {
|
|
683
|
+
this.declarations = this.declarations.map((offset) => map(offset));
|
|
684
|
+
}
|
|
671
685
|
this.customFolds = this.customFolds.map((fold) => mapRange(fold, map));
|
|
672
686
|
this.find.mapBounds(changes);
|
|
673
687
|
for (const [layer, marks] of this.changeLayers) {
|
|
@@ -801,20 +815,25 @@ export class EditorView {
|
|
|
801
815
|
if (this.disposed || this.settings.folding === false) {
|
|
802
816
|
return;
|
|
803
817
|
}
|
|
804
|
-
const ranges = this.
|
|
805
|
-
? []
|
|
806
|
-
: this.model.getFoldingRanges({
|
|
807
|
-
indentation: /^(python|py|yaml|yml)$/.test(this.settings.language ?? ''),
|
|
808
|
-
tabSize: this.settings.tabSize,
|
|
809
|
-
...(this.settings.language === undefined ? {} : { language: this.settings.language }),
|
|
810
|
-
...(this.foldHints === null ? {} : { hints: this.foldHints })
|
|
811
|
-
});
|
|
818
|
+
const ranges = this.structureRanges();
|
|
812
819
|
this.foldRanges = this.withCustomFolds(ranges);
|
|
813
820
|
this.outline.setStructure(structuralEntries(ranges, this.model, (from, to) => this.model.slice(from, to), (offset) => this.model.matchBracket(offset, this.settings.language)?.mate));
|
|
814
821
|
const anchors = new Set(this.foldRanges.map((range) => range.from));
|
|
815
822
|
this.collapsed = new Set([...this.collapsed].filter((anchor) => anchors.has(anchor)));
|
|
816
823
|
this.refoldLayout();
|
|
817
824
|
}
|
|
825
|
+
/* The folding ranges the document has now, a server's included, whether or not the folds are drawn. */
|
|
826
|
+
structureRanges() {
|
|
827
|
+
if (this.model.getLength() > FOLD_LIMIT) {
|
|
828
|
+
return [];
|
|
829
|
+
}
|
|
830
|
+
return this.model.getFoldingRanges({
|
|
831
|
+
indentation: /^(python|py|yaml|yml)$/.test(this.settings.language ?? ''),
|
|
832
|
+
tabSize: this.settings.tabSize,
|
|
833
|
+
...(this.settings.language === undefined ? {} : { language: this.settings.language }),
|
|
834
|
+
...(this.foldHints === null ? {} : { hints: this.foldHints })
|
|
835
|
+
});
|
|
836
|
+
}
|
|
818
837
|
/* The folds a person made of a selection, which the document's own structure does not know, among the ones it does. */
|
|
819
838
|
withCustomFolds(ranges) {
|
|
820
839
|
const custom = this.customFolds.flatMap((fold) => {
|
|
@@ -1023,6 +1042,49 @@ export class EditorView {
|
|
|
1023
1042
|
this.applyFoldDefaults();
|
|
1024
1043
|
this.refoldLayout();
|
|
1025
1044
|
}
|
|
1045
|
+
/* The places Method Up and Down stop at; they follow their text through edits until set again, and null goes back to the editor's own reading. */
|
|
1046
|
+
setDeclarations(offsets) {
|
|
1047
|
+
this.declarations = offsets === null ? null : [...new Set(offsets)].sort((left, right) => left - right);
|
|
1048
|
+
}
|
|
1049
|
+
methodStops() {
|
|
1050
|
+
if (this.declarations !== null) {
|
|
1051
|
+
return this.declarations;
|
|
1052
|
+
}
|
|
1053
|
+
const sections = this.foldRanges.filter((range) => range.kind === 'section').map((range) => this.model.getLine(range.startLine).start);
|
|
1054
|
+
return [...new Set([...this.outline.declarationStops(this.model), ...sections])].sort((left, right) => left - right);
|
|
1055
|
+
}
|
|
1056
|
+
/* Moves the one caret to the first line of the next or previous change mark, of any layer. False when there is none. */
|
|
1057
|
+
goToChange(direction) {
|
|
1058
|
+
const line = this.model.positionAt(this.model.getPrimary().head).line;
|
|
1059
|
+
const { runs } = this.resolvedChanges();
|
|
1060
|
+
// A run the caret is in is where it already is; a deleted run is the line its mark sits on.
|
|
1061
|
+
const target = direction === 1 ? runs.find((run) => run.start > line) : runs.findLast((run) => (run.kind === 'deleted' ? run.start : run.end) < line);
|
|
1062
|
+
if (target === undefined) {
|
|
1063
|
+
return false;
|
|
1064
|
+
}
|
|
1065
|
+
const offset = this.model.getLine(Math.min(target.start, this.model.getLineCount() - 1)).start;
|
|
1066
|
+
this.model.setSelections([{ anchor: offset, head: offset }]);
|
|
1067
|
+
this.revealOffset(offset, 'center');
|
|
1068
|
+
return true;
|
|
1069
|
+
}
|
|
1070
|
+
/* Moves the one caret to the previous or next declaration on another line. False when there is none. */
|
|
1071
|
+
goToMethod(direction) {
|
|
1072
|
+
// The structure is read after a pause in typing, so a press right after an edit reads it now.
|
|
1073
|
+
if (this.declarations === null) {
|
|
1074
|
+
this.refreshFolds();
|
|
1075
|
+
}
|
|
1076
|
+
const line = this.model.positionAt(this.model.getPrimary().head).line;
|
|
1077
|
+
const stops = this.methodStops();
|
|
1078
|
+
const target = direction === 1
|
|
1079
|
+
? stops.find((offset) => this.model.positionAt(offset).line > line)
|
|
1080
|
+
: stops.findLast((offset) => this.model.positionAt(offset).line < line);
|
|
1081
|
+
if (target === undefined) {
|
|
1082
|
+
return false;
|
|
1083
|
+
}
|
|
1084
|
+
this.model.setSelections([{ anchor: target, head: target }]);
|
|
1085
|
+
this.revealOffset(target, direction === 1 ? 'centerDown' : 'centerUp');
|
|
1086
|
+
return true;
|
|
1087
|
+
}
|
|
1026
1088
|
/* Hands over what a language server knows about the folds; null forgets it. The defaults fold what the answer names, once. */
|
|
1027
1089
|
setFoldHints(hints) {
|
|
1028
1090
|
this.foldHints = hints;
|
|
@@ -1866,6 +1928,9 @@ export class EditorView {
|
|
|
1866
1928
|
});
|
|
1867
1929
|
}
|
|
1868
1930
|
}
|
|
1931
|
+
if (this.hippieSource !== null) {
|
|
1932
|
+
marks.push({ className: 'se-hippie-source', rects: this.paintRectangles(this.hippieSource.from, this.hippieSource.to, rows) });
|
|
1933
|
+
}
|
|
1869
1934
|
const marginX = this.settings.rightMargin === null ? null : this.settings.rightMargin * this.layout.metrics.charWidth;
|
|
1870
1935
|
// A margin past the content would stretch the scroll extent to itself, so it shows only where the text or the view reaches it.
|
|
1871
1936
|
if (marginX !== null && marginX < Math.max(this.layout.width, this.viewportWidth)) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adecore/editor",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.44.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"test": "bun test --conditions=source"
|
|
55
55
|
},
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@adecore/editor-core": "0.
|
|
57
|
+
"@adecore/editor-core": "0.44.0",
|
|
58
58
|
"linkedom": "^0.18.14",
|
|
59
59
|
"shiki": "^4.5.0"
|
|
60
60
|
},
|