Spaces:
Sleeping
Sleeping
| import { indentLess } from '@codemirror/commands'; | |
| import { indentUnit } from '@codemirror/language'; | |
| import { EditorSelection, EditorState, Line, type ChangeSpec } from '@codemirror/state'; | |
| import { EditorView, type KeyBinding } from '@codemirror/view'; | |
| export const indentKeyBinding: KeyBinding = { | |
| key: 'Tab', | |
| run: indentMore, | |
| shift: indentLess, | |
| }; | |
| function indentMore({ state, dispatch }: EditorView) { | |
| if (state.readOnly) { | |
| return false; | |
| } | |
| dispatch( | |
| state.update( | |
| changeBySelectedLine(state, (from, to, changes) => { | |
| changes.push({ from, to, insert: state.facet(indentUnit) }); | |
| }), | |
| { userEvent: 'input.indent' }, | |
| ), | |
| ); | |
| return true; | |
| } | |
| function changeBySelectedLine( | |
| state: EditorState, | |
| cb: (from: number, to: number | undefined, changes: ChangeSpec[], line: Line) => void, | |
| ) { | |
| return state.changeByRange((range) => { | |
| const changes: ChangeSpec[] = []; | |
| const line = state.doc.lineAt(range.from); | |
| // just insert single indent unit at the current cursor position | |
| if (range.from === range.to) { | |
| cb(range.from, undefined, changes, line); | |
| } | |
| // handle the case when multiple characters are selected in a single line | |
| else if (range.from < range.to && range.to <= line.to) { | |
| cb(range.from, range.to, changes, line); | |
| } else { | |
| let atLine = -1; | |
| // handle the case when selection spans multiple lines | |
| for (let pos = range.from; pos <= range.to; ) { | |
| const line = state.doc.lineAt(pos); | |
| if (line.number > atLine && (range.empty || range.to > line.from)) { | |
| cb(line.from, undefined, changes, line); | |
| atLine = line.number; | |
| } | |
| pos = line.to + 1; | |
| } | |
| } | |
| const changeSet = state.changes(changes); | |
| return { | |
| changes, | |
| range: EditorSelection.range(changeSet.mapPos(range.anchor, 1), changeSet.mapPos(range.head, 1)), | |
| }; | |
| }); | |
| } | |