Committing before help rework
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
# CliGen::Command
|
||||
|
||||
## Overview
|
||||
The `CliGen::Command` class is used to hook into the macro system of crystal & to provide you macros that help cut down on boiler plate and allow the framework to check all of your provided values at compiletime to cut down on configuration issues at runtime.
|
||||
|
||||
|
||||
# SubTopics
|
||||
- [Macros](./Command/Macros.md)
|
||||
@@ -0,0 +1,173 @@
|
||||
# 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
|
||||
@@ -0,0 +1,55 @@
|
||||
# CliGen::Command Macros
|
||||
|
||||
## TOC
|
||||
- [Overview](#Overview)
|
||||
|
||||
## Overview
|
||||
This page is dedicated to discussing the macros associated & embedded in the `CliGen::Command` class.
|
||||
|
||||
|
||||
## Macros
|
||||
### argument
|
||||
This macro used in a Command subclass does one thing and well. It helps define an instance variable with valid annotation keys and helps debug any misconfigurations before you experience them via the compiler and/or during runtime.
|
||||
|
||||
```crystal
|
||||
require "cligen"
|
||||
|
||||
@[CliGen::CommandInfo(description: "Thing")]
|
||||
class MyClass << CliGen::Command
|
||||
argument(myvar : String = "abc",
|
||||
description: "This var changes the printed string",
|
||||
options: %w[ abc def ghi ]
|
||||
)
|
||||
|
||||
def main
|
||||
puts "Chosen string : %s" % @myvar
|
||||
end
|
||||
end
|
||||
```
|
||||
*Example: String Argument*
|
||||
|
||||
The above essentialy expands out to the following
|
||||
|
||||
```crystal
|
||||
require "cligen"
|
||||
|
||||
@[CliGen::CommandInfo(description: "Thing")]
|
||||
class MyClass << CliGen::Command
|
||||
|
||||
@[CliGen::Argument(description: "This var changes the printed string", options: %w[ abc def ghi ])]
|
||||
@myvar : String = "abc"
|
||||
|
||||
def main
|
||||
puts "Chosen string : %s" % @myvar
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
It simply provides you a user friendly "DSL" to define a (sometimes) extensive annotation that would be a PITA to do by hand.
|
||||
|
||||
However, the use of the macro has much more attributed to it than just doing this.
|
||||
|
||||
For a more detailed walkthrough & it's required keys go to the [argument macro doc](./Macro/argument.md).
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
# CliGen::CommandNode(T)
|
||||
@@ -0,0 +1,3 @@
|
||||
# CliGen::Flag(T)
|
||||
|
||||
## Overview
|
||||
@@ -0,0 +1,9 @@
|
||||
# CliGen Codebase
|
||||
|
||||
## Overview
|
||||
This codebase relies HEAVILY on crystal macros as a way to parse the AST to learn what is defined in order to generate the runtime objects to handle input parsing & command routing.
|
||||
|
||||
## Topics
|
||||
- [Command](./Command.md)
|
||||
- [CommandNode](./CommandNode.md)
|
||||
- [Flag](./Flag.md)
|
||||
Reference in New Issue
Block a user