174 lines
5.1 KiB
Markdown
174 lines
5.1 KiB
Markdown
# CliGen::Command.argument Macro
|
|
|
|
## TOC
|
|
- [Overview](#Overview)
|
|
|
|
## Overview
|
|
This macro as explained briefly in the [Macros Doc](../Macros.md), handles setting up and configuring instance variables & configuring instance variables & annotations as well as checking for misconfigurations in your provided macro arguments before you experience.
|
|
|
|
Overall this is used for annotating instance variables for the CliGen framework can know how to create your [CliGen::Flag(T)][flag-doc] objects.
|
|
|
|
```crystal
|
|
class MyCmd < CliGen::Command
|
|
argument(myvar : String = "test",
|
|
short: "-m",
|
|
long: "--myvar",
|
|
description: "This is my test flag",
|
|
options: %w[ test test2 test3 ]
|
|
)
|
|
|
|
def main
|
|
puts "@myvar was #{@myvar}"
|
|
end
|
|
end
|
|
```
|
|
|
|
## Caveots
|
|
### Dedicated short & long flasg
|
|
A unfortunate limitation is that the `-h|--help` & `-v|--verbose` flags are all allocated to two internal flags used by all [CommandNode(T)][commandnode-doc] objects
|
|
|
|
### Duplicate Short Flags
|
|
While this is limited to Flags defined in your Command
|
|
|
|
## Arguments
|
|
### short:
|
|
**Type:** StringLiteral
|
|
**Required:** false
|
|
|
|
This represents the short form of the flag bring provided. it is optional as
|
|
not all flags have to have a short form flag.
|
|
|
|
### long:
|
|
**Type:** StringLiteral
|
|
**Required:** true*
|
|
|
|
This represents the long-form of the flag. It is required in order to generate
|
|
the [Flag(T)][flag-doc].
|
|
|
|
### description:
|
|
Type: StringLiteral
|
|
Required: true
|
|
|
|
This is the description of your flag and is required for `Flag(T)` creation
|
|
|
|
### delimiter:
|
|
**Type:** StringLiteral
|
|
**Required:** false
|
|
|
|
For [Flag][flag-doc](Array(T)) flags this is the delimiter that will seperate any inline args (ex: "," will split "a,b,c") provided at the commandline. If nil/not provided, the framework will default to ',' as this is the usual choice.
|
|
|
|
### env_var:
|
|
**Type:** StringLiteral
|
|
**Required:** false
|
|
|
|
This is the ENV VAR that can be used to specify your flag value when not
|
|
provided by the user.
|
|
|
|
### validation:
|
|
**Type:** ProcLiteral
|
|
**Required:** false
|
|
|
|
This is a proc that can be used to provide an ad-hoc way of verifying the
|
|
value provided by a user.
|
|
|
|
```crystal
|
|
validation: ->(i : Int32) : Bool do
|
|
(1..23).includes?(i)
|
|
end
|
|
```
|
|
*Example: Int Validator*
|
|
|
|
This is used as a fallback to where the options: key doesn't cleanly
|
|
provide enough of a check for the provided values.
|
|
|
|
Note:
|
|
The input value MUST be the same as the value type as the instance
|
|
variable. Otherwise CliGen will not compile. IF requested I can
|
|
add a raw_validation: key as well to do the same but for just the
|
|
String variable provided by the user.
|
|
|
|
### on_match:
|
|
**Type:** ProcLiteral
|
|
**Required:** false
|
|
|
|
Much like validation, this is used as a hook for doing arbitrary actions
|
|
with the parsed value from the user (very useful for global flags).
|
|
|
|
```crystal
|
|
on_match: ->(arg : String) do
|
|
begin
|
|
::Log.setup(level: ::Log::Severity.parse(arg))
|
|
rescue e : ArgumentError
|
|
STDERR.puts "ERROR : Failed to set to #{arg} log level: (#{e.class}: #{e.message})"
|
|
end
|
|
end
|
|
```
|
|
*Example: Log level setter*
|
|
|
|
NOTE: This specific example will be reworked once Enum support is added to the framework to do checking directly.
|
|
|
|
In this way you can use on_match: to hook a global flag and have it call some
|
|
arbitrary method elsewhere in the codebase to help setup the environment
|
|
before the main command is run.
|
|
|
|
### options:
|
|
**Type:** ArrayLiteral(T)|Call
|
|
**Required:** false
|
|
|
|
CURRENTLY this is being as a way of providing a static set of values that we
|
|
are to use when doing a provided argument.
|
|
|
|
```crystal
|
|
options: %w[ a b c ]
|
|
```
|
|
*Example: Options for string var*
|
|
|
|
Howver, this currently also supports delegating the retrieval of values (in array format) to be learned at runtime by providing a call to a global methods/class method/util method/etc
|
|
|
|
```crystal
|
|
module MyModule
|
|
def self.my_method : Array(String)
|
|
if File.exists?("/etc/valid_things.txt")
|
|
File.read("/etc/valid_things.txt").split(",")
|
|
else
|
|
%w[ a b c ]
|
|
end
|
|
end
|
|
|
|
CliGen.add_global_flag(String,
|
|
short: "-t",
|
|
long: "--test",
|
|
description: "This does things. I promise",
|
|
options: ::MyModule.my_method,
|
|
on_match: ->(t : String) do
|
|
puts "Matched #{t}"
|
|
end
|
|
)
|
|
end
|
|
```
|
|
*Example: Deletgating to runtime*
|
|
|
|
Doing things this way gives you some runtime flexibility, but makes you
|
|
responsible for ensuring that it doesn't crash or provide incorrect data
|
|
at runtime. As (unfortunately) the framework doesn't account for developer
|
|
error at runtime like it can at compile-time with a static array of
|
|
values.
|
|
|
|
### format:
|
|
**Type:** RegexLiteral
|
|
**Required:** false
|
|
|
|
This metadata is used to provide (mostly for strings when you don't have a
|
|
statically known list of values that can be provided at runtime, but you
|
|
want to filter out invalid options.
|
|
|
|
```crystal
|
|
format: /^([a-z0-9]+)(,?[a-z0-9]+)+$/
|
|
```
|
|
EX: filtering for csv formatted info
|
|
|
|
|
|
[command-doc]: ../../Command.md
|
|
[flag-doc]: ../../Flag.md
|
|
[commandnode-doc]: ../../CommandNode.md
|