/* PLAN 588 지킴 헬퍼 — 단축키 등록부(`A00_Common/key_registry.ts`) · CAD 묶음 · 찾기(`app_settings_find.ts`) * 를 그 자리에서 트랜스파일해 Node 로 돌림. 가짜 localStorage 로 바꾼 키를 넣어 봄. * 결과 = 표준출력 JSON 한 벌. 짝 = `test_588_key_registry.py`. */ const fs = require("fs"); const path = require("path"); const ts = require(path.join(__dirname, "..", "..", "config", "node_modules", "typescript")); const ROOT = path.join(__dirname, "..", ".."); const mods = {}; function load(rel) { const js = ts.transpileModule(fs.readFileSync(path.join(ROOT, rel), "utf8"), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2020 }, }).outputText; const box = { exports: {} }; const req = (p) => mods[path.basename(p)] ?? {}; new Function("exports", "module", "require", js)(box.exports, box, req); return (mods[path.basename(rel, ".ts")] = box.exports); } load("A00_Common/input_prefs.ts"); load("A00_Common/key_shortcut.ts"); load("B07_DesignDetail/openwebcad/src/ribbon/ribbon.config.ts"); const reg = load("A00_Common/key_registry.ts"); const find = load("A00_Common/app_settings_find.ts"); const catalog = require( path.join(ROOT, "B07_DesignDetail/openwebcad/src/commands/command-catalog.json"), ); const store = new Map(); globalThis.localStorage = { getItem: (k) => (store.has(k) ? store.get(k) : null) }; const setKeys = (keys) => store.set(mods.input_prefs.INPUT_PREFS_KEY, JSON.stringify({ keys })); const ev = (key, code, extra = {}) => ({ key, code, ctrlKey: false, altKey: false, shiftKey: false, ...extra, }); const out = {}; // ① CAD 묶음 · 찾기 const groups = find.cadCommandGroups(catalog.map((c) => c.id)); out.groups = groups.map((g) => ({ label: g.label, n: g.ids.length })); out.groupIds = groups.flatMap((g) => g.ids); out.other = groups.find((g) => !g.label)?.ids ?? []; const hits = (q) => catalog.filter((c) => find.matchesFind(q, [c.id, c.label, ...c.aliases])).map((c) => c.id); out.find = { sun: hits("선"), L: hits("L"), sunPl: hits("선 pl"), blank: hits(" ").length, none: hits("zzqq"), }; // ② 키 글 out.chord = { hangulCtrlZ: reg.chordOf(ev("ㅋ", "KeyZ", { ctrlKey: true })), ctrlShiftZ: reg.chordOf(ev("Z", "KeyZ", { ctrlKey: true, shiftKey: true })), meta: reg.chordOf(ev("z", "KeyZ", { metaKey: true })), space: reg.chordOf(ev(" ", "Space")), shiftOnly: reg.chordOf(ev("Shift", "ShiftLeft", { shiftKey: true })), process: reg.chordOf(ev("Process", "")), f3: reg.chordOf(ev("F3", "F3")), shiftDigit: reg.chordOf(ev("!", "Digit1", { ctrlKey: true, shiftKey: true })), arrow: reg.chordOf(ev("ArrowUp", "ArrowUp", { shiftKey: true })), label: reg.keyLabel("Shift+ArrowUp"), }; // ③ 판정 — 기본 · 바꾼 키 · 못 바꾸는 줄은 바꾼 값 무시 const del = ev("Delete", "Delete"); out.keyIs = { delDefault: reg.keyIs(del, "plan.delete"), hangulUndo: reg.keyIs(ev("ㅋ", "KeyZ", { ctrlKey: true }), "plan.undo"), }; setKeys({ "plan.delete": ["Ctrl+D"], "all.escape": ["Q"] }); out.keyIs.delAfter = reg.keyIs(del, "plan.delete"); out.keyIs.ctrlDAfter = reg.keyIs(ev("ㅇ", "KeyD", { ctrlKey: true }), "plan.delete"); out.keyIs.fixedIgnored = reg.actionKeys("all.escape"); out.keyIs.cadAction = reg.keyAction(ev("F7", "F7"), "cad"); store.clear(); // ④ 겹침 검사 const chk = (keys) => reg.checkKeys(keys); out.check = { none: chk({}), sameScope: chk({ "plan.delete": ["Ctrl+Z"] }), withAll: chk({ "plan.delete": ["Escape"] }), withLoupe: chk({ "plan.delete": ["Z"] }), otherPage: chk({ "plan.delete": ["F3"] }), reserved: chk({ "plan.delete": ["F5"] }), cadLetter: chk({ "cad.snap": ["Q"] }), cadShiftLetter: chk({ "cad.snap": ["Shift+Q"] }), cadCtrl: chk({ "cad.snap": ["Ctrl+Q"] }), samePage: chk({ "b05.undo": ["Enter"] }), swap: chk({ "plan.undo": ["Ctrl+Y"], "plan.redo": ["Ctrl+Z"] }), both: chk({ "plan.drawFinish": ["F2"], "plan.drawBack": ["F2"] }), }; // ⑤ 등록부 꼴 out.actions = reg.KEY_ACTIONS.map((a) => ({ id: a.id, scope: a.scope, keys: a.keys, fixed: !!a.fixed, })); out.scopes = Object.keys(reg.KEY_SCOPES); process.stdout.write(JSON.stringify(out));