refactor: impl
This commit is contained in:
@@ -1,45 +1,14 @@
|
||||
import { createSignal } from "solid-js";
|
||||
import type {
|
||||
MdCommanderCommand,
|
||||
MdCommanderCommandMap,
|
||||
CommanderEntry,
|
||||
CompletionItem,
|
||||
TrackerItem,
|
||||
TrackerAttribute,
|
||||
TrackerCommand,
|
||||
TrackerViewMode,
|
||||
MdCommanderCommandMap,
|
||||
} from "../types";
|
||||
import { parseInput, getCompletions } from "./completions";
|
||||
import { setupHelpCommand, clearCommand, rollCommand, trackCommand, untrackCommand, listTrackCommand } from "../commands";
|
||||
import {
|
||||
addTrackerItem as addTracker,
|
||||
removeTrackerItem as removeTracker,
|
||||
updateTrackerAttribute as updateTrackerAttr,
|
||||
updateTrackerClasses as updateTrackerClassesStore,
|
||||
moveTrackerItem as moveTracker,
|
||||
removeTrackerClass as removeClassFromTracker,
|
||||
getTrackerItems,
|
||||
getTrackerHistory,
|
||||
findTrackerIndex,
|
||||
} from "../stores";
|
||||
|
||||
// ==================== 默认命令 ====================
|
||||
|
||||
export const defaultCommands: MdCommanderCommandMap = {
|
||||
help: { command: "help" }, // 占位,稍后初始化
|
||||
clear: clearCommand,
|
||||
roll: rollCommand,
|
||||
track: trackCommand,
|
||||
untrack: untrackCommand,
|
||||
list: listTrackCommand,
|
||||
};
|
||||
|
||||
// 初始化默认命令(包括 help)
|
||||
export function initializeCommands(customCommands?: MdCommanderCommandMap): MdCommanderCommandMap {
|
||||
const commands = { ...defaultCommands, ...customCommands };
|
||||
commands.help = setupHelpCommand(commands);
|
||||
return commands;
|
||||
}
|
||||
|
||||
// ==================== Commander Hook ====================
|
||||
|
||||
@@ -58,30 +27,31 @@ export interface UseCommanderReturn {
|
||||
handleCommand: () => void;
|
||||
updateCompletions: () => void;
|
||||
acceptCompletion: () => void;
|
||||
commands: MdCommanderCommandMap;
|
||||
commands: () => MdCommanderCommandMap;
|
||||
setCommands: (cmds: MdCommanderCommandMap) => void;
|
||||
historyIndex: () => number;
|
||||
setHistoryIndex: (v: number) => void;
|
||||
commandHistory: () => string[];
|
||||
navigateHistory: (direction: 'up' | 'down') => void;
|
||||
navigateHistory: (direction: "up" | "down") => void;
|
||||
|
||||
// Tracker 相关 - 直接暴露 store API
|
||||
// Tracker 相关
|
||||
viewMode: () => TrackerViewMode;
|
||||
setViewMode: (mode: TrackerViewMode) => void;
|
||||
trackerItems: () => TrackerItem[];
|
||||
trackerHistory: () => TrackerCommand[];
|
||||
addTrackerItem: typeof addTracker;
|
||||
removeTrackerItem: typeof removeTracker;
|
||||
addTrackerItem: (item: Omit<TrackerItem, "id">) => TrackerItem;
|
||||
removeTrackerItem: (emmet: string) => boolean;
|
||||
removeTrackerItemByIndex: (index: number) => void;
|
||||
updateTrackerAttribute: typeof updateTrackerAttr;
|
||||
updateTrackerAttribute: (emmet: string, attrName: string, attr: TrackerAttribute) => boolean;
|
||||
updateTrackerAttributeByIndex: (index: number, attrName: string, attr: TrackerAttribute) => void;
|
||||
updateTrackerClassesByIndex: (index: number, classes: string[]) => void;
|
||||
moveTrackerItem: typeof moveTracker;
|
||||
moveTrackerItemByIndex: (index: number, direction: 'up' | 'down') => void;
|
||||
removeTrackerItemClass: typeof removeClassFromTracker;
|
||||
moveTrackerItem: (emmet: string, direction: "up" | "down") => boolean;
|
||||
moveTrackerItemByIndex: (index: number, direction: "up" | "down") => void;
|
||||
removeTrackerItemClass: (emmet: string, className: string) => boolean;
|
||||
removeTrackerItemClassByIndex: (index: number, className: string) => void;
|
||||
}
|
||||
|
||||
export function useCommander(customCommands?: MdCommanderCommandMap): UseCommanderReturn {
|
||||
export function useCommander(initialCommands?: MdCommanderCommandMap): UseCommanderReturn {
|
||||
const [inputValue, setInputValue] = createSignal("");
|
||||
const [entries, setEntries] = createSignal<CommanderEntry[]>([]);
|
||||
const [showCompletions, setShowCompletions] = createSignal(false);
|
||||
@@ -91,8 +61,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
const [commandHistory, setCommandHistory] = createSignal<string[]>([]);
|
||||
const [historyIndex, setHistoryIndex] = createSignal(-1);
|
||||
const [viewMode, setViewMode] = createSignal<TrackerViewMode>("history");
|
||||
|
||||
const commands = initializeCommands(customCommands);
|
||||
const [commands, setCommands] = createSignal<MdCommanderCommandMap>(initialCommands || {});
|
||||
|
||||
// ==================== 命令执行 ====================
|
||||
|
||||
@@ -100,9 +69,10 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
const input = inputValue().trim();
|
||||
if (!input) return;
|
||||
|
||||
const parsed = parseInput(input, commands);
|
||||
const cmds = commands();
|
||||
const parsed = parseInput(input, cmds);
|
||||
const commandName = parsed.command;
|
||||
const cmd = commands[commandName!];
|
||||
const cmd = cmds[commandName!];
|
||||
|
||||
let result: { message: string; type?: "success" | "error" | "warning" | "info"; isHtml?: boolean };
|
||||
|
||||
@@ -110,7 +80,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
result = { message: `未知命令:${commandName}`, type: "error" };
|
||||
} else if (cmd.handler) {
|
||||
try {
|
||||
result = cmd.handler({ params: parsed.params, options: parsed.options }, commands);
|
||||
result = cmd.handler({ params: parsed.params, options: parsed.options }, cmds);
|
||||
} catch (e) {
|
||||
result = {
|
||||
message: `执行错误:${e instanceof Error ? e.message : String(e)}`,
|
||||
@@ -143,7 +113,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
// ==================== 自动补全 ====================
|
||||
|
||||
const updateCompletions = () => {
|
||||
const comps = getCompletions(inputValue(), commands);
|
||||
const comps = getCompletions(inputValue(), commands());
|
||||
setCompletions(comps);
|
||||
setShowCompletions(comps.length > 0 && isFocused());
|
||||
setSelectedCompletionState(0);
|
||||
@@ -151,8 +121,8 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
|
||||
const setSelectedCompletion = (v: number | ((prev: number) => number)) => {
|
||||
const maxIdx = completions().length - 1;
|
||||
if (typeof v === 'function') {
|
||||
setSelectedCompletionState(prev => {
|
||||
if (typeof v === "function") {
|
||||
setSelectedCompletionState((prev) => {
|
||||
const next = v(prev);
|
||||
return Math.max(0, Math.min(next, maxIdx));
|
||||
});
|
||||
@@ -168,7 +138,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
if (!comp) return;
|
||||
|
||||
const input = inputValue();
|
||||
const parsed = parseInput(input, commands);
|
||||
const parsed = parseInput(input, commands());
|
||||
let newValue: string;
|
||||
|
||||
if (comp.type === "command") {
|
||||
@@ -179,7 +149,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
.join(" ");
|
||||
newValue = `${parsed.command || ""} ${existingOptions}${existingOptions ? " " : ""}${comp.insertText}`;
|
||||
} else if (comp.type === "value") {
|
||||
const cmd = parsed.command ? commands[parsed.command] : null;
|
||||
const cmd = parsed.command ? commands()[parsed.command] : null;
|
||||
const paramDefs = cmd?.parameters || [];
|
||||
const usedParams = Object.keys(parsed.params);
|
||||
const isTypingLastParam = paramDefs.length === usedParams.length && !input.endsWith(" ");
|
||||
@@ -204,12 +174,12 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
|
||||
// ==================== 命令历史 ====================
|
||||
|
||||
const navigateHistory = (direction: 'up' | 'down') => {
|
||||
const navigateHistory = (direction: "up" | "down") => {
|
||||
const history = commandHistory();
|
||||
if (history.length === 0) return;
|
||||
|
||||
let newIndex = historyIndex();
|
||||
if (direction === 'up') {
|
||||
if (direction === "up") {
|
||||
if (newIndex < history.length - 1) newIndex++;
|
||||
} else {
|
||||
if (newIndex > 0) {
|
||||
@@ -226,37 +196,47 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
};
|
||||
|
||||
// ==================== Tracker 操作 ====================
|
||||
const {
|
||||
getTrackerItems,
|
||||
getTrackerHistory,
|
||||
addTrackerItem,
|
||||
removeTrackerItem,
|
||||
updateTrackerAttribute,
|
||||
updateTrackerClasses,
|
||||
moveTrackerItem,
|
||||
removeTrackerClass,
|
||||
} = require("../stores") as typeof import("../stores");
|
||||
|
||||
const getEmmetFromIndex = (index: number): string | null => {
|
||||
const items = getTrackerItems();
|
||||
if (index < 0 || index >= items.length) return null;
|
||||
const item = items[index];
|
||||
return `${item.tag}${item.id ? '#' + item.id : ''}${item.classes.length > 0 ? '.' + item.classes.join('.') : ''}`;
|
||||
return `${item.tag}${item.id ? "#" + item.id : ""}${item.classes.length > 0 ? "." + item.classes.join(".") : ""}`;
|
||||
};
|
||||
|
||||
const removeTrackerItemByIndex = (index: number) => {
|
||||
const emmet = getEmmetFromIndex(index);
|
||||
if (emmet) removeTracker(emmet);
|
||||
if (emmet) removeTrackerItem(emmet);
|
||||
};
|
||||
|
||||
const updateTrackerAttributeByIndex = (index: number, attrName: string, attr: TrackerAttribute) => {
|
||||
const emmet = getEmmetFromIndex(index);
|
||||
if (emmet) updateTrackerAttr(emmet, attrName, attr);
|
||||
if (emmet) updateTrackerAttribute(emmet, attrName, attr);
|
||||
};
|
||||
|
||||
const updateTrackerClassesByIndex = (index: number, classes: string[]) => {
|
||||
const emmet = getEmmetFromIndex(index);
|
||||
if (emmet) updateTrackerClassesStore(emmet, classes);
|
||||
if (emmet) updateTrackerClasses(emmet, classes);
|
||||
};
|
||||
|
||||
const moveTrackerItemByIndex = (index: number, direction: 'up' | 'down') => {
|
||||
const moveTrackerItemByIndex = (index: number, direction: "up" | "down") => {
|
||||
const emmet = getEmmetFromIndex(index);
|
||||
if (emmet) moveTracker(emmet, direction);
|
||||
if (emmet) moveTrackerItem(emmet, direction);
|
||||
};
|
||||
|
||||
const removeTrackerItemClassByIndex = (index: number, className: string) => {
|
||||
const emmet = getEmmetFromIndex(index);
|
||||
if (emmet) removeClassFromTracker(emmet, className);
|
||||
if (emmet) removeTrackerClass(emmet, className);
|
||||
};
|
||||
|
||||
return {
|
||||
@@ -275,6 +255,7 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
updateCompletions,
|
||||
acceptCompletion,
|
||||
commands,
|
||||
setCommands,
|
||||
historyIndex,
|
||||
setHistoryIndex,
|
||||
commandHistory,
|
||||
@@ -283,15 +264,15 @@ export function useCommander(customCommands?: MdCommanderCommandMap): UseCommand
|
||||
setViewMode,
|
||||
trackerItems: getTrackerItems,
|
||||
trackerHistory: getTrackerHistory,
|
||||
addTrackerItem: addTracker,
|
||||
removeTrackerItem: removeTracker,
|
||||
addTrackerItem,
|
||||
removeTrackerItem,
|
||||
removeTrackerItemByIndex,
|
||||
updateTrackerAttribute: updateTrackerAttr,
|
||||
updateTrackerAttribute,
|
||||
updateTrackerAttributeByIndex,
|
||||
updateTrackerClassesByIndex,
|
||||
moveTrackerItem: moveTracker,
|
||||
moveTrackerItem,
|
||||
moveTrackerItemByIndex,
|
||||
removeTrackerItemClass: removeClassFromTracker,
|
||||
removeTrackerItemClass,
|
||||
removeTrackerItemClassByIndex,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user