Файли
openidea/src/features/macros/editorKeys.ts
T
l0ng-ai c6621c5c36 fix(editor): Count wide characters as two columns in column editing (#172)
Column-based editing computed columns with countColumn / findColumn, which count every grapheme as one column, and up/down and Clone Caret moved by pixel x, so block selections and cloned carets drifted on lines with CJK, fullwidth punctuation, Hangul, kana or emoji. A shared visible-column helper (UI side only, UTF-16 offsets in and out) now counts East Asian wide/fullwidth characters and emoji (ZWJ sequences, modifiers, flags, VS16) as 2, combining marks and format characters as 0, and expands tabs to the next tab stop.

It drives Alt+drag block selection, drag and Shift+arrows in Column Selection Mode, middle-drag block selection (new; not on Linux, where middle-click pastes the primary selection), the up/down goal column (kept across short lines; soft-wrapped and folded lines still move visually), Clone Caret Above/Below, the caret move after Comment Line, Tab padding to the next indent stop, and macro playback of arrow keys.

Claude-Session: https://claude.ai/code/session_01Dq6jQQn8ZhRfkkyj3PRutA
2026-10-29 08:32:15 +08:00

89 рядки
2.8 KiB
TypeScript

/**
* Editing and caret keys a macro records in the editor (keys the IDE keymap
* does not bind run CodeMirror commands directly), and their replay.
*/
import {
cursorCharLeft,
cursorCharRight,
cursorDocEnd,
cursorDocStart,
cursorGroupLeft,
cursorGroupRight,
cursorLineBoundaryBackward,
cursorLineBoundaryForward,
cursorPageDown,
cursorPageUp,
deleteCharBackward,
deleteCharForward,
deleteGroupBackward,
deleteGroupForward,
indentLess,
insertNewlineAndIndent,
insertTab,
selectCharLeft,
selectCharRight,
selectDocEnd,
selectDocStart,
selectGroupLeft,
selectGroupRight,
selectLineBoundaryBackward,
selectLineBoundaryForward,
selectPageDown,
selectPageUp,
} from "@codemirror/commands";
import type { Command } from "@codemirror/view";
import { cursorLineDown, cursorLineUp, selectLineDown, selectLineUp } from "@/editor/core/cm/verticalMotion";
/** Recorded key name (`Shift+ArrowLeft`, `Alt+Backspace`) → command. */
export const EDITOR_KEY_COMMANDS: Record<string, Command> = {
Enter: insertNewlineAndIndent,
Backspace: deleteCharBackward,
Delete: deleteCharForward,
"Alt+Backspace": deleteGroupBackward,
"Alt+Delete": deleteGroupForward,
Tab: insertTab,
"Shift+Tab": indentLess,
ArrowLeft: cursorCharLeft,
ArrowRight: cursorCharRight,
ArrowUp: cursorLineUp,
ArrowDown: cursorLineDown,
"Shift+ArrowLeft": selectCharLeft,
"Shift+ArrowRight": selectCharRight,
"Shift+ArrowUp": selectLineUp,
"Shift+ArrowDown": selectLineDown,
"Alt+ArrowLeft": cursorGroupLeft,
"Alt+ArrowRight": cursorGroupRight,
"Alt+Shift+ArrowLeft": selectGroupLeft,
"Alt+Shift+ArrowRight": selectGroupRight,
Home: cursorLineBoundaryBackward,
End: cursorLineBoundaryForward,
"Shift+Home": selectLineBoundaryBackward,
"Shift+End": selectLineBoundaryForward,
PageUp: cursorPageUp,
PageDown: cursorPageDown,
"Shift+PageUp": selectPageUp,
"Shift+PageDown": selectPageDown,
"Meta+ArrowLeft": cursorLineBoundaryBackward,
"Meta+ArrowRight": cursorLineBoundaryForward,
"Meta+Shift+ArrowLeft": selectLineBoundaryBackward,
"Meta+Shift+ArrowRight": selectLineBoundaryForward,
"Meta+ArrowUp": cursorDocStart,
"Meta+ArrowDown": cursorDocEnd,
"Ctrl+Home": cursorDocStart,
"Ctrl+End": cursorDocEnd,
"Ctrl+Shift+Home": selectDocStart,
"Ctrl+Shift+End": selectDocEnd,
"Ctrl+ArrowLeft": cursorGroupLeft,
"Ctrl+ArrowRight": cursorGroupRight,
};
/** The recorded name of a key event, or null when it is not an editor key a macro records. */
export function editorKeyName(
e: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">,
): string | null {
const name = [e.metaKey && "Meta", e.ctrlKey && "Ctrl", e.altKey && "Alt", e.shiftKey && "Shift", e.key]
.filter(Boolean)
.join("+");
return name in EDITOR_KEY_COMMANDS ? name : null;
}