@adecore/editor 0.22.1 → 0.23.1
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/attribution.d.ts +9 -8
- package/dist/attribution.js +44 -9
- package/dist/bidi.d.ts +44 -0
- package/dist/bidi.js +26 -0
- package/dist/column-selection.js +2 -1
- package/dist/controller.d.ts +6 -1
- package/dist/controller.js +93 -3
- package/dist/editor.css +81 -1
- package/dist/engine.js +189 -41
- package/dist/fake.d.ts +45 -5
- package/dist/fake.js +121 -13
- package/dist/find-search.d.ts +26 -0
- package/dist/find-search.js +130 -0
- package/dist/find.d.ts +50 -2
- package/dist/find.js +575 -25
- package/dist/geometry-stops.d.ts +6 -0
- package/dist/geometry-stops.js +47 -0
- package/dist/grammar-preparation.d.ts +29 -0
- package/dist/grammar-preparation.js +147 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +2 -0
- package/dist/keymap-table.d.ts +10 -1
- package/dist/keymap-table.js +37 -1
- package/dist/keymap.d.ts +1 -0
- package/dist/keymap.js +4 -1
- package/dist/layout-changes.d.ts +6 -0
- package/dist/layout-changes.js +27 -0
- package/dist/layout.d.ts +45 -2
- package/dist/layout.js +202 -58
- package/dist/offsets.d.ts +1 -0
- package/dist/offsets.js +23 -0
- package/dist/outline.js +5 -4
- package/dist/paint.d.ts +11 -3
- package/dist/paint.js +180 -34
- package/dist/search-client.d.ts +27 -0
- package/dist/search-client.js +210 -0
- package/dist/search-protocol.d.ts +103 -0
- package/dist/search-protocol.js +3 -0
- package/dist/search-worker.d.ts +11 -0
- package/dist/search-worker.js +137 -0
- package/dist/semantic.d.ts +2 -1
- package/dist/semantic.js +6 -1
- package/dist/shiki-document.d.ts +8 -0
- package/dist/shiki-document.js +93 -0
- package/dist/shiki-worker.d.ts +65 -0
- package/dist/shiki-worker.js +265 -0
- package/dist/shiki.d.ts +1 -0
- package/dist/shiki.js +96 -33
- package/dist/testing.d.ts +1 -0
- package/dist/tokens.d.ts +2 -0
- package/dist/tokens.js +37 -7
- package/dist/touch.d.ts +27 -0
- package/dist/touch.js +100 -0
- package/dist/types.d.ts +86 -2
- package/dist/uniform-geometry.d.ts +7 -0
- package/dist/uniform-geometry.js +49 -0
- package/dist/view.d.ts +69 -17
- package/dist/view.js +427 -97
- package/dist/worker-client.d.ts +37 -0
- package/dist/worker-client.js +195 -0
- package/package.json +17 -2
- package/src/attribution.ts +50 -14
- package/src/bidi.ts +32 -0
- package/src/column-selection.ts +2 -1
- package/src/controller.ts +97 -3
- package/src/editor.css +81 -1
- package/src/engine.ts +222 -42
- package/src/fake.ts +157 -14
- package/src/find-search.ts +165 -0
- package/src/find.ts +622 -21
- package/src/geometry-stops.ts +51 -0
- package/src/grammar-preparation.ts +158 -0
- package/src/index.ts +10 -0
- package/src/keymap-table.ts +44 -2
- package/src/keymap.ts +5 -1
- package/src/layout-changes.ts +33 -0
- package/src/layout.ts +262 -63
- package/src/offsets.ts +24 -0
- package/src/outline.ts +5 -4
- package/src/paint.ts +202 -36
- package/src/search-client.ts +306 -0
- package/src/search-protocol.ts +100 -0
- package/src/search-worker.ts +171 -0
- package/src/semantic.ts +8 -2
- package/src/shiki-document.ts +143 -0
- package/src/shiki-worker.ts +344 -0
- package/src/shiki.ts +103 -33
- package/src/testing.ts +2 -0
- package/src/tokens.ts +36 -7
- package/src/touch.ts +134 -0
- package/src/types.ts +178 -8
- package/src/uniform-geometry.ts +57 -0
- package/src/view.ts +505 -102
- package/src/worker-client.ts +212 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
export function stopCount(geometry) {
|
|
2
|
+
return geometry.uniform === undefined ? geometry.offsets.length : geometry.text.length + 1;
|
|
3
|
+
}
|
|
4
|
+
export function offsetOfStop(geometry, stop) {
|
|
5
|
+
return geometry.uniform === undefined ? geometry.offsets[stop] : stop;
|
|
6
|
+
}
|
|
7
|
+
export function rowOfStop(geometry, stop) {
|
|
8
|
+
if (geometry.uniform === undefined) {
|
|
9
|
+
return geometry.rowOf[stop];
|
|
10
|
+
}
|
|
11
|
+
let first = 0;
|
|
12
|
+
let last = geometry.rowStarts.length;
|
|
13
|
+
while (first < last) {
|
|
14
|
+
const middle = (first + last) >>> 1;
|
|
15
|
+
if (geometry.rowStarts[middle] <= stop) {
|
|
16
|
+
first = middle + 1;
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
last = middle;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return Math.max(0, first - 1);
|
|
23
|
+
}
|
|
24
|
+
export function xOfStop(geometry, stop, affinity = 'before') {
|
|
25
|
+
if (geometry.uniform === undefined) {
|
|
26
|
+
return geometry[affinity][stop];
|
|
27
|
+
}
|
|
28
|
+
const row = rowOfStop(geometry, stop);
|
|
29
|
+
return geometry.uniform[row === 0 ? 'first' : 'continuation'][stop - geometry.rowStarts[row]];
|
|
30
|
+
}
|
|
31
|
+
export function stopAtOffset(geometry, offset) {
|
|
32
|
+
if (geometry.uniform !== undefined) {
|
|
33
|
+
return Math.min(geometry.text.length, Math.max(0, Math.ceil(offset)));
|
|
34
|
+
}
|
|
35
|
+
let first = 0;
|
|
36
|
+
let last = geometry.offsets.length;
|
|
37
|
+
while (first < last) {
|
|
38
|
+
const middle = (first + last) >>> 1;
|
|
39
|
+
if (geometry.offsets[middle] < offset) {
|
|
40
|
+
first = middle + 1;
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
last = middle;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return Math.min(geometry.offsets.length - 1, first);
|
|
47
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { DocumentChange, DocumentModel } from '@adecore/editor-core';
|
|
2
|
+
import type { LineTokenizer } from './types.ts';
|
|
3
|
+
type Schedule = (callback: () => void, delay: number) => () => void;
|
|
4
|
+
export declare class GrammarPreparation {
|
|
5
|
+
private tokenizer;
|
|
6
|
+
private generation;
|
|
7
|
+
private pending;
|
|
8
|
+
private size;
|
|
9
|
+
private lastLine;
|
|
10
|
+
private full;
|
|
11
|
+
private running;
|
|
12
|
+
private due;
|
|
13
|
+
private paused;
|
|
14
|
+
private disposed;
|
|
15
|
+
private cancelTimer;
|
|
16
|
+
private readonly model;
|
|
17
|
+
private readonly changed;
|
|
18
|
+
private readonly schedule;
|
|
19
|
+
constructor(model: Pick<DocumentModel, 'getText' | 'getLine' | 'positionAt'>, changed: () => void, schedule?: Schedule);
|
|
20
|
+
begin(): void;
|
|
21
|
+
ready(tokenizer: LineTokenizer | null): void;
|
|
22
|
+
edited(batches: readonly (readonly DocumentChange[])[]): void;
|
|
23
|
+
pause(paused: boolean): void;
|
|
24
|
+
dispose(): void;
|
|
25
|
+
private clear;
|
|
26
|
+
private scheduleFlush;
|
|
27
|
+
private flush;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
const scheduleTimer = (callback, delay) => {
|
|
2
|
+
const timer = setTimeout(callback, delay);
|
|
3
|
+
return () => clearTimeout(timer);
|
|
4
|
+
};
|
|
5
|
+
const MAX_BUFFER = 64 * 1024;
|
|
6
|
+
/* Edits collect language declarations without making every key wait for grammar loading. */
|
|
7
|
+
export class GrammarPreparation {
|
|
8
|
+
tokenizer = null;
|
|
9
|
+
generation = 0;
|
|
10
|
+
pending = [];
|
|
11
|
+
size = 0;
|
|
12
|
+
lastLine = -1;
|
|
13
|
+
full = false;
|
|
14
|
+
running = false;
|
|
15
|
+
due = false;
|
|
16
|
+
paused = false;
|
|
17
|
+
disposed = false;
|
|
18
|
+
cancelTimer = null;
|
|
19
|
+
model;
|
|
20
|
+
changed;
|
|
21
|
+
schedule;
|
|
22
|
+
constructor(model, changed, schedule = scheduleTimer) {
|
|
23
|
+
this.model = model;
|
|
24
|
+
this.changed = changed;
|
|
25
|
+
this.schedule = schedule;
|
|
26
|
+
}
|
|
27
|
+
begin() {
|
|
28
|
+
this.generation++;
|
|
29
|
+
this.tokenizer = null;
|
|
30
|
+
this.clear();
|
|
31
|
+
}
|
|
32
|
+
ready(tokenizer) {
|
|
33
|
+
this.tokenizer = tokenizer;
|
|
34
|
+
this.scheduleFlush();
|
|
35
|
+
}
|
|
36
|
+
edited(batches) {
|
|
37
|
+
if (this.disposed || this.paused) {
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
if (this.tokenizer === null || batches.length !== 1) {
|
|
41
|
+
this.full = true;
|
|
42
|
+
this.lastLine = -1;
|
|
43
|
+
}
|
|
44
|
+
else if (this.tokenizer.prepare === undefined) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
else if (!this.full) {
|
|
48
|
+
let shift = 0;
|
|
49
|
+
let through = -1;
|
|
50
|
+
for (const change of batches[0]) {
|
|
51
|
+
const first = this.model.positionAt(change.from + shift).line;
|
|
52
|
+
const last = this.model.positionAt(change.from + shift + change.insertedLength).line;
|
|
53
|
+
shift += change.insertedLength - (change.to - change.from);
|
|
54
|
+
for (let line = Math.max(first, through + 1); line <= last; line++) {
|
|
55
|
+
const text = this.model.getLine(line).text;
|
|
56
|
+
const replacing = batches[0].length === 1 && first === last && line === this.lastLine;
|
|
57
|
+
if (replacing) {
|
|
58
|
+
this.size -= this.pending.pop().length + 1;
|
|
59
|
+
}
|
|
60
|
+
this.size += text.length + 1;
|
|
61
|
+
if (this.size > MAX_BUFFER) {
|
|
62
|
+
this.full = true;
|
|
63
|
+
this.pending = [];
|
|
64
|
+
this.lastLine = -1;
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
this.pending.push(text);
|
|
68
|
+
this.lastLine = line;
|
|
69
|
+
}
|
|
70
|
+
through = last;
|
|
71
|
+
if (this.full) {
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
this.scheduleFlush();
|
|
77
|
+
}
|
|
78
|
+
pause(paused) {
|
|
79
|
+
if (this.paused === paused) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.paused = paused;
|
|
83
|
+
this.generation++;
|
|
84
|
+
this.clear();
|
|
85
|
+
if (!paused) {
|
|
86
|
+
this.full = true;
|
|
87
|
+
this.scheduleFlush();
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
dispose() {
|
|
91
|
+
this.disposed = true;
|
|
92
|
+
this.generation++;
|
|
93
|
+
this.clear();
|
|
94
|
+
this.tokenizer = null;
|
|
95
|
+
}
|
|
96
|
+
clear() {
|
|
97
|
+
this.cancelTimer?.();
|
|
98
|
+
this.cancelTimer = null;
|
|
99
|
+
this.pending = [];
|
|
100
|
+
this.size = 0;
|
|
101
|
+
this.lastLine = -1;
|
|
102
|
+
this.full = false;
|
|
103
|
+
this.due = false;
|
|
104
|
+
}
|
|
105
|
+
scheduleFlush() {
|
|
106
|
+
if (this.disposed || this.paused || this.tokenizer?.prepare === undefined || (!this.full && this.pending.length === 0)) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
this.cancelTimer?.();
|
|
110
|
+
this.due = false;
|
|
111
|
+
this.cancelTimer = this.schedule(() => {
|
|
112
|
+
this.cancelTimer = null;
|
|
113
|
+
this.due = true;
|
|
114
|
+
void this.flush();
|
|
115
|
+
}, 200);
|
|
116
|
+
}
|
|
117
|
+
async flush() {
|
|
118
|
+
const tokenizer = this.tokenizer;
|
|
119
|
+
if (this.running || this.disposed || this.paused || tokenizer?.prepare === undefined || !this.due) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const generation = this.generation;
|
|
123
|
+
const text = this.full ? this.model.getText() : this.pending.join('\n');
|
|
124
|
+
this.pending = [];
|
|
125
|
+
this.size = 0;
|
|
126
|
+
this.lastLine = -1;
|
|
127
|
+
this.full = false;
|
|
128
|
+
this.due = false;
|
|
129
|
+
this.running = true;
|
|
130
|
+
try {
|
|
131
|
+
await tokenizer.prepare(text);
|
|
132
|
+
if (!this.disposed && !this.paused && generation === this.generation && tokenizer === this.tokenizer) {
|
|
133
|
+
// A load completed while paused may already have rebuilt this grammar.
|
|
134
|
+
this.changed();
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Keep the current colors; a later edit may retry the failed load.
|
|
139
|
+
}
|
|
140
|
+
finally {
|
|
141
|
+
this.running = false;
|
|
142
|
+
if (this.due) {
|
|
143
|
+
void this.flush();
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { MAX_REPLACEMENT_PAGE, MAX_REPLACEMENT_CHARACTERS } from './search-protocol.ts';
|
|
1
2
|
export { AGENT_COLORS } from './attribution.ts';
|
|
3
|
+
export { findDocComments, MAX_DOC_COMMENTS, type DocComment } from '@adecore/editor-core';
|
|
2
4
|
export { createSmartEditorEngine } from './engine.ts';
|
|
3
5
|
export { DEFAULT_SMART_KEYS } from './smart-keys.ts';
|
|
4
6
|
export { shikiScopeColors, shikiTokenizers } from './shiki.ts';
|
|
5
|
-
export type { Editor, EditorAttributionHover, EditorAttributionMark, EditorMarkColor, EditorBlock, EditorChangeKind, EditorChangeMark, EditorCodeVision, EditorCodeVisionEntry, EditorClick, EditorCodeBlockOptions, EditorClickHandler, EditorCommand, EditorContextMenu, EditorEngine, EditorFindQuery, EditorFoldHints, EditorFoldRangeHint, EditorFoldOutline, EditorFoldRange, EditorFoldSymbol, EditorFolds, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorIndentation, EditorContentChange, EditorHighlight, EditorHighlightKind, EditorHover, EditorGhostText, EditorInlayHint, EditorKeyHandler, EditorLineAction, EditorLineHighlight, EditorMarker, EditorMessages, EditorMarkerSeverity, EditorReveal, EditorRect, EditorSmartKeys, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorTextChange, EditorTrackedRange, EditorRunCommand, EditorSelectionRanges, EditorTheme, EditorViewCommand, EditorWidget, FoldRole, KeyChord, LineToken, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
|
|
7
|
+
export type { Editor, EditorAttributionHover, EditorAttributionMark, EditorMarkColor, EditorBlock, EditorChangeKind, EditorChangeMark, EditorCodeVision, EditorCodeVisionEntry, EditorClick, EditorCodeBlockOptions, EditorClickHandler, EditorCommand, EditorContextMenu, EditorEngine, EditorFindQuery, EditorFoldHints, EditorFoldRangeHint, EditorFoldOutline, EditorFoldRange, EditorFoldSymbol, EditorFolds, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterIcon, EditorGutterMarker, EditorReplacement, EditorIndentation, EditorContentChange, EditorHighlight, EditorHighlightKind, EditorHover, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorLineAction, EditorLineHighlight, EditorMarker, EditorInputPopup, EditorMessages, EditorMarkerSeverity, EditorReveal, EditorRect, EditorSmartKeys, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorApplyEditsOptions, EditorTextChange, EditorTrackedRange, EditorRunCommand, EditorSelectionRanges, EditorTheme, EditorViewCommand, EditorWidget, FoldRole, KeyChord, LineToken, LineTokenKind, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
export { MAX_REPLACEMENT_PAGE, MAX_REPLACEMENT_CHARACTERS } from './search-protocol.js';
|
|
1
2
|
export { AGENT_COLORS } from './attribution.js';
|
|
3
|
+
export { findDocComments, MAX_DOC_COMMENTS } from '@adecore/editor-core';
|
|
2
4
|
export { createSmartEditorEngine } from './engine.js';
|
|
3
5
|
export { DEFAULT_SMART_KEYS } from './smart-keys.js';
|
|
4
6
|
export { shikiScopeColors, shikiTokenizers } from './shiki.js';
|
package/dist/keymap-table.d.ts
CHANGED
|
@@ -82,6 +82,8 @@ export declare const KEYMAP: {
|
|
|
82
82
|
readonly goToImplementation: KeyBinding;
|
|
83
83
|
readonly peekDefinition: KeyBinding;
|
|
84
84
|
readonly peekReferences: KeyBinding;
|
|
85
|
+
readonly callHierarchy: KeyBinding;
|
|
86
|
+
readonly toggleRenderedDocs: KeyBinding;
|
|
85
87
|
readonly historyBack: KeyBinding;
|
|
86
88
|
readonly historyForward: KeyBinding;
|
|
87
89
|
readonly recentLocations: KeyBinding;
|
|
@@ -94,9 +96,16 @@ export declare const KEYMAP: {
|
|
|
94
96
|
readonly replace: KeyBinding;
|
|
95
97
|
};
|
|
96
98
|
export type KeymapId = keyof typeof KEYMAP;
|
|
97
|
-
export type
|
|
99
|
+
export type OptionalKeymapId = 'toggleRenderedDocs';
|
|
100
|
+
export type Keymap = Readonly<Record<Exclude<KeymapId, OptionalKeymapId>, KeyBinding> & Partial<Record<OptionalKeymapId, KeyBinding>>>;
|
|
98
101
|
export type KeymapOverrides = Partial<Record<KeymapId, Partial<KeyBinding>>>;
|
|
99
102
|
export declare const KEYMAP_IDS: KeymapId[];
|
|
100
103
|
export declare function resolveKeymap(overrides?: KeymapOverrides): Keymap;
|
|
101
104
|
export declare function chordOf(id: KeymapId, apple: boolean, keymap?: Keymap): string | null;
|
|
102
105
|
export declare function parseChord(text: string): KeyChord;
|
|
106
|
+
export declare function typesInsteadOfChord(event: {
|
|
107
|
+
key: string;
|
|
108
|
+
code?: string;
|
|
109
|
+
ctrlKey: boolean;
|
|
110
|
+
altKey: boolean;
|
|
111
|
+
}, apple: boolean): boolean;
|
package/dist/keymap-table.js
CHANGED
|
@@ -81,6 +81,8 @@ export const KEYMAP = {
|
|
|
81
81
|
goToImplementation: bind('Mod+Alt+B'),
|
|
82
82
|
peekDefinition: bind('Alt+Space', 'Ctrl+Shift+I'),
|
|
83
83
|
peekReferences: bind('Alt+F7'),
|
|
84
|
+
callHierarchy: bind('Ctrl+Alt+H'),
|
|
85
|
+
toggleRenderedDocs: bind('Ctrl+Alt+Q'),
|
|
84
86
|
historyBack: bind('Mod+[', 'Ctrl+Alt+ArrowLeft'),
|
|
85
87
|
historyForward: bind('Mod+]', 'Ctrl+Alt+ArrowRight'),
|
|
86
88
|
recentLocations: bind('Mod+Shift+E'),
|
|
@@ -98,7 +100,7 @@ export function resolveKeymap(overrides = {}) {
|
|
|
98
100
|
}
|
|
99
101
|
/* The chord of a command on a platform, or null when the platform has none. */
|
|
100
102
|
export function chordOf(id, apple, keymap = KEYMAP) {
|
|
101
|
-
return keymap[id][apple ? 'mac' : 'other'];
|
|
103
|
+
return (keymap[id] ?? KEYMAP[id])[apple ? 'mac' : 'other'];
|
|
102
104
|
}
|
|
103
105
|
const MODIFIERS = new Map([
|
|
104
106
|
['Mod', 'mod'],
|
|
@@ -128,3 +130,37 @@ export function parseChord(text) {
|
|
|
128
130
|
}
|
|
129
131
|
return chord;
|
|
130
132
|
}
|
|
133
|
+
const BASE_PUNCTUATION = {
|
|
134
|
+
Comma: ',',
|
|
135
|
+
Period: '.',
|
|
136
|
+
Slash: '/',
|
|
137
|
+
Semicolon: ';',
|
|
138
|
+
Quote: "'",
|
|
139
|
+
Backquote: '`',
|
|
140
|
+
Backslash: '\\',
|
|
141
|
+
BracketLeft: '[',
|
|
142
|
+
BracketRight: ']',
|
|
143
|
+
Minus: '-',
|
|
144
|
+
Equal: '='
|
|
145
|
+
};
|
|
146
|
+
/* The character a physical key has with no layer on it, null for a key that has none, such as an arrow or Enter. */
|
|
147
|
+
function baseCharacter(code) {
|
|
148
|
+
const letter = /^Key([A-Z])$/.exec(code);
|
|
149
|
+
if (letter !== null) {
|
|
150
|
+
return letter[1].toLowerCase();
|
|
151
|
+
}
|
|
152
|
+
const digit = /^(?:Digit|Numpad)([0-9])$/.exec(code);
|
|
153
|
+
return digit !== null ? digit[1] : (BASE_PUNCTUATION[code] ?? null);
|
|
154
|
+
}
|
|
155
|
+
/*
|
|
156
|
+
* Whether Ctrl and Alt together type a character instead of pressing a chord. AltGr reports both, on Windows even
|
|
157
|
+
* for the left Ctrl and Alt, and a browser may report AltGraph for Option, so the state is no evidence: the character is.
|
|
158
|
+
* Never on Apple platforms, where Option types with no Ctrl.
|
|
159
|
+
*/
|
|
160
|
+
export function typesInsteadOfChord(event, apple) {
|
|
161
|
+
if (apple || !event.ctrlKey || !event.altKey || event.code === undefined || [...event.key].length !== 1) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
const base = baseCharacter(event.code);
|
|
165
|
+
return base !== null && event.key.toLowerCase() !== base;
|
|
166
|
+
}
|
package/dist/keymap.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export interface KeyLike {
|
|
|
8
8
|
metaKey: boolean;
|
|
9
9
|
altKey: boolean;
|
|
10
10
|
shiftKey: boolean;
|
|
11
|
+
getModifierState?(key: string): boolean;
|
|
11
12
|
}
|
|
12
13
|
export type MoveKey = 'ArrowLeft' | 'ArrowRight' | 'ArrowUp' | 'ArrowDown' | 'PageUp' | 'PageDown';
|
|
13
14
|
export type KeyAction = {
|
package/dist/keymap.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { chordOf, KEYMAP, KEYMAP_IDS, parseChord } from './keymap-table.js';
|
|
1
|
+
import { chordOf, KEYMAP, KEYMAP_IDS, parseChord, typesInsteadOfChord } from './keymap-table.js';
|
|
2
2
|
const MOVES = new Set(['ArrowLeft', 'ArrowRight', 'ArrowUp', 'ArrowDown', 'PageUp', 'PageDown']);
|
|
3
3
|
function command(name) {
|
|
4
4
|
return { type: 'command', command: name };
|
|
@@ -98,6 +98,9 @@ function keyMatches(chordKey, event) {
|
|
|
98
98
|
}
|
|
99
99
|
/* Whether an event is a chord, with `mod` as Cmd on macOS and Ctrl elsewhere and every modifier the chord does not name up. */
|
|
100
100
|
export function chordMatches(chord, event, apple) {
|
|
101
|
+
if (typesInsteadOfChord(event, apple)) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
101
104
|
const wantsMeta = chord.meta || (chord.mod && apple);
|
|
102
105
|
const wantsCtrl = chord.ctrl || (chord.mod && !apple);
|
|
103
106
|
return (wantsMeta === event.metaKey &&
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { offsetMapper } from './offsets.js';
|
|
2
|
+
export function lineChangeMapper(batches) {
|
|
3
|
+
const steps = batches.map((changes) => ({ changes, map: offsetMapper(changes) }));
|
|
4
|
+
return (bounds) => {
|
|
5
|
+
let { start, end } = bounds;
|
|
6
|
+
for (const { changes, map } of steps) {
|
|
7
|
+
let first = 0;
|
|
8
|
+
let last = changes.length;
|
|
9
|
+
while (first < last) {
|
|
10
|
+
const middle = (first + last) >>> 1;
|
|
11
|
+
if (changes[middle].to < start) {
|
|
12
|
+
first = middle + 1;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
last = middle;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
// Touching either boundary can merge lines or change a CRLF ending.
|
|
19
|
+
if (changes[first] !== undefined && changes[first].from <= end) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
start = map(start);
|
|
23
|
+
end = map(end);
|
|
24
|
+
}
|
|
25
|
+
return { start, end };
|
|
26
|
+
};
|
|
27
|
+
}
|
package/dist/layout.d.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
-
import type { Position } from '@adecore/editor-core';
|
|
1
|
+
import type { DocumentChange, Position } from '@adecore/editor-core';
|
|
2
2
|
export type Affinity = 'before' | 'after';
|
|
3
|
+
export interface VerticalWindow {
|
|
4
|
+
top: number;
|
|
5
|
+
bottom: number;
|
|
6
|
+
}
|
|
7
|
+
export interface SubRowBand {
|
|
8
|
+
first: number;
|
|
9
|
+
last: number;
|
|
10
|
+
}
|
|
11
|
+
export declare function subRowBand(top: number, subRows: number, lineHeight: number, window: VerticalWindow, block?: number): SubRowBand;
|
|
3
12
|
export interface LayoutDocument {
|
|
4
13
|
getLineCount(): number;
|
|
5
14
|
getLine(line: number): {
|
|
@@ -22,6 +31,9 @@ export interface Inlay {
|
|
|
22
31
|
at: number;
|
|
23
32
|
text: string;
|
|
24
33
|
tooltip?: string;
|
|
34
|
+
parts?: readonly string[];
|
|
35
|
+
gapLeft?: number;
|
|
36
|
+
gapRight?: number;
|
|
25
37
|
composition?: boolean;
|
|
26
38
|
ghost?: boolean;
|
|
27
39
|
}
|
|
@@ -34,6 +46,18 @@ export interface BlockWidget {
|
|
|
34
46
|
height?: number;
|
|
35
47
|
revision?: number;
|
|
36
48
|
lens?: boolean;
|
|
49
|
+
fixed?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface BlockReplacement {
|
|
52
|
+
id: string;
|
|
53
|
+
from: number;
|
|
54
|
+
to: number;
|
|
55
|
+
render: (container: HTMLElement) => void;
|
|
56
|
+
height?: number;
|
|
57
|
+
revision?: number;
|
|
58
|
+
label?: string;
|
|
59
|
+
enterable?: boolean;
|
|
60
|
+
onReveal?: () => void;
|
|
37
61
|
}
|
|
38
62
|
export interface FoldState {
|
|
39
63
|
startLine: number;
|
|
@@ -55,6 +79,7 @@ export interface TextRow extends RowBase {
|
|
|
55
79
|
tail: number | null;
|
|
56
80
|
head: number | null;
|
|
57
81
|
subRows: number;
|
|
82
|
+
replacement?: BlockReplacement;
|
|
58
83
|
}
|
|
59
84
|
export interface BlockRow extends RowBase {
|
|
60
85
|
kind: 'block';
|
|
@@ -77,6 +102,7 @@ export interface InlineBox {
|
|
|
77
102
|
export interface LineGeometry {
|
|
78
103
|
start: number;
|
|
79
104
|
end: number;
|
|
105
|
+
next: number;
|
|
80
106
|
text: string;
|
|
81
107
|
offsets: number[];
|
|
82
108
|
before: number[];
|
|
@@ -84,6 +110,11 @@ export interface LineGeometry {
|
|
|
84
110
|
rowOf: number[];
|
|
85
111
|
rowStarts: number[];
|
|
86
112
|
rowEnds: number[];
|
|
113
|
+
rowTriggers: number[];
|
|
114
|
+
uniform?: {
|
|
115
|
+
first: readonly number[];
|
|
116
|
+
continuation: readonly number[];
|
|
117
|
+
};
|
|
87
118
|
runs: TextRun[];
|
|
88
119
|
inlays: InlineBox[];
|
|
89
120
|
subRows: number;
|
|
@@ -100,22 +131,32 @@ export declare const BOTTOM_PADDING = 8;
|
|
|
100
131
|
export declare const RIGHT_PADDING = 16;
|
|
101
132
|
export declare function wrapIndent(text: string, metrics: LayoutMetrics, limit: number): number;
|
|
102
133
|
export declare function wrapStops(text: string, offsets: readonly number[], metrics: LayoutMetrics, limit: number): number[];
|
|
134
|
+
export declare function scanDenseLine(line: {
|
|
135
|
+
start: number;
|
|
136
|
+
end: number;
|
|
137
|
+
text: string;
|
|
138
|
+
next?: number;
|
|
139
|
+
}, metrics: LayoutMetrics, limit: number | null, lineInlays: readonly Inlay[]): LineGeometry;
|
|
103
140
|
export declare function scanLine(line: {
|
|
104
141
|
start: number;
|
|
105
142
|
end: number;
|
|
106
143
|
text: string;
|
|
144
|
+
next?: number;
|
|
107
145
|
}, metrics: LayoutMetrics, limit: number | null, lineInlays: readonly Inlay[]): LineGeometry;
|
|
108
146
|
export interface LayoutConfig {
|
|
109
147
|
textChanged?: boolean;
|
|
148
|
+
changes?: readonly (readonly DocumentChange[])[];
|
|
110
149
|
metrics?: LayoutMetrics;
|
|
111
150
|
wrapWidth?: number | null;
|
|
112
151
|
inlays?: readonly Inlay[];
|
|
113
152
|
blocks?: readonly BlockWidget[];
|
|
114
153
|
folds?: readonly FoldState[];
|
|
154
|
+
replacements?: readonly BlockReplacement[];
|
|
115
155
|
}
|
|
116
156
|
export declare class EditorLayout {
|
|
117
157
|
rows: LayoutRow[];
|
|
118
158
|
height: number;
|
|
159
|
+
lineHeightsVersion: number;
|
|
119
160
|
width: number;
|
|
120
161
|
private lineRows;
|
|
121
162
|
private geometryCache;
|
|
@@ -125,12 +166,14 @@ export declare class EditorLayout {
|
|
|
125
166
|
private inlays;
|
|
126
167
|
private blocks;
|
|
127
168
|
private folds;
|
|
169
|
+
private replacements;
|
|
128
170
|
private wrapWidth;
|
|
129
171
|
readonly document: LayoutDocument;
|
|
130
172
|
metrics: LayoutMetrics;
|
|
131
173
|
constructor(document: LayoutDocument, metrics: LayoutMetrics);
|
|
132
174
|
get wrapping(): boolean;
|
|
133
175
|
configure(config: LayoutConfig): void;
|
|
176
|
+
private retainGeometry;
|
|
134
177
|
private rowCountOf;
|
|
135
178
|
private rebuild;
|
|
136
179
|
private clampToLine;
|
|
@@ -163,7 +206,7 @@ export declare class EditorLayout {
|
|
|
163
206
|
offset: number;
|
|
164
207
|
rowEnd: boolean;
|
|
165
208
|
};
|
|
166
|
-
rectangles(from: number, to: number, rows: readonly LayoutRow[]): LayoutRect[];
|
|
209
|
+
rectangles(from: number, to: number, rows: readonly LayoutRow[], window?: VerticalWindow): LayoutRect[];
|
|
167
210
|
verticalOffset(offset: number, direction: -1 | 1, x: number, distance?: number): number;
|
|
168
211
|
horizontalOffset(offset: number, direction: -1 | 1): number;
|
|
169
212
|
}
|