https://github.com/modpm/cmd
Simple, intuitive library for building CLI applications in D.
https://github.com/modpm/cmd
args-parser argument-parser arguments-parser chainable cli cli-framework cli-library cli-parser command-line command-line-parser commander dlang library option-parser options-parsing subcommands
Last synced: 7 days ago
JSON representation
Simple, intuitive library for building CLI applications in D.
- Host: GitHub
- URL: https://github.com/modpm/cmd
- Owner: modpm
- License: gpl-3.0
- Created: 2025-09-09T13:35:50.000Z (6 months ago)
- Default Branch: main
- Last Pushed: 2025-11-26T10:01:47.000Z (4 months ago)
- Last Synced: 2025-11-27T23:04:34.137Z (3 months ago)
- Topics: args-parser, argument-parser, arguments-parser, chainable, cli, cli-framework, cli-library, cli-parser, command-line, command-line-parser, commander, dlang, library, option-parser, options-parsing, subcommands
- Language: D
- Homepage: https://modpm.github.io/cmd/
- Size: 96.7 KB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: COPYING
- Codeowners: .github/CODEOWNERS
Awesome Lists containing this project
README
# cmd
[](https://modpm.github.io/cmd)
[](https://github.com/modpm/cmd)
[](https://github.com/modpm/cmd/actions/workflows/build.yaml)
[](https://code.dlang.org/packages/cmd)
[](https://github.com/modpm/cmd/blob/main/COPYING)
[](https://code.dlang.org/packages/cmd)
[](https://code.dlang.org/packages/cmd)
A simple, intuitive library for building CLI applications in D.
[**API Reference Documentation**](https://modpm.github.io/cmd)
## Features
- **Nested subcommands** — Supports hierarchical command structures, allowing commands to contain other commands.
- **Flexible arguments** — Required (`<>`) and optional (`[]`) arguments with variadic support (`...`).
- **Rich option handling** — Supports `--option=value`, `--option value`, and grouped short flags such as `-abc`
(equivalent to `-a -b -c`).
- **Automatic help generation** — Built-in help and usage text generation.
- **Array collection** — Repeated options are automatically collected as arrays.
- **Type-safe parsing** — Clean API for accessing parsed arguments and options.
## Quick Start
Here’s a minimal example that splits a string:
```d
import std.stdio;
import std.string;
import cmd.program;
void main(string[] argv)
{
auto args = new Program("split")
.description("Split a string")
.versionString("1.0.0")
.versionOption("--version", "Show version information")
.helpOption("-h, --help", "Show help for command")
.argument("", "String to split")
.option("-s, --separator ", "Separator character")
.option("--first", "Return only the first element")
.parse(argv);
auto parts = args.argument("string").split(args.option("separator"));
if (args.hasFlag("first"))
writeln(parts[0]);
else
writeln(parts);
}
```
### Usage
```bash
$ ./split "hello,world,foo" --separator ","
["hello", "world", "foo"]
$ ./split "hello,world,foo" --separator "," --first
hello
```
**Note:** [`versionOption()`](https://modpm.github.io/cmd/cmd.program.Program.versionOption.2.html) enables a version flag for your program (e.g., `--version`), and [`helpOption()`](https://modpm.github.io/cmd/cmd.program.Program.helpOption.1.html) enables a help flag (e.g., `-h` or `--help`). When specified, these flags are handled automatically: the library will print the version or help message and exit.
## Options and Flags
Use [`option()`](https://modpm.github.io/cmd/cmd.command.Command.option.html) to add named parameters to your commands:
### Option Types
```d
ParsedArgs args = new Program("example")
// Required option - user must provide a value
.option("-t, --target ", "Target name")
// Optional with default value
.option("-p, --port [number]", "Port number", "8080")
// Optional without default
.option("-c, --config [file]", "Configuration file")
// Boolean flag - without a parameter
.option("--verbose", "Enable verbose output")
.option("-q, --quiet", "Suppress output")
.parse(argv);
```
### Accessing Values
Please see the API reference page for [`ParsedArgs`](https://modpm.github.io/cmd/cmd.parsed_args.ParsedArgs.html).
```d
// Get option value (first occurrence)
const string target = args.option("target");
const string port = args.option("port");
// Get all values for repeated options
// const string[] targets = args.optionList("target");
// Check if optional option is present
if (args.hasOption("--config")) {
const string config = args.option("--config");
// ...
}
// Check boolean flags
if (args.hasFlag("verbose"))
writeln("Verbose mode enabled");
const bool quiet = args.hasFlag("-q");
```
You can access options using:
- `option("target")` - access by long name (explicit for long names)
- `option("t")` - access by short name (implicit, could be ambiguous)
- `option("-t")` - access by short name (explicit)
- `option("--target")` - access by long name (explicit, stylistic)
(also applies for `hasOption()`, `hasFlag()`, etc.)
## Arguments
Use [`argument()`](https://modpm.github.io/cmd/cmd.command.Command.argument.html) to add positional arguments that users provide in order:
```d
new Program("file-processor")
.argument("", "Input file path") // Required
.argument("[output]", "Output file path") // Optional
```
### Variadic Arguments
Variadic (rest) arguments can be added as the last argument in your command to accept multiple values. Optional variadic `[files...]` accepts ≥ 0 values, required variadic `` needs ≥ 1.
```d
new Program("search")
// …
.argument("", "Files to search")
```
### Accessing Arguments
```d
const string inputFile = args.argument("input");
// Check if optional argument was provided
if (args.hasArgument("output")) {
const string outputFile = args.argument("output");
}
// Get all values of variadic
const string[] files = args.argumentList("files");
```
**Note:** Required arguments after optional ones are technically allowed, but behave counter-intuitively and ambiguously for the user. It is strongly recommended not to use optional positional arguments before required ones—consider re-ordering the arguments, or using named parameters (options).
## Working with Subcommands
Build complex CLI applications with nested subcommands using [`command()`](https://modpm.github.io/cmd/cmd.command.Command.command.html). Here’s an example with basic subcommands.
```d
import std.stdio;
import std.string;
import cmd.program;
import cmd.command;
void main(string[] args)
{
new Program("subcommands")
.description("A CLI application with subcommands")
.versionString("1.0.0")
.helpOption("-h, --help", "Show help for command")
.command(new Command("split")
.description("Split a string")
.argument("", "String to split")
.option("-s, --separator ", "Separator character")
.action((args) {
auto parts = args.argument("string").split(args.option("separator"));
writeln(parts);
return 0;
})
)
.command(new Command("greet")
.description("Greet someone")
.argument("", "Name of the person to greet")
.option("--excited", "Add excitement to the greeting")
.action((args) {
auto msg = "Hello, " ~ args.argument("name");
if (args.hasFlag("excited"))
msg ~= "!!!";
writeln(msg);
return 0;
})
)
.run(args);
}
```
### Usage
```bash
$ ./subcommands split "hello,world" --separator ","
$ ./subcommands greet Alice --excited
$ ./subcommands split --help # Shows help for the split subcommand
```
**Important:** A command cannot have both subcommands and arguments. Choose one pattern per command level.
Commands can be nested endlessly.
## Custom Command Classes
Create modular command implementations by extending [`Command`](https://modpm.github.io/cmd/cmd.command.Command.html) (or [`Program`](https://modpm.github.io/cmd/cmd.program.Program.html)):
```d
module modular.commands.greet;
import std.stdio;
import cmd.command;
import cmd.parsed_args;
class GreetCommand : Command
{
public this()
{
super("greet")
.description("Greet someone")
.argument("", "Name of the person to greet")
.option("--excited", "Add excitement to the greeting")
.action(&execute);
}
private int execute(ParsedArgs args)
{
auto msg = "Hello, " ~ args.argument("name");
if (args.hasFlag("excited"))
msg ~= "!!!";
writeln(msg);
return 0;
}
}
```
### Integration
```d
// …
import modular.commands.greet;
import cmd.program;
void main(string[] args)
{
new Program("modular")
.command(new GreetCommand())
.run(args);
}
```
## Built-in Help Command
Enable `help` as a subcommand using [`HelpCommand`](https://modpm.github.io/cmd/cmd.help_command.HelpCommand.html):
```d
// …
import cmd.help_command;
new Program("myapp")
.description("My CLI application")
.command(new Command("deploy").description("Deploy the application"))
.command(new Command("status").description("Check application status"))
.command(new HelpCommand()) // Adds the built-in ‘help’ subcommand
.run(args);
```
### Usage
```bash
$ myapp help # Show help for program
$ myapp help deploy # Show help for deploy command
```
## Error Handling
The library provides clear error messages for common mistakes during args parsing and exits with status code `2`:
```
error: unknown command 'unknown-command'
error: missing value for option 'target'
error: unknown option 'invalid-option'
error: unexpected argument 'extra'
error: missing required option '-t, --target '
error: missing required argument 'input'
```
You can also trigger custom errors in your command actions using the [`error(string)`](https://modpm.github.io/cmd/cmd.command.Command.error.1.html) and [`noreturn error(string, int)`](https://modpm.github.io/cmd/cmd.command.Command.error.2.html) methods on `Command`:
```d
.action((args) {
if (someCondition) {
args.command.error("error message"); // Does not exit (only prints error)
// or
args.command.error("error message", 1); // Exits with status
}
return 0;
});
```
The `error` methods can be overridden to customise the error format.
## Licence
Copyright © 2025 Zefir Kirilov.
This project is licenced under the [GPL-3.0](https://github.com/modpm/cmd/blob/main/COPYING) licence.