cyamli
A command line tool to generate command line interfaces for your command line tools from the YAML-based CLI schemas.
Highlights
- It defines the CLI schema in YAML.
- It provides a typed CLI code generator.
CLI schema
The CLI schema definition is provided in cli-schema-definition.ts.
CLI code generator
From a YAML file written according to the CLI schema definition, cyamli generates a typed code for handling command line arguments.
Installation
cyamli can be installed as follows:
go install "github.com/Jumpaku/cyamli/cmd/cyamli@latest"
Or use go generate as follows:
//go:generate "github.com/Jumpaku/cyamli/cmd/cyamli@latest" -schema-path=path/to/cli.yaml -out-path=path/to/cli.gen.go
Usage
- Generating the CLI type.
- Overwriting the CLI object.
- Executing program.
Generating the CLI type
Prepare the CLI schema for your application, for example:
name: greet
description: this is an example program
options:
-help:
short: -h
description: Show help information.
type: boolean
subcommands:
hello:
description: Prints "Hello, <target name>! My name is <greeter>!"
options:
-target-name:
short: -t
description: The name of the person to be said hello.
arguments:
- name: greeter
description: The name of the person who says hello.
Run cyamli as follows:
cyamli golang < path/to/cli-schema.yaml > path/to/generated/code.go
The above generates a Go code which includes:
type CLI
type CLI_Input
type CLI_Hello
type CLI_Hello_Input
func NewCLI() CLI
func Run(cli CLI, args []string) error
Overwriting the CLI object
To define the behavior of your program, you can utilize the generated types and functions as follows:
func main() {
// Create the CLI object
cli := NewCLI()
// Overwrite behaviors
cli.FUNC = showHelp
cli.Hello.FUNC = sayHello
// Run with command line arguments
if err := Run(cli, os.Args); err != nil {
panic(err)
}
}
Example implementations for showHelp and sayHello are as follows:
func showHelp(subcommand []string, input CLI_Input, inputErr error) (err error) {
if input.Opt_Help {
fmt.Println("This is an example program.")
} else {
fmt.Println("Do nothing.")
}
return nil
}
func sayHello(subcommand []string, input CLI_Hello_Input, inputErr error) (err error) {
hello := "Hello"
if input.Opt_TargetName != "" {
hello += ", " + input.Opt_TargetName
}
hello += "! My name is " + input.Arg_Greeter + "!"
fmt.Println(hello)
return nil
}
Executing program
Execute the main function as follows
go run main.go -h
# => This is an example program.
go run main.go hello Alice
# => Hello! My name is Alice!
go run main.go hello -target-name=Bob Alice
# => Hello, Bob! My name is Alice!
Examples
The example CLI applications are found in https://github.com/Jumpaku/cyamli/tree/main/examples .
Details
Supported programming languages
Only Go is supported currently.
Auto-generated help descriptions
cyamli can provide auto-generated simple or detail help descriptions for commands defined by the CLI schema.
The following functions generate help descriptions using cyamli as a Go library.
func showSimpleDescription(subcommand []string, writer io.Writer, inputErr error) {
schema := LoadSchema()
_ = description.DescribeCommand(
description.SimpleExecutor(),
description.CreateCommandData(schema.Program.Name, schema.Program.Version, subcommand, schema.Find(subcommand)),
writer,
)
}
func showDetailDescription(subcommand []string, writer io.Writer) {
schema := LoadSchema()
_ = description.DescribeCommand(
description.DetailExecutor(),
description.CreateCommandData(schema.Program.Name, schema.Program.Version, subcommand, schema.Find(subcommand)),
writer,
)
}
An example output for showSimpleDescription:
greet hello:
Prints "Hello, <target name>! My name is <greeter>!"
Usage:
$ greet hello [<option>|<argument>]... [-- [<argument>]...]
Options:
-target-name
Arguments:
<greeter>
An example output for showDetailDescription:
greet hello:
Prints "Hello, <target name>! My name is <greeter>!"
Usage:
$ greet hello [<option>|<argument>]... [-- [<argument>]...]
Options:
-target-name=<string>, -t=<string> (default=""):
The name of the person to be said hello.
Arguments:
[0] <greeter:string>
The name of the person who says hello.
Handling command line arguments
<program> <subcommand> [<option>|<argument>]... [-- [<argument>]...]
<program> is the path to your executable file.
<subcommand> is a sequence of tokens, which represents a path in the command tree illustrated in your CLI schema.
- Each element of
<subcommand> must match the regular expression ^[a-z][a-z0-9]*$.
<subcommand> may be empty, which means the execution of the root command.
<option> represents an option, which is a token in form of <option_name>[=<option_value>].
<option_name> must match the regular expression ^(-[a-z][a-z0-9]*)+$ (or ^-[a-z]$ in short version).
<option_value> must be a string that can be parsed as a value of the type of the option.
=<option_value> can be omitted if the type of the option is boolean.
<argument> represents an argument, which must be a string that can be parsed as a value of the type of the argument.
- Tokens after
-- are handled as arguments even if prefixed by -.