|
| 1 | +# `defaultCommand` Configuration |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The `defaultCommand` option allows you to specify what happens when a CLI |
| 6 | +command is invoked **without any arguments**. This works for both the main |
| 7 | +application command (via `@cli`) and subcommands (via `@command`). |
| 8 | + |
| 9 | +## When Does `defaultCommand` Trigger? |
| 10 | + |
| 11 | +### Main Command |
| 12 | + |
| 13 | +For the main application command, `defaultCommand` triggers when: |
| 14 | + |
| 15 | +```bash |
| 16 | +# Running the CLI with NO arguments at all |
| 17 | +myapp |
| 18 | + |
| 19 | +# This is equivalent to not providing any flags, subcommands, or positional arguments |
| 20 | +``` |
| 21 | + |
| 22 | +**Does NOT trigger when:** |
| 23 | + |
| 24 | +```bash |
| 25 | +myapp --help # Has an argument (--help flag) |
| 26 | +myapp subcommand # Has an argument (subcommand) |
| 27 | +myapp input.txt # Has an argument (positional argument) |
| 28 | +myapp --verbose # Has an argument (--verbose flag) |
| 29 | +``` |
| 30 | + |
| 31 | +### Subcommands |
| 32 | + |
| 33 | +For subcommands, `defaultCommand` triggers when the subcommand is invoked |
| 34 | +**without additional arguments**: |
| 35 | + |
| 36 | +```bash |
| 37 | +# Subcommand invoked with NO additional arguments |
| 38 | +myapp serve |
| 39 | + |
| 40 | +# This means the subcommand name is provided, but nothing after it |
| 41 | +``` |
| 42 | + |
| 43 | +**Does NOT trigger when:** |
| 44 | + |
| 45 | +```bash |
| 46 | +myapp serve --help # Subcommand has an argument (--help flag) |
| 47 | +myapp serve --port 8080 # Subcommand has arguments |
| 48 | +myapp serve input.txt # Subcommand has a positional argument |
| 49 | +``` |
| 50 | + |
| 51 | +## Usage Examples |
| 52 | + |
| 53 | +### Main Command with `defaultCommand: "help"` |
| 54 | + |
| 55 | +```typescript |
| 56 | +import { Args, cli } from "@sigma/parse"; |
| 57 | + |
| 58 | +@cli({ |
| 59 | + name: "calculator", |
| 60 | + description: "A simple calculator", |
| 61 | + defaultCommand: "help", |
| 62 | +}) |
| 63 | +class Calculator extends Args { |
| 64 | + @description("First number") |
| 65 | + a: number = 0; |
| 66 | + |
| 67 | + @description("Second number") |
| 68 | + b: number = 0; |
| 69 | +} |
| 70 | + |
| 71 | +// When run with no arguments: |
| 72 | +// $ calculator |
| 73 | +// Shows help text automatically |
| 74 | +``` |
| 75 | + |
| 76 | +### Subcommand with `defaultCommand: "help"` |
| 77 | + |
| 78 | +```typescript |
| 79 | +import { Args, cli, command, description, subCommand } from "@sigma/parse"; |
| 80 | + |
| 81 | +@command({ defaultCommand: "help" }) |
| 82 | +class ServeCommand { |
| 83 | + @description("Port to serve on") |
| 84 | + port: number = 3000; |
| 85 | + |
| 86 | + @description("Host to bind to") |
| 87 | + host: string = "localhost"; |
| 88 | +} |
| 89 | + |
| 90 | +@cli({ |
| 91 | + name: "devtool", |
| 92 | + description: "Development tool", |
| 93 | +}) |
| 94 | +class DevTool extends Args { |
| 95 | + @description("Start the server") |
| 96 | + @subCommand(ServeCommand) |
| 97 | + serve?: ServeCommand; |
| 98 | +} |
| 99 | + |
| 100 | +// When run without subcommand arguments: |
| 101 | +// $ devtool serve |
| 102 | +// Shows help for the serve subcommand (not the main help) |
| 103 | +// |
| 104 | +// Usage: |
| 105 | +// devtool serve [options] |
| 106 | +// |
| 107 | +// Options: |
| 108 | +// --port <number> (default: 3000) |
| 109 | +// Port to serve on |
| 110 | +// --host <string> (default: "localhost") |
| 111 | +// Host to bind to |
| 112 | +``` |
| 113 | + |
| 114 | +### Main Command with `defaultCommand` Pointing to a Subcommand |
| 115 | + |
| 116 | +```typescript |
| 117 | +import { Args, cli, command, subCommand } from "@sigma/parse"; |
| 118 | + |
| 119 | +@command |
| 120 | +class InitCommand { |
| 121 | + @description("Project name") |
| 122 | + name: string = "my-project"; |
| 123 | +} |
| 124 | + |
| 125 | +@cli({ |
| 126 | + name: "devtool", |
| 127 | + description: "Development tool", |
| 128 | + defaultCommand: "init", // Execute init by default |
| 129 | +}) |
| 130 | +class DevTool extends Args { |
| 131 | + @description("Initialize a new project") |
| 132 | + @subCommand(InitCommand) |
| 133 | + init?: InitCommand; |
| 134 | +} |
| 135 | + |
| 136 | +// When run with no arguments: |
| 137 | +// $ devtool |
| 138 | +// Automatically executes: devtool init |
| 139 | +// Result: init command runs with default values (name = "my-project") |
| 140 | +``` |
| 141 | + |
| 142 | +## Behavior Details |
| 143 | + |
| 144 | +### `defaultCommand: "help"` |
| 145 | + |
| 146 | +When set to `"help"`, the command will display its help text and exit (or throw |
| 147 | +if `exitOnHelp: false`). |
| 148 | + |
| 149 | +### `defaultCommand: "<subcommand-name>"` |
| 150 | + |
| 151 | +When set to a subcommand name, that subcommand will be executed with **no |
| 152 | +additional arguments** (using its default values). |
| 153 | + |
| 154 | +### No `defaultCommand` Set |
| 155 | + |
| 156 | +When `defaultCommand` is not specified: |
| 157 | + |
| 158 | +- The command executes normally with default values |
| 159 | +- No special behavior occurs |
| 160 | + |
| 161 | +## Inheritance Rules |
| 162 | + |
| 163 | +### Subcommands DO NOT Inherit Parent's `defaultCommand` |
| 164 | + |
| 165 | +This is by design to allow fine-grained control: |
| 166 | + |
| 167 | +```typescript |
| 168 | +@command // No defaultCommand - will execute with defaults |
| 169 | +class BuildCommand { |
| 170 | + minify: boolean = false; |
| 171 | +} |
| 172 | + |
| 173 | +@command({ defaultCommand: "help" }) // Has its own defaultCommand |
| 174 | +class ServeCommand { |
| 175 | + port: number = 3000; |
| 176 | +} |
| 177 | + |
| 178 | +@cli({ |
| 179 | + name: "devtool", |
| 180 | + defaultCommand: "help", // Only applies to main command |
| 181 | +}) |
| 182 | +class DevTool extends Args { |
| 183 | + @subCommand(BuildCommand) |
| 184 | + build?: BuildCommand; |
| 185 | + |
| 186 | + @subCommand(ServeCommand) |
| 187 | + serve?: ServeCommand; |
| 188 | +} |
| 189 | + |
| 190 | +// $ devtool |
| 191 | +// Shows help (main command's defaultCommand) |
| 192 | + |
| 193 | +// $ devtool build |
| 194 | +// Executes build with defaults (no defaultCommand set on BuildCommand) |
| 195 | + |
| 196 | +// $ devtool serve |
| 197 | +// Shows help for serve (ServeCommand has defaultCommand: "help") |
| 198 | +``` |
| 199 | + |
| 200 | +### Error Handling Options ARE Inherited |
| 201 | + |
| 202 | +While `defaultCommand` is not inherited, other options like `exitOnError` and |
| 203 | +`exitOnHelp` **are** inherited by subcommands: |
| 204 | + |
| 205 | +```typescript |
| 206 | +@command({ defaultCommand: "help" }) |
| 207 | +class ServeCommand { |
| 208 | + port: number = 3000; |
| 209 | +} |
| 210 | + |
| 211 | +@cli({ |
| 212 | + name: "devtool", |
| 213 | + exitOnHelp: false, // This IS inherited by subcommands |
| 214 | +}) |
| 215 | +class DevTool extends Args { |
| 216 | + @subCommand(ServeCommand) |
| 217 | + serve?: ServeCommand; |
| 218 | +} |
| 219 | + |
| 220 | +// When help is shown, it will throw ParseError instead of exiting |
| 221 | +// because exitOnHelp: false is inherited |
| 222 | +``` |
| 223 | + |
| 224 | +## Common Patterns |
| 225 | + |
| 226 | +### 1. Help by Default Everywhere |
| 227 | + |
| 228 | +```typescript |
| 229 | +@command({ defaultCommand: "help" }) |
| 230 | +class SubCommand { |
| 231 | + // ... |
| 232 | +} |
| 233 | + |
| 234 | +@cli({ |
| 235 | + name: "myapp", |
| 236 | + defaultCommand: "help", |
| 237 | +}) |
| 238 | +class MyApp extends Args { |
| 239 | + @subCommand(SubCommand) |
| 240 | + sub?: SubCommand; |
| 241 | +} |
| 242 | + |
| 243 | +// Both main command and subcommand show help when called without args |
| 244 | +``` |
| 245 | + |
| 246 | +### 2. Auto-Execute Default Subcommand |
| 247 | + |
| 248 | +```typescript |
| 249 | +@command |
| 250 | +class DefaultCommand { |
| 251 | + // ... |
| 252 | +} |
| 253 | + |
| 254 | +@cli({ |
| 255 | + name: "myapp", |
| 256 | + defaultCommand: "default", // Execute 'default' subcommand when no args |
| 257 | +}) |
| 258 | +class MyApp extends Args { |
| 259 | + @subCommand(DefaultCommand) |
| 260 | + default?: DefaultCommand; |
| 261 | +} |
| 262 | + |
| 263 | +// $ myapp |
| 264 | +// Automatically runs the default subcommand |
| 265 | +``` |
| 266 | + |
| 267 | +### 3. Mixed Behavior |
| 268 | + |
| 269 | +```typescript |
| 270 | +@command({ defaultCommand: "help" }) |
| 271 | +class ComplexCommand { |
| 272 | + // Show help if called without args |
| 273 | +} |
| 274 | + |
| 275 | +@command |
| 276 | +class SimpleCommand { |
| 277 | + // Execute with defaults if called without args |
| 278 | +} |
| 279 | + |
| 280 | +@cli({ |
| 281 | + name: "myapp", |
| 282 | + // No defaultCommand - will fail if called without args |
| 283 | +}) |
| 284 | +class MyApp extends Args { |
| 285 | + @subCommand(ComplexCommand) |
| 286 | + complex?: ComplexCommand; |
| 287 | + |
| 288 | + @subCommand(SimpleCommand) |
| 289 | + simple?: SimpleCommand; |
| 290 | +} |
| 291 | + |
| 292 | +// $ myapp |
| 293 | +// Error: missing subcommand |
| 294 | + |
| 295 | +// $ myapp complex |
| 296 | +// Shows help for complex command |
| 297 | + |
| 298 | +// $ myapp simple |
| 299 | +// Executes simple command with defaults |
| 300 | +``` |
| 301 | + |
| 302 | +## Summary |
| 303 | + |
| 304 | +| Scenario | Triggers When | Example | |
| 305 | +| ---------------------------------- | ------------------------------------------ | ---------------------------- | |
| 306 | +| Main command with `defaultCommand` | No arguments at all | `myapp` | |
| 307 | +| Subcommand with `defaultCommand` | Subcommand invoked without additional args | `myapp serve` | |
| 308 | +| `defaultCommand: "help"` | Shows help text | Display usage information | |
| 309 | +| `defaultCommand: "<name>"` | Executes named subcommand | Run subcommand with defaults | |
| 310 | +| No `defaultCommand` | Normal execution | Use default values | |
0 commit comments