diff --git a/src/components/md-commander/hooks/useCommander.ts b/src/components/md-commander/hooks/useCommander.ts index 4d61edf..ec93e97 100644 --- a/src/components/md-commander/hooks/useCommander.ts +++ b/src/components/md-commander/hooks/useCommander.ts @@ -118,7 +118,8 @@ export function parseInput(input: string, commands?: MdCommanderCommandMap): { // 检查是否有未完成的位置参数 if (paramIndex < paramDefs.length) { const lastPart = parts[parts.length - 1]; - if (lastPart && !lastPart.startsWith("-")) { + // 只有当最后一个部分不是命令本身时,才设置为未完成参数 + if (lastPart && !lastPart.startsWith("-") && parts.length > 1) { result.incompleteParam = { index: paramIndex, value: lastPart, @@ -166,30 +167,65 @@ export function getCompletions( // 检查是否需要参数补全 const paramDefs = cmd.parameters || []; const usedParams = Object.keys(parsed.params); - - // 如果还有未填的参数,提供参数值补全 - if (paramDefs.length > usedParams.length) { - const paramDef = paramDefs[usedParams.length]; + + // 判断是否正在输入最后一个参数(没有尾随空格) + const isTypingLastParam = paramDefs.length === usedParams.length && + trimmed.length > 0 && + !trimmed.endsWith(" ") && + !trimmed.split(/\s+/)[trimmed.split(/\s+/).length - 1].startsWith("-"); + + // 如果还有未填的参数,或者当前参数可能未完成 + if (paramDefs.length > usedParams.length || parsed.incompleteParam || isTypingLastParam) { + // 确定当前参数的索引 + let paramIndex: number; + if (parsed.incompleteParam !== undefined) { + paramIndex = parsed.incompleteParam.index; + } else if (isTypingLastParam) { + // 正在编辑最后一个参数 + paramIndex = paramDefs.length - 1; + } else { + paramIndex = usedParams.length; + } + + const paramDef = paramDefs[paramIndex]; + if (!paramDef) return []; + + // 获取当前输入值 + let currentValue = parsed.incompleteParam?.value || ""; + if (isTypingLastParam && !parsed.incompleteParam) { + const parts = trimmed.split(/\s+/); + currentValue = parts[parts.length - 1] || ""; + } + + // 模板补全 + if (paramDef.templates) { + return paramDef.templates + .filter((t) => t.label.toLowerCase().includes(currentValue.toLowerCase())) + .map((t) => ({ + label: t.label, + type: "value" as "value", + description: t.description, + insertText: t.insertText, + })); + } + if (paramDef.type === "enum" && paramDef.values) { - const currentValue = parsed.incompleteParam?.value || ""; return paramDef.values .filter((v) => v.startsWith(currentValue)) .map((v) => ({ label: v, - type: "value", + type: "value" as "value", description: paramDef.description, insertText: v, })); } // 其他类型的参数,显示提示 - if (parsed.incompleteParam) { - return [{ - label: `<${paramDef.name}>`, - type: "value", - description: `${paramDef.type}${paramDef.required !== false ? " (必填)" : ""}: ${paramDef.description || ""}`, - insertText: "", - }]; - } + return [{ + label: `<${paramDef.name}>`, + type: "value" as "value", + description: `${paramDef.type}${paramDef.required !== false ? " (必填)" : ""}: ${paramDef.description || ""}`, + insertText: "", + }]; } // 选项补全 @@ -369,6 +405,7 @@ export function useCommander( if (!comp) return; const input = inputValue(); + const trimmed = input.trim(); const parsed = parseInput(input, commands); let newValue: string; @@ -385,14 +422,26 @@ export function useCommander( const cmd = parsed.command ? commands[parsed.command] : null; const paramDefs = cmd?.parameters || []; const usedParams = Object.keys(parsed.params); - - if (paramDefs.length > usedParams.length) { + + const base = parsed.command || ""; + const existingOptions = Object.entries(parsed.options) + .map(([k, v]) => `--${k}=${v}`) + .join(" "); + + // 判断是否正在编辑最后一个参数(使用原始 input 检查尾随空格) + const isTypingLastParam = paramDefs.length === usedParams.length && + input.length > 0 && + !input.endsWith(" "); + + if (isTypingLastParam) { + // 替换最后一个参数 + const parts = trimmed.split(/\s+/); + parts.pop(); // 移除正在输入的参数 + const existingParams = parts.slice(1).join(" "); // 跳过命令 + newValue = `${base}${existingParams ? " " + existingParams : ""} ${comp.insertText}${existingOptions ? " " + existingOptions : ""}`; + } else if (paramDefs.length > usedParams.length) { // 当前参数的补全 - const base = parsed.command || ""; const existingParams = Object.values(parsed.params).join(" "); - const existingOptions = Object.entries(parsed.options) - .map(([k, v]) => `--${k}=${v}`) - .join(" "); newValue = `${base} ${existingParams}${existingParams ? " " : ""}${comp.insertText}${existingOptions ? " " + existingOptions : ""}`; } else { newValue = input;