Files
fluxer/fluxer_app/src/features/lexical/composer/ComposerCodeIndent.ts
T

49 lines
1.6 KiB
TypeScript

// SPDX-License-Identifier: AGPL-3.0-or-later
import type {ComposerTypeaheadActiveState} from '@app/features/lexical/composer/ComposerTypeaheadModifierGuard';
import {analyzeCodeIndent} from '@app/features/lexical/composer/codeBlockIndent';
import {
$captureSelectionOffsets,
$getComposerScanText,
$replaceComposerRange,
$selectComposerRange,
} from '@app/features/lexical/composer/composerOffsets';
import {COMMAND_PRIORITY_HIGH, KEY_TAB_COMMAND, type LexicalEditor} from 'lexical';
export function registerComposerCodeIndent(
editor: LexicalEditor,
typeaheadActiveRef: ComposerTypeaheadActiveState,
): () => void {
return editor.registerCommand(
KEY_TAB_COMMAND,
(event: KeyboardEvent) => {
if (typeaheadActiveRef.current) {
return false;
}
const offsets = $captureSelectionOffsets();
if (offsets == null) {
return false;
}
const backward = offsets.anchor > offsets.focus;
const start = Math.min(offsets.anchor, offsets.focus);
const end = Math.max(offsets.anchor, offsets.focus);
const plan = analyzeCodeIndent($getComposerScanText(), start, end, event != null && event.shiftKey === true);
if (plan == null) {
return false;
}
if (event != null) {
event.preventDefault();
}
for (const edit of [...plan.edits].sort((a, b) => b.start - a.start)) {
$replaceComposerRange(edit.start, edit.end, {kind: 'text', text: edit.text}, {trailing: false});
}
$selectComposerRange(
backward ? plan.selectionEnd : plan.selectionStart,
backward ? plan.selectionStart : plan.selectionEnd,
);
return true;
},
COMMAND_PRIORITY_HIGH,
);
}