- 새 src/commands/prompt.ts — PromptSpec · renderPrompt(키워드 물음은 「또는」 없음) · matchOption(initget 줄임) · 세션 기억 · OPT · SELECT_OBJECTS - 새 inputController/prompt-input.ts — routeTyped 사다리(점 · 옵션 묻는 중 명령 이름 거절 · 식 · 단위 거절 · 투명 ') · 알림 줄 · 덧물음 · cancelActiveCommand · undoCommand - 새 tools/factories/end-command.ts — final(END) 갈고리 → 같은 틱 선택 도구 · state.ts 갈고리 · LASTPOINT - sequence-tool v2 — ROUTE · id · prompt · when · next · options · keyword · loopFrom · escCommits · pickfirst · 확정 뒤 기본 끝 · Esc 늘 끝 - 흠 — N1 ②③ · N5 · N6 · N11 · N18(앞글자 실행 없앰) · H1(Ctrl · Alt 글자 안 쌓음 · Ctrl+C · X · Shift+C · Shift+V · 1) · 우클릭 = 쉴 때 반복 · SE 뺌 · ED 더함 - 시험 — cad-drive 도우미 · prompt-frame · prompt-contract · 옛 시험 손질(keyboard-chain · ime-sink · command-catalog · input-prefs-cad · eraser 녹화) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01QfHKQs7J3hQELKMWQMUJEy
151 lines
5.3 KiB
TypeScript
151 lines
5.3 KiB
TypeScript
/**
|
|
* 명령 레지스트리 — 리본·명령행·단축키가 읽는 단일 소스.
|
|
* 새 명령은 commands.*.ts에 한 줄 추가하면 세 곳에 동시에 나타난다.
|
|
*/
|
|
import type { AnyToolMachine, CadCommand } from './command.types';
|
|
import type { Tool } from '../tools';
|
|
import {
|
|
DIMENSION_COMMANDS,
|
|
LEADER_COMMANDS,
|
|
MARKUP_COMMANDS,
|
|
TABLE_COMMANDS,
|
|
TEXT_COMMANDS,
|
|
} from './commands.annotate';
|
|
import { DRAW_COMMANDS } from './commands.draw';
|
|
import { FILE_COMMANDS } from './commands.file';
|
|
import { INSERT_COMMANDS } from './commands.insert';
|
|
import { LAYER_COMMANDS } from './commands.layer';
|
|
import {
|
|
CLIPBOARD_COMMANDS,
|
|
GROUP_COMMANDS,
|
|
INQUIRY_COMMANDS,
|
|
PROPERTY_COMMANDS,
|
|
} from './commands.utility';
|
|
import { ALIGN_COMMANDS, MODIFY_COMMANDS } from './commands.modify';
|
|
import { VIEW_COMMANDS } from './commands.view';
|
|
import { inputPrefs } from '../../../../A00_Common/input_prefs';
|
|
import '../tools/factories/end-command'; // 명령 끝 → 쉬는 상태 갈고리
|
|
|
|
const ALL_COMMANDS: CadCommand[] = [
|
|
...DRAW_COMMANDS,
|
|
...MODIFY_COMMANDS,
|
|
...ALIGN_COMMANDS,
|
|
...TEXT_COMMANDS,
|
|
...DIMENSION_COMMANDS,
|
|
...LEADER_COMMANDS,
|
|
...TABLE_COMMANDS,
|
|
...MARKUP_COMMANDS,
|
|
...LAYER_COMMANDS,
|
|
...PROPERTY_COMMANDS,
|
|
...GROUP_COMMANDS,
|
|
...INQUIRY_COMMANDS,
|
|
...CLIPBOARD_COMMANDS,
|
|
...INSERT_COMMANDS,
|
|
...VIEW_COMMANDS,
|
|
...FILE_COMMANDS,
|
|
];
|
|
|
|
const COMMANDS_BY_ID = new Map<string, CadCommand>(
|
|
ALL_COMMANDS.map((command) => [command.id, command])
|
|
);
|
|
|
|
const COMMANDS_BY_ALIAS = new Map<string, CadCommand>();
|
|
for (const command of ALL_COMMANDS) {
|
|
for (const alias of command.aliases ?? []) {
|
|
if (!COMMANDS_BY_ALIAS.has(alias)) {
|
|
COMMANDS_BY_ALIAS.set(alias, command);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 확정한 도면에서도 쓸 수 있는 명령 — **보는 일만 하는 것들**이다
|
|
* (2026-09-01 사용자 확정: 확정하면 수정이 안 되고, 풀려면 [수정]을 누른다).
|
|
*
|
|
* 허용을 명시하는 쪽으로 짠다. 새 편집 명령이 늘어도 자동으로 막히고, 반대로 짜면
|
|
* 새 명령마다 여기 적어야 해 언젠가 빠뜨린다.
|
|
*/
|
|
const VIEW_ONLY_COMMAND_IDS: ReadonlySet<string> = new Set([
|
|
// 보기 — 확대·이동·다시그리기·선택
|
|
...VIEW_COMMANDS.map((command) => command.id),
|
|
// 조회 — 거리·면적·각도처럼 재기만 하는 것
|
|
...INQUIRY_COMMANDS.map((command) => command.id),
|
|
// 도면층 보이기·잠금 — 객체를 건드리지 않는 것만 (LAYMCH·LAYCUR·LAYMRG·LAYDEL 제외)
|
|
'LAYER',
|
|
'LAYCURSET',
|
|
'LAYOFF',
|
|
'LAYON',
|
|
'LAYFRZ',
|
|
'LAYTHW',
|
|
'LAYLCK',
|
|
'LAYULK',
|
|
'LAYISO',
|
|
'LAYUNISO',
|
|
'LAYERP',
|
|
'LAYERSTATE',
|
|
'LAYERSTATERESTORE',
|
|
'LAYWALK',
|
|
// 파일 — 내보내기와 클립보드 복사는 도면을 바꾸지 않는다
|
|
'EXPORT',
|
|
'EXPORTSVG',
|
|
'EXPORTPNG',
|
|
'COPYCLIP',
|
|
'COPYBASE',
|
|
'TOAREA', // 고른 범위 → 면적산출 표(M02 83장)
|
|
]);
|
|
|
|
/** 확정한 도면에서 이 명령을 실행해도 되는가. */
|
|
export const isViewOnlyCommand = (command: CadCommand): boolean =>
|
|
VIEW_ONLY_COMMAND_IDS.has(command.id);
|
|
|
|
export const getAllCommands = (): CadCommand[] => ALL_COMMANDS;
|
|
|
|
export const getCommandById = (id: string): CadCommand | undefined => COMMANDS_BY_ID.get(id);
|
|
|
|
/** 활성 도구로 어떤 명령이 실행 중인지 되짚는다 (리본 강조·상태 표시용) */
|
|
export const getCommandByTool = (tool: Tool | null): CadCommand | undefined =>
|
|
tool ? ALL_COMMANDS.find((command) => command.tool === tool) : undefined;
|
|
|
|
/** 도구형 명령의 xstate 머신 표 — 도구 활성화 경로가 이 표만 본다 */
|
|
export const TOOL_STATE_MACHINES = Object.fromEntries(
|
|
ALL_COMMANDS.filter((command) => command.tool && command.machine).map((command) => [
|
|
command.tool,
|
|
command.machine,
|
|
])
|
|
) as Record<Tool, AnyToolMachine>;
|
|
|
|
/** 내 별칭(☰ [설정] · `cadAliases`) 이 가리키는 명령들 — 부를 때마다 읽어 저장 즉시 따름 */
|
|
function userAliasCommands(match: (alias: string) => boolean): CadCommand[] {
|
|
return Object.entries(inputPrefs().cadAliases).flatMap(([id, aliases]) => {
|
|
const command = COMMANDS_BY_ID.get(id);
|
|
return command && aliases.some(match) ? [command] : [];
|
|
});
|
|
}
|
|
|
|
/** 명령행 입력 해석 — 이름 > 내 별칭 > 기본 별칭(acad.pgp 식) 딱 맞음만(앞글자 실행 없음 · 후보는 목록) */
|
|
export function resolveCommandInput(input: string): CadCommand | undefined {
|
|
const text = input.trim().toUpperCase().replace(/^_/, '');
|
|
if (!text) return undefined;
|
|
return (
|
|
COMMANDS_BY_ID.get(text) ??
|
|
userAliasCommands((alias) => alias === text)[0] ??
|
|
COMMANDS_BY_ALIAS.get(text)
|
|
);
|
|
}
|
|
|
|
/** 접두사가 같은 명령 후보 (커서 옆 자동완성 목록에 쓴다) */
|
|
export function matchCommandPrefixes(input: string): CadCommand[] {
|
|
const text = input.trim().toUpperCase();
|
|
if (!text) return [];
|
|
const byAlias = ALL_COMMANDS.filter((command) =>
|
|
(command.aliases ?? []).some((alias) => alias.startsWith(text))
|
|
);
|
|
const byId = ALL_COMMANDS.filter((command) => command.id.startsWith(text));
|
|
const byUser = userAliasCommands((alias) => alias.startsWith(text));
|
|
return [...new Set([...byUser, ...byAlias, ...byId])];
|
|
}
|
|
|
|
/** 명령행 자동완성에 보여줄 문자열 (예: "LINE (L) 선") */
|
|
export const describeCommand = (command: CadCommand): string =>
|
|
`${command.id}${command.aliases?.length ? ` (${command.aliases[0]})` : ''} ${command.label}`;
|