Parser for command line arguments, keywords, options and environment variables
- Parse command line arguments, keywords, flags, options and environment variables.
- Define command line parameters with DSL or keyword arguments.
- Access all parameter values from hash-like params.
- Define global parameters with inheritance.
- Accept command line parameters in any order.
- Handle complex inputs like lists and maps.
- Convert inputs to basic and more complex object types.
- Generate help from parameter definitions.
- Customise help with usage methods such as header, example and more.
- Collect parsing errors for a better user experience.
Add this line to your application's Gemfile:
gem "tty-option"And then execute:
$ bundle install
Or install it yourself as:
$ gem install tty-option
- 1. Usage
- 2. API
Include the TTY::Option module and define parameters to parse command
line input.
Choose from arguments, keywords, flags, options and environment variables.
For example, here is a quick demo of how to create a command that mixes all parameter types:
class Command
include TTY::Option
usage do
program "dock"
command "run"
desc "Run a command in a new container"
example "Set working directory (-w)",
" $ dock run -w /path/to/dir/ ubuntu pwd"
example <<~EOS
Mount volume
$ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
EOS
end
argument :image do
required
desc "The name of the image to use"
end
argument :command do
optional
desc "The command to run inside the image"
end
keyword :restart do
default "no"
permit %w[no on-failure always unless-stopped]
desc "Restart policy to apply when a container exits"
end
flag :detach do
short "-d"
long "--detach"
desc "Run container in background and print container ID"
end
flag :help do
short "-h"
long "--help"
desc "Print usage"
end
option :name do
required
long "--name string"
desc "Assign a name to the container"
end
option :port do
arity one_or_more
short "-p"
long "--publish list"
convert :list
desc "Publish a container's port(s) to the host"
end
def run
if params[:help]
print help
elsif params.errors.any?
puts params.errors.summary
else
pp params.to_h
end
end
endThen create a command instance:
cmd = Command.newAnd given the following input on the command line:
restart=always -d -p 5000:3000 5001:8080 --name web ubuntu:16.4 bash
Read the command line input (aka ARGV) with parse:
cmd.parseOr provide an array of inputs:
cmd.parse(%w[restart=always -d -p 5000:3000 5001:8080 --name web ubuntu:16.4 bash])Finally, run the command to see parsed values:
cmd.run
# =>
# {:help=>false,
# :detach=>true,
# :port=>["5000:3000", "5001:8080"],
# :name=>"web",
# :restart=>"always",
# :image=>"ubuntu:16.4",
# :command=>"bash"}Use the params to access all parameters:
cmd.params[:name] # => "web"
cmd.params["command"] # => "bashGiven the --help flag on the command line:
cmd.parse(%w[--help])Use the help method to print help information to the terminal:
print cmd.helpThis will result in the following output:
Usage: dock run [OPTIONS] IMAGE [COMMAND] [RESTART=RESTART]
Run a command in a new container
Arguments:
IMAGE The name of the image to use
COMMAND The command to run inside the image
Keywords:
RESTART=RESTART Restart policy to apply when a container exits (permitted:
no, on-failure, always, unless-stopped) (default "no")
Options:
-d, --detach Run container in background and print container ID
-h, --help Print usage
--name string Assign a name to the container
-p, --publish list Publish a container's port(s) to the host
Examples:
Set working directory (-w)
$ dock run -w /path/to/dir/ ubuntu pwd
Mount volume
$ dock run -v `pwd`:`pwd` -w `pwd` ubuntu pwd
Given an invalid command line input:
cmd.parse(%w[--unknown])Use the errors method to print all errors:
puts params.errors.summaryThis will print a summary of all errors:
Errors:
1) Invalid option '--unknown'
2) Option '--publish' should appear at least 1 time but appeared 0 times
3) Option '--name' must be provided
4) Argument 'image' must be provided
Use the argument method to parse positional arguments.
Provide a name as a string or symbol to define an argument. The name will serve as a default label for the help display and a key to retrieve a value from the params:
argument :fooGiven the following command line input:
11 12 13
This would result only in one argument parsed and the remaining ignored:
params[:foo] # => "11"The argument method accepts a block to define
parameter settings.
For example, use the arity and convert settings to parse many positional arguments:
argument :foo do
name "foo(int)" # name for help display
arity one_or_more # how many times can appear
convert :int_list # convert input to a list of integers
validate ->(v) { v < 14 } # validation rule
desc "Argument description" # description for help display
endParser would collect all values and convert them to integers given previous input:
params[:foo] # => [11, 12, 13]The argument method can also accept settings as keyword arguments:
argument :foo,
name: "foo(int)",
arity: "+",
convert: :int_list,
validate: ->(v) { v < 14 },
desc: "Argument description"Use the keyword method to parse keyword arguments.
Provide a name as a string or symbol to define a keyword argument. The name will serve as a command line input name, a default label for the help display and a key to retrieve a value from the params:
keyword :fooParser will use the parameter name to match the input name on the command line by default.
Given the following command line input:
foo=11
This would result in:
params[:foo] # => "11"Note that the parser performs no conversion of the value.
The keyword method accepts a block to define
parameter settings.
For example, use the arity and convert settings to parse many keyword arguments:
keyword :foo do
required # by default keyword is not required
arity one_or_more # how many times can appear
convert :int_list # convert input to a list of integers
validate ->(v) { v < 14 } # validation rule
desc "Keyword description" # description for help display
endGiven the following command line input:
foo=10,11 foo=12 13
This would result in an array of integers:
params[:foo] # => [10, 11, 12, 13]The keyword method can also accept settings as keyword arguments:
keyword :foo,
required: true,
arity: :+,
convert: :int_list,
validate: ->(v) { v < 14 },
desc: "Keyword description"Use the flag or option methods to parse options.
Provide a name as a string or symbol to define an option. The name will serve as a command line input name, a label for the help display and a key to retrieve a value from the params:
option :fooParser will use the parameter name to generate a long option name by default.
Given the following command line input:
--foo
This would result in:
params[:foo] # => trueThe flag and option methods accept a block to define
parameter settings.
For example, to specify a different name for the parsed option, use the short and long settings:
option :foo do
short "-f" # define a short name
long "--foo" # define a long name
endGiven the following short name on the command line:
-f
This would result in:
params[:foo] # => true
An option can accept an argument. The argument can be either required
or optional. To define a required argument, provide an extra label
in short or long settings. The label can be any string. When
both short and long names are present, only specify an argument
for the long name.
For example, for both short and long names to accept a required integer argument:
option :foo do
short "-f"
long "--foo int"
# or
long "--foo=int"
endGiven the following command line input:
--foo=11
This would result in:
params[:foo] # => "11"Note that the parser performs no conversion of the argument.
To define an optional argument, surround it with square brackets.
For example, to accept an optional integer argument:
option :foo do
long "--foo [int]"
endUse the arity and convert settings to parse many options given as a list of integers:
option :foo do
required # by default option is not required
arity one_or_more # how many times option can appear
short "-f" # declare a short flag name
long "--foo ints" # declare a long flag with a required argument
convert :int_list # convert input to a list of integers
validate ->(v) { v < 14 } # validation rule
desc "Option description" # description for help display
endGiven the following command line input:
--foo=10,11 -f 12 13
This would result in an array of integers:
params[:foo] # => [10, 11, 12, 13]The option method can also accept settings as keyword arguments:
option :foo,
required: true,
arity: :+,
short: "-f",
long: "--foo ints",
convert: :int_list,
validate: -> { |v| v < 14 },
desc: "Option description"There is a convenience flag method to specify a command line option that
accepts no argument:
flag :fooFor example, a typical scenario is to specify the help flag:
flag :help do
short "-h"
long "--help"
desc "Print usage"
endUse the environment or env methods to parse environment variables.
Provide a name as a string or symbol to define an environment variable. The name will serve as a command line input name, a default label for the help display and a key to retrieve a value from the params:
environment :foo
# or
env :fooParser will use the parameter name to match the input name on the command line by default.
Given the following command line input:
FOO=11
The result would be:
params[:foo] # => "11"Note that the parser performs no conversion of the value.
The environment method accepts a block to define
parameter settings.
For example, use the name setting to change a default variable name:
environment :foo do
name "FOO_ENV"
endGiven the following command line input:
FOO_ENV=11
This would result in:
params[:foo] # => "11"For example, use the arity and convert settings to parse many environment variables given as a list of integers:
environment :foo do
required # by default environment is not required
arity one_or_more # how many times env var can appear
name "FOO_ENV" # the command line input name
convert :int_list # convert input to a map of integers
validate ->(v) { v < 14 } # validation rule
desc "Environment description" # description for help display
endGiven the following command line input:
FOO_ENV=10,11 FOO_ENV=12 13
This would result in an array of integers:
params[:foo] # => [10, 11, 12, 13]The environment method can also accept settings as keyword arguments:
environment :foo,
required: true,
arity: :+,
name: "FOO_ENV",
convert: :int_list,
validate: ->(v) { v < 14 },
desc: "Environment description"All parameter types support the following settings except for
short and long, which are option specific.
Use the arity setting to describe how many times a given parameter may
appear on the command line.
Every parameter can appear only once by default. In the case of arguments, the parser will match the first input and ignore the rest. For other parameter types, any extra parameter occurrence will override previously parsed input. Setting the arity requirement overrides this behaviour.
For example, to match an argument exactly two times:
argument :foo do
arity 2
endGiven the following command line input:
bar bazThis would result in an array of strings:
params[:foo] # => ["bar", "baz"]Another example is to match exactly three occurrences of a keyword:
keyword :foo do
arity 3
endAnd then given the following on the command line:
foo=1 foo=2 foo=3
This would result in an array of strings:
params[:foo] # => ["1", "2", "3"]Use :any, :*, -1, any or zero_or_more to specify that parameter
may appear any number of times.
For example, to expect an argument to appear zero or more times:
argument :foo do
arity zero_or_more
endUse :+ or one_or_more to specify that parameter must appear at least once.
For example, to expect an option with an argument to appear one or more times:
option :foo do
arity one_or_more
short "-f"
long "--foo string"
endUse at_least to specify the least number of times a parameter can appear:
For example, to expect a keyword to appear at least three times:
keyword :foo do
arity at_least(3)
endThe help method will handle the arity for the usage banner.
For example, given the following argument definition:
argument :foo do
arity one_or_more
endThe usage banner would display:
Usage: foobar FOO [FOO...]
Use the convert setting to transform any parameter argument to another type.
The convert accepts a conversion name as a predefined symbol or class.
For example, to convert an argument to an integer:
argument :foo do
convert :int
# or
convert Integer
endThe supported conversion types are:
:boolor:boolean- e.g.yes,1,y,tbecomestrue,no,0,n,fbecomesfalse:date- e.g.28/03/2020becomes#<Date: 2020-03-28...>:float- e.g.-1becomes-1.0:intor:integer- e.g.+1becomes1:pathor:pathname- e.g./foo/bar/bazbecomes#<Pathname:/foo/bar/baz>:regexor:regexp- e.g.foo|barbecomes/foo|bar/:uri- e.g.foo.combecomes#<URI::Generic foo.com>:symor:symbol- e.g.foobecomes:foo:listor:array- e.g.a,b,cbecomes["a", "b", "c"]:mapor:hash- e.g.a:1 b:2 c:3becomes{a: "1", b: "2", c: "3"}
To convert to an array of a given type, specify plural or append an array
orlist to any base type:
:bools,:bool_arrayor:bool_list- e.g.t,f,tbecomes[true, false, true]:floats,:float_arrayor:float_list- e.g.1,2,3becomes[1.0, 2.0, 3.0]:ints,:int_arrayor:int_list- e.g.1,2,3becomes[1, 2, 3]
Or, use the list_of method and pass the type as a first argument.
To convert to a hash with values of a given type, append a hash or map to
any base type:
:bool_hashor:bool_map- e.ga:t b:f c:tbecomes{a: true, b: false, c: true}:float_hashor:float_map- e.ga:1 b:2 c:3becomes{a: 1.0, b: 2.0, c: 3.0}:int_hashor:int_map- e.ga:1 b:2 c:3becomes{a: 1, b: 2, c: 3}
Or, use the map_of method and pass the type as a first argument.
For example, given options with a required list and map arguments:
option :foo do
long "--foo list"
convert :bools
# or
convert list_of(:bool)
end
option :bar do
long "--bar map"
convert :int_map
# or
convert map_of(:int)
endAnd then parsing the following command line input:
--foo t,f,t --bar a:1 b:2 c:3
This would result in an array of booleans and a hash with integer values:
params[:foo] # => [true, false, true]
params[:bar] # => {:a=>1, :b=>2, :c=>3}Use a Proc object to define custom conversion.
For example, to convert the command line input to uppercase:
option :foo do
long "--foo string"
convert ->(val) { val.upcase }
endUse the default setting to specify a default value for an optional parameter.
The parser will use default when the command line input isn't present.
For example, given the following option definition:
option :foo do
long "--foo string"
default "bar"
endWhen the option --foo isn't present on the command line, the params
will have a default value set:
params[:foo] # => "bar"Or, use a Proc object to specify a default value:
option :foo do
long "--foo string"
default -> { "bar" }
endA parameter cannot be both required and have a default value. This will raise
ConfigurationError. The parser treats positional arguments as required.
To have a default for a required argument make it optional:
argument :foo do
optional
default "bar"
desc "Argument description"
endThe usage description for a given parameter will display the default value:
Usage: foobar [FOO]
Arguments:
FOO Argument description (default "bar")
Use the description or desc setting to provide a summary for
a parameter. The help method uses a parameter
description to generate a usage display.
For example, given an option with a description:
option :foo do
desc "Option description"
endThis will result in the following help display:
Usage: foobar [OPTIONS]
Options:
--foo Option description
2.5.5 hidden
Use the hidden setting to hide a parameter from the help display.
For example, given a standard argument and a hidden one:
argument :foo
argument :bar do
hidden
endThe above will hide the :bar parameter from the usage banner:
Usage: foobar FOO
Only flag and option parameters can use
the long setting.
Use the long setting to define a long name for an option. By convention,
a long name uses a double dash followed by many characters.
When you don't specify a short or long name, the parameter name will serve as the option's long name by default.
For example, to define the --foo option:
option :fooTo change the default name to the --fuu option:
option :foo do
long "--fuu"
endA long option can accept an argument. The argument can be either required or optional. To define a required argument, separate it from the option name with a space or an equal sign.
For the :foo option to accept a required integer argument:
option :foo do
long "--foo int"
endThese are all equivalent ways to define a long option with a required argument:
long "--foo int"
long "--foo=int"To define an optional argument, surround it with square brackets. Like the required argument, separate it from the option name with a space or an equal sign. It is possible to skip the space, but that would make the option description hard to read.
For the :foo option to accept an optional integer argument:
option :foo do
long "--foo [int]"
endThese are all equivalent ways to define a long option with an optional argument:
long "--foo [int]"
long "--foo=[int]"
long "--foo[int]"When specifying short and long option names, only define the argument for the long name.
For example, to define an option with short and long names that accepts a required integer argument:
option :foo do
short "-f"
long "--foo int"
endNote that the parser performs no conversion of the argument. Use the convert setting to transform the argument type.
The parser will use a parameter name to match command line inputs by default. It will convert underscores in a name into dashes when matching input.
For example, given the :foo_bar keyword definition:
keyword :foo_barAnd the following command line input:
foo-bar=baz
This would result in:
params[:foo_bar] # => "baz"Use the name setting to change the parameter default input name.
keyword :foo_bar do
name "fum"
endGiven the following command line input:
fum=baz
This would result in:
params[:foo_bar] # => "baz"Use uppercase characters when changing the input name for environment variables:
env :foo do
name "FOO_VAR"
endAll parameters are optional apart from positional arguments.
Use the optional setting to mark a parameter as optional.
For example, given a required argument and an optional one:
argument :foo do
desc "Foo argument description"
end
argument :bar do
optional
desc "Bar argument description"
endAnd given the following command line input:
baz
This would result in:
params[:foo] # => "baz"
params[:bar] # => nilThe usage banner will display an optional argument surrounded by brackets:
Usage: foobar FOO [BAR]
Arguments:
FOO Foo argument description
BAR Bar argument description
Use the permit setting to restrict input to a set of possible values.
For example, to restrict the :foo option to only "bar" and "baz" strings:
option :foo do
long "--foo string"
permit %w[bar baz]
endGiven the following command line input:
--foo bar
This would result in:
params[:foo] # => "bar"Given not permitted value qux on the command line:
--foo qux
This would raise a TTY::Option::UnpermittedArgument error and
make the params invalid.
The parser checks permitted values after applying conversion first. Because of this, permit setting needs its values to be already of the correct type.
For example, given integer conversion, permitted values need to be integers as well:
option :foo do
long "--foo int"
convert :int
permit [11, 12, 13]
endThen given not permitted integer:
--foo 14
This would invalidate params and collect the
TTY::Option::UnpermittedArgument error.
The help method displays permitted values in the parameter description.
For example, given the following option:
option :foo do
short "-f"
long "--foo string"
permit %w[a b c d]
desc "Option description"
endThen the description for the option would be:
Usage: foobar [OPTIONS]
Options:
-f, --foo string Option description (permitted: a, b, c, d)
Parser only requires arguments to be present on the command line by default. Any other parameters like options, keywords and environment variables are optional.
Use the required setting to force parameter presence in command line input.
For example, given a required keyword and an optional one:
keyword :foo do
required
desc "Foo keyword description"
end
keyword :bar do
desc "Bar keyword description"
endAnd given the following command line input:
foo=baz
This would result in:
params[:foo] # => "baz"
params[:bar] # => nilGiven the following command line input without the foo keyword:
bar=baz
This would raise a TTY::Option::MissingParameter error.
Then printing errors summary would display the following error description:
Error: keyword 'foo' must be provided
The usage banner displays the required parameters first. Then surrounds any optional parameters in brackets.
The help display for the above keywords would be:
Usage: foobar FOO=FOO [BAR=BAR]
Keywords:
FOO=FOO Foo keyword description
BAR=BAR Bar keyword description
Only flag and option parameters can use
the short setting.
Use the short setting to define a short name for an option. By convention,
a short name uses a single dash followed by a single alphanumeric character.
For example, to define the -f option:
option :foo do
short "-f"
endA short option can accept an argument. The argument can be either required or optional. To define a required argument, separate it from the option name with a space or an equal sign. It is possible to skip the space, but that would make the option description hard to read.
For the :foo option to accept a required integer argument:
option :foo do
short "-f int"
endThese are all equivalent ways to define a short option with a required argument:
short "-f int"
short "-f=int"
short "-fint"To define an optional argument, surround it with square brackets. Like the required argument, separate it from the option name with a space or an equal sign. It is possible to skip the space, but that would make the option description hard to read.
For the :foo option to accept an optional integer argument:
option :foo do
short "-f [int]"
endThese are all equivalent ways to define a short option with an optional argument:
short "-f [int]"
short "-f=[int]"
short "-f[int]"When specifying short and long option names, only define the argument for the long name.
For example, to define an option with short and long names that accepts a required integer argument:
option :foo do
short "-f"
long "--foo int"
endNote that the parser performs no conversion of the argument. Use the convert setting to transform the argument type.
Use the validate setting to ensure that inputs match a validation rule.
The rule can be a string, a regular expression or a Proc object.
For example, to ensure the --foo option only accepts digits:
option :foo do
long "--foo int"
validate "\d+"
endGiven the following command line input:
--foo bar
This would raise a TTY::Option::InvalidArgument error that would
make params invalid.
Then printing errors summary would output:
Error: value of `bar` fails validation for '--foo' option
To define a validation rule as a Proc object that accepts
an argument to check:
keyword :foo do
convert :int
validate ->(val) { val < 12 }
endThe parser validates a value after applying conversion first. Because of this, the value inside a validation rule is already of the correct type.
Given the following command line input:
foo=13
This would raise a TTY::Option::InvalidArgument error and make
params invalid.
Then using the errors summary would print the following error:
Error: value of `13` fails validation for 'foo' keyword
Use the parse method to match command line inputs against defined parameters.
The parse method reads the input from the command line (aka ARGV) and
the environment variables (aka ENV) by default. It also accepts inputs
as an argument. This is useful when testing commands.
For example, given the following parameter definitions:
argument :foo
flag :bar
keyword :baz
env :quxThen parsing the command line inputs:
parse(%w[12 --bar baz=a QUX=b])This would result in:
params[:foo] # => "12"
params[:bar] # => true
params[:baz] # => "a"
params[:qux] # => "b"The parser doesn't force any order for the parameters except for arguments.
For example, reordering inputs for the previous parameter definitions:
parse(%w[12 QUX=b --bar baz=a])This would result in the same values:
params[:foo] # => "12"
params[:bar] # => true
params[:baz] # => "a"
params[:qux] # => "b"The parser handles compact shorthand options that start with a single dash. These must be boolean options except for the last one that can accept an argument.
For example, passing three flags and an option with an argument to parse:
parse(%w[-f -b -q -s 12])
This is equivalent to parsing:
parse(%w[-fbqs 12])
Parameter parsing stops at the -- terminator. The parser collects leftover
inputs and makes them accessible with the remaining method.
For example, given extra input after the terminator:
parse(%w[12 baz=a QUX=b -- --fum])This would result in:
params[:foo] # => 12
params[:bar] # => false
params[:baz] # => "a"
params[:qux] # => "b"
params.remaining # => ["--fum"]The parse method doesn't raise any errors by default. Why? Displaying
error backtraces in the terminal output may not be helpful for users.
Instead, the parser collects any errors and exposes them through the
errors method.
Use the :raise_on_parse_error keyword set to true to raise parsing errors:
parse(raise_on_parse_error: true)Parsing errors inherit from TTY::Option::ParseError.
For example, to catch parsing errors:
begin
parse(raise_on_parse_error: true)
rescue TTY::Option::ParseError => err
...
endUsers can provide any input, including parameters the parser didn't expect and define.
When the parser finds an unknown input on the command line, it raises
a TTY::Option::InvalidParameter error and adds it to the
errors array.
Use the :check_invalid_params keyword set to false to ignore unknown
inputs during parsing:
parse(check_invalid_params: false)This way, the parser will collect all the unrecognised inputs into the remaining array.
All defined parameters are accessible from the params object.
The params object behaves like a hash with indifferent access. It doesn't
differentiate between arguments, keywords, options or environment variables.
Because of that, each parameter needs to have a unique name.
For example, given a command with all parameter types:
class Command
include TTY::Option
argument :foo
keyword :bar
option :baz do
long "--baz string"
end
env :qux
def run
print params[:foo]
print params["bar"]
print params["baz"]
print params[:qux]
end
endAnd the following command line input:
a bar=b --baz c QUX=d
Then instantiating the command:
cmd = Command.newAnd parsing command line input:
cmd.parseAnd running the command:
cmd.runThis would result in the following output:
abcd
The parse method only raises configuration errors. The parsing errors are
not raised by default. Instead, the errors method on the params object
gives access to any parsing error.
params.errors # => TTY::Option::AggregateErrorsThe errors method returns an TTY::Option::AggregateErrors object that
is an Enumerable.
For example, to iterate over all the errors:
params.errors.each do |error|
...
endThe TTY::Option::AggregateErrors object has the following
convenience methods:
messages- an array of all error messagessummary- a string of formatted error messages ready to display in the terminal
For example, given an argument that needs to appear at least two times in the command line input:
argument :foo do
arity at_least(2)
endAnd parsing only one argument from the command line input:
parse(%w[12])Then printing errors summary:
puts params.errors.summaryThis would print the following error message:
Error: argument 'foo' should appear at least 2 times but appeared 1 time
Adding integer conversion to the previous example:
argument :foo do
arity at_least(2)
convert :int
endAnd given only one invalid argument to parse:
parse(%w[zzz])The summary would be:
Errors:
1) Argument 'foo' should appear at least 2 times but appeared 1 time
2) Cannot convert value of `zzz` into 'int' type for 'foo' argument
Use the :raise_on_parse_error keyword to raise parsing errors on invalid input.
Consider using the tty-exit gem for more expressive exit code reporting.
For example, the TTY::Exit module provides the exit_with method:
class Command
include TTY::Exit
include TTY::Option
def run
if params.errors.any?
exit_with(:usage_error, params.errors.summary)
end
...
end
endWhen the parser finds an unknown input on the command line, it raises
a TTY::Option::InvalidParameter error and adds it to the
errors array.
Use the :check_invalid_params keyword
set to false to ignore unknown inputs during parsing:
parse(check_invalid_params: false)This way, the parser will collect all the unrecognised inputs
into an array. The remaining method on the params gives access
to all invalid inputs.
For example, given an unknown option to parse:
parse(%w[--unknown])Then inspecting the remaining inputs:
params.remaining # => ["--unknown"]The parser leaves any inputs after the -- terminator alone. Instead,
it collects them into the remaining array. This is useful when passing
inputs over to other command line applications.
Use the valid? method to check that command line inputs meet all
validation rules.
The valid? method is available on the params object:
params.valid? # => trueUse the errors method to check for any errors and not only validation rules:
params.errors.any?The usage method accepts a block that configures the
help display.
Use the header setting to display information above the banner.
For example, to explain a program's purpose:
usage do
header "A command line interface for foo service"
endThis would print:
A command line interface for foo service
Usage: foo [OPTIONS]
The header setting accepts many arguments, each representing a single
paragraph. An empty string displays as a new line.
For example, to create an introduction with two paragraphs separated by an empty line:
usage do
header "A command line interface for foo service",
"",
"Access and retrieve data from foo service"
endOr, add two paragraphs using the header setting twice:
usage do
header "A command line interface for foo service"
header "Access and retrieve data from foo service"
endBoth would result in the same output:
A command line interface for foo service
Access and retrieve data from foo service
Usage: foo [OPTIONS]
The program setting uses an executable file name to generate a program
name by default.
For example, to override the default name:
usage do
program "custom-name"
endThen usage banner will display a custom program name:
Usage: custom-name
The command setting uses a class name to generate a command name by default.
It converts a class name into a dash case.
For example, given the following command class name:
class NetworkCreate
include TTY::Option
endThe command name would become network-create.
Use the command or commands setting to change the default command name.
For example, to change the previous class's default command name:
class NetworkCreate
include TTY::Option
usage do
command "net-create"
end
endThe usage banner would be:
Usage: program net-create
Use the commands setting for naming a subcommand.
For example, to add create command as a subcommand:
module Network
class Create
include TTY::Option
usage do
commands "network", "create"
end
end
endThis will result in the following usage banner:
Usage: program network create
Use the no_command setting to skip having a command name:
usage do
no_command
endThis will display only the program name:
Usage: program
The banner setting combines program, command and parameter names
to generate usage banner.
For example, given the following usage and parameter definitions:
usage do
program "prog"
command "cmd"
end
argument :foo
keyword :bar
option :baz
env :quxThen usage banner would print as follows:
Usage: prog cmd [OPTIONS] [ENVIRONMENT] FOO [BAR=BAR]
The help generator displays the usage banner first unless a header is set.
Use the banner setting to create a custom usage display.
For example, to change the parameters format:
usage do
program "prog"
command "cmd"
banner "Usage: #{program} #{command.first} <opts> <envs> foo [bar=bar]"
endThis would display as:
Usage: prog cmd <opts> <envs> foo [bar=bar]
Use the :param_display setting to change the banner parameters format.
Use description or desc setting to display information right after
the usage banner.
For example, to give extra information:
usage do
desc "A description for foo service"
endThis would print:
Usage: foo [OPTIONS]
A description for foo service
The desc setting accepts many arguments, each representing a single
paragraph. An empty string displays as a new line.
For example, to create a description with two paragraphs separated by an empty line:
usage do
desc "A description for foo service",
"",
"Learn more about foo service\nby reading tutorials"
endOr, add two paragraphs using the desc setting twice:
usage do
desc "A description for foo service",
desc <<~EOS
Learn more about foo service
by reading tutorials
EOS
endBoth would result in the same output:
Usage: foo [OPTIONS]
A description for foo service
Learn more about foo service
by reading tutorials
Use the example or examples setting to add a usage examples section
to the help display.
The example setting accepts many arguments, each representing a single
paragraph. An empty string displays as a new line.
For instance, to create an example usage displayed on two lines:
usage do
example "Some example how to use foo",
" $ foo bar"
endThis will result in the following help output:
Examples:
Some example how to use foo
$ foo bar
Or, add two examples using the example setting twice:
usage do
example "Some example how to use foo",
" $ foo bar"
example <<~EOS
Another example how to use foo"
$ foo baz
EOS
endThe examples section would display the following:
Examples:
Some example how to use foo
$ foo bar
Another example how to use foo
$ foo baz
Use the footer setting to display text after all information
in the usage help.
For example, to reference further help:
usage do
footer "Run a command followed by --help to see more info."
endThis would print as follows:
Usage: foo [OPTIONS]
Run a command followed by --help to see more info.
The footer setting accepts many arguments, each representing a single
paragraph. An empty string displays as a new line.
For example, to display further help with two paragraphs separated by an empty line:
usage do
footer "Run a command followed by --help to see more info.",
"",
"Report bugs to the mailing list."
endOr, add two paragraphs using the footer setting twice:
usage do
footer "Run a command followed by --help to see more info."
footer "Report bugs to the mailing list."
endBoth would result in the same output:
Usage: foo [OPTIONS]
Run a command followed by --help to see more info.
Report bugs to the mailing list.
Use the help method to generate usage information about defined parameters.
The usage describes how to add different sections to the help display.
For example, given the following command class definition with
a run method that prints help:
class Command
include TTY::Option
usage do
program "foobar"
no_command
header "foobar CLI"
desc "CLI description"
example "Example usage"
footer "Run --help to see more info"
end
argument :foo, desc: "Argument description"
keyword :bar, desc: "Keyword description"
option :baz, desc: "Option description"
env :qux, desc: "Environment description"
flag :help do
short "-h"
long "--help"
desc "Print usage"
end
def run
if params[:help]
print help
exit
end
end
endRunning the command with --help flag:
cmd = Command.new
cmd.parse(%w[--help])
cmd.runThis would result in the following help display:
foobar CLI
Usage: foobar [OPTIONS] [ENVIRONMENT] FOO [BAR=BAR]
CLI description
Arguments:
FOO Argument description
Keywords:
BAR=BAR Keyword description
Options:
--baz Option description
-h, --help Print usage
Environment:
QUX Environment description
Examples:
Example usage
Run --help to see more info
Pass a block to the help method to change generated usage information.
The block accepts a single argument, a TTY::Option::Sections object.
This object provides hash-like access to each named part of the help display.
The following are the names of all supported sections ordered by help display from top to bottom:
:header:banner:description:arguments:keywords:options:environments:examples:footer
Accessing a named section returns a TTY::Option::Section object
with name and content methods.
For example, to access the arguments section content:
help do |sections|
sections[:arguments].content # => "\nArguments:\n FOO Argument description"
endTo add a new section, use the add_after and add_before methods. These
methods accept three arguments. The first argument is the section name
to add after or before. The second argument is a new section name,
and the last is content to add.
For example, to insert a new commands section after the description:
help do |sections|
sections.add_after :description, :commands, <<~EOS.chomp
Commands:
create Create command description
delete Delete command description
EOS
endGiven the following usage and parameter definition:
usage do
program "prog"
command "cmd"
desc "Program description"
end
argument :foo do
desc "Foo argument description"
endThe help display would be:
Usage: prog cmd FOO
Program description
Commands:
create Create command description
delete Delete command description
Arguments:
FOO Argument description
Use delete and replace methods to change existing sections.
For example, to remove a header section:
help do |sections|
sections.delete :header
endOr, to replace the content of a footer section:
help do |sections|
sections.replace :footer, "\nReport bugs to the mailing list."
endThe help output has no indentation except for displaying parameters by default.
Use the :indent keyword to change the indentation of the help display.
For example, to indent help display by two spaces:
help(indent: 2)The help generator orders parameters alphabetically within each section by default.
Use the :order keyword to change the default ordering.
The :order expects a Proc object as a value. The Proc accepts
a single argument, an array of parameters within a section.
For example, to preserve the parameter definition order:
help(order: ->(params) { params })The usage banner displays positional and keyword arguments in uppercase letters by default.
For example, given the following parameter definitions:
usage do
program "prog"
end
argument :foo, desc: "Argument description"
keyword :bar, desc: "Keyword description"
option :baz, desc: "Option description"
env :qux, desc: "Environment description"The usage banner would print as follows:
Usage: prog [OPTIONS] [ENVIRONMENT] FOO [BAR=BAR]
Use the :param_display keyword to change the banner parameter formatting.
The :param_display expects a Proc object as a value. The Proc accepts
a single argument, a parameter name within a section.
For example, to lowercase and surround parameters with < and > brackets:
help(param_display: ->(param) { "<#{param.downcase}>" })This would result in the following usage banner and parameter sections:
Usage: prog [<options>] [<environment>] <foo> [<bar>=<bar>]
Arguments:
<foo> Argument description
Keywords:
<bar>=<bar> Keyword description
Options:
--baz Option description
Environment:
QUX Environment description
The help generator wraps content at the width of 80 columns by default.
Use the :width keyword to change it, for example, to 120 columns:
help(width: 120)Use the tty-screen gem to change the help display based on terminal width.
For example, to expand the help display to the full width of the terminal window:
help(width: TTY::Screen.width)After checking out the repo, run bin/setup to install dependencies.
Then, run rake spec to run the tests. You can also run bin/console
for an interactive prompt that will allow you to experiment.
To install this gem onto your local machine, run bundle exec rake install.
To release a new version, update the version number in version.rb, and then
run bundle exec rake release, which will create a git tag for the version,
push git commits and tags, and push the .gem file to
rubygems.org.
Bug reports and pull requests are welcome on GitHub at https://github.com/piotrmurach/tty-option. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the code of conduct.
The gem is available as open source under the terms of the MIT License.
Everyone interacting in the TTY::Option project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the code of conduct.
Copyright (c) 2020 Piotr Murach. See LICENSE for further details.
