Browse Source

implement multi-cursor

WNomunomu 1 year ago
parent
commit
48faba1628
1 changed files with 63 additions and 0 deletions
  1. 63 0
      packages/editor/src/client/stores/use-editor-shortcuts.ts

+ 63 - 0
packages/editor/src/client/stores/use-editor-shortcuts.ts

@@ -0,0 +1,63 @@
+import { useEffect, useCallback } from 'react';
+
+import type { SelectionRange } from '@codemirror/state';
+import { EditorSelection } from '@codemirror/state';
+import { keymap } from '@codemirror/view';
+
+import type { UseCodeMirrorEditor } from '../services';
+
+import type { EditorView } from 'src/interfaces';
+
+
+export const useEditorShortcuts = (
+    codeMirrorEditor?: UseCodeMirrorEditor,
+): void => {
+
+  const addMultiCursor = useCallback((view: EditorView, direction: 'up' | 'down') => {
+
+    const selection = view.state.selection;
+    const doc = view.state.doc;
+    const ranges = selection.ranges;
+    const newRanges: SelectionRange[] = [];
+
+    ranges.forEach((range) => {
+
+      const head = range.head;
+      const line = doc.lineAt(head);
+      const targetLine = direction === 'up' ? line.number - 1 : line.number + 1;
+
+      if (targetLine < 1 || targetLine > doc.lines) return;
+
+      const targetLineText = doc.line(targetLine);
+
+      const col = Math.min(range.head - line.from, targetLineText.length);
+      const cursorPos = targetLineText.from + col;
+
+      newRanges.push(EditorSelection.cursor(cursorPos));
+
+    });
+
+    if (newRanges.length) {
+      const transaction = {
+        selection: EditorSelection.create([...ranges, ...newRanges]),
+      };
+
+      view.dispatch(transaction);
+    }
+
+    return true;
+  }, []);
+
+  useEffect(() => {
+
+    const extension = keymap.of([
+      { key: 'mod-alt-ArrowUp', run: view => addMultiCursor(view, 'up') },
+      { key: 'mod-alt-ArrowDown', run: view => addMultiCursor(view, 'down') },
+    ]);
+
+    const cleanupFunction = codeMirrorEditor?.appendExtensions?.(extension);
+    return cleanupFunction;
+
+  }, [addMultiCursor, codeMirrorEditor]);
+
+};