@adecore/editor 0.42.0 → 0.43.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.
@@ -1,5 +1,5 @@
1
1
  import type { Keymap } from './keymap-table.ts';
2
- import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorKeyHandler, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
2
+ import type { EditorClickHandler, EditorInlayClickHandler, EditorContextMenu, EditorCopy, EditorKeyHandler, EditorPasteOptions, EditorRunCommand, EditorSelectionRanges, KeyChord } from './types.ts';
3
3
  import type { EditorView } from './view.ts';
4
4
  export interface ControllerOptions {
5
5
  keymap?: Keymap;
@@ -10,12 +10,16 @@ export interface ControllerOptions {
10
10
  zoom(step: -1 | 0 | 1): void;
11
11
  wheelZooms(): boolean;
12
12
  }
13
+ export declare function rememberCopy(text: string, wholeLines: boolean): void;
13
14
  export declare class InputController {
14
15
  private readonly native;
15
16
  private readonly pointer;
16
17
  private readonly touch;
17
18
  private readonly cleanup;
18
19
  private readonly keyHandlers;
20
+ private readonly navigateListeners;
21
+ private readonly copyListeners;
22
+ private wordSources;
19
23
  private readonly gesture;
20
24
  private readonly clickHandlers;
21
25
  private readonly inlayHandlers;
@@ -41,14 +45,17 @@ export declare class InputController {
41
45
  private applyEdits;
42
46
  private replaceSelections;
43
47
  private unfoldCarets;
44
- private paste;
48
+ pasteText(text: string, options?: EditorPasteOptions): boolean;
49
+ onCopy(listener: (copy: EditorCopy) => void): () => void;
45
50
  private commandOptions;
51
+ setWordSources(source: (() => readonly string[]) | null): void;
46
52
  private viewCommand;
47
53
  private wheel;
48
54
  command(name: EditorRunCommand): boolean;
49
55
  setSelectionRanges(provider: EditorSelectionRanges | null): void;
50
56
  private expandThrough;
51
57
  private modelCommand;
58
+ onNavigate(listener: (from: number) => void): () => void;
52
59
  private typeText;
53
60
  private movePages;
54
61
  private toggleColumnMode;
@@ -16,9 +16,12 @@ const MODIFYING = new Set([
16
16
  'deleteLine',
17
17
  'moveLineUp',
18
18
  'moveLineDown',
19
+ 'moveStatementUp',
20
+ 'moveStatementDown',
19
21
  'toggleLineComment',
20
22
  'toggleBlockComment',
21
23
  'startNewLine',
24
+ 'completeCurrentStatement',
22
25
  'startNewLineBefore',
23
26
  'splitLine',
24
27
  'joinLines',
@@ -34,8 +37,11 @@ const MODIFYING = new Set([
34
37
  'reverseLines',
35
38
  'uniqueLines',
36
39
  'convertIndentsToSpaces',
37
- 'convertIndentsToTabs'
40
+ 'convertIndentsToTabs',
41
+ 'hippieCompletion',
42
+ 'hippieBackwardCompletion'
38
43
  ]);
44
+ const CODE_BLOCK_COMMANDS = new Set(['codeBlockStart', 'codeBlockEnd', 'codeBlockStartWithSelection', 'codeBlockEndWithSelection']);
39
45
  const VIEW_COMMANDS = new Set([
40
46
  'collapseRegion',
41
47
  'expandRegion',
@@ -54,11 +60,23 @@ const VIEW_COMMANDS = new Set([
54
60
  'toggleColumnMode',
55
61
  'increaseFontSize',
56
62
  'decreaseFontSize',
57
- 'resetFontSize'
63
+ 'resetFontSize',
64
+ 'methodUp',
65
+ 'methodDown',
66
+ 'nextChange',
67
+ 'previousChange',
68
+ 'pasteAsPlainText'
58
69
  ]);
59
70
  const ZOOM_STEPS = { increaseFontSize: 1, decreaseFontSize: -1, resetFontSize: 0 };
60
71
  /* The clipboard text of the last copy or cut of a bare caret, which pastes back as whole lines. Shared, since it can be pasted in another editor. */
61
72
  let lineClip = null;
73
+ /*
74
+ * Makes `text` the copy that pastes back as whole lines (or not), for a paste from a history that kept what the
75
+ * copy was. The clipboard itself is the caller's.
76
+ */
77
+ export function rememberCopy(text, wholeLines) {
78
+ lineClip = wholeLines ? text : null;
79
+ }
62
80
  function selectionSignature(selections) {
63
81
  return selections.map((selection) => `${selection.anchor}:${selection.head}`).join(',');
64
82
  }
@@ -76,6 +94,9 @@ export class InputController {
76
94
  touch;
77
95
  cleanup = [];
78
96
  keyHandlers = new Set();
97
+ navigateListeners = new Set();
98
+ copyListeners = new Set();
99
+ wordSources = null;
79
100
  gesture;
80
101
  clickHandlers = new Set();
81
102
  inlayHandlers = new Set();
@@ -186,7 +207,7 @@ export class InputController {
186
207
  });
187
208
  this.listen(input, 'paste', (event) => {
188
209
  event.preventDefault();
189
- this.paste(event.clipboardData?.getData('text/plain') ?? '');
210
+ this.pasteText(event.clipboardData?.getData('text/plain') ?? '');
190
211
  });
191
212
  this.listen(input, 'copy', (event) => this.copy(event, false));
192
213
  this.listen(input, 'cut', (event) => this.copy(event, true));
@@ -245,6 +266,8 @@ export class InputController {
245
266
  }
246
267
  this.cleanup.length = 0;
247
268
  this.keyHandlers.clear();
269
+ this.navigateListeners.clear();
270
+ this.copyListeners.clear();
248
271
  }
249
272
  blockedByReadOnly() {
250
273
  return this.view.blockedByReadOnly();
@@ -278,15 +301,25 @@ export class InputController {
278
301
  this.view.ensureVisible(selection.head);
279
302
  }
280
303
  }
281
- paste(text) {
304
+ /* Pastes as a paste from the clipboard does; false when a read-only editor refused. */
305
+ pasteText(text, options = {}) {
282
306
  if (this.blockedByReadOnly()) {
283
- return;
307
+ return false;
284
308
  }
285
309
  this.unfoldCarets();
286
310
  this.historyGroup++;
287
- this.view.model.paste(this.native.normalizeNewlines(text), { ...this.commandOptions(), wholeLines: text !== '' && text === lineClip });
311
+ const pasted = this.view.model.paste(this.native.normalizeNewlines(text), {
312
+ ...this.commandOptions(),
313
+ ...(options.reindent === false ? { indentOnPaste: false } : {}),
314
+ wholeLines: options.wholeLines ?? (text !== '' && text === lineClip)
315
+ });
288
316
  this.historyGroup++;
289
317
  this.view.revealCaret();
318
+ return pasted;
319
+ }
320
+ /* Told what a copy or cut put on the clipboard. */
321
+ onCopy(listener) {
322
+ return subscribe(this.copyListeners, listener);
290
323
  }
291
324
  commandOptions() {
292
325
  const { settings } = this.view;
@@ -300,14 +333,21 @@ export class InputController {
300
333
  tabOutOfClosers: keys.tabOutOfClosers,
301
334
  smartEnter: keys.smartIndentOnEnter,
302
335
  indentOnPaste: keys.indentOnPaste,
336
+ indentGuides: settings.guides,
303
337
  smartSemicolon: keys.smartSemicolon,
304
338
  smartArrow: keys.smartArrow,
305
339
  language: settings.language ?? 'plaintext',
306
340
  camelCase: keys.camelHumps,
307
341
  visualLine: (offset) => this.view.rowOf(offset),
308
- lineSpan: (line) => this.view.lineSpan(line)
342
+ lineSpan: (line) => this.view.lineSpan(line),
343
+ structure: () => this.view.structureRanges(),
344
+ ...(this.wordSources === null ? {} : { wordSources: this.wordSources })
309
345
  };
310
346
  }
347
+ /* The texts Hippie completion takes words from after those of this document; null takes them away. */
348
+ setWordSources(source) {
349
+ this.wordSources = source;
350
+ }
311
351
  /* Folding is the view's, since it knows where the ranges are. */
312
352
  viewCommand(name) {
313
353
  const { view } = this;
@@ -315,6 +355,25 @@ export class InputController {
315
355
  this.options.zoom(ZOOM_STEPS[name]);
316
356
  return true;
317
357
  }
358
+ if (name === 'methodUp' || name === 'methodDown') {
359
+ const from = view.model.getPrimary().head;
360
+ const moved = view.goToMethod(name === 'methodUp' ? -1 : 1);
361
+ if (moved) {
362
+ emit(this.navigateListeners, from);
363
+ }
364
+ return moved;
365
+ }
366
+ if (name === 'pasteAsPlainText') {
367
+ // The clipboard is read once a person asks, and an editor with no way to read it does nothing.
368
+ if (this.blockedByReadOnly() || globalThis.navigator?.clipboard?.readText === undefined) {
369
+ return false;
370
+ }
371
+ void navigator.clipboard.readText().then((text) => this.pasteText(text, { reindent: false }), () => undefined);
372
+ return true;
373
+ }
374
+ if (name === 'nextChange' || name === 'previousChange') {
375
+ return view.goToChange(name === 'nextChange' ? 1 : -1);
376
+ }
318
377
  if (view.settings.folding === false && name !== 'toggleColumnMode') {
319
378
  return false;
320
379
  }
@@ -413,7 +472,10 @@ export class InputController {
413
472
  }
414
473
  }
415
474
  }
416
- const folded = name === 'moveLineUp' || name === 'moveLineDown' ? this.view.getFolds().collapsed : [];
475
+ const before = model.getPrimary().head;
476
+ const folded = name === 'moveLineUp' || name === 'moveLineDown' || name === 'moveStatementUp' || name === 'moveStatementDown'
477
+ ? this.view.getFolds().collapsed
478
+ : [];
417
479
  const result = model.execute(name, {
418
480
  ...this.commandOptions(),
419
481
  onLinesMoved: (moves) => this.view.refoldMoved(folded, moves)
@@ -424,9 +486,19 @@ export class InputController {
424
486
  if (name === 'smartEnd' || name === 'selectSmartEnd') {
425
487
  this.view.markRowEnd(model.getPrimary().head);
426
488
  }
489
+ if (name === 'hippieCompletion' || name === 'hippieBackwardCompletion') {
490
+ this.view.setHippieSource(model.hippieSource);
491
+ }
427
492
  this.view.revealCaret();
493
+ if (CODE_BLOCK_COMMANDS.has(name) && model.getPrimary().head !== before) {
494
+ emit(this.navigateListeners, before);
495
+ }
428
496
  return result;
429
497
  }
498
+ /* Told the offset the primary caret left when a command that navigates moved it. */
499
+ onNavigate(listener) {
500
+ return subscribe(this.navigateListeners, listener);
501
+ }
430
502
  typeText(text) {
431
503
  if (this.blockedByReadOnly()) {
432
504
  return;
@@ -651,6 +723,7 @@ export class InputController {
651
723
  if (event.isComposing || this.native.composing) {
652
724
  return;
653
725
  }
726
+ this.view.setHippieSource(null);
654
727
  const added = this.gesture.keydown(event);
655
728
  if (added !== null) {
656
729
  event.preventDefault();
@@ -726,6 +799,7 @@ export class InputController {
726
799
  : selections.map((selection) => model.slice(Math.min(selection.anchor, selection.head), Math.max(selection.anchor, selection.head))).join('\n');
727
800
  event.clipboardData?.setData('text/plain', text);
728
801
  lineClip = empty ? text : null;
802
+ emit(this.copyListeners, { text, wholeLines: empty, cut });
729
803
  if (!cut || this.blockedByReadOnly()) {
730
804
  return;
731
805
  }
package/dist/editor.css CHANGED
@@ -652,11 +652,16 @@
652
652
  .se-find-match,
653
653
  .se-find-current,
654
654
  .se-occurrence,
655
+ .se-hippie-source,
655
656
  .se-bracket-match,
656
657
  .se-bracket-unmatched {
657
658
  position: absolute;
658
659
  border-radius: var(--radius-xs);
659
660
  }
661
+ .se-hippie-source {
662
+ background: color-mix(in srgb, var(--accent) 22%, transparent);
663
+ border-radius: var(--radius-sm);
664
+ }
660
665
  .se-find-match {
661
666
  background: var(--find-match);
662
667
  }
@@ -747,6 +752,14 @@
747
752
  white-space: pre;
748
753
  cursor: default;
749
754
  }
755
+ .se-swatch {
756
+ height: 12px;
757
+ margin-top: calc((var(--code-line-height, 20px) - 12px) / 2);
758
+ padding: 0;
759
+ border-radius: var(--radius-sm);
760
+ box-shadow: inset 0 0 0 1px var(--border);
761
+ cursor: pointer;
762
+ }
750
763
  .se-inlay-link {
751
764
  text-decoration: underline;
752
765
  text-underline-offset: 2px;
package/dist/engine.js CHANGED
@@ -35,6 +35,8 @@ class SmartEditor {
35
35
  lensRevisions = new Map();
36
36
  tokenizerRequest = 0;
37
37
  settingText = false;
38
+ /* The hints of each owner, in the order the owners first set theirs. */
39
+ inlayOwners = new Map();
38
40
  disposed = false;
39
41
  engine;
40
42
  constructor(engine, element, options) {
@@ -302,14 +304,21 @@ class SmartEditor {
302
304
  ...(marker.message === undefined ? {} : { message: marker.message })
303
305
  })));
304
306
  }
305
- setInlayHints(hints) {
306
- this.view.setInlays(hints.map((hint, index) => ({
307
+ setInlayHints(hints, owner = DEFAULT_WIDGET_OWNER) {
308
+ if (hints.length === 0) {
309
+ this.inlayOwners.delete(owner);
310
+ }
311
+ else {
312
+ this.inlayOwners.set(owner, hints);
313
+ }
314
+ this.view.setInlays([...this.inlayOwners.values()].flat().map((hint, index) => ({
307
315
  id: hint.id ?? `hint-${index}`,
308
316
  at: this.offsetAt(hint.position),
309
317
  text: hint.label,
310
318
  ...(hint.parts === undefined ? {} : { parts: hint.parts }),
311
319
  ...(hint.paddingLeft ? { gapLeft: INLAY_GAP } : {}),
312
- ...(hint.paddingRight ? { gapRight: INLAY_GAP } : {})
320
+ ...(hint.paddingRight ? { gapRight: INLAY_GAP } : {}),
321
+ ...(hint.swatch === undefined ? {} : { swatch: hint.swatch })
313
322
  })));
314
323
  }
315
324
  onInlayHover(listener) {
@@ -681,6 +690,24 @@ class SmartEditor {
681
690
  setFoldHints(hints) {
682
691
  this.view.setFoldHints(hints === null ? null : this.foldHintsByOffset(hints));
683
692
  }
693
+ setDeclarations(positions) {
694
+ this.view.setDeclarations(positions === null ? null : positions.map((position) => this.offsetAt(position)));
695
+ }
696
+ onNavigate(listener) {
697
+ return this.controller.onNavigate((from) => listener(this.positionAt(from)));
698
+ }
699
+ hasFocus() {
700
+ return this.view.focused;
701
+ }
702
+ setWordSources(source) {
703
+ this.controller.setWordSources(source);
704
+ }
705
+ onCopy(listener) {
706
+ return this.controller.onCopy(listener);
707
+ }
708
+ paste(text, options) {
709
+ return this.controller.pasteText(text, options);
710
+ }
684
711
  foldHintsByOffset(hints) {
685
712
  const lineOf = (line) => this.model.getLine(Math.min(line, this.model.getLineCount() - 1));
686
713
  const within = (line, character) => Math.min(line.end, line.start + Math.max(0, character));
package/dist/fake.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWhitespaceCleanup, EditorWidget } from './types.ts';
1
+ import type { Editor, EditorAttributionHover, EditorAttributionMark, EditorBlock, EditorCodeBlockOptions, EditorLineAction, EditorReplacement, EditorLineHighlight, LineToken, EditorChangeMark, EditorCodeVision, EditorClick, EditorClickHandler, EditorContextMenu, EditorContentChange, EditorEngine, EditorFindQuery, EditorFindState, EditorReplaceOptions, EditorGutterAction, EditorGutterMarker, EditorHighlight, EditorHover, EditorIndentation, EditorGhostText, EditorInlayClick, EditorInlayClickHandler, EditorInlayHint, EditorInlayTarget, EditorKeyHandler, EditorInputPopup, EditorMarker, EditorMessages, EditorOptions, EditorPosition, EditorRemoteCursor, EditorRange, EditorReveal, EditorRect, EditorRunCommand, EditorSelectionRanges, EditorFoldHints, EditorFoldOutline, EditorFolds, EditorSemanticToken, EditorSmartKeys, EditorApplyEditsOptions, EditorCopy, EditorPasteOptions, EditorTextChange, EditorTrackedRange, EditorTheme, EditorWhitespaceCleanup, EditorWidget } from './types.ts';
2
2
  import { type Listener } from './listeners.ts';
3
3
  export declare class FakeEditor implements Editor {
4
4
  readonly element: HTMLElement;
@@ -142,6 +142,22 @@ export declare class FakeEditor implements Editor {
142
142
  todoWords: readonly string[] | undefined;
143
143
  setTodoWords(words: readonly string[]): void;
144
144
  setFoldHints(hints: EditorFoldHints | null): void;
145
+ declarations: readonly EditorPosition[] | null;
146
+ setDeclarations(positions: readonly EditorPosition[] | null): void;
147
+ private readonly navigations;
148
+ onNavigate(listener: (from: EditorPosition) => void): () => void;
149
+ navigate(from: EditorPosition): void;
150
+ hasFocus(): boolean;
151
+ private readonly copies;
152
+ onCopy(listener: (copy: EditorCopy) => void): () => void;
153
+ copy(text: string, wholeLines?: boolean, cut?: boolean): void;
154
+ readonly pastes: Array<{
155
+ text: string;
156
+ options: EditorPasteOptions | undefined;
157
+ }>;
158
+ paste(text: string, options?: EditorPasteOptions): boolean;
159
+ wordSources: (() => readonly string[]) | null;
160
+ setWordSources(source: (() => readonly string[]) | null): void;
145
161
  setSmartKeys(keys: Partial<EditorSmartKeys>): void;
146
162
  setIndentation(indentation: EditorIndentation): void;
147
163
  markers: readonly EditorMarker[];
@@ -161,7 +177,8 @@ export declare class FakeEditor implements Editor {
161
177
  private readonly keys;
162
178
  setMarkers(markers: readonly EditorMarker[]): void;
163
179
  inlayHints: readonly EditorInlayHint[];
164
- setInlayHints(hints: readonly EditorInlayHint[]): void;
180
+ private readonly inlayOwners;
181
+ setInlayHints(hints: readonly EditorInlayHint[], owner?: string): void;
165
182
  private readonly inlayHovers;
166
183
  private readonly inlayHandlers;
167
184
  inlayLink: {
package/dist/fake.js CHANGED
@@ -581,6 +581,59 @@ export class FakeEditor {
581
581
  setFoldHints(hints) {
582
582
  this.foldHints = hints;
583
583
  }
584
+ declarations = null;
585
+ setDeclarations(positions) {
586
+ this.declarations = positions;
587
+ }
588
+ navigations = new Set();
589
+ onNavigate(listener) {
590
+ return subscribe(this.navigations, listener);
591
+ }
592
+ /* Stands for a command that navigated: tells the listeners the caret left `from`. */
593
+ navigate(from) {
594
+ emit(this.navigations, from);
595
+ }
596
+ hasFocus() {
597
+ return this.focused;
598
+ }
599
+ copies = new Set();
600
+ onCopy(listener) {
601
+ return subscribe(this.copies, listener);
602
+ }
603
+ /* Stands for a copy or cut of a person: tells the listeners what went on the clipboard. */
604
+ copy(text, wholeLines = false, cut = false) {
605
+ emit(this.copies, { text, wholeLines, cut });
606
+ }
607
+ /* Every paste a host asked for, with its options. */
608
+ pastes = [];
609
+ /* Puts the text at every caret, one line per caret when the lines are as many as the carets, and leaves the carets behind it. */
610
+ paste(text, options) {
611
+ this.assertLive();
612
+ this.pastes.push({ text, options });
613
+ if (this.readOnly || text === '') {
614
+ return false;
615
+ }
616
+ const lines = text.split('\n');
617
+ const selections = [...this.selections].sort((left, right) => Math.min(left.anchor, left.head) - Math.min(right.anchor, right.head));
618
+ const perCaret = lines.length === selections.length;
619
+ const edits = selections.map((selection, index) => ({
620
+ from: Math.min(selection.anchor, selection.head),
621
+ to: Math.max(selection.anchor, selection.head),
622
+ text: perCaret ? lines[index] : text
623
+ }));
624
+ return this.edit(edits, 'command', false, () => {
625
+ let shift = 0;
626
+ return edits.map((edit) => {
627
+ const caret = edit.from + shift + edit.text.length;
628
+ shift += edit.text.length - (edit.to - edit.from);
629
+ return { anchor: caret, head: caret };
630
+ });
631
+ });
632
+ }
633
+ wordSources = null;
634
+ setWordSources(source) {
635
+ this.wordSources = source;
636
+ }
584
637
  setSmartKeys(keys) {
585
638
  this.smartKeys = keys;
586
639
  }
@@ -601,10 +654,17 @@ export class FakeEditor {
601
654
  setMarkers(markers) {
602
655
  this.markers = markers;
603
656
  }
604
- /* What the host drew as hints last. */
657
+ /* What the host drew as hints last, every owner's together. */
605
658
  inlayHints = [];
606
- setInlayHints(hints) {
607
- this.inlayHints = hints;
659
+ inlayOwners = new Map();
660
+ setInlayHints(hints, owner = 'default') {
661
+ if (hints.length === 0) {
662
+ this.inlayOwners.delete(owner);
663
+ }
664
+ else {
665
+ this.inlayOwners.set(owner, hints);
666
+ }
667
+ this.inlayHints = [...this.inlayOwners.values()].flat();
608
668
  }
609
669
  inlayHovers = new Set();
610
670
  inlayHandlers = new Set();
@@ -872,6 +932,8 @@ export class FakeEditor {
872
932
  this.changes.clear();
873
933
  this.textChanges.clear();
874
934
  this.carets.clear();
935
+ this.navigations.clear();
936
+ this.copies.clear();
875
937
  this.hovers.clear();
876
938
  this.inlayHovers.clear();
877
939
  this.inlayHandlers.clear();
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export { findDocComments, MAX_DOC_COMMENTS, type DocComment } from '@adecore/edi
4
4
  export { DEFAULT_TODO_WORDS, findTodos, type TodoMatch, type TodoOptions } from '@adecore/editor-core';
5
5
  export { detectIndentation, type DetectedIndentation } from '@adecore/editor-core';
6
6
  export { createSmartEditorEngine } from './engine.ts';
7
+ export { rememberCopy } from './controller.ts';
7
8
  export { DEFAULT_SMART_KEYS } from './smart-keys.ts';
8
9
  export { shikiScopeColors, shikiTokenizers } from './shiki.ts';
9
- 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, EditorWhitespaceCleanup, EditorWidget, EditorZoom, FoldRole, KeyChord, LineToken, LineTokenKind, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
10
+ 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, EditorCopy, EditorPasteOptions, EditorTextChange, EditorTrackedRange, EditorRunCommand, EditorSelectionRanges, EditorTheme, EditorViewCommand, EditorWhitespaceCleanup, EditorWidget, EditorZoom, FoldRole, KeyChord, LineToken, LineTokenKind, ScopeColorSource, ScopeColors, ScopeStyle, EditorSemanticToken, LineTokenizer, SmartEditorEngineOptions, TokenizedLine, TokenizerSource } from './types.ts';
package/dist/index.js CHANGED
@@ -4,5 +4,6 @@ export { findDocComments, MAX_DOC_COMMENTS } from '@adecore/editor-core';
4
4
  export { DEFAULT_TODO_WORDS, findTodos } from '@adecore/editor-core';
5
5
  export { detectIndentation } from '@adecore/editor-core';
6
6
  export { createSmartEditorEngine } from './engine.js';
7
+ export { rememberCopy } from './controller.js';
7
8
  export { DEFAULT_SMART_KEYS } from './smart-keys.js';
8
9
  export { shikiScopeColors, shikiTokenizers } from './shiki.js';
@@ -18,10 +18,15 @@ export declare const KEYMAP: {
18
18
  readonly deleteLine: KeyBinding;
19
19
  readonly moveLineUp: KeyBinding;
20
20
  readonly moveLineDown: KeyBinding;
21
+ readonly moveStatementUp: KeyBinding;
22
+ readonly moveStatementDown: KeyBinding;
21
23
  readonly toggleLineComment: KeyBinding;
22
24
  readonly toggleBlockComment: KeyBinding;
23
25
  readonly joinLines: KeyBinding;
24
26
  readonly startNewLine: KeyBinding;
27
+ readonly completeCurrentStatement: KeyBinding;
28
+ readonly hippieCompletion: KeyBinding;
29
+ readonly hippieBackwardCompletion: KeyBinding;
25
30
  readonly startNewLineBefore: KeyBinding;
26
31
  readonly splitLine: KeyBinding;
27
32
  readonly toggleCase: KeyBinding;
@@ -34,6 +39,18 @@ export declare const KEYMAP: {
34
39
  readonly expandSelection: KeyBinding;
35
40
  readonly shrinkSelection: KeyBinding;
36
41
  readonly matchBrace: KeyBinding;
42
+ readonly methodUp: KeyBinding;
43
+ readonly methodDown: KeyBinding;
44
+ readonly lastEditLocation: KeyBinding;
45
+ readonly nextEditLocation: KeyBinding;
46
+ readonly pasteFromHistory: KeyBinding;
47
+ readonly pasteAsPlainText: KeyBinding;
48
+ readonly nextChange: KeyBinding;
49
+ readonly previousChange: KeyBinding;
50
+ readonly codeBlockStart: KeyBinding;
51
+ readonly codeBlockEnd: KeyBinding;
52
+ readonly codeBlockStartWithSelection: KeyBinding;
53
+ readonly codeBlockEndWithSelection: KeyBinding;
37
54
  readonly selectNextOccurrence: KeyBinding;
38
55
  readonly unselectOccurrence: KeyBinding;
39
56
  readonly selectAllOccurrences: KeyBinding;
@@ -80,6 +97,7 @@ export declare const KEYMAP: {
80
97
  readonly renameSymbol: KeyBinding;
81
98
  readonly organizeImports: KeyBinding;
82
99
  readonly formatDocument: KeyBinding;
100
+ readonly wrapWithAbbreviation: KeyBinding;
83
101
  readonly selectionToChat: KeyBinding;
84
102
  readonly inlineEdit: KeyBinding;
85
103
  readonly suggestInline: KeyBinding;
@@ -91,6 +109,7 @@ export declare const KEYMAP: {
91
109
  readonly peekDefinition: KeyBinding;
92
110
  readonly peekReferences: KeyBinding;
93
111
  readonly callHierarchy: KeyBinding;
112
+ readonly typeHierarchy: KeyBinding;
94
113
  readonly toggleRenderedDocs: KeyBinding;
95
114
  readonly historyBack: KeyBinding;
96
115
  readonly historyForward: KeyBinding;
@@ -104,7 +123,7 @@ export declare const KEYMAP: {
104
123
  readonly replace: KeyBinding;
105
124
  };
106
125
  export type KeymapId = keyof typeof KEYMAP;
107
- export type OptionalKeymapId = 'toggleRenderedDocs' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize' | 'sortLines' | 'reverseLines' | 'uniqueLines' | 'convertIndentsToSpaces' | 'convertIndentsToTabs';
126
+ export type OptionalKeymapId = 'toggleRenderedDocs' | 'increaseFontSize' | 'decreaseFontSize' | 'resetFontSize' | 'sortLines' | 'reverseLines' | 'uniqueLines' | 'convertIndentsToSpaces' | 'convertIndentsToTabs' | 'completeCurrentStatement' | 'hippieCompletion' | 'hippieBackwardCompletion' | 'moveStatementUp' | 'moveStatementDown' | 'lastEditLocation' | 'nextEditLocation' | 'methodUp' | 'methodDown' | 'pasteFromHistory' | 'pasteAsPlainText' | 'nextChange' | 'previousChange' | 'codeBlockStart' | 'codeBlockEnd' | 'codeBlockStartWithSelection' | 'codeBlockEndWithSelection' | 'wrapWithAbbreviation' | 'typeHierarchy';
108
127
  export type Keymap = Readonly<Record<Exclude<KeymapId, OptionalKeymapId>, KeyBinding> & Partial<Record<OptionalKeymapId, KeyBinding>>>;
109
128
  export type KeymapOverrides = Partial<Record<KeymapId, Partial<KeyBinding>>>;
110
129
  export declare const KEYMAP_IDS: KeymapId[];
@@ -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
- shrinkSelection: bind('Alt+ArrowDown'),
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
- selectTextStart: bind('Meta+Shift+ArrowUp', null),
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('Meta+Shift+ArrowDown', null),
75
+ selectTextEnd: bind(null),
57
76
  collapse: bind('Mod+-'),
58
77
  expand: bind('Mod+='),
59
78
  collapseAll: bind('Mod+Shift+-'),
@@ -81,6 +100,7 @@ export const KEYMAP = {
81
100
  renameSymbol: bind('Shift+F6'),
82
101
  organizeImports: bind('Ctrl+Alt+O'),
83
102
  formatDocument: bind('Mod+Alt+L'),
103
+ wrapWithAbbreviation: bind('Mod+Alt+J'),
84
104
  selectionToChat: bind(null),
85
105
  inlineEdit: bind(null),
86
106
  suggestInline: bind(null),
@@ -92,6 +112,7 @@ export const KEYMAP = {
92
112
  peekDefinition: bind('Alt+Space', 'Ctrl+Shift+I'),
93
113
  peekReferences: bind('Alt+F7'),
94
114
  callHierarchy: bind('Ctrl+Alt+H'),
115
+ typeHierarchy: bind('Ctrl+H'),
95
116
  toggleRenderedDocs: bind('Ctrl+Alt+Q'),
96
117
  historyBack: bind('Mod+[', 'Ctrl+Alt+ArrowLeft'),
97
118
  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
@@ -36,7 +36,9 @@ export interface Inlay {
36
36
  gapRight?: number;
37
37
  composition?: boolean;
38
38
  ghost?: boolean;
39
+ swatch?: string;
39
40
  }
41
+ export declare const SWATCH_SIZE = 12;
40
42
  export interface BlockWidget {
41
43
  id: string;
42
44
  at: number;