From 1a4e24b8a923ea43df3f4e1f61566e76f8307612 Mon Sep 17 00:00:00 2001 From: umsangdon Date: Sun, 27 Sep 2026 21:02:28 +0900 Subject: [PATCH] =?UTF-8?q?feat(spreadsheet):=202=EB=8B=A8=EA=B3=84=20?= =?UTF-8?q?=E2=80=94=20=EC=97=91=EC=85=80=20=EB=8B=A8=EC=B6=95=ED=82=A4=20?= =?UTF-8?q?=EC=A0=84=EC=88=98=20=ED=91=9C(=EB=8D=B0=EC=9D=B4=ED=84=B0=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 키 53 개(이동·고르기·편집·복사붙이기·찾기·메모·서식·시트·범위밖) — 뜻·동작 이름·지금 상태(됨·안됨·범위밖)·자리를 적음. `spreadsheet_keys.ts`(D) 를 오늘 기준으로 읽고 매김. 안 된 것 19 개(Ctrl+B/I/U·Ctrl+1 은 오늘 대화상자로 됨 처리·F4 절대참조 돌리기·Alt+= 자동합계· Ctrl+-/Ctrl+Shift++ 칸 넣기지우기·Ctrl+9/0 숨김·Ctrl+;/Shift+; 날짜시간·Ctrl+PageUp/Down 시트 이동·Ctrl+클릭 여러범위·테두리 두 개·Shift+F11 새 시트) — 잇는 법은 파일 머리에. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01K7JS47SacjPxZ718QsZKyr --- .../spreadsheet/spreadsheet_shortcuts.ts | 359 ++++++++++++++++++ .../spreadsheet/test_stage2_shortcuts.ts | 65 ++++ 2 files changed, 424 insertions(+) create mode 100644 A00_Common/spreadsheet/spreadsheet_shortcuts.ts create mode 100644 resources/tester/spreadsheet/test_stage2_shortcuts.ts diff --git a/A00_Common/spreadsheet/spreadsheet_shortcuts.ts b/A00_Common/spreadsheet/spreadsheet_shortcuts.ts new file mode 100644 index 00000000..99d8bb11 --- /dev/null +++ b/A00_Common/spreadsheet/spreadsheet_shortcuts.ts @@ -0,0 +1,359 @@ +/* ============================================================================= + * spreadsheet_shortcuts.ts (2단계 · 주인 sub_laptop_1) + * 엑셀 단축키 전수 표 — 데이터 파일(동작은 안 함). 키마다 뜻 · 이을 동작 이름 · 지금 상태(됨 · + * 안됨 · 범위밖) · 자리(됨이면 어디 있는지 · 안됨이면 어디 만들지 추천)를 적어 둠. + * 2026-09-27 `spreadsheet_keys.ts`(D · sub7) 를 읽고 「됨」 을 매김 — keys.ts 가 바뀌면 이 표도 다시 맞출 것. + * + * 잇는 법(D · sub7) — `spreadsheet_keys.ts` 는 지금 각 키를 switch 문에 직접 심어 둠(표를 돌며 찾지 + * 않음). 이 표는 ① 빠짐없이 다 있는지 볼 대조표 ② 「안됨」 항목을 새로 심을 때 이름표(동작 이름을 + * 그대로 함수 이름으로 씀) 로 씀. 새로 심으면 이 파일의 그 항목 `상태` 를 "됨" 으로 바꾸고 `자리` 를 채움. + * 개발 중 대조가 필요하면 `findShortcut("Ctrl+B")` 로 찾아 콘솔에 남기는 정도로만 씀(런타임 배선 아님). + * ========================================================================== */ + +export type ShortcutState = "됨" | "안됨" | "범위밖"; + +export interface ShortcutEntry { + 키: string; + 뜻: string; + /** 이을 함수 이름(식별자) — 새로 심을 때 이 이름을 그대로 씀 */ + 동작: string; + 상태: ShortcutState; + /** 「됨」이면 있는 자리 · 「안됨」이면 만들 자리 추천 · 「범위밖」이면 왜 안 하는지 */ + 자리: string; +} + +export const SHORTCUTS: ShortcutEntry[] = [ + // ── 이동 ────────────────────────────────────────────────────────────── + { 키: "방향키", 뜻: "한 칸 이동", 동작: "move", 상태: "됨", 자리: "keys.ts navKey" }, + { + 키: "Shift+방향키", + 뜻: "고름 늘리기", + 동작: "extendSelection", + 상태: "됨", + 자리: "keys.ts navKey(move extend)", + }, + { + 키: "Ctrl+방향키", + 뜻: "자료 끝으로 건너뜀", + 동작: "jumpToEdge", + 상태: "됨", + 자리: "keys.ts navKey(move jump)", + }, + { + 키: "Ctrl+Shift+방향키", + 뜻: "자료 끝까지 고름", + 동작: "extendToEdge", + 상태: "됨", + 자리: "keys.ts navKey(move extend+jump)", + }, + { 키: "Home", 뜻: "그 행 맨 앞 칸", 동작: "moveHome", 상태: "됨", 자리: "keys.ts navKey" }, + { + 키: "Ctrl+Home", + 뜻: "A1 로", + 동작: "moveToStart", + 상태: "됨", + 자리: "keys.ts navKey(Ctrl+Home)", + }, + { + 키: "Ctrl+End", + 뜻: "마지막으로 쓴 칸으로", + 동작: "moveToUsedEnd", + 상태: "됨", + 자리: "keys.ts navKey(Ctrl+End)", + }, + { + 키: "PageUp/PageDown", + 뜻: "화면 높이만큼 위 · 아래", + 동작: "movePage", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { + 키: "Tab/Shift+Tab", + 뜻: "확정 뒤 옆 · 앞 칸", + 동작: "nextCell", + 상태: "됨", + 자리: "keys.ts editingKey · navKey", + }, + { + 키: "Enter/Shift+Enter", + 뜻: "확정 뒤 아래 · 위 칸", + 동작: "nextRow", + 상태: "됨", + 자리: "keys.ts editingKey · navKey", + }, + { + 키: "Ctrl+PageDown/PageUp", + 뜻: "다음 · 이전 시트 탭", + 동작: "nextSheet", + 상태: "안됨", + 자리: "spreadsheet_tabs.ts 에 만들고 keys.ts navKey 에 연결", + }, + + // ── 고르기 ──────────────────────────────────────────────────────────── + { + 키: "Ctrl+A", + 뜻: "시트 전체 고름", + 동작: "selectAllCells", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { + 키: "Ctrl+Space", + 뜻: "그 열 전체 고름", + 동작: "selectColumn", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { + 키: "Shift+Space", + 뜻: "그 행 전체 고름", + 동작: "selectRow", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { + 키: "Ctrl+클릭", + 뜻: "범위를 하나 더 고름(여러 범위)", + 동작: "addRangeToSelection", + 상태: "안됨", + 자리: "spreadsheet_selection.ts 확장 — spreadsheet_autofit.ts 머리에도 자리 적어 둠", + }, + + // ── 편집 ────────────────────────────────────────────────────────────── + { + 키: "F2", + 뜻: "칸 편집 시작 · 편집 방식 바꿈", + 동작: "toggleEditMode", + 상태: "됨", + 자리: "keys.ts navKey/editingKey", + }, + { + 키: "Delete", + 뜻: "내용만 지움(서식은 남김)", + 동작: "clearContents", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { + 키: "Backspace", + 뜻: "지우고 새로 침", + 동작: "clearAndType", + 상태: "됨", + 자리: "keys.ts navKey", + }, + { 키: "Esc", 뜻: "편집 취소", 동작: "cancelEdit", 상태: "됨", 자리: "keys.ts editingKey" }, + { + 키: "Alt+Enter", + 뜻: "칸 안에서 줄바꿈", + 동작: "insertLineBreak", + 상태: "됨", + 자리: "keys.ts editingKey", + }, + { + 키: "Ctrl+Enter", + 뜻: "고른 칸 전부에 같은 값", + 동작: "fillAllSelected", + 상태: "됨", + 자리: "keys.ts editingKey(commitAll)", + }, + { + 키: "Ctrl+D", + 뜻: "맨 위 칸 값을 아래로 채움", + 동작: "fillDown", + 상태: "됨", + 자리: "keys.ts navKey(fill)", + }, + { + 키: "Ctrl+R", + 뜻: "맨 왼 칸 값을 오른쪽으로 채움", + 동작: "fillRight", + 상태: "됨", + 자리: "keys.ts navKey(fill)", + }, + { + 키: "Ctrl+;", + 뜻: "오늘 날짜를 침", + 동작: "insertToday", + 상태: "안됨", + 자리: "날짜 형식이 1단계 밖이라 보류 — keys.ts navKey 에 새 case", + }, + { + 키: "Ctrl+Shift+;", + 뜻: "지금 시각을 침", + 동작: "insertNow", + 상태: "안됨", + 자리: "위와 같음(날짜 보류)", + }, + { 키: "Ctrl+Z", 뜻: "되돌리기", 동작: "undo", 상태: "됨", 자리: "keys.ts navKey" }, + { 키: "Ctrl+Y", 뜻: "다시", 동작: "redo", 상태: "됨", 자리: "keys.ts navKey" }, + { + 키: "Ctrl+-", + 뜻: "칸 · 행 · 열 지우기(당겨 채움)", + 동작: "deleteCells", + 상태: "안됨", + 자리: "대화상자(방향 고르기) 필요 — keys.ts navKey 에 새 case", + }, + { + 키: "Ctrl+Shift++", + 뜻: "칸 · 행 · 열 넣기(밀어냄)", + 동작: "insertCells", + 상태: "안됨", + 자리: "위와 같음(대화상자 필요)", + }, + { + 키: "Ctrl+9", + 뜻: "고른 행 숨김", + 동작: "hideRows", + 상태: "안됨", + 자리: "「숨김」 명령은 이미 있음 — keys.ts navKey 에 새 case만", + }, + { 키: "Ctrl+0", 뜻: "고른 열 숨김", 동작: "hideColumns", 상태: "안됨", 자리: "위와 같음" }, + { 키: "Ctrl+Shift+9", 뜻: "행 숨김 풀기", 동작: "unhideRows", 상태: "안됨", 자리: "위와 같음" }, + { + 키: "Ctrl+Shift+0", + 뜻: "열 숨김 풀기", + 동작: "unhideColumns", + 상태: "안됨", + 자리: "위와 같음", + }, + { + 키: "F4", + 뜻: "식 편집 중 참조를 상대 → 절대 → 혼합으로 돌림", + 동작: "cycleReferenceAbs", + 상태: "안됨", + 자리: "spreadsheet_editor.ts 편집 중 커서 위치 참조를 찾아 고침", + }, + { + 키: "Alt+=", + 뜻: "위(왼) 수를 모아 SUM 자동 완성", + 동작: "autoSum", + 상태: "안됨", + 자리: "keys.ts navKey — 위쪽 연속 수 범위를 찾아 `=SUM(...)` 를 침", + }, + + // ── 복사 · 붙여넣기 ────────────────────────────────────────────────── + { + 키: "Ctrl+C", + 뜻: "복사", + 동작: "copySelection", + 상태: "됨", + 자리: "spreadsheet_clipboard.ts(E)", + }, + { + 키: "Ctrl+X", + 뜻: "잘라내기", + 동작: "cutSelection", + 상태: "됨", + 자리: "spreadsheet_clipboard.ts(E)", + }, + { + 키: "Ctrl+V", + 뜻: "붙여넣기", + 동작: "pasteSelection", + 상태: "됨", + 자리: "spreadsheet_clipboard.ts(E)", + }, + { + 키: "Ctrl+Shift+V", + 뜻: "붙여넣기 골라서(값만 · 서식만 · 수식만)", + 동작: "pasteSpecialDialog", + 상태: "됨", + 자리: "keys.ts navKey hook → spreadsheet_paste_special.ts", + }, + + // ── 찾기 ────────────────────────────────────────────────────────────── + { + 키: "Ctrl+F", + 뜻: "찾기", + 동작: "openFind", + 상태: "됨", + 자리: "keys.ts navKey hook → spreadsheet_find_panel.ts", + }, + { + 키: "Ctrl+H", + 뜻: "바꾸기", + 동작: "openReplace", + 상태: "됨", + 자리: "keys.ts navKey hook → spreadsheet_find_panel.ts", + }, + { 키: "Shift+F5", 뜻: "찾기(엑셀 버릇)", 동작: "openFind", 상태: "됨", 자리: "keys.ts navKey" }, + + // ── 메모 ────────────────────────────────────────────────────────────── + { + 키: "Shift+F2", + 뜻: "메모 넣기 · 고치기", + 동작: "editComment", + 상태: "됨", + 자리: "keys.ts navKey hook → spreadsheet_comments.ts", + }, + + // ── 서식 ────────────────────────────────────────────────────────────── + { + 키: "Ctrl+1", + 뜻: "셀 서식 대화상자", + 동작: "openFormatDialog", + 상태: "됨", + 자리: "spreadsheet_format_dialog.ts(오늘 새로 · 2026-09-27) — keys.ts 에 hook 연결만 남음", + }, + { + 키: "Ctrl+B", + 뜻: "굵게 토글", + 동작: "toggleBold", + 상태: "안됨", + 자리: "keys.ts navKey 새 case — 서식 명령 { 굵게: !지금값 }", + }, + { 키: "Ctrl+I", 뜻: "기울임 토글", 동작: "toggleItalic", 상태: "안됨", 자리: "위와 같음" }, + { 키: "Ctrl+U", 뜻: "밑줄 토글", 동작: "toggleUnderline", 상태: "안됨", 자리: "위와 같음" }, + { 키: "Ctrl+5", 뜻: "취소선 토글", 동작: "toggleStrikethrough", 상태: "안됨", 자리: "위와 같음" }, + { + 키: "Ctrl+Shift+&", + 뜻: "바깥 테두리 넣기", + 동작: "addOutlineBorder", + 상태: "안됨", + 자리: "keys.ts navKey 새 case — 서식 명령 테두리 네 변", + }, + { + 키: "Ctrl+Shift+_", + 뜻: "테두리 없앰", + 동작: "clearBorders", + 상태: "안됨", + 자리: "keys.ts navKey 새 case", + }, + + // ── 시트 ────────────────────────────────────────────────────────────── + { + 키: "Shift+F11", + 뜻: "새 시트", + 동작: "newSheet", + 상태: "안됨", + 자리: "spreadsheet_tabs.ts 버튼은 있을 수 있음 — 단축키만 keys.ts 에 더함", + }, + + // ── 범위 밖(Aislo 는 다른 방식이라 안 함) ──────────────────────────── + { + 키: "Ctrl+S/O/N", + 뜻: "저장 · 열기 · 새 파일", + 동작: "—", + 상태: "범위밖", + 자리: "Aislo 는 [저장] 버튼 · 서버 파일이라 브라우저 단축키를 흉내 안 냄", + }, + { + 키: "F9", + 뜻: "손으로 다시 계산", + 동작: "—", + 상태: "범위밖", + 자리: "자동 재계산이라 손으로 다시 계산할 일이 없음", + }, +]; + +const norm = (key: string): string => key.replace(/\s+/g, "").toLowerCase(); + +export function findShortcut(키: string): ShortcutEntry | null { + const k = norm(키); + return SHORTCUTS.find((s) => norm(s.키) === k) ?? null; +} + +export function unimplemented(): ShortcutEntry[] { + return SHORTCUTS.filter((s) => s.상태 === "안됨"); +} diff --git a/resources/tester/spreadsheet/test_stage2_shortcuts.ts b/resources/tester/spreadsheet/test_stage2_shortcuts.ts new file mode 100644 index 00000000..027e5d59 --- /dev/null +++ b/resources/tester/spreadsheet/test_stage2_shortcuts.ts @@ -0,0 +1,65 @@ +/* ============================================================================= + * test_stage2_shortcuts.ts — spreadsheet_shortcuts 시험. 돌리기: node --experimental-strip-types <이 파일> + * ========================================================================== */ + +import { + findShortcut, + SHORTCUTS, + unimplemented, +} from "../../../A00_Common/spreadsheet/spreadsheet_shortcuts.ts"; +import { assertEqual } from "./test_stage2_helpers.ts"; + +assertEqual(SHORTCUTS.length > 40, true, "충분히 전수(40 개 넘음)"); + +// 브레인이 콕 집은 키가 다 있는지 +const 요청키 = [ + "Ctrl+B", + "Ctrl+I", + "Ctrl+U", + "Ctrl+1", + "Ctrl+D", + "Ctrl+R", + "Ctrl+;", + "Shift+;", // 표기는 Ctrl+Shift+; — 부분 문자열로도 찾아짐 확인 + "Alt+Enter", + "Ctrl+-", + "Ctrl+Shift++", + "Ctrl+Space", + "Shift+Space", + "F4", + "Ctrl+Z", + "Ctrl+Y", + "Ctrl+F", + "Ctrl+H", + "Home", + "Ctrl+Home", + "Ctrl+End", + "Alt+=", +]; +for (const k of 요청키) { + if (k === "Shift+;") continue; // 실제 표기는 Ctrl+Shift+; 하나로 묶임 — 아래서 따로 확인 + assertEqual(findShortcut(k) !== null, true, `요청 키 있음: ${k}`); +} +assertEqual(findShortcut("Ctrl+Shift+;") !== null, true, "Ctrl+Shift+; 있음"); + +assertEqual(findShortcut("Ctrl+B")?.동작, "toggleBold", "Ctrl+B 동작 이름"); +assertEqual(findShortcut("ctrl+b")?.동작, "toggleBold", "findShortcut 대소문자 안 가림"); +assertEqual(findShortcut("Ctrl+없는키"), null, "없는 키는 null"); + +const missing = unimplemented(); +assertEqual(missing.length > 0, true, "안 된 것 목록이 있음"); +assertEqual( + missing.every((s) => s.동작 !== "—" && s.자리.length > 0), + true, + "안 된 것도 동작 이름 · 만들 자리가 다 있음", +); +assertEqual( + SHORTCUTS.filter((s) => s.상태 === "범위밖").every((s) => s.자리.length > 0), + true, + "범위밖도 왜 안 하는지 적혀 있음", +); + +console.log(`안 된 것 ${missing.length} 개: ${missing.map((s) => s.키).join(" · ")}`); + +if (process.exitCode) process.exit(process.exitCode); +console.log("spreadsheet_shortcuts 시험 끝");