|
|
@@ -1,16 +1,17 @@
|
|
|
import { useEffect } from 'react';
|
|
|
|
|
|
-import type { SelectionRange, Extension } from '@codemirror/state';
|
|
|
-import { EditorSelection, type ChangeSpec } from '@codemirror/state';
|
|
|
+import type { EditorView } from '@codemirror/view';
|
|
|
import {
|
|
|
- keymap, type Command, EditorView, type KeyBinding,
|
|
|
+ keymap, type Command, type KeyBinding,
|
|
|
} from '@codemirror/view';
|
|
|
|
|
|
import type { UseCodeMirrorEditor } from '../services';
|
|
|
+import { useAddMultiCursorCommand } from '../services/use-codemirror-editor/utils/add-multi-cursor';
|
|
|
import type { InsertMarkdownElements } from '../services/use-codemirror-editor/utils/insert-markdown-elements';
|
|
|
import { useInsertMarkdownElements } from '../services/use-codemirror-editor/utils/insert-markdown-elements';
|
|
|
import { useInsertPrefix } from '../services/use-codemirror-editor/utils/insert-prefix';
|
|
|
import type { InsertPrefix } from '../services/use-codemirror-editor/utils/insert-prefix';
|
|
|
+import { useMakeCodeBlockExtension } from '../services/use-codemirror-editor/utils/make-text-code-block';
|
|
|
|
|
|
import type { KeyMapMode } from 'src/consts';
|
|
|
|
|
|
@@ -41,118 +42,7 @@ const generateAddMarkdownSymbolCommand = (
|
|
|
return addMarkdownSymbolCommand;
|
|
|
};
|
|
|
|
|
|
-const makeTextCodeBlock: Command = (view: EditorView) => {
|
|
|
- const state = view.state;
|
|
|
- const doc = state.doc;
|
|
|
- const changes: ChangeSpec[] = [];
|
|
|
- const newSelections: SelectionRange[] = [];
|
|
|
-
|
|
|
- state.selection.ranges.forEach((range) => {
|
|
|
- const startLine = doc.lineAt(range.from);
|
|
|
- const endLine = doc.lineAt(range.to);
|
|
|
- const selectedText = doc.sliceString(range.from, range.to, '');
|
|
|
- const isAlreadyWrapped = selectedText.startsWith('```') && selectedText.endsWith('```');
|
|
|
-
|
|
|
- const codeBlockMarkerLength = 4;
|
|
|
-
|
|
|
- if (isAlreadyWrapped) {
|
|
|
- const startMarkerEnd = startLine.from + codeBlockMarkerLength;
|
|
|
- const endMarkerStart = endLine.to - codeBlockMarkerLength;
|
|
|
-
|
|
|
- changes.push({
|
|
|
- from: startLine.from,
|
|
|
- to: startMarkerEnd,
|
|
|
- insert: '',
|
|
|
- });
|
|
|
-
|
|
|
- changes.push({
|
|
|
- from: endMarkerStart,
|
|
|
- to: endLine.to,
|
|
|
- insert: '',
|
|
|
- });
|
|
|
-
|
|
|
- newSelections.push(EditorSelection.range(startLine.from, endMarkerStart - codeBlockMarkerLength));
|
|
|
- }
|
|
|
- else {
|
|
|
- // Add code block markers
|
|
|
- changes.push({
|
|
|
- from: startLine.from,
|
|
|
- insert: '```\n',
|
|
|
- });
|
|
|
-
|
|
|
- changes.push({
|
|
|
- from: endLine.to,
|
|
|
- insert: '\n```',
|
|
|
- });
|
|
|
-
|
|
|
- if (selectedText.length === 0) {
|
|
|
- newSelections.push(EditorSelection.cursor(startLine.from + codeBlockMarkerLength));
|
|
|
- }
|
|
|
- else {
|
|
|
- newSelections.push(EditorSelection.range(startLine.from, endLine.to + codeBlockMarkerLength * 2));
|
|
|
- }
|
|
|
- }
|
|
|
- });
|
|
|
-
|
|
|
- view.dispatch({
|
|
|
- changes,
|
|
|
- selection: EditorSelection.create(newSelections),
|
|
|
- });
|
|
|
-
|
|
|
- return true;
|
|
|
-};
|
|
|
-
|
|
|
-const addMultiCursor = (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;
|
|
|
-};
|
|
|
-
|
|
|
-const makeCodeBlockExtension: Extension = EditorView.domEventHandlers({
|
|
|
- keydown: (event, view) => {
|
|
|
-
|
|
|
- const isModKey = event.ctrlKey || event.metaKey;
|
|
|
-
|
|
|
- if (event.code === 'KeyC' && event.shiftKey && event.altKey && isModKey) {
|
|
|
- event.preventDefault();
|
|
|
- makeTextCodeBlock(view);
|
|
|
- return true;
|
|
|
- }
|
|
|
-
|
|
|
- return false;
|
|
|
- },
|
|
|
-});
|
|
|
-
|
|
|
-export const useCustomKeyBindings = (view?: EditorView, keyMapName?: KeyMapMode): KeyBinding[] => {
|
|
|
+const useCustomKeyBindings = (view?: EditorView, keyMapName?: KeyMapMode): KeyBinding[] => {
|
|
|
|
|
|
const insertMarkdownElements = useInsertMarkdownElements(view);
|
|
|
|
|
|
@@ -171,10 +61,12 @@ export const useCustomKeyBindings = (view?: EditorView, keyMapName?: KeyMapMode)
|
|
|
return customKeyBindings;
|
|
|
};
|
|
|
|
|
|
-export const useKeyBindings = (view?: EditorView, customKeyBindings?: KeyBinding[]): KeyBinding[] => {
|
|
|
+const useKeyBindings = (view?: EditorView, customKeyBindings?: KeyBinding[]): KeyBinding[] => {
|
|
|
|
|
|
const insertMarkdownElements = useInsertMarkdownElements(view);
|
|
|
const insertPrefix = useInsertPrefix(view);
|
|
|
+ const upMultiCursorCommand = useAddMultiCursorCommand('up');
|
|
|
+ const downMultiCursorCommand = useAddMultiCursorCommand('down');
|
|
|
|
|
|
const keyBindings: KeyBinding[] = [
|
|
|
{ key: 'mod-shift-i', run: generateAddMarkdownSymbolCommand(insertMarkdownElements, '*', '*') },
|
|
|
@@ -184,8 +76,8 @@ export const useKeyBindings = (view?: EditorView, customKeyBindings?: KeyBinding
|
|
|
{ key: 'mod-shift-8', run: generateAddMarkdownSymbolCommand(insertPrefix, '-') },
|
|
|
{ key: 'mod-shift-9', run: generateAddMarkdownSymbolCommand(insertPrefix, '>') },
|
|
|
{ key: 'mod-shift-u', run: generateAddMarkdownSymbolCommand(insertMarkdownElements, '[', ']()') },
|
|
|
- { key: 'mod-alt-ArrowUp', run: view => addMultiCursor(view, 'up') },
|
|
|
- { key: 'mod-alt-ArrowDown', run: view => addMultiCursor(view, 'down') },
|
|
|
+ { key: 'mod-alt-ArrowUp', run: upMultiCursorCommand },
|
|
|
+ { key: 'mod-alt-ArrowDown', run: downMultiCursorCommand },
|
|
|
];
|
|
|
|
|
|
if (customKeyBindings != null) {
|
|
|
@@ -195,12 +87,17 @@ export const useKeyBindings = (view?: EditorView, customKeyBindings?: KeyBinding
|
|
|
return keyBindings;
|
|
|
};
|
|
|
|
|
|
-export const useKeyboardShortcuts = (codeMirrorEditor?: UseCodeMirrorEditor, keyBindings?: KeyBinding[]): void => {
|
|
|
+export const useKeyboardShortcuts = (codeMirrorEditor?: UseCodeMirrorEditor, keymapModeName?: KeyMapMode): void => {
|
|
|
+
|
|
|
+ const customKeyBindings = useCustomKeyBindings(codeMirrorEditor?.view, keymapModeName);
|
|
|
+ const keyBindings = useKeyBindings(codeMirrorEditor?.view, customKeyBindings);
|
|
|
+
|
|
|
+ const makeCodeBlockExtension = useMakeCodeBlockExtension();
|
|
|
|
|
|
useEffect(() => {
|
|
|
const cleanupFunction = codeMirrorEditor?.appendExtensions?.([makeCodeBlockExtension]);
|
|
|
return cleanupFunction;
|
|
|
- }, [codeMirrorEditor]);
|
|
|
+ }, [codeMirrorEditor, makeCodeBlockExtension]);
|
|
|
|
|
|
useEffect(() => {
|
|
|
|