53 lines
1.4 KiB
TypeScript
53 lines
1.4 KiB
TypeScript
/**
|
|
* 字符转置功能
|
|
* 交换光标前后的字符
|
|
*/
|
|
|
|
import { EditorSelection, findClusterBreak } from "@codemirror/state";
|
|
import { getNoteBlockFromPos } from "./state";
|
|
|
|
/**
|
|
* 交换光标前后的字符
|
|
*/
|
|
export const transposeChars = ({ state, dispatch }: { state: any; dispatch: any }): boolean => {
|
|
if (state.readOnly) {
|
|
return false;
|
|
}
|
|
|
|
let changes = state.changeByRange((range: any) => {
|
|
// 防止在代码块的开始或结束位置进行字符转置,因为这会破坏块语法
|
|
const block = getNoteBlockFromPos(state, range.from);
|
|
if (block && (range.from === block.content.from || range.from === block.content.to)) {
|
|
return { range };
|
|
}
|
|
|
|
if (!range.empty || range.from == 0 || range.from == state.doc.length) {
|
|
return { range };
|
|
}
|
|
|
|
let pos = range.from;
|
|
let line = state.doc.lineAt(pos);
|
|
let from = pos == line.from ? pos - 1 : findClusterBreak(line.text, pos - line.from, false) + line.from;
|
|
let to = pos == line.to ? pos + 1 : findClusterBreak(line.text, pos - line.from, true) + line.from;
|
|
|
|
return {
|
|
changes: {
|
|
from,
|
|
to,
|
|
insert: state.doc.slice(pos, to).append(state.doc.slice(from, pos))
|
|
},
|
|
range: EditorSelection.cursor(to)
|
|
};
|
|
});
|
|
|
|
if (changes.changes.empty) {
|
|
return false;
|
|
}
|
|
|
|
dispatch(state.update(changes, {
|
|
scrollIntoView: true,
|
|
userEvent: "move.character"
|
|
}));
|
|
|
|
return true;
|
|
};
|