src/lib/org/keymap.js (view raw)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
import { keymap } from '@codemirror/view';
import { insertNewlineAndIndent } from '@codemirror/commands';
import {
adjustHeading,
insertNewListItem,
isChecklistLine,
isHeadingLine,
} from './editorUtils.js';
function promoteHeading(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
if (!isHeadingLine(line.text)) return false;
const next = adjustHeading(line.text, -1);
if (next === line.text) return false;
view.dispatch({ changes: { from: line.from, to: line.to, insert: next } });
return true;
}
function demoteHeading(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
if (!isHeadingLine(line.text)) return false;
const next = adjustHeading(line.text, 1);
if (next === line.text) return false;
view.dispatch({ changes: { from: line.from, to: line.to, insert: next } });
return true;
}
function continueListItem(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
const prefix = insertNewListItem(line.text);
view.dispatch({
changes: { from: line.to, insert: `\n${prefix}` },
selection: { anchor: line.to + 1 + prefix.length },
});
return true;
}
function indentListLine(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
if (!/^(\s*)([-+*]|\d+\.)\s+/.test(line.text) && !isChecklistLine(line.text)) {
return false;
}
view.dispatch({
changes: { from: line.from, to: line.from, insert: ' ' },
selection: { anchor: view.state.selection.main.head + 2 },
});
return true;
}
function handleTab(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
if (isHeadingLine(line.text)) {
return demoteHeading(view);
}
if (indentListLine(view)) return true;
return insertNewlineAndIndent(view);
}
function handleShiftTab(view) {
const line = view.state.doc.lineAt(view.state.selection.main.head);
if (isHeadingLine(line.text)) {
return promoteHeading(view);
}
if (isChecklistLine(line.text) || /^(\s*)([-+*]|\d+\.)\s+/.test(line.text)) {
const match = line.text.match(/^(\s*)/);
const indent = match?.[1] ?? '';
if (indent.length >= 2) {
view.dispatch({
changes: { from: line.from, to: line.to, insert: line.text.slice(2) },
});
return true;
}
}
return false;
}
export const orgKeymap = keymap.of([
{ key: 'Tab', run: handleTab },
{ key: 'Shift-Tab', run: handleShiftTab },
{ key: 'Mod-Enter', run: continueListItem },
]);
|