@pablozaiden/terminatui 0.6.0 → 0.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pablozaiden/terminatui",
3
- "version": "0.6.0",
3
+ "version": "0.6.3",
4
4
  "description": "Terminal UI and Command Line Application Framework",
5
5
  "repository": {
6
6
  "url": "https://github.com/PabloZaiden/terminatui",
@@ -21,6 +21,7 @@ export class HelpCommand extends Command<OptionSchema> {
21
21
  private allCommands: AnyCommand[] = [];
22
22
  private appName: string;
23
23
  private appVersion: string;
24
+ private commandPath: string[] = [];
24
25
 
25
26
  constructor(config: {
26
27
  parentCommand?: AnyCommand;
@@ -35,6 +36,14 @@ export class HelpCommand extends Command<OptionSchema> {
35
36
  this.appVersion = config.appVersion;
36
37
  }
37
38
 
39
+ /**
40
+ * Set the command path for this help command.
41
+ * Called by the Application before executing help.
42
+ */
43
+ setCommandPath(path: string[]): void {
44
+ this.commandPath = path;
45
+ }
46
+
38
47
  /**
39
48
  * Help command is CLI-only (auto-injected for CLI use, not shown in TUI).
40
49
  */
@@ -45,11 +54,15 @@ export class HelpCommand extends Command<OptionSchema> {
45
54
  override async execute(): Promise<CommandResult> {
46
55
  let helpText: string;
47
56
 
57
+ // Get the parent command path (exclude "help" from the end if present)
58
+ const parentPath = this.commandPath.filter(p => p !== KNOWN_COMMANDS.help);
59
+
48
60
  if (this.parentCommand) {
49
61
  // Show help for the parent command
50
62
  helpText = generateCommandHelp(this.parentCommand, {
51
63
  appName: this.appName,
52
64
  version: this.appVersion,
65
+ commandPath: parentPath,
53
66
  globalOptionsSchema: GLOBAL_OPTIONS_SCHEMA,
54
67
  });
55
68
  } else {
@@ -1,7 +1,6 @@
1
1
  import { AppContext, type AppConfig } from "./context.ts";
2
2
  import { Command, type AnyCommand, ConfigValidationError, type CommandExecutionContext } from "./command.ts";
3
3
  import { CommandRegistry } from "./registry.ts";
4
- import { ExecutionMode } from "../types/execution.ts";
5
4
  import { LogLevel, type LoggerConfig } from "./logger.ts";
6
5
  import {
7
6
  extractCommandChain,
@@ -341,8 +340,10 @@ export class Application {
341
340
  return;
342
341
  }
343
342
 
344
- // Determine execution mode
345
- const mode = this.detectExecutionMode(command, flagArgs);
343
+ // If this is a help command being executed directly, set its command path
344
+ if ('setCommandPath' in command && typeof command.setCommandPath === 'function') {
345
+ (command as { setCommandPath: (path: string[]) => void }).setCommandPath(commandPath);
346
+ }
346
347
 
347
348
  // Parse options
348
349
  const schema = command.options ?? {};
@@ -364,13 +365,13 @@ export class Application {
364
365
  let options;
365
366
  try {
366
367
  options = parseOptionValues(schema, parsedValues);
367
- } catch (err) {
368
- // Enum validation error from parseOptionValues
369
- AppContext.current.logger.error(`Error: ${(err as Error).message}\n`);
370
- await this.printHelpForCommand(command, commandPath);
371
- process.exitCode = 1;
372
- return;
373
- }
368
+ } catch (err) {
369
+ // Enum validation error from parseOptionValues
370
+ AppContext.current.logger.error(`Error: ${(err as Error).message}\n`);
371
+ await this.printHelpForCommand(command, commandPath);
372
+ process.exitCode = 1;
373
+ return;
374
+ }
374
375
 
375
376
 
376
377
  // Validate options (required, min/max, etc.)
@@ -409,17 +410,14 @@ export class Application {
409
410
  const ctx: CommandExecutionContext = { signal: new AbortController().signal };
410
411
  const commandResult = await command.execute(config, ctx);
411
412
 
412
- // In CLI mode, handle result output
413
- if (mode === ExecutionMode.Cli) {
414
- if (commandResult.success) {
415
- // Output data as JSON to stdout if present
416
- if (commandResult.data !== undefined) {
417
- console.log(JSON.stringify(commandResult.data, null, 2));
418
- }
419
- } else {
420
- // Set exit code for failures
421
- process.exitCode = 1;
413
+ if (commandResult.success) {
414
+ // Output data as JSON to stdout if present
415
+ if (commandResult.data !== undefined) {
416
+ console.log(JSON.stringify(commandResult.data, null, 2));
422
417
  }
418
+ } else {
419
+ // Set exit code for failures
420
+ process.exitCode = 1;
423
421
  }
424
422
  } catch (e) {
425
423
  error = e as Error;
@@ -456,6 +454,11 @@ export class Application {
456
454
  throw new Error(`Help command not injected for '${resolvedCommandPath.join(" ")}'`);
457
455
  }
458
456
 
457
+ // Set the command path on the help command so it can generate correct usage
458
+ if ('setCommandPath' in helpCommand && typeof helpCommand.setCommandPath === 'function') {
459
+ (helpCommand as { setCommandPath: (path: string[]) => void }).setCommandPath(resolvedCommandPath);
460
+ }
461
+
459
462
  await this.executeCommand(helpCommand, [], [...resolvedCommandPath, KNOWN_COMMANDS.help]);
460
463
  }
461
464
 
@@ -479,19 +482,6 @@ export class Application {
479
482
  return !hasCustomExecute;
480
483
  }
481
484
 
482
- /**
483
- * Detect the execution mode based on command and args.
484
- */
485
- private detectExecutionMode(command: AnyCommand, args: string[]): ExecutionMode {
486
- // If no args and command supports TUI, use TUI mode
487
- if (args.length === 0 && command.supportsTui()) {
488
- return ExecutionMode.Tui;
489
- }
490
-
491
- // Otherwise use CLI mode
492
- return ExecutionMode.Cli;
493
- }
494
-
495
485
  /**
496
486
  * Parse global options from argv.
497
487
  * Returns the parsed global options and remaining args.
@@ -514,7 +504,7 @@ export class Application {
514
504
  const rawGlobalOptions = parseOptionValues(GLOBAL_OPTIONS_SCHEMA, result.values) as GlobalOptions;
515
505
 
516
506
  const globalOptions: GlobalOptions = { ...rawGlobalOptions };
517
-
507
+
518
508
  const remainingArgs: string[] = [];
519
509
  for (const token of result.tokens ?? []) {
520
510
  if (token.kind === "positional") {
package/src/core/help.ts CHANGED
@@ -112,7 +112,7 @@ export function formatExamples(command: AnyCommand): string {
112
112
  * @returns Formatted help text
113
113
  */
114
114
  export function generateCommandHelp(command: AnyCommand, options: HelpOptions = {}): string {
115
- const { appName = "cli", version } = options;
115
+ const { appName = "cli", version, commandPath = [] } = options;
116
116
  const sections: string[] = [];
117
117
 
118
118
  // Header with version
@@ -164,8 +164,14 @@ export function generateCommandHelp(command: AnyCommand, options: HelpOptions =
164
164
 
165
165
  // Help hint
166
166
  if (command.hasSubCommands()) {
167
+ // Build the full command path for the hint
168
+ const fullPath = [appName, ...commandPath];
169
+ // Add command name if not already in path
170
+ if (commandPath.length === 0 || commandPath[commandPath.length - 1] !== command.name) {
171
+ fullPath.push(command.name);
172
+ }
167
173
  sections.push(
168
- `\n${colors.dim(`Run '${appName} ${command.name} <command> help' for more information on a command.`)}`
174
+ `\n${colors.dim(`Run '${fullPath.join(" ")} <command> help' for more information on a command.`)}`
169
175
  );
170
176
  }
171
177
 
@@ -1,11 +0,0 @@
1
- /**
2
- * Execution mode determines how a command runs.
3
- * - Cli: Command-line mode with arguments, executes and exits
4
- * - Tui: Terminal UI mode with interactive rendering
5
- */
6
- export enum ExecutionMode {
7
- /** Command-line mode: parse args, execute, exit */
8
- Cli = "cli",
9
- /** Terminal UI mode: interactive render loop */
10
- Tui = "tui",
11
- }