diff --git a/docs/ru/FEATURES.md b/docs/ru/FEATURES.md index f4ac509..0ae1189 100644 --- a/docs/ru/FEATURES.md +++ b/docs/ru/FEATURES.md @@ -44,7 +44,7 @@ - Генерация скрипта автодополнения для bash/zsh/fish: `gromlab-create completion --shell `. - Автодополнение доступно только для глобальной установки CLI. -- Автодополнение шаблонов из `.templates/` и переменных `--` выбранного шаблона (кроме `name`). +- Автодополнение шаблонов из ближайшей `.templates/` (по дереву вверх) и переменных `--` выбранного шаблона (кроме `name`). ## Обновления CLI diff --git a/package.json b/package.json index cb3d23e..455d12b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@gromlab/create", - "version": "0.1.1", + "version": "0.1.3", "description": "Template-based file generator CLI", "license": "MIT", "publishConfig": { diff --git a/src/completion.ts b/src/completion.ts index e33714f..838496f 100644 --- a/src/completion.ts +++ b/src/completion.ts @@ -5,14 +5,28 @@ import { detectRunMode } from './runtime'; const BIN_NAMES = ['gromlab-create', 'create']; -function templatesDir(cwd: string): string { - return path.resolve(cwd, '.templates'); +function findNearestTemplatesDir(startDir: string): string | undefined { + let current = path.resolve(startDir); + while (true) { + const candidate = path.join(current, '.templates'); + try { + if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) { + return candidate; + } + } catch { + // ignore errors and keep walking up + } + const parent = path.dirname(current); + if (parent === current) break; + current = parent; + } + return undefined; } function listTemplates(cwd: string): string[] { - const dir = templatesDir(cwd); + const dir = findNearestTemplatesDir(cwd); try { - if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return []; + if (!dir) return []; return listTemplateNames(dir); } catch { return []; @@ -20,7 +34,9 @@ function listTemplates(cwd: string): string[] { } function listTemplateVars(cwd: string, templateName: string): string[] { - const dir = path.join(templatesDir(cwd), templateName); + const root = findNearestTemplatesDir(cwd); + if (!root) return []; + const dir = path.join(root, templateName); try { if (!fs.existsSync(dir) || !fs.statSync(dir).isDirectory()) return []; const vars = Array.from(collectTemplateVariables(dir)) @@ -225,7 +241,8 @@ export function handleInternalCommand(args: string[], cwd: string = process.cwd( return true; } - const normalized = shell.trim().toLowerCase(); + let normalized = shell.trim().toLowerCase(); + if (normalized === 'zh') normalized = 'zsh'; let script = ''; if (normalized === 'bash') script = buildBashCompletion(); if (normalized === 'zsh') script = buildZshCompletion();