UNPKG

nx

Version:

The core Nx plugin contains the core functionality of Nx like the project graph, nx commands and task orchestration.

121 lines (120 loc) 4.93 kB
"use strict"; // Slow-path completion: command/subcommand/flag names. Runs after // tryValueCompletion has nothing to offer. Object.defineProperty(exports, "__esModule", { value: true }); exports.DESC_SEPARATOR = void 0; exports.tryCommandSurfaceCompletion = tryCommandSurfaceCompletion; exports.getTopLevelCommands = getTopLevelCommands; exports.getCommandCompletions = getCommandCompletions; exports.formatDescription = formatDescription; exports.shellRendersDescriptions = shellRendersDescriptions; const trigger_1 = require("./trigger"); const argv_layout_1 = require("./argv-layout"); const metadata_1 = require("./metadata"); const command_handlers_1 = require("./command-handlers"); /** Slow-path entry point. Returns true if anything was emitted. */ function tryCommandSurfaceCompletion(argv = process.argv) { const parsed = (0, argv_layout_1.parseCompletionArgs)(argv); if (parsed === null) return false; const matched = getCommandCompletions(parsed.current, parsed.tokens); const completions = matched !== null ? matched : getTopLevelCommands(parsed.current, shellRendersDescriptions()); if (completions === null || completions.length === 0) return false; for (const line of completions) { console.log(line); } return true; } /** Top-level command names. Unions yargs handlers with the completion * registry's single-token paths (infix targets). */ function getTopLevelCommands(current, withDesc) { const handlers = (0, command_handlers_1.getNxCommandHandlers)(); const seen = new Set(); const completions = []; for (const name of Object.keys(handlers)) { if (name === '$0' || name.startsWith('_')) continue; if (current && !name.startsWith(current)) continue; const handler = handlers[name]; if (handler?.description === false) continue; // hidden seen.add(name); const desc = withDesc ? formatDescription(handler?.description) : ''; completions.push(desc ? `${name}${exports.DESC_SEPARATOR}${desc}` : name); } // Infix targets + any other top-level completion-only paths. for (const name of (0, metadata_1.getRegisteredTopLevelPaths)()) { if (seen.has(name)) continue; if (current && !name.startsWith(current)) continue; seen.add(name); completions.push(name); } return completions; } /** * Enumerates subcommands + options of a matched top-level command. Returns * null when no top-level command name is matched in `args`. */ function getCommandCompletions(current, args) { const handlers = (0, command_handlers_1.getNxCommandHandlers)(); const cmdName = args.find((a) => handlers[a]); if (!cmdName) { return null; } const handler = handlers[cmdName]; // Once we recognize a top-level command in `args`, we own the slot — // return [] (not null) for the "found a command but can't enumerate its // surface" case so the caller doesn't fall back to top-level commands // (which would mis-offer e.g. `exec` for `nx g c ex`). if (typeof handler.builder !== 'function') { return []; } const intro = (0, command_handlers_1.introspectBuilder)(handler.builder); if (!intro) return []; const completions = []; const isFlagPrefix = current.startsWith('-'); const withDesc = shellRendersDescriptions(); if (!isFlagPrefix) { for (const [name, desc] of intro.subcommands) { const formatted = withDesc ? formatDescription(desc) : ''; completions.push(formatted ? `${name}${exports.DESC_SEPARATOR}${formatted}` : name); } } for (const [name, desc] of intro.options) { const formatted = withDesc ? formatDescription(desc) : ''; completions.push(formatted ? `--${name}${exports.DESC_SEPARATOR}${formatted}` : `--${name}`); } if (!current) { return completions; } const flagName = current.replace(/^-+/, ''); return completions.filter((c) => { if (isFlagPrefix) { return c.startsWith(`--${flagName}`); } return c.startsWith(current); }); } /** value\tdescription separator. TAB because completion values can contain * colons (`my-app:build`); descriptions get TABs collapsed. */ exports.DESC_SEPARATOR = '\t'; /** Strip the y18n marker yargs prepends to its built-in --help / --version * descriptions, and collapse stray TABs so they can't forge the * value/description separator. */ function formatDescription(raw) { if (!raw) return ''; return raw.replace(/^__yargsString__:/, '').replace(/\t/g, ' '); } /** zsh (compadd -d) and fish (complete -a) parse `value\tdescription`. */ function shellRendersDescriptions() { const shell = (0, trigger_1.getCompletionShell)(); return shell === 'zsh' || shell === 'fish'; }