Added new macro features. resolve_value + default: key. Added raises to prevent CliGen features from being used outside of a already parsed state, and worked on specs. Will be working on specs later on as well to finish covering regex & redo timeparse & relative_operations
This commit is contained in:
1 parent
3fa77f5707
commit
8fab6912fc
89 files changed
+3609
-509
No files matched your search
@@ -42,10 +42,19 @@ this project's own test programs.
|
||||
Compile-time flow, in order:
|
||||
|
||||
1. `Command.inherited` installs a `macro finished` hook on each subclass, which calls
|
||||
`define_command_initializer` (and `def_init` when `@[CommandInfo(def_init: true)]`).
|
||||
2. `CliGen::App`'s `macro finished` (in `app/generate.cr`) walks `CliGen::Command.subclasses`
|
||||
and emits `App.generate`, which constructs the runtime `Flag(T)` / `CommandNode(T)` object tree.
|
||||
3. At runtime `App.process` lazily calls `generate`, then walks `ARGV`.
|
||||
`validate_command_tree`, `define_command_initializer`, `generate_gather_handler`,
|
||||
`generate_register_command`, `generate_gather_handler` (and `define_singleton_init`
|
||||
when `@[CommandInfo(singleton_init: true)]`).
|
||||
2. Each subclass therefore gets its own `self.register_command(array, parent:)` that
|
||||
builds *its* `CommandNode(T)` + `Flag(T)` objects and recurses into its children.
|
||||
3. `CliGen::App`'s `macro finished` (in `app/generate.cr`) selects the **root** commands —
|
||||
those whose `@[CommandInfo]` has no `parent:` — and calls `register_command` on each.
|
||||
4. At runtime `App.process` lazily calls `generate`, then walks `ARGV`.
|
||||
|
||||
Nesting is expressed by **annotation, not inheritance**: a subcommand subclasses
|
||||
`CliGen::Command` directly and names its parent via `@[CommandInfo(parent: Other)]`.
|
||||
Subclassing a `Command` instead would give it subclasses, which turns `T` into the
|
||||
virtual type `T+` and makes `T.has_constant?`/`T.methods` fail with a compiler BUG.
|
||||
|
||||
### Entry point: `src/cligen.cr`
|
||||
|
||||
@@ -137,12 +146,23 @@ derived as `long.gsub(/--/,"").gsub(/-/,"_").upcase`. Both macros reject an expl
|
||||
|
||||
Run at the top of every `process`, so misconfiguration fails on first invocation:
|
||||
|
||||
- `Flag#check!` — rejects `-h` / `--help` (`ReservedFlagError`).
|
||||
- **Compile time** — `check_flag_vars` validates every declaration (both `argument` and
|
||||
`add_global_flag` route through it); `validate_command_tree` rejects a missing
|
||||
`@[CommandInfo]`, a self-parent, and `parent:` cycles.
|
||||
- **Load time** — `add_global_flag` constructs the flag, then checks `GLOBAL_FLAGS` for a
|
||||
`long_key`/`short` collision and `abort`s with `__FILE__:__LINE__` of the call site.
|
||||
Runs during module init, so it is outside `handle_command_raises`.
|
||||
- `Flag#check!` — validates `short` against `FLAG_SHORT` and `long_key` against
|
||||
`FLAG_LONG`. Only invoked on `@flags`, never on `GLOBAL_FLAGS`, which is why the
|
||||
built-in `--help`/`--verbose` don't trip their own checks.
|
||||
- `CommandNode#check!` — duplicate shorts/longs across `@flags + GLOBAL_FLAGS`
|
||||
(`DuplicateFlagError`), duplicate child command names (`DuplicateCommandError`), and
|
||||
(when `T != Nil`) requires either subcommands or a `#main` (`MissingDispatchError`).
|
||||
- `App#check!` — `super`, then env-var collisions across `all_flags + GLOBAL_FLAGS`.
|
||||
`all_flags` recurses the whole tree; empty env vars are excluded.
|
||||
- `App#check!` — `super`, then env-var collisions across `all_flags.uniq + GLOBAL_FLAGS`.
|
||||
`all_flags` recurses the whole tree. **The `.uniq` is load-bearing**: a parent's flag
|
||||
object can appear in several nodes, and `uniq` collapses it via `Reference` identity
|
||||
(`Flag` overrides neither `==` nor `hash`). Adding a custom `==` to `Flag` would
|
||||
silently make this collapse *distinct* flags and stop catching real collisions.
|
||||
|
||||
### Errors: `src/cligen/exceptions.cr`
|
||||
|
||||
@@ -219,8 +239,8 @@ Called inside a `CliGen::Command` subclass:
|
||||
| Macro | File | Purpose |
|
||||
|---|---|---|
|
||||
| `argument(var : T, description, ...)` | `command/argument.cr` | Declares a flag-backed ivar. Options: `long`, `short`, `validation`, `on_match`, `def_setter`, `def_getter`, `options`, `delimiter`, `format`, `allow_no_verification`, `env_var` |
|
||||
| `selection(var : T, description, options, ...)` | `command/selection.cr` | Like `argument` but constrained to a fixed option list |
|
||||
| `subcommand(func, description, examples) { ... }` | `command/subcommand.cr` | Defines a `@[SubCommand]` method from a block |
|
||||
| `resolve_value(var, default: nil)` | `command/resolve_value.cr` | Reads a flag value from this command **or any ancestor**. Walks the `parent:` chain at compile time to find the declaring class, then walks `handler.parent?` at runtime to find its node. Returns the exact `T`, not a union. If the declaring ivar has no default, `default:` is **required** — the emitted `%default : T = ...` makes Crystal type-check it at the call site, and a `rescue MissingRequiredFlagError` uses it as the fallback |
|
||||
| `help_template(filepath)` | `command/help_template.cr` | Per-command ECR override |
|
||||
|
||||
Module-level:
|
||||
@@ -230,7 +250,12 @@ Module-level:
|
||||
| `CliGen.add_global_flag(T, long:, description:, ...)` | `global_flag/add_global_flag.cr` | Appends to `GLOBAL_FLAGS`; visible on every command |
|
||||
| `CliGen.override_help_template(filepath)` | `cligen.cr` | Project-wide ECR override |
|
||||
|
||||
`global_flag.cr` dogfoods `add_global_flag` for the built-in `-v/--verbose`.
|
||||
`global_flag.cr` dogfoods `add_global_flag` for the built-in `-v/--verbose` and
|
||||
`-h/--help`, both passing `internal: true` to bypass the reserved-name check.
|
||||
|
||||
`CliGen::MAX_COMMAND_DEPTH` (default 32, user-overridable by defining it before the
|
||||
requires) bounds every parent-chain walk — macros have no `while`, so the walks are
|
||||
`{% for i in (1..MAX_COMMAND_DEPTH) %}` with a sentinel. It doubles as the cycle guard.
|
||||
|
||||
### Extension points
|
||||
|
||||
@@ -244,15 +269,14 @@ in `flag.cr`.
|
||||
|
||||
## Annotations
|
||||
|
||||
`src/cligen/annotations.cr` declares seven; only five are wired:
|
||||
`src/cligen/annotations.cr` declares six; only four are wired:
|
||||
|
||||
| Annotation | Applied to | Status |
|
||||
|---|---|---|
|
||||
| `@[CommandInfo(description:, def_init:)]` | Command subclass | **Required.** `description` must be a `StringLiteral`; `def_init: true` generates a no-arg initializer + `self.get` singleton accessor |
|
||||
| `@[Argument(short:, long:, description:, validation:, on_match:, options:, delimiter:, format:, env_var:)]` | ivar | Emitted by `argument` **and** `selection`; read by `App.generate` and `define_command_initializer` |
|
||||
| `@[CommandInfo(description:, parent:, singleton_init:)]` | Command subclass | **Required.** `description` must be a `StringLiteral`. `parent:` names the command this is a subcommand of (see nesting above). `singleton_init: true` generates a no-arg initializer + `self.get` accessor — note the check is `== true`, so any other value silently does nothing |
|
||||
| `@[Argument(short:, long:, description:, validation:, on_match:, options:, delimiter:, format:, env_var:)]` | ivar | Emitted by `argument`; read by `App.generate` and `define_command_initializer` |
|
||||
| `@[SubCommand(description:, examples:)]` | method | Emitted by `subcommand`; read by `CommandNode#subcommands` and the dispatch `case` |
|
||||
| `@[PreRunCommand]` | method | Run unconditionally before subcommand dispatch |
|
||||
| `@[Selection]` | ivar | *Read* by `generate`/`define_command_initializer`, but never emitted — `selection` emits `@[Argument]`. Effectively dead. |
|
||||
| `@[ProxyCommand]` | — | Declared only; unused |
|
||||
| `@[Trigger]` | — | Declared only; unused |
|
||||
|
||||
@@ -264,9 +288,30 @@ These have each caused real bugs in this codebase — check for them before touc
|
||||
`==` silently returns false and `<` raises `undefined macro method 'Path#<'`. Call
|
||||
`.resolve` first: `validation.return_type.resolve == Bool`, `type.resolve <= Array`.
|
||||
Generic type *parameters* (`T` inside `Flag(T)`) are already `TypeNode` and are safe as-is.
|
||||
This is the single most frequent bug in this codebase — it has appeared five separate
|
||||
times, and it usually fails *silently* (a `Path == TypeNode` comparison is just always
|
||||
false) or with an unrelated-looking error like `undefined macro method 'Path#annotation'`.
|
||||
Resolve once at the point of extraction, not at each use.
|
||||
- **`{% cond %}` failing inside a macro reports the wrong line.** When a macro expression
|
||||
raises, the error points at the line that *consumes* the variable, not the assignment
|
||||
that blew up — "undefined macro variable `x`" almost always means the line assigning `x`
|
||||
errored. Look one line up.
|
||||
- **Macros cannot be called from macro scope.** `{% if some_macro(x) %}` gives
|
||||
`undefined macro method`. Macros emit code; they don't return values to the evaluator.
|
||||
To share logic, either precompute into a constant both can read, or accept duplication.
|
||||
- **`@type.instance_vars` only works in method scope.** In class-body scope (including a
|
||||
`macro finished` directly in a class body) it raises "instance vars are not yet
|
||||
initialized". Declaring an ivar requires class-body scope, so a macro can never read one
|
||||
class's ivars *and* declare ivars in another. Constants are readable in both scopes and
|
||||
are the way around it (`@type.constant("X") << ...` mutates one).
|
||||
- **Macro `for` has no `break`**, and reassigning the loop variable does nothing. Bound the
|
||||
loop and guard the body with a sentinel (`{% unless done || found %}`).
|
||||
- **Emitted locals leak into the caller's scope.** `flg = ...` in a macro body clobbers a
|
||||
user's `flg`. Use `%flg`, which is unique per expansion (and avoids type unions when the
|
||||
same macro is called with different `T` in one scope).
|
||||
- **`{% verbatim do %}`** is required whenever a macro body must emit macro code that runs
|
||||
in the *subclass's* `macro finished` context (see `command.cr`, `def_init.cr`,
|
||||
`define_command_initializer.cr`).
|
||||
in the *subclass's* `macro finished` context (see `command.cr`,
|
||||
`define_singleton_init.cr`, `define_command_initializer.cr`).
|
||||
- Signed/unsigned dispatch is done by string inspection, since there's no `UInt` supertype
|
||||
to test against: `{% int_case = T.stringify =~ /^UInt/ ? "uint?".id : "int?".id %}`.
|
||||
- `macro finished` ordering is why `App.generate` can see every `Command` subclass.
|
||||
@@ -278,6 +323,17 @@ These have each caused real bugs in this codebase — check for them before touc
|
||||
`String`-array `process` overload, then generates most `it` blocks with `{% for int in
|
||||
Int.subclasses %}` etc. so every numeric width is covered. `MyGoodData` / `MyBadData`
|
||||
exercise `Coercable` / `Parsable`, including the "didn't mark anything processed" failure.
|
||||
- `spec/cligen/command_spec.cr` — `resolve_value` at depth 1/2/3, both construction paths
|
||||
(`define_singleton_init`'s no-arg `new` and `new(handler:)`), and the required-flag raise.
|
||||
- `spec/cligen/timeparse_spec.cr` / `relative_operation_spec.cr` — the time subsystem.
|
||||
- `spec/cligen/regex_spec.cr` — the flag and date matchers.
|
||||
|
||||
**Two spec hazards, both already hit:** env vars set in one example leak into others, so
|
||||
anything touching `ENV` needs a `before_each { ENV.delete(...) }` — run `crystal spec
|
||||
--order=<n>` for a few seeds before trusting a green suite. And time assertions must not
|
||||
compare two independently-sampled clocks; `RelativeOperation#apply` takes an explicit
|
||||
`Time`, so assert against a fixed `Time.utc` and reserve bracket assertions for
|
||||
`Timeparse.parse`'s single `Time.local` call. Check `TZ=UTC crystal spec` too.
|
||||
|
||||
`utils/flag_matrix.cr` + `utils/flag_matrix.sh` cover what specs can't: env vars must be
|
||||
set before process startup, so each of the 16 cases needs its own process. Run this after
|
||||
@@ -285,9 +341,14 @@ touching value resolution, `check!`, or help rendering.
|
||||
|
||||
## Current state (branch `object_rework`)
|
||||
|
||||
Green: `crystal build --no-codegen` clean, `crystal spec` 164 examples / 0 failures,
|
||||
`./utils/flag_matrix.sh` 16/16. Targeting v0.2.0 (`shard.yml` and `CliGen::VERSION` both
|
||||
still say `0.1.0`).
|
||||
Green: `crystal build --no-codegen` clean, `crystal spec` 276 examples / 0 failures,
|
||||
`./utils/flag_matrix.sh` 16/16. `shard.yml` and `CliGen::VERSION` are both bumped to
|
||||
`0.2.0`; no git tag exists yet.
|
||||
|
||||
**Verifying a change needs a consuming app, not just the lib build.** `crystal build
|
||||
src/cligen.cr --no-codegen` does not instantiate `App.process`, `check_for_env_duplicates`,
|
||||
or `satisfied?`, so type errors there stay invisible. Write a throwaway `require "cligen"`
|
||||
program with a `Command` subclass and build *that*.
|
||||
|
||||
Known gaps, all deliberate:
|
||||
|
||||
@@ -295,9 +356,19 @@ Known gaps, all deliberate:
|
||||
DESIGN.md marks it as planned.
|
||||
- **`Array(Time)`** — unsupported; the three array element chains have no `Time` case.
|
||||
- **Colon-based relative time formats** (`[-+]%H:%M:%S`) — documented in DESIGN.md as planned.
|
||||
- `@[Selection]`, `@[ProxyCommand]`, `@[Trigger]` are dead (see above).
|
||||
- The `Fiber.yield` log-flush workaround in `app.cr` is fragile; synchronous dispatch
|
||||
would be deterministic.
|
||||
- `@[ProxyCommand]` and `@[Trigger]` are declared but unused (see above).
|
||||
- The `Fiber.yield` in `app.cr`'s `handle_command_raises` is **load-bearing, not
|
||||
superstition** — Crystal's default `Log` backend dispatches async at INFO even with no
|
||||
`Log.setup` call, so without the yield `abort`'s synchronous stderr write beats the log
|
||||
lines that explain it. A sync dispatcher would be deterministic but is the *consumer's*
|
||||
global setting, so the library can't impose it.
|
||||
- `resolve_value` can no longer raise `MissingRequiredFlagError` — the declaring ivar
|
||||
either has a default or the call site must supply one, so both paths are covered. The
|
||||
gate applies only to the parent-chain branch; a local ivar was already resolved during
|
||||
`initialize`, and the not-found branch raises at compile time regardless.
|
||||
- `resolve_value`'s own cycle detection is unreachable: `validate_command_tree` runs in
|
||||
`macro finished` and catches cycles before any method body instantiates. The `commands`
|
||||
array it accumulates is still live — it feeds the "valid options are..." error listing.
|
||||
|
||||
## Repo conventions
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ This document outlines the overall design of the CliGen shard & it's underlying
|
||||
|
||||
## How it works/High-Level overview
|
||||
|
||||
Using crystal macros, you define the shape (arguments/flags, selections, work functions/subcommands, etc) and later on in `src/cligen/app/generate.cr` will use macros to (at compile time) generate `CommandNode(T)` objects & `Flag(T)` objects to contain your command/subcommand/arg parsing code from the data you provided in your `CliGen::Command` subclass.
|
||||
Using crystal macros, you define the shape (arguments/flags, work functions/subcommands, etc) and later on in `src/cligen/app/generate.cr` will use macros to (at compile time) generate `CommandNode(T)` objects & `Flag(T)` objects to contain your command/subcommand/arg parsing code from the data you provided in your `CliGen::Command` subclass.
|
||||
|
||||
|
||||
## Architecture
|
||||
@@ -72,8 +72,8 @@ The examples like above provide a "DSL-esk" way of defining:
|
||||
- Instance Variables,
|
||||
- Short/Long flags
|
||||
- Description of the flags (used in the help output as well)
|
||||
- A verification proc/lambda for doing ad-hoc checks of the value provided by the user (essentially allowing you to implement your own option: key like in selection)
|
||||
- Selections (currently compile-time and will open it up to runtime collecting of options later on based on defined annotations in the class)
|
||||
- A verification proc/lambda for doing ad-hoc checks of the value provided by the user (for cases where the `options:` key isn't expressive enough)
|
||||
- A static list of valid options via the `options:` key (currently compile-time; will open up to runtime collection of options later on)
|
||||
- define subcommands of this current command
|
||||
|
||||
|
||||
@@ -405,7 +405,7 @@ This object serves as a wrapper around ARGV objects/strings/items and is used to
|
||||
|
||||
### Markdown Documentation Generation
|
||||
|
||||
Since all command metadata is present in annotations at compile time (`@[CliGen::CommandInfo]`, `@[CliGen::SubCommand]`, `@[CliGen::Argument]`, `@[CliGen::Selection]`), the framework can walk the same structures that `generate.cr` already walks and render them into a Markdown document instead of a `CommandNode` tree.
|
||||
Since all command metadata is present in annotations at compile time (`@[CliGen::CommandInfo]`, `@[CliGen::SubCommand]`, `@[CliGen::Argument]`), the framework can walk the same structures that `generate.cr` already walks and render them into a Markdown document instead of a `CommandNode` tree.
|
||||
|
||||
The generation would be driven by a `macro finished` block (similar to `generate.cr`) that emits a `self.generate_docs` class method on `App`. This method walks every `Command` subclass and its annotations to produce a structured document.
|
||||
|
||||
@@ -466,7 +466,7 @@ complete -F _myapp myapp
|
||||
Implementation notes:
|
||||
|
||||
* Script body generated at compile time via a `macro finished` walk of `Command.subclasses`
|
||||
* `@[CliGen::Selection]` options (`%w[json yaml ecr]`) can be included as valid completions for their flag
|
||||
* `@[CliGen::Argument]` options (`%w[json yaml ecr]`) can be included as valid completions for their flag
|
||||
* Install path: `myapp --generate-completion bash > ~/.bash_completion.d/myapp` or printed with instructions
|
||||
* Same annotation data used by the doc generator, so both stay in sync with the command definition
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ A Crystal shard that generates CLI parsers from class definitions using annotati
|
||||
|
||||
## How It Works
|
||||
|
||||
Subclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]` or `@[CliGen::Selection]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.
|
||||
Subclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.
|
||||
|
||||
## Installation
|
||||
|
||||
|
||||
+10
-5
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+288
-13
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -396,12 +401,22 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/def_init.cr
|
||||
cligen/command/define_command_initializer.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/define_command_initializer.cr
|
||||
cligen/command/define_singleton_init.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/generate_gather_handler.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/generate_register_command.cr
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -411,7 +426,7 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/selection.cr
|
||||
cligen/command/resolve_value.cr
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -421,6 +436,11 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/validate_command_tree.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command_node.cr
|
||||
|
||||
<br/>
|
||||
@@ -500,8 +520,33 @@
|
||||
</dt>
|
||||
|
||||
|
||||
<dt class="entry-const" id="MAX_COMMAND_DEPTH">
|
||||
<strong>MAX_COMMAND_DEPTH</strong> = <code><span class="n">32</span></code>
|
||||
</dt>
|
||||
|
||||
<dd class="entry-const-doc">
|
||||
<h1><a id="cli-genmax-command-depth" class="anchor" href="#cli-genmax-command-depth"> <svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>CliGen::MAX_COMMAND_DEPTH</h1>
|
||||
<p>This exists to prevent the user from defining a command tree
|
||||
that extends past the compile-time configured max via the
|
||||
CliGen::MAX_COMMAND_DEPTH constant.</p>
|
||||
<p>The reason this is a thing is because crystal macros don't allow for
|
||||
unbounded while's/until's in macros, meaning it always has to be
|
||||
deterministic. SO to deal with this and still allow for subcommand
|
||||
defining you need either go with the default (32 command depth) or
|
||||
define your own larger max (understand this will affect compile-time
|
||||
due to this directly affecting loops in the Command macros).</p>
|
||||
<p>So to still support this I had to make bounded for-loops usng</p>
|
||||
<pre><code class="language-crystal"><span class="o">{%</span> <span class="k">for</span> i <span class="k">in</span> (<span class="n">1</span>..<span class="t">CliGen</span><span class="t">::</span><span class="t">MAX_COMMAND_DEPTH</span>) <span class="o">%}</span>
|
||||
...<span class="k">do</span> checks...
|
||||
<span class="o">{%</span> <span class="k">end</span> }</code></pre>
|
||||
</dd>
|
||||
|
||||
|
||||
<dt class="entry-const" id="VERSION">
|
||||
<strong>VERSION</strong> = <code><span class="s">"0.1.0"</span></code>
|
||||
<strong>VERSION</strong> = <code><span class="s">"0.2.0"</span></code>
|
||||
</dt>
|
||||
|
||||
|
||||
@@ -525,7 +570,9 @@
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#add_global_flag%28type%2C%2A%2Clong%2Cdescription%2Cenv_var%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Cdefault%3Dnil%2Con_match%3Dnil%29-macro" class="signature"><strong>add_global_flag</strong>(type, *, long, description, env_var = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, default = <span class="n">nil</span>, on_match = <span class="n">nil</span>)</a>
|
||||
<a href="#add_global_flag%28type%2C%2A%2Clong%2Cdescription%2Cenv_var%3D%22%22%2Cshort%3Dnil%2Cvalidation%3Dnil%2Cdefault%3Dnil%2Con_match%3Dnil%2Coptions%3Dnil%2Cformat%3Dnil%2Cinternal%3Dfalse%29-macro" class="signature"><strong>add_global_flag</strong>(type, *, long, description, env_var = <span class="s">""</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, default = <span class="n">nil</span>, on_match = <span class="n">nil</span>, options = <span class="n">nil</span>, format = <span class="n">nil</span>, internal = <span class="n">false</span>)</a>
|
||||
|
||||
<div class="summary"><p>This macro provides a user-friendly way to define a global flag for your project.</p></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -558,12 +605,240 @@
|
||||
Macro Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="add_global_flag(type,*,long,description,env_var=nil,short=nil,validation=nil,default=nil,on_match=nil)-macro">
|
||||
<div class="entry-detail" id="add_global_flag(type,*,long,description,env_var="",short=nil,validation=nil,default=nil,on_match=nil,options=nil,format=nil,internal=false)-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>add_global_flag</strong>(type, *, long, description, env_var = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, default = <span class="n">nil</span>, on_match = <span class="n">nil</span>)
|
||||
macro <strong>add_global_flag</strong>(type, *, long, description, env_var = <span class="s">""</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, default = <span class="n">nil</span>, on_match = <span class="n">nil</span>, options = <span class="n">nil</span>, format = <span class="n">nil</span>, internal = <span class="n">false</span>)
|
||||
|
||||
<a class="method-permalink" href="#add_global_flag%28type%2C%2A%2Clong%2Cdescription%2Cenv_var%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Cdefault%3Dnil%2Con_match%3Dnil%29-macro">#</a>
|
||||
<a class="method-permalink" href="#add_global_flag%28type%2C%2A%2Clong%2Cdescription%2Cenv_var%3D%22%22%2Cshort%3Dnil%2Cvalidation%3Dnil%2Cdefault%3Dnil%2Con_match%3Dnil%2Coptions%3Dnil%2Cformat%3Dnil%2Cinternal%3Dfalse%29-macro">#</a>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
|
||||
<p>This macro provides a user-friendly way to define a global flag for your
|
||||
project.</p>
|
||||
<h2><a id="what-does-this-do" class="anchor" href="#what-does-this-do">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>What does this do?</h2>
|
||||
<p>This macro is used to help define & check a global flag to be used in the
|
||||
all levels of commands.</p>
|
||||
<p>When provided it will parse your values & serialize them into a Flag(T)
|
||||
object & insert it in the CliGen::GLOBAL_FLAGS array after checking if
|
||||
a flag using it's <code>--long</code> is already in use. In the case that that long
|
||||
is already used it will raise at runtime and you'll need to choose another
|
||||
long.</p>
|
||||
<h2><a id="arguments" class="anchor" href="#arguments">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>Arguments</h2>
|
||||
<h3><a id="type-type-node" class="anchor" href="#type-type-node">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>type: TypeNode</h3>
|
||||
<p><strong>Required:</strong> true</p>
|
||||
<p>This is the type of the flag (Bool, Int32, String, etc).</p>
|
||||
<h3><a id="long-string-literal" class="anchor" href="#long-string-literal">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>long: StringLiteral</h3>
|
||||
<p><strong>Required:</strong> true</p>
|
||||
<p>This is the long form of the flag that will be matched at the command-line</p>
|
||||
<h3><a id="description-string-literal" class="anchor" href="#description-string-literal">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>description: StringLiteral</h3>
|
||||
<p><strong>Required:</strong> true</p>
|
||||
<p>This is the full length description of the flag that will be presented in the
|
||||
help text provided to the user.</p>
|
||||
<h3><a id="env-var-string-literal" class="anchor" href="#env-var-string-literal">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>env_var: StringLiteral</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>This is an ENV VAR that can be used to set this value without providing an
|
||||
argument via the CLI. By default it will (unless explicitly disbled by
|
||||
passing <code>env_var: nil</code> as an argument to disable the env_var entirely)
|
||||
will parse your long flag and set the ENV VAR to the un "--" portion of it</p>
|
||||
<p><strong>Warning:</strong> Incompatible ENV VAR formatting</p>
|
||||
<p>When providing ENV VARs manually you cannot provide any whitespace or "-"
|
||||
characters internally to it. As thse are both incompatible with ENV VARs.</p>
|
||||
<p>If you provide an ENV VAR with these the framework will raise at
|
||||
compile-time and tell you to change them.</p>
|
||||
<p><strong>Note:</strong> Auto Generates ENV VAR from flag long</p>
|
||||
<p>If you did not provide a ENV VAR manually (or disable it via setting it to
|
||||
nil), the macro will use the long flag to create a ENV VAR that can be
|
||||
matched. In this case if the flag has any internal "-" chars they will
|
||||
be replaced with "_" so "--long--flag--name"/"--long-flag-name" ->
|
||||
"LONG_FLAG_NAME".</p>
|
||||
<p>When you provide a long: with a trailing ARGUMENT (ex: "--item ITEM",
|
||||
"--item=ITEM") the flag will first be split on the whitespace or "="
|
||||
prior to being used for the ENV_VAR.</p>
|
||||
<h3><a id="short-string-literal" class="anchor" href="#short-string-literal">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>short: StringLiteral</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>This is the short form of a flag ("--filename" -> "-f") that can be matched
|
||||
during parsing.</p>
|
||||
<p><strong>Note:</strong> Alphabetic characters only</p>
|
||||
<p>Unlike some other frameworks that might support numeric flags, due to the
|
||||
issues around supporting them & being able to discern if these are arguments
|
||||
(-1/signed int's) or short flags ("--one" -> "-1"), I've determined that I
|
||||
will not be supporting numeric flags as this causes a number of
|
||||
complications/complexities around ARGV parsing.</p>
|
||||
<h3><a id="default-t" class="anchor" href="#default-t">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>default: T</h3>
|
||||
<p><strong>Required:</strong> ?false?</p>
|
||||
<p>This is the default value of the flag (String -> "abc", Int32 -> 0, etc)
|
||||
that will be returned if no direct (via parsing CLI args) or indirect
|
||||
(by parsing ENV VAR values) arguments are provided.</p>
|
||||
<p>While not technically required, it's advised to always set a default
|
||||
when creating flags as if you don't and nothing is parsed/provided
|
||||
when Flag(T)#value! is called it will raise a
|
||||
CliGen::MissingRequiredFlagError exception at the call site.</p>
|
||||
<h3><a id="options-array-literaltcall" class="anchor" href="#options-array-literaltcall">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>options: ArrayLiteral(T)|Call</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>This argument sets a static list of accepted arguments to a specific subset
|
||||
of values.</p>
|
||||
<p>EX: Output format</p>
|
||||
<pre><code class="language-crystal"><span class="t">CliGen</span>.add_global_flag(<span class="t">String</span>,
|
||||
default: <span class="s">"ecr"</span>,
|
||||
short: <span class="s">"-f"</span>,
|
||||
long: <span class="s">"--format"</span>,
|
||||
description: <span class="s">"Provide the preferred output format"</span>,
|
||||
options: <span class="s">%w[ json yaml ecr ]</span>
|
||||
)</code></pre>
|
||||
<p><strong>Note:</strong> Support for runtime resolution</p>
|
||||
<p>While the primary value of this is static arrays of values, you can also
|
||||
delegate the discovery of values to a global method or helper method in
|
||||
your codebase.</p>
|
||||
<p>HOWEVER, when doing so ALWAYS ensure that you are providing a full path
|
||||
to your method, as the the macro has no way of determining relative paths
|
||||
in your modules. While, provided you are doing this in the same context as
|
||||
the method you are running, this shouldn't be an issue, however best
|
||||
practices dictate you provide a full path just to be careful.</p>
|
||||
<p>EX: Delegated resolution</p>
|
||||
<pre><code class="language-crystal"><span class="k">module</span> <span class="t">ABC</span>
|
||||
<span class="k">def</span> <span class="m">self</span>.items
|
||||
<span class="s">%w[ a b c d e f g taco ]</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
|
||||
<span class="t">CliGen</span>.add_global_flag(<span class="t">String</span>,
|
||||
default: <span class="s">"a"</span>,
|
||||
short: <span class="s">"-i"</span>,
|
||||
long: <span class="s">"--item"</span>,
|
||||
description: <span class="s">"Provide an item to print"</span>,
|
||||
options: <span class="t">::</span><span class="t">ABC</span>.items
|
||||
)</code></pre>
|
||||
<h3><a id="format-regex-literal" class="anchor" href="#format-regex-literal">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>format: RegexLiteral</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>This exists to handle (for String & Custom Data Types) filtering & checking
|
||||
that an argument being provided by a user is being given in a specific
|
||||
format.</p>
|
||||
<p>This is something you use when you're only wanting to validate formatting,
|
||||
if you plan to do more specific/extensive validation you should use the
|
||||
validation: field.</p>
|
||||
<p>EX: Hostname matching</p>
|
||||
<pre><code class="language-crystal"><span class="t">CliGen</span>.add_global_flag(<span class="t">Array</span>(<span class="t">String</span>),
|
||||
default: <span class="o">[]</span> <span class="k">of</span> <span class="t">String</span>,
|
||||
short: <span class="s">"-H"</span>,
|
||||
long: <span class="s">"--hostname"</span>,
|
||||
description: <span class="s">"Provide a hostname to do remote work on"</span>,
|
||||
format: <span class="s">/^[a-zA-Z]{3}[0-9]+node[0-9]$/</span>
|
||||
)</code></pre>
|
||||
<h3><a id="validation-proc-literalt-bool" class="anchor" href="#validation-proc-literalt-bool">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>validation: ProcLiteral(T, Bool)</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>Here you can provide a ad-hoc proc for doing validations of a provided
|
||||
argument that can't easily be done by providing a static <code>options:</code> value.</p>
|
||||
<p><strong>Note:</strong> Explicit input & return type requirement</p>
|
||||
<p>The explicit input <code>: T</code> & return <code>: Bool</code> turn types are required as the
|
||||
macros I setup are trying to enforce that both the input & return types
|
||||
are explicity to avoid truthy & falsey semantics.</p>
|
||||
<p>EX: checking int range</p>
|
||||
<pre><code class="language-crystal"><span class="t">CliGen</span>.add_global_flag(<span class="t">Int32</span>,
|
||||
short: <span class="s">"-p"</span>,
|
||||
long: <span class="s">"--port"</span>,
|
||||
description: <span class="s">"Provide a single port to test against"</span>,
|
||||
validation: <span class="o">-></span>(port : <span class="t">Int32</span>) : <span class="t">Bool</span> <span class="k">do</span>
|
||||
(<span class="t">UInt16</span><span class="t">::</span><span class="t">MIN</span>..<span class="t">UInt16</span><span class="t">::</span><span class="t">MAX</span>).includes?(port)
|
||||
<span class="k">end</span>
|
||||
)</code></pre>
|
||||
<p>EX: file existance check</p>
|
||||
<pre><code class="language-crystal"><span class="t">CliGen</span>.add_global_flag(<span class="t">String</span>,
|
||||
short: <span class="s">"-i"</span>,
|
||||
long: <span class="s">"--filename"</span>,
|
||||
description: <span class="s">"Provide a file that will serve as the input for this program"</span>,
|
||||
validation: <span class="o">-></span>(file : <span class="t">String</span>) : <span class="t">Bool</span> <span class="k">do</span>
|
||||
<span class="k">if</span> <span class="t">File</span>.exists?(file)
|
||||
<span class="n">true</span>
|
||||
<span class="k">else</span>
|
||||
<span class="t">STDERR</span>.puts <span class="s">"ERROR : --filename : Provided file (</span><span class="i">#{</span>file<span class="i">}</span><span class="s">) does not exist"</span>
|
||||
<span class="n">false</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>
|
||||
)</code></pre>
|
||||
<h3><a id="on-match-proc-literalt-nil" class="anchor" href="#on-match-proc-literalt-nil">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>on_match: ProcLiteral(T, Nil)</h3>
|
||||
<p><strong>Required:</strong> false</p>
|
||||
<p>This option is where you provide the proc for handling ad-hoc</p>
|
||||
<p>EX: Configuring the stdlib log level</p>
|
||||
<pre><code class="language-crystal"><span class="t">CliGen</span>.add_global_flag(<span class="t">String</span>,
|
||||
long: <span class="s">"--log-level LEVEL"</span>,
|
||||
short: <span class="s">"-l"</span>,
|
||||
description: <span class="s">"Set the current log level of the stdlib Log library"</span>,
|
||||
options: <span class="s">%w[ trace debug notice info warn error fatal ]</span>,
|
||||
on_match: <span class="o">-></span>(level : <span class="t">String</span>) <span class="k">do</span>
|
||||
<span class="t">::</span><span class="t">Log</span>.setup(level: <span class="t">::</span><span class="t">Log</span><span class="t">::</span><span class="t">Severity</span>.parse(level))
|
||||
<span class="k">end</span>
|
||||
)</code></pre>
|
||||
<p>EX: Collecting arguments in a global array</p>
|
||||
<pre><code class="language-crystal"><span class="k">module</span> <span class="t">MyModule</span>
|
||||
<span class="t">MY_ARRAY</span> <span class="o">=</span> <span class="o">[]</span> <span class="k">of</span> <span class="t">String</span>
|
||||
<span class="t">CliGen</span>.add_global_flag(<span class="t">String</span>,
|
||||
long: <span class="s">"--filename FILE"</span>,
|
||||
short: <span class="s">"-i"</span>,
|
||||
description: <span class="s">"Provide a single file to check against (repeatable)"</span>,
|
||||
validation: <span class="o">-></span>(file : <span class="t">String</span>) : <span class="t">Bool</span> <span class="k">do</span>
|
||||
<span class="k">if</span> <span class="t">File</span>.exists?(file)
|
||||
<span class="n">true</span>
|
||||
<span class="k">else</span>
|
||||
<span class="t">STDERR</span>.puts <span class="s">"ERROR : --filename : </span><span class="i">#{</span>file<span class="i">}</span><span class="s"> does not exist"</span>
|
||||
<span class="n">false</span>
|
||||
<span class="k">end</span>
|
||||
<span class="k">end</span>,
|
||||
on_match: <span class="o">-></span>(file : <span class="t">String</span>) <span class="k">do</span>
|
||||
<span class="t">::</span><span class="t">MyModule</span><span class="t">::</span><span class="t">MY_ARRAY</span> <span class="o"><<</span> file
|
||||
<span class="k">end</span>
|
||||
)
|
||||
<span class="k">end</span></code></pre>
|
||||
<p>For more detailed documentation please visit the wiki in the repo. All topics are covered there in much greater detail than inline documentation here</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
+43
-9
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -419,6 +424,11 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
</h2>
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#get-class-method" class="signature"><strong>.get</strong></a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#handle_command_raises%28%26%29%3ANil-class-method" class="signature"><strong>.handle_command_raises</strong>(&) : Nil</a>
|
||||
|
||||
@@ -500,8 +510,8 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
<h3>Constructor methods inherited from class <code><a href="../CliGen/CommandNode.html">CliGen::CommandNode(Nil)</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/CommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = <span class="n">nil</span>)</span>
|
||||
<a href="../CliGen/CommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), parent : BaseCommandNode | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)</span>
|
||||
new</a>
|
||||
|
||||
|
||||
@@ -519,6 +529,11 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
<h3>Instance methods inherited from class <code><a href="../CliGen/BaseCommandNode.html">CliGen::BaseCommandNode</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#all_commands%3AArray%28BaseCommandNode%29-instance-method" class="tooltip">
|
||||
<span>all_commands : Array(BaseCommandNode)</span>
|
||||
all_commands</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#all_flags%3AArray%28BaseFlag%29-instance-method" class="tooltip">
|
||||
<span>all_flags : Array(BaseFlag)</span>
|
||||
all_flags</a>,
|
||||
@@ -584,6 +599,11 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
name</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#parent%3F%3ABaseCommandNode%7CNil-instance-method" class="tooltip">
|
||||
<span>parent? : BaseCommandNode | Nil</span>
|
||||
parent?</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#process%28args%3AArray%28String%29%29%3ANil-instance-method" class="tooltip">
|
||||
<span>process(args : Array(String)) : Nil<br/>process(args : Array(CliGen::Arg)) : Nil</span>
|
||||
process</a>,
|
||||
@@ -611,8 +631,8 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
<h3>Constructor methods inherited from class <code><a href="../CliGen/BaseCommandNode.html">CliGen::BaseCommandNode</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, description : String | Nil = <span class="n">nil</span>)</span>
|
||||
<a href="../CliGen/BaseCommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, parent : BaseCommandNode | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)</span>
|
||||
new</a>
|
||||
|
||||
|
||||
@@ -689,6 +709,20 @@ for global-flag matching, then hands off to the matched child CommandNode.</p>
|
||||
Class Method Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="get-class-method">
|
||||
<div class="signature">
|
||||
|
||||
def self.<strong>get</strong>
|
||||
|
||||
<a class="method-permalink" href="#get-class-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="handle_command_raises(&):Nil-class-method">
|
||||
<div class="signature">
|
||||
|
||||
|
||||
+10
-5
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -346,7 +351,7 @@
|
||||
</h2>
|
||||
|
||||
<p>This is used for annotating instance variables for the CliGen framework can know how to create your <code><a href="../CliGen/Flag.html">CliGen::Flag</a>(T)</code> objects</p>
|
||||
<p>WHILE this is usually being handled by the <code><a href="../CliGen/Command.html#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3Dnil%29-macro">CliGen::Command.argument</a></code> macro
|
||||
<p>WHILE this is usually being handled by the <code><a href="../CliGen/Command.html#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3D%22%22%29-macro">CliGen::Command.argument</a></code> macro
|
||||
inside of the class body.</p>
|
||||
<p>EX:</p>
|
||||
<pre><code class="language-crystal"><span class="k">class</span> <span class="t">MyCmd</span> <span class="o"><</span> <span class="t">CliGen</span><span class="t">::</span><span class="t">Command</span>
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -429,7 +434,7 @@ Everything that doesn't depend on T lives here.</p>
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, description : String | Nil = <span class="n">nil</span>)</a>
|
||||
<a href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, parent : BaseCommandNode | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -451,6 +456,11 @@ Everything that doesn't depend on T lives here.</p>
|
||||
</h2>
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#all_commands%3AArray%28BaseCommandNode%29-instance-method" class="signature"><strong>#all_commands</strong> : Array(BaseCommandNode)</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#all_flags%3AArray%28BaseFlag%29-instance-method" class="signature"><strong>#all_flags</strong> : Array(BaseFlag)</a>
|
||||
|
||||
@@ -521,6 +531,11 @@ Everything that doesn't depend on T lives here.</p>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#parent%3F%3ABaseCommandNode%7CNil-instance-method" class="signature"><strong>#parent?</strong> : BaseCommandNode | Nil</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#process%28args%3AArray%28String%29%29%3ANil-instance-method" class="signature"><strong>#process</strong>(args : Array(String)) : Nil</a>
|
||||
|
||||
@@ -592,12 +607,12 @@ Everything that doesn't depend on T lives here.</p>
|
||||
Constructor Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="new(name:String,flags:Array(BaseFlag),commands:Array(BaseCommandNode),pre_run_commands:Array(RunCommand),post_run_commands:Array(RunCommand),meta:CommandMeta,description:String|Nil=nil)-class-method">
|
||||
<div class="entry-detail" id="new(name:String,flags:Array(BaseFlag),commands:Array(BaseCommandNode),pre_run_commands:Array(RunCommand),post_run_commands:Array(RunCommand),meta:CommandMeta,parent:BaseCommandNode|Nil=nil,description:String|Nil=nil)-class-method">
|
||||
<div class="signature">
|
||||
|
||||
def self.<strong>new</strong>(name : String, flags : Array(<a href="../CliGen/BaseFlag.html">BaseFlag</a>), commands : Array(<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>), pre_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), post_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), meta : <a href="../CliGen/CommandMeta.html">CommandMeta</a>, description : String | Nil = <span class="n">nil</span>)
|
||||
def self.<strong>new</strong>(name : String, flags : Array(<a href="../CliGen/BaseFlag.html">BaseFlag</a>), commands : Array(<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>), pre_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), post_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), meta : <a href="../CliGen/CommandMeta.html">CommandMeta</a>, parent : <a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a> | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)
|
||||
|
||||
<a class="method-permalink" href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cdescription%3AString%7CNil%3Dnil%29-class-method">#</a>
|
||||
<a class="method-permalink" href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
@@ -622,6 +637,20 @@ Everything that doesn't depend on T lives here.</p>
|
||||
Instance Method Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="all_commands:Array(BaseCommandNode)-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
def <strong>all_commands</strong> : Array(<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>)
|
||||
|
||||
<a class="method-permalink" href="#all_commands%3AArray%28BaseCommandNode%29-instance-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="all_flags:Array(BaseFlag)-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
@@ -818,6 +847,20 @@ Everything that doesn't depend on T lives here.</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="parent?:BaseCommandNode|Nil-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
def <strong>parent?</strong> : <a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a> | Nil
|
||||
|
||||
<a class="method-permalink" href="#parent%3F%3ABaseCommandNode%7CNil-instance-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="process(args:Array(String)):Nil-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
|
||||
+18
-13
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -417,7 +422,7 @@
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method" class="signature"><strong>.new</strong>(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta)</a>
|
||||
<a href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%7CNil%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method" class="signature"><strong>.new</strong>(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : FlagMeta)</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -455,7 +460,7 @@
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#env_var%3AString-instance-method" class="signature"><strong>#env_var</strong> : String</a>
|
||||
<a href="#env_var%3AString%7CNil-instance-method" class="signature"><strong>#env_var</strong> : String | Nil</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -548,12 +553,12 @@
|
||||
Constructor Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="new(var:String,short:String|Nil,long:String,env_var:String,description:String,delimiter:String,meta:FlagMeta)-class-method">
|
||||
<div class="entry-detail" id="new(var:String,short:String|Nil,long:String,env_var:String|Nil,description:String,delimiter:String,meta:FlagMeta)-class-method">
|
||||
<div class="signature">
|
||||
|
||||
def self.<strong>new</strong>(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : <a href="../CliGen/FlagMeta.html">FlagMeta</a>)
|
||||
def self.<strong>new</strong>(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : <a href="../CliGen/FlagMeta.html">FlagMeta</a>)
|
||||
|
||||
<a class="method-permalink" href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method">#</a>
|
||||
<a class="method-permalink" href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%7CNil%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
@@ -620,12 +625,12 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="env_var:String-instance-method">
|
||||
<div class="entry-detail" id="env_var:String|Nil-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
def <strong>env_var</strong> : String
|
||||
def <strong>env_var</strong> : String | Nil
|
||||
|
||||
<a class="method-permalink" href="#env_var%3AString-instance-method">#</a>
|
||||
<a class="method-permalink" href="#env_var%3AString%7CNil-instance-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+209
-35
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -373,12 +378,22 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/def_init.cr
|
||||
cligen/command/define_command_initializer.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/define_command_initializer.cr
|
||||
cligen/command/define_singleton_init.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/generate_gather_handler.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/generate_register_command.cr
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -388,7 +403,7 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/selection.cr
|
||||
cligen/command/resolve_value.cr
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -398,6 +413,11 @@
|
||||
<br/>
|
||||
|
||||
|
||||
cligen/command/validate_command_tree.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -418,12 +438,7 @@
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3Dnil%29-macro" class="signature"><strong>argument</strong>(variable, description, long = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, def_setter = <span class="n">false</span>, def_getter = <span class="n">false</span>, options = <span class="n">nil</span>, delimiter = <span class="s">","</span>, format = <span class="n">nil</span>, allow_no_verification = <span class="n">false</span>, env_var = <span class="n">nil</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#def_init-macro" class="signature"><strong>def_init</strong></a>
|
||||
<a href="#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3D%22%22%29-macro" class="signature"><strong>argument</strong>(variable, description, long = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, def_setter = <span class="n">false</span>, def_getter = <span class="n">false</span>, options = <span class="n">nil</span>, delimiter = <span class="s">","</span>, format = <span class="n">nil</span>, allow_no_verification = <span class="n">false</span>, env_var = <span class="s">""</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -432,13 +447,32 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#define_singleton_init-macro" class="signature"><strong>define_singleton_init</strong></a>
|
||||
|
||||
<div class="summary"><p>This macro simply provides a easy singleton initializer for your command to allow for you do (if this class isn't the target of a command) to still be able to gather a Command object without having to have it as the target.</p></div>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#generate_gather_handler-macro" class="signature"><strong>generate_gather_handler</strong></a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#generate_register_command-macro" class="signature"><strong>generate_register_command</strong></a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#help_template%28filepath%29-macro" class="signature"><strong>help_template</strong>(filepath)</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#selection%28variable%2Cdescription%2Coptions%2Cshort%3Dnil%2Clong%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%29-macro" class="signature"><strong>selection</strong>(variable, description, options, short = <span class="n">nil</span>, long = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>)</a>
|
||||
<a href="#resolve_value%28variable%2C%2A%2Cdefault%3Dnil%29-macro" class="signature"><strong>resolve_value</strong>(variable, *, default = <span class="n">nil</span>)</a>
|
||||
|
||||
<div class="summary"><p>This macro is just meant to provide the user an ability to resolve instance var/varibles from parent commands.</p></div>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -447,10 +481,34 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#validate_command_tree-macro" class="signature"><strong>validate_command_tree</strong></a>
|
||||
|
||||
<div class="summary"><p>This macro serves as a compile-time checker of the command-tree to validate that there is no recursive references of the command-list that would possibly cause a recursive stack-overflow during App.generate when App begins registering all user defined commands.</p></div>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="instance-method-summary" class="anchor" href="#instance-method-summary">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Instance Method Summary
|
||||
</h2>
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#handler%3F%3ABool-instance-method" class="signature"><strong>#handler?</strong> : Bool</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
<div class="methods-inherited">
|
||||
@@ -497,26 +555,12 @@
|
||||
Macro Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="argument(variable,description,long=nil,short=nil,validation=nil,on_match=nil,def_setter=false,def_getter=false,options=nil,delimiter=",",format=nil,allow_no_verification=false,env_var=nil)-macro">
|
||||
<div class="entry-detail" id="argument(variable,description,long=nil,short=nil,validation=nil,on_match=nil,def_setter=false,def_getter=false,options=nil,delimiter=",",format=nil,allow_no_verification=false,env_var="")-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>argument</strong>(variable, description, long = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, def_setter = <span class="n">false</span>, def_getter = <span class="n">false</span>, options = <span class="n">nil</span>, delimiter = <span class="s">","</span>, format = <span class="n">nil</span>, allow_no_verification = <span class="n">false</span>, env_var = <span class="n">nil</span>)
|
||||
macro <strong>argument</strong>(variable, description, long = <span class="n">nil</span>, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, def_setter = <span class="n">false</span>, def_getter = <span class="n">false</span>, options = <span class="n">nil</span>, delimiter = <span class="s">","</span>, format = <span class="n">nil</span>, allow_no_verification = <span class="n">false</span>, env_var = <span class="s">""</span>)
|
||||
|
||||
<a class="method-permalink" href="#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3Dnil%29-macro">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="def_init-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>def_init</strong>
|
||||
|
||||
<a class="method-permalink" href="#def_init-macro">#</a>
|
||||
<a class="method-permalink" href="#argument%28variable%2Cdescription%2Clong%3Dnil%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Cdef_setter%3Dfalse%2Cdef_getter%3Dfalse%2Coptions%3Dnil%2Cdelimiter%3D%22%2C%22%2Cformat%3Dnil%2Callow_no_verification%3Dfalse%2Cenv_var%3D%22%22%29-macro">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
@@ -539,6 +583,60 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="define_singleton_init-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>define_singleton_init</strong>
|
||||
|
||||
<a class="method-permalink" href="#define_singleton_init-macro">#</a>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
|
||||
<p>This macro simply provides a easy singleton initializer for your command
|
||||
to allow for you do (if this class isn't the target of a command) to still
|
||||
be able to gather a Command object without having to have it as the target.</p>
|
||||
<p>This will setup the default (no args) initializer to gather the handler from
|
||||
CliGen::App and then resolve all of the ivar (CliGen managed) to the parsed
|
||||
values from the associated Flag(T) object that (if the process itself is
|
||||
being started by CliGen the provided flags will store the value to be
|
||||
set here)</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="generate_gather_handler-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>generate_gather_handler</strong>
|
||||
|
||||
<a class="method-permalink" href="#generate_gather_handler-macro">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="generate_register_command-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>generate_register_command</strong>
|
||||
|
||||
<a class="method-permalink" href="#generate_register_command-macro">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="help_template(filepath)-macro">
|
||||
<div class="signature">
|
||||
|
||||
@@ -553,12 +651,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="selection(variable,description,options,short=nil,long=nil,validation=nil,on_match=nil)-macro">
|
||||
<div class="entry-detail" id="resolve_value(variable,*,default=nil)-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>selection</strong>(variable, description, options, short = <span class="n">nil</span>, long = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>)
|
||||
macro <strong>resolve_value</strong>(variable, *, default = <span class="n">nil</span>)
|
||||
|
||||
<a class="method-permalink" href="#selection%28variable%2Cdescription%2Coptions%2Cshort%3Dnil%2Clong%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%29-macro">#</a>
|
||||
<a class="method-permalink" href="#resolve_value%28variable%2C%2A%2Cdefault%3Dnil%29-macro">#</a>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
|
||||
<p>This macro is just meant to provide the user an ability to resolve instance
|
||||
var/varibles from parent commands. Simply to allow subcommands to be able
|
||||
to retrieve values from their parents</p>
|
||||
<p>As an aside, this (as written) can only be used for variables that have
|
||||
a default defined (ex: @var : Int32 = 3)</p>
|
||||
<p>For variables that (in your parent class) isn't set with a default value,
|
||||
you will need to provide the (default: <val>) kwarg to set your own
|
||||
runtime default if the value itself cannot be ensured by the compiler.</p>
|
||||
<p>This is a requirement as this macro MUST always return a value without
|
||||
rasing, and the only way to do that is force the user to provide a
|
||||
default of their choosing.</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
@@ -581,7 +694,68 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="entry-detail" id="validate_command_tree-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>validate_command_tree</strong>
|
||||
|
||||
<a class="method-permalink" href="#validate_command_tree-macro">#</a>
|
||||
</div>
|
||||
|
||||
<div class="doc">
|
||||
|
||||
<p>This macro serves as a compile-time checker of the command-tree to
|
||||
validate that there is no recursive references of the command-list
|
||||
that would possibly cause a recursive stack-overflow during App.generate
|
||||
when App begins registering all user defined commands.</p>
|
||||
<p>However, while this does exist, due to the way that the App.generate method
|
||||
handles gathering root commands it makes this edge-case impossible to hit
|
||||
aside from manually running the
|
||||
Command#register_command([] of CliGen::Command) method.</p>
|
||||
<p>However, with this in place this issue cannot be hit at runtime as this will
|
||||
prevent compilation if a recursive/circular command tree exists.</p>
|
||||
<p>Additionally, this exists to prevent the user from defining a command tree
|
||||
that extends past the compile-time configured max via the
|
||||
CliGen::MAX_COMMAND_DEPTH constant.</p>
|
||||
<p>The reason this is a thing is because crystal macros don't allow for
|
||||
unbounded while's/until's in macros, meaning it always has to be
|
||||
deterministic. SO to deal with this and still allow for subcommand
|
||||
defining you need either go with the default (32 command depth) or
|
||||
define your own larger max (understand this will affect compile-time
|
||||
due to this directly affecting loops in the Command macros).</p>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="instance-method-detail" class="anchor" href="#instance-method-detail">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Instance Method Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="handler?:Bool-instance-method">
|
||||
<div class="signature">
|
||||
|
||||
def <strong>handler?</strong> : Bool
|
||||
|
||||
<a class="method-permalink" href="#handler%3F%3ABool-instance-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -398,7 +403,7 @@
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = <span class="n">nil</span>)</a>
|
||||
<a href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), parent : BaseCommandNode | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -456,6 +461,11 @@
|
||||
<h3>Instance methods inherited from class <code><a href="../CliGen/BaseCommandNode.html">CliGen::BaseCommandNode</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#all_commands%3AArray%28BaseCommandNode%29-instance-method" class="tooltip">
|
||||
<span>all_commands : Array(BaseCommandNode)</span>
|
||||
all_commands</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#all_flags%3AArray%28BaseFlag%29-instance-method" class="tooltip">
|
||||
<span>all_flags : Array(BaseFlag)</span>
|
||||
all_flags</a>,
|
||||
@@ -521,6 +531,11 @@
|
||||
name</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#parent%3F%3ABaseCommandNode%7CNil-instance-method" class="tooltip">
|
||||
<span>parent? : BaseCommandNode | Nil</span>
|
||||
parent?</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#process%28args%3AArray%28String%29%29%3ANil-instance-method" class="tooltip">
|
||||
<span>process(args : Array(String)) : Nil<br/>process(args : Array(CliGen::Arg)) : Nil</span>
|
||||
process</a>,
|
||||
@@ -548,8 +563,8 @@
|
||||
<h3>Constructor methods inherited from class <code><a href="../CliGen/BaseCommandNode.html">CliGen::BaseCommandNode</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/BaseCommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, description : String | Nil = <span class="n">nil</span>)</span>
|
||||
<a href="../CliGen/BaseCommandNode.html#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cmeta%3ACommandMeta%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method" class="tooltip">
|
||||
<span>new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, parent : BaseCommandNode | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)</span>
|
||||
new</a>
|
||||
|
||||
|
||||
@@ -600,12 +615,12 @@
|
||||
Constructor Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="new(name:String,flags:Array(BaseFlag),commands:Array(BaseCommandNode),pre_run_commands:Array(RunCommand),post_run_commands:Array(RunCommand),description:String|Nil=nil)-class-method">
|
||||
<div class="entry-detail" id="new(name:String,flags:Array(BaseFlag),commands:Array(BaseCommandNode),pre_run_commands:Array(RunCommand),post_run_commands:Array(RunCommand),parent:BaseCommandNode|Nil=nil,description:String|Nil=nil)-class-method">
|
||||
<div class="signature">
|
||||
|
||||
def self.<strong>new</strong>(name : String, flags : Array(<a href="../CliGen/BaseFlag.html">BaseFlag</a>), commands : Array(<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>), pre_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), post_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), description : String | Nil = <span class="n">nil</span>)
|
||||
def self.<strong>new</strong>(name : String, flags : Array(<a href="../CliGen/BaseFlag.html">BaseFlag</a>), commands : Array(<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>), pre_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), post_run_commands : Array(<a href="../CliGen/RunCommand.html">RunCommand</a>), parent : <a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a> | Nil = <span class="n">nil</span>, description : String | Nil = <span class="n">nil</span>)
|
||||
|
||||
<a class="method-permalink" href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cdescription%3AString%7CNil%3Dnil%29-class-method">#</a>
|
||||
<a class="method-permalink" href="#new%28name%3AString%2Cflags%3AArray%28BaseFlag%29%2Ccommands%3AArray%28BaseCommandNode%29%2Cpre_run_commands%3AArray%28RunCommand%29%2Cpost_run_commands%3AArray%28RunCommand%29%2Cparent%3ABaseCommandNode%7CNil%3Dnil%2Cdescription%3AString%7CNil%3Dnil%29-class-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -0,0 +1,444 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Crystal Docs 1.20.3">
|
||||
<meta name="crystal_docs.project_version" content="object_rework-dev">
|
||||
<meta name="crystal_docs.project_name" content="CliGenerator">
|
||||
|
||||
|
||||
|
||||
<link href="../css/style.css" rel="stylesheet" type="text/css" />
|
||||
<script type="text/javascript" src="../js/doc.js"></script>
|
||||
|
||||
<meta name="repository-name" content="CliGenerator">
|
||||
<title>CliGen::Common - CliGenerator object_rework-dev</title>
|
||||
<script type="text/javascript">
|
||||
CrystalDocs.base_path = "../";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg class="hidden">
|
||||
<symbol id="octicon-link" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path>
|
||||
</symbol>
|
||||
</svg>
|
||||
<input type="checkbox" id="sidebar-btn">
|
||||
<label for="sidebar-btn" id="sidebar-btn-label">
|
||||
<svg class="open" xmlns="http://www.w3.org/2000/svg" height="2em" width="2em" viewBox="0 0 512 512"><title>Open Sidebar</title><path fill="currentColor" d="M80 96v64h352V96H80zm0 112v64h352v-64H80zm0 112v64h352v-64H80z"></path></svg>
|
||||
<svg class="close" xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" viewBox="0 0 512 512"><title>Close Sidebar</title><path fill="currentColor" d="m118.6 73.4-45.2 45.2L210.7 256 73.4 393.4l45.2 45.2L256 301.3l137.4 137.3 45.2-45.2L301.3 256l137.3-137.4-45.2-45.2L256 210.7Z"></path></svg>
|
||||
</label>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="search-box">
|
||||
<input type="search" class="search-input" placeholder="Search..." spellcheck="false" aria-label="Search">
|
||||
</div>
|
||||
|
||||
<div class="project-summary">
|
||||
<h1 class="project-name">
|
||||
<a href="../index.html">
|
||||
CliGenerator
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<span class="project-version">
|
||||
object_rework-dev
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-results hidden">
|
||||
<ul class="search-list"></ul>
|
||||
</div>
|
||||
|
||||
<div class="types-list">
|
||||
<ul>
|
||||
|
||||
<li class="parent open current" data-id="CliGenerator/CliGen" data-name="cligen">
|
||||
<a href="../CliGen.html">CliGen</a>
|
||||
|
||||
<ul>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/App" data-name="cligen::app">
|
||||
<a href="../CliGen/App.html">App</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Arg" data-name="cligen::arg">
|
||||
<a href="../CliGen/Arg.html">Arg</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ArgReprocessedError" data-name="cligen::argreprocessederror">
|
||||
<a href="../CliGen/ArgReprocessedError.html">ArgReprocessedError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Argument" data-name="cligen::argument">
|
||||
<a href="../CliGen/Argument.html">Argument</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/BaseCommandNode" data-name="cligen::basecommandnode">
|
||||
<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/BaseFlag" data-name="cligen::baseflag">
|
||||
<a href="../CliGen/BaseFlag.html">BaseFlag</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Coercable" data-name="cligen::coercable">
|
||||
<a href="../CliGen/Coercable.html">Coercable</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Command" data-name="cligen::command">
|
||||
<a href="../CliGen/Command.html">Command</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandInfo" data-name="cligen::commandinfo">
|
||||
<a href="../CliGen/CommandInfo.html">CommandInfo</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandMeta" data-name="cligen::commandmeta">
|
||||
<a href="../CliGen/CommandMeta.html">CommandMeta</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandNode" data-name="cligen::commandnode(t)">
|
||||
<a href="../CliGen/CommandNode.html">CommandNode</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" current" data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/DuplicateCommandError" data-name="cligen::duplicatecommanderror">
|
||||
<a href="../CliGen/DuplicateCommandError.html">DuplicateCommandError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/DuplicateFlagError" data-name="cligen::duplicateflagerror">
|
||||
<a href="../CliGen/DuplicateFlagError.html">DuplicateFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Error" data-name="cligen::error">
|
||||
<a href="../CliGen/Error.html">Error</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Flag" data-name="cligen::flag(t)">
|
||||
<a href="../CliGen/Flag.html">Flag</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagArgumentError" data-name="cligen::flagargumenterror">
|
||||
<a href="../CliGen/FlagArgumentError.html">FlagArgumentError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagBundleError" data-name="cligen::flagbundleerror">
|
||||
<a href="../CliGen/FlagBundleError.html">FlagBundleError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagMeta" data-name="cligen::flagmeta">
|
||||
<a href="../CliGen/FlagMeta.html">FlagMeta</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagMissingArgumentError" data-name="cligen::flagmissingargumenterror">
|
||||
<a href="../CliGen/FlagMissingArgumentError.html">FlagMissingArgumentError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagNotFoundError" data-name="cligen::flagnotfounderror">
|
||||
<a href="../CliGen/FlagNotFoundError.html">FlagNotFoundError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Format" data-name="cligen::format">
|
||||
<a href="../CliGen/Format.html">Format</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/HelpRequestedError" data-name="cligen::helprequestederror">
|
||||
<a href="../CliGen/HelpRequestedError.html">HelpRequestedError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalError" data-name="cligen::internalerror">
|
||||
<a href="../CliGen/InternalError.html">InternalError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidOptionError" data-name="cligen::invalidoptionerror">
|
||||
<a href="../CliGen/InvalidOptionError.html">InvalidOptionError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MatchType" data-name="cligen::matchtype">
|
||||
<a href="../CliGen/MatchType.html">MatchType</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MissingDispatchError" data-name="cligen::missingdispatcherror">
|
||||
<a href="../CliGen/MissingDispatchError.html">MissingDispatchError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MissingRequiredFlagError" data-name="cligen::missingrequiredflagerror">
|
||||
<a href="../CliGen/MissingRequiredFlagError.html">MissingRequiredFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Parsable" data-name="cligen::parsable">
|
||||
<a href="../CliGen/Parsable.html">Parsable</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ParseableInvariantError" data-name="cligen::parseableinvarianterror">
|
||||
<a href="../CliGen/ParseableInvariantError.html">ParseableInvariantError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/PreRunCommand" data-name="cligen::preruncommand">
|
||||
<a href="../CliGen/PreRunCommand.html">PreRunCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ProxyCommand" data-name="cligen::proxycommand">
|
||||
<a href="../CliGen/ProxyCommand.html">ProxyCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Regex" data-name="cligen::regex">
|
||||
<a href="../CliGen/Regex.html">Regex</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RegexInvariantError" data-name="cligen::regexinvarianterror">
|
||||
<a href="../CliGen/RegexInvariantError.html">RegexInvariantError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ReservedFlagError" data-name="cligen::reservedflagerror">
|
||||
<a href="../CliGen/ReservedFlagError.html">ReservedFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RunCommand" data-name="cligen::runcommand">
|
||||
<a href="../CliGen/RunCommand.html">RunCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RuntimeError" data-name="cligen::runtimeerror">
|
||||
<a href="../CliGen/RuntimeError.html">RuntimeError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommandInfo" data-name="cligen::subcommandinfo">
|
||||
<a href="../CliGen/SubCommandInfo.html">SubCommandInfo</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="parent " data-id="CliGenerator/CliGen/Timeparse" data-name="cligen::timeparse">
|
||||
<a href="../CliGen/Timeparse.html">Timeparse</a>
|
||||
|
||||
<ul>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Timeparse/OperationUnit" data-name="cligen::timeparse::operationunit">
|
||||
<a href="../CliGen/Timeparse/OperationUnit.html">OperationUnit</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Timeparse/RelativeOperation" data-name="cligen::timeparse::relativeoperation">
|
||||
<a href="../CliGen/Timeparse/RelativeOperation.html">RelativeOperation</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/TimeParseError" data-name="cligen::timeparseerror">
|
||||
<a href="../CliGen/TimeParseError.html">TimeParseError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Trigger" data-name="cligen::trigger">
|
||||
<a href="../CliGen/Trigger.html">Trigger</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/UnknownCommandNodeError" data-name="cligen::unknowncommandnodeerror">
|
||||
<a href="../CliGen/UnknownCommandNodeError.html">UnknownCommandNodeError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/UnknownFlagError" data-name="cligen::unknownflagerror">
|
||||
<a href="../CliGen/UnknownFlagError.html">UnknownFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ValidationError" data-name="cligen::validationerror">
|
||||
<a href="../CliGen/ValidationError.html">ValidationError</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-content">
|
||||
<h1 class="type-name">
|
||||
|
||||
<span class="kind">
|
||||
module
|
||||
</span> CliGen::<wbr>Common
|
||||
|
||||
</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="defined-in" class="anchor" href="#defined-in">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Defined in:
|
||||
</h2>
|
||||
|
||||
|
||||
cligen/common/check_flag_vars.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="macro-summary" class="anchor" href="#macro-summary">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Macro Summary
|
||||
</h2>
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#check_flag_vars%28%2A%2Ctype%2Clong%2Cdescription%2Craise_base%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Coptions%3Dnil%2Cformat%3Dnil%2Cenv_var%3Dnil%2Cdelimiter%3D%22%2C%22%2Callow_no_verification%3Dfalse%2Cinternal%3Dfalse%29-macro" class="signature"><strong>check_flag_vars</strong>(*, type, long, description, raise_base, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, options = <span class="n">nil</span>, format = <span class="n">nil</span>, env_var = <span class="n">nil</span>, delimiter = <span class="s">","</span>, allow_no_verification = <span class="n">false</span>, internal = <span class="n">false</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="methods-inherited">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="macro-detail" class="anchor" href="#macro-detail">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Macro Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="check_flag_vars(*,type,long,description,raise_base,short=nil,validation=nil,on_match=nil,options=nil,format=nil,env_var=nil,delimiter=",",allow_no_verification=false,internal=false)-macro">
|
||||
<div class="signature">
|
||||
|
||||
macro <strong>check_flag_vars</strong>(*, type, long, description, raise_base, short = <span class="n">nil</span>, validation = <span class="n">nil</span>, on_match = <span class="n">nil</span>, options = <span class="n">nil</span>, format = <span class="n">nil</span>, env_var = <span class="n">nil</span>, delimiter = <span class="s">","</span>, allow_no_verification = <span class="n">false</span>, internal = <span class="n">false</span>)
|
||||
|
||||
<a class="method-permalink" href="#check_flag_vars%28%2A%2Ctype%2Clong%2Cdescription%2Craise_base%2Cshort%3Dnil%2Cvalidation%3Dnil%2Con_match%3Dnil%2Coptions%3Dnil%2Cformat%3Dnil%2Cenv_var%3Dnil%2Cdelimiter%3D%22%2C%22%2Callow_no_verification%3Dfalse%2Cinternal%3Dfalse%29-macro">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" current" data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+10
-5
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+18
-13
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -384,7 +389,7 @@
|
||||
<ul class="list-summary">
|
||||
|
||||
<li class="entry-summary">
|
||||
<a href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%2Cdescription%3AString%2Cdelimiter%3AString%3D%22%2C%22%2Cdefault%3AT%7CNil%3Dnil%2Coptions%3AArray%28T%29%7CNil%3Dnil%2Cvalidate%3AT-%3EBool%7CNil%3Dnil%2Con_match%3AProc%28T%2CNil%29%7CNil%3Dnil%2Cformat%3A%3A%3ARegex%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String = <span class="s">","</span>, default : T | Nil = <span class="n">nil</span>, options : Array(T) | Nil = <span class="n">nil</span>, validate : T -> Bool | Nil = <span class="n">nil</span>, on_match : Proc(T, Nil) | Nil = <span class="n">nil</span>, format : ::Regex | Nil = <span class="n">nil</span>)</a>
|
||||
<a href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%7CNil%2Cdescription%3AString%2Cdelimiter%3AString%3D%22%2C%22%2Cdefault%3AT%7CNil%3Dnil%2Coptions%3AArray%28T%29%7CNil%3Dnil%2Cvalidate%3AT-%3EBool%7CNil%3Dnil%2Con_match%3AProc%28T%2CNil%29%7CNil%3Dnil%2Cformat%3A%3A%3ARegex%7CNil%3Dnil%29-class-method" class="signature"><strong>.new</strong>(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String = <span class="s">","</span>, default : T | Nil = <span class="n">nil</span>, options : Array(T) | Nil = <span class="n">nil</span>, validate : T -> Bool | Nil = <span class="n">nil</span>, on_match : Proc(T, Nil) | Nil = <span class="n">nil</span>, format : ::Regex | Nil = <span class="n">nil</span>)</a>
|
||||
|
||||
</li>
|
||||
|
||||
@@ -467,8 +472,8 @@
|
||||
description</a>,
|
||||
|
||||
|
||||
<a href="../CliGen/BaseFlag.html#env_var%3AString-instance-method" class="tooltip">
|
||||
<span>env_var : String</span>
|
||||
<a href="../CliGen/BaseFlag.html#env_var%3AString%7CNil-instance-method" class="tooltip">
|
||||
<span>env_var : String | Nil</span>
|
||||
env_var</a>,
|
||||
|
||||
|
||||
@@ -524,8 +529,8 @@
|
||||
<h3>Constructor methods inherited from class <code><a href="../CliGen/BaseFlag.html">CliGen::BaseFlag</a></code></h3>
|
||||
|
||||
|
||||
<a href="../CliGen/BaseFlag.html#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method" class="tooltip">
|
||||
<span>new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta)</span>
|
||||
<a href="../CliGen/BaseFlag.html#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%7CNil%2Cdescription%3AString%2Cdelimiter%3AString%2Cmeta%3AFlagMeta%29-class-method" class="tooltip">
|
||||
<span>new(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : FlagMeta)</span>
|
||||
new</a>
|
||||
|
||||
|
||||
@@ -576,12 +581,12 @@
|
||||
Constructor Detail
|
||||
</h2>
|
||||
|
||||
<div class="entry-detail" id="new(var:String,short:String|Nil,long:String,env_var:String,description:String,delimiter:String=",",default:T|Nil=nil,options:Array(T)|Nil=nil,validate:T->Bool|Nil=nil,on_match:Proc(T,Nil)|Nil=nil,format:::Regex|Nil=nil)-class-method">
|
||||
<div class="entry-detail" id="new(var:String,short:String|Nil,long:String,env_var:String|Nil,description:String,delimiter:String=",",default:T|Nil=nil,options:Array(T)|Nil=nil,validate:T->Bool|Nil=nil,on_match:Proc(T,Nil)|Nil=nil,format:::Regex|Nil=nil)-class-method">
|
||||
<div class="signature">
|
||||
|
||||
def self.<strong>new</strong>(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String = <span class="s">","</span>, default : T | Nil = <span class="n">nil</span>, options : Array(T) | Nil = <span class="n">nil</span>, validate : T -> Bool | Nil = <span class="n">nil</span>, on_match : Proc(T, Nil) | Nil = <span class="n">nil</span>, format : ::Regex | Nil = <span class="n">nil</span>)
|
||||
def self.<strong>new</strong>(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String = <span class="s">","</span>, default : T | Nil = <span class="n">nil</span>, options : Array(T) | Nil = <span class="n">nil</span>, validate : T -> Bool | Nil = <span class="n">nil</span>, on_match : Proc(T, Nil) | Nil = <span class="n">nil</span>, format : ::Regex | Nil = <span class="n">nil</span>)
|
||||
|
||||
<a class="method-permalink" href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%2Cdescription%3AString%2Cdelimiter%3AString%3D%22%2C%22%2Cdefault%3AT%7CNil%3Dnil%2Coptions%3AArray%28T%29%7CNil%3Dnil%2Cvalidate%3AT-%3EBool%7CNil%3Dnil%2Con_match%3AProc%28T%2CNil%29%7CNil%3Dnil%2Cformat%3A%3A%3ARegex%7CNil%3Dnil%29-class-method">#</a>
|
||||
<a class="method-permalink" href="#new%28var%3AString%2Cshort%3AString%7CNil%2Clong%3AString%2Cenv_var%3AString%7CNil%2Cdescription%3AString%2Cdelimiter%3AString%3D%22%2C%22%2Cdefault%3AT%7CNil%3Dnil%2Coptions%3AArray%28T%29%7CNil%3Dnil%2Cvalidate%3AT-%3EBool%7CNil%3Dnil%2Con_match%3AProc%28T%2CNil%29%7CNil%3Dnil%2Cformat%3A%3A%3ARegex%7CNil%3Dnil%29-class-method">#</a>
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+10
-5
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -0,0 +1,403 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<meta name="generator" content="Crystal Docs 1.20.3">
|
||||
<meta name="crystal_docs.project_version" content="object_rework-dev">
|
||||
<meta name="crystal_docs.project_name" content="CliGenerator">
|
||||
|
||||
|
||||
|
||||
<link href="../css/style.css" rel="stylesheet" type="text/css" />
|
||||
<script type="text/javascript" src="../js/doc.js"></script>
|
||||
|
||||
<meta name="repository-name" content="CliGenerator">
|
||||
<title>CliGen::InternalVar - CliGenerator object_rework-dev</title>
|
||||
<script type="text/javascript">
|
||||
CrystalDocs.base_path = "../";
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<svg class="hidden">
|
||||
<symbol id="octicon-link" viewBox="0 0 16 16">
|
||||
<path fill="currentColor" fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path>
|
||||
</symbol>
|
||||
</svg>
|
||||
<input type="checkbox" id="sidebar-btn">
|
||||
<label for="sidebar-btn" id="sidebar-btn-label">
|
||||
<svg class="open" xmlns="http://www.w3.org/2000/svg" height="2em" width="2em" viewBox="0 0 512 512"><title>Open Sidebar</title><path fill="currentColor" d="M80 96v64h352V96H80zm0 112v64h352v-64H80zm0 112v64h352v-64H80z"></path></svg>
|
||||
<svg class="close" xmlns="http://www.w3.org/2000/svg" width="2em" height="2em" viewBox="0 0 512 512"><title>Close Sidebar</title><path fill="currentColor" d="m118.6 73.4-45.2 45.2L210.7 256 73.4 393.4l45.2 45.2L256 301.3l137.4 137.3 45.2-45.2L301.3 256l137.3-137.4-45.2-45.2L256 210.7Z"></path></svg>
|
||||
</label>
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="search-box">
|
||||
<input type="search" class="search-input" placeholder="Search..." spellcheck="false" aria-label="Search">
|
||||
</div>
|
||||
|
||||
<div class="project-summary">
|
||||
<h1 class="project-name">
|
||||
<a href="../index.html">
|
||||
CliGenerator
|
||||
</a>
|
||||
</h1>
|
||||
|
||||
<span class="project-version">
|
||||
object_rework-dev
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="search-results hidden">
|
||||
<ul class="search-list"></ul>
|
||||
</div>
|
||||
|
||||
<div class="types-list">
|
||||
<ul>
|
||||
|
||||
<li class="parent open current" data-id="CliGenerator/CliGen" data-name="cligen">
|
||||
<a href="../CliGen.html">CliGen</a>
|
||||
|
||||
<ul>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/App" data-name="cligen::app">
|
||||
<a href="../CliGen/App.html">App</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Arg" data-name="cligen::arg">
|
||||
<a href="../CliGen/Arg.html">Arg</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ArgReprocessedError" data-name="cligen::argreprocessederror">
|
||||
<a href="../CliGen/ArgReprocessedError.html">ArgReprocessedError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Argument" data-name="cligen::argument">
|
||||
<a href="../CliGen/Argument.html">Argument</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/BaseCommandNode" data-name="cligen::basecommandnode">
|
||||
<a href="../CliGen/BaseCommandNode.html">BaseCommandNode</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/BaseFlag" data-name="cligen::baseflag">
|
||||
<a href="../CliGen/BaseFlag.html">BaseFlag</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Coercable" data-name="cligen::coercable">
|
||||
<a href="../CliGen/Coercable.html">Coercable</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Command" data-name="cligen::command">
|
||||
<a href="../CliGen/Command.html">Command</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandInfo" data-name="cligen::commandinfo">
|
||||
<a href="../CliGen/CommandInfo.html">CommandInfo</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandMeta" data-name="cligen::commandmeta">
|
||||
<a href="../CliGen/CommandMeta.html">CommandMeta</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/CommandNode" data-name="cligen::commandnode(t)">
|
||||
<a href="../CliGen/CommandNode.html">CommandNode</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/DuplicateCommandError" data-name="cligen::duplicatecommanderror">
|
||||
<a href="../CliGen/DuplicateCommandError.html">DuplicateCommandError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/DuplicateFlagError" data-name="cligen::duplicateflagerror">
|
||||
<a href="../CliGen/DuplicateFlagError.html">DuplicateFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Error" data-name="cligen::error">
|
||||
<a href="../CliGen/Error.html">Error</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Flag" data-name="cligen::flag(t)">
|
||||
<a href="../CliGen/Flag.html">Flag</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagArgumentError" data-name="cligen::flagargumenterror">
|
||||
<a href="../CliGen/FlagArgumentError.html">FlagArgumentError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagBundleError" data-name="cligen::flagbundleerror">
|
||||
<a href="../CliGen/FlagBundleError.html">FlagBundleError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagMeta" data-name="cligen::flagmeta">
|
||||
<a href="../CliGen/FlagMeta.html">FlagMeta</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagMissingArgumentError" data-name="cligen::flagmissingargumenterror">
|
||||
<a href="../CliGen/FlagMissingArgumentError.html">FlagMissingArgumentError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/FlagNotFoundError" data-name="cligen::flagnotfounderror">
|
||||
<a href="../CliGen/FlagNotFoundError.html">FlagNotFoundError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Format" data-name="cligen::format">
|
||||
<a href="../CliGen/Format.html">Format</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/HelpRequestedError" data-name="cligen::helprequestederror">
|
||||
<a href="../CliGen/HelpRequestedError.html">HelpRequestedError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalError" data-name="cligen::internalerror">
|
||||
<a href="../CliGen/InternalError.html">InternalError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" current" data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidOptionError" data-name="cligen::invalidoptionerror">
|
||||
<a href="../CliGen/InvalidOptionError.html">InvalidOptionError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MatchType" data-name="cligen::matchtype">
|
||||
<a href="../CliGen/MatchType.html">MatchType</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MissingDispatchError" data-name="cligen::missingdispatcherror">
|
||||
<a href="../CliGen/MissingDispatchError.html">MissingDispatchError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/MissingRequiredFlagError" data-name="cligen::missingrequiredflagerror">
|
||||
<a href="../CliGen/MissingRequiredFlagError.html">MissingRequiredFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Parsable" data-name="cligen::parsable">
|
||||
<a href="../CliGen/Parsable.html">Parsable</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ParseableInvariantError" data-name="cligen::parseableinvarianterror">
|
||||
<a href="../CliGen/ParseableInvariantError.html">ParseableInvariantError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/PreRunCommand" data-name="cligen::preruncommand">
|
||||
<a href="../CliGen/PreRunCommand.html">PreRunCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ProxyCommand" data-name="cligen::proxycommand">
|
||||
<a href="../CliGen/ProxyCommand.html">ProxyCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Regex" data-name="cligen::regex">
|
||||
<a href="../CliGen/Regex.html">Regex</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RegexInvariantError" data-name="cligen::regexinvarianterror">
|
||||
<a href="../CliGen/RegexInvariantError.html">RegexInvariantError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ReservedFlagError" data-name="cligen::reservedflagerror">
|
||||
<a href="../CliGen/ReservedFlagError.html">ReservedFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RunCommand" data-name="cligen::runcommand">
|
||||
<a href="../CliGen/RunCommand.html">RunCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/RuntimeError" data-name="cligen::runtimeerror">
|
||||
<a href="../CliGen/RuntimeError.html">RuntimeError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommandInfo" data-name="cligen::subcommandinfo">
|
||||
<a href="../CliGen/SubCommandInfo.html">SubCommandInfo</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class="parent " data-id="CliGenerator/CliGen/Timeparse" data-name="cligen::timeparse">
|
||||
<a href="../CliGen/Timeparse.html">Timeparse</a>
|
||||
|
||||
<ul>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Timeparse/OperationUnit" data-name="cligen::timeparse::operationunit">
|
||||
<a href="../CliGen/Timeparse/OperationUnit.html">OperationUnit</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Timeparse/RelativeOperation" data-name="cligen::timeparse::relativeoperation">
|
||||
<a href="../CliGen/Timeparse/RelativeOperation.html">RelativeOperation</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/TimeParseError" data-name="cligen::timeparseerror">
|
||||
<a href="../CliGen/TimeParseError.html">TimeParseError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Trigger" data-name="cligen::trigger">
|
||||
<a href="../CliGen/Trigger.html">Trigger</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/UnknownCommandNodeError" data-name="cligen::unknowncommandnodeerror">
|
||||
<a href="../CliGen/UnknownCommandNodeError.html">UnknownCommandNodeError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/UnknownFlagError" data-name="cligen::unknownflagerror">
|
||||
<a href="../CliGen/UnknownFlagError.html">UnknownFlagError</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ValidationError" data-name="cligen::validationerror">
|
||||
<a href="../CliGen/ValidationError.html">ValidationError</a>
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="main-content">
|
||||
<h1 class="type-name">
|
||||
|
||||
<span class="kind">
|
||||
annotation
|
||||
</span> CliGen::<wbr>InternalVar
|
||||
|
||||
</h1>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<h2>
|
||||
<a id="defined-in" class="anchor" href="#defined-in">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>
|
||||
Defined in:
|
||||
</h2>
|
||||
|
||||
|
||||
cligen/annotations.cr
|
||||
|
||||
<br/>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div class="methods-inherited">
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" current" data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+22
-7
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -390,8 +395,13 @@
|
||||
</dt>
|
||||
|
||||
|
||||
<dt class="entry-const" id="FLAG_LONG">
|
||||
<strong>FLAG_LONG</strong> = <code><span class="s">/^--[a-zA-Z0-9][a-zA-Z0-9-_]+$/</span></code>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt class="entry-const" id="FLAG_MULTIPLE_SHORT">
|
||||
<strong>FLAG_MULTIPLE_SHORT</strong> = <code><span class="s">/^-[a-zA-Z0-9]+$/</span></code>
|
||||
<strong>FLAG_MULTIPLE_SHORT</strong> = <code><span class="s">/^-[a-zA-Z][a-zA-Z]+$/</span></code>
|
||||
</dt>
|
||||
|
||||
|
||||
@@ -400,8 +410,13 @@
|
||||
</dt>
|
||||
|
||||
|
||||
<dt class="entry-const" id="FLAG_SHORT">
|
||||
<strong>FLAG_SHORT</strong> = <code><span class="s">/^-[a-zA-Z]$/</span></code>
|
||||
</dt>
|
||||
|
||||
|
||||
<dt class="entry-const" id="FLAG_WITH_ARG">
|
||||
<strong>FLAG_WITH_ARG</strong> = <code><span class="s">/^(?<flag>(-[a-zA-Z]|--[a-zA-Z-_]+))="?(?<arg>\S+?)"?$/</span></code>
|
||||
<strong>FLAG_WITH_ARG</strong> = <code><span class="s">/^(?<flag>(-[a-zA-Z]|--[a-zA-Z0-9][a-zA-Z0-9-_]+))="?(?<arg>.+?)"?$/</span></code>
|
||||
</dt>
|
||||
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" current" data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="../CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="../CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="../CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="../CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="../CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="../CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
|
||||
+11
-6
@@ -117,6 +117,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Common" data-name="cligen::common">
|
||||
<a href="CliGen/Common.html">Common</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/ConfigurationError" data-name="cligen::configurationerror">
|
||||
<a href="CliGen/ConfigurationError.html">ConfigurationError</a>
|
||||
|
||||
@@ -182,6 +187,11 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InternalVar" data-name="cligen::internalvar">
|
||||
<a href="CliGen/InternalVar.html">InternalVar</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/InvalidFlagValueError" data-name="cligen::invalidflagvalueerror">
|
||||
<a href="CliGen/InvalidFlagValueError.html">InvalidFlagValueError</a>
|
||||
|
||||
@@ -252,11 +262,6 @@
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/Selection" data-name="cligen::selection">
|
||||
<a href="CliGen/Selection.html">Selection</a>
|
||||
|
||||
</li>
|
||||
|
||||
<li class=" " data-id="CliGenerator/CliGen/SubCommand" data-name="cligen::subcommand">
|
||||
<a href="CliGen/SubCommand.html">SubCommand</a>
|
||||
|
||||
@@ -334,7 +339,7 @@
|
||||
<use href="#octicon-link"/>
|
||||
</svg>
|
||||
</a>How It Works</h2>
|
||||
<p>Subclass <code><a href="CliGen/Command.html">CliGen::Command</a></code>, annotate your instance variables with <code>@[<a href="CliGen/Argument.html">CliGen::Argument</a>]</code> or <code>@[<a href="CliGen/Selection.html">CliGen::Selection</a>]</code>, and register the command with an <code><a href="CliGen/App.html">CliGen::App</a></code>. At compile time, macros inspect the annotations and generate typed <code>Flag(T)</code> objects; at runtime, <code>CliGen::App.process</code> walks the <code>CommandNode</code> tree to route arguments, populate your command instance, and dispatch to the right method.</p>
|
||||
<p>Subclass <code><a href="CliGen/Command.html">CliGen::Command</a></code>, annotate your instance variables with <code>@[<a href="CliGen/Argument.html">CliGen::Argument</a>]</code>, and register the command with an <code><a href="CliGen/App.html">CliGen::App</a></code>. At compile time, macros inspect the annotations and generate typed <code>Flag(T)</code> objects; at runtime, <code>CliGen::App.process</code> walks the <code>CommandNode</code> tree to route arguments, populate your command instance, and dispatch to the right method.</p>
|
||||
<h2><a id="installation" class="anchor" href="#installation">
|
||||
<svg class="octicon-link" aria-hidden="true">
|
||||
<use href="#octicon-link"/>
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
{"repository_name":"CliGenerator","body":"# cligen\n\nA Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.\n\n## How It Works\n\nSubclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]` or `@[CliGen::Selection]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n ```yaml\n dependencies:\n cligen:\n git: https://git.arcanium.tech/tristan/cligen\n ```\n\n2. Run `shards install`\n\n## Usage\n\n```crystal\nrequire \"cligen\"\n\n@[CliGen::CommandInfo(description: \"Greet someone\")]\nclass Greet < CliGen::Command\n @[CliGen::Argument(short: \"-n\", long: \"--name VALUE\", description: \"Name to greet\")]\n @name : String = \"world\"\n \n argument(otherval : String = \"abc\",\n long: \"--other\",\n short: \"-o\",\n options: %w[ abc def ghi ],\n description: \"This provides a way of setting the second string taht is printed\"\n )\n \n argument(myvars : Array(String) = [ \"a\" ],\n short: \"-m\",\n options: %w[ a b c ],\n description: \"Provide multiple things to be printed out in the main function\"\n )\n\n def main\n puts \"1) Hello, #{@name}!\"\n puts \"2) #{@otherval}\"\n @myvars.each_with_index do |var, index|\n puts \"%d) %s\" % [ 3 + index, var ]\n end\n end\nend\n\nCliGen::App.process\n```\n\n```\n$ myapp greet --name Alice -m a a -m a,a,b\n1) Hello, Alice!\n2) abc\n3) a \n4) a \n5) a \n6) a \n7) b\n```\n\nFull API documentation and design notes are in [`design.adoc`](design.adoc).\n\n## Architecture\n\nAs a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.\n\nSubclassing to `CliGen::Command` injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library `src/cligen/app/generate.cr` to generate a object graph of your commands and all annotated \"arguments/flags\" and stores them in a tree from the App object itself.\n\nThis allows the project to \"learn\" your project & generate a command tree from the defined data.\n\nThe MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with `CliGen::Coercable` && `CliGen::Parsable` modules and define the `self.parse_args(args : Array(CliGen::Arg)` and `self.coerce(arg : String)` class methods.\n\nEX:\n```crystal\nmodule MyModule\n class MyData\n extend CliGen::Parsable\n extend CliGen::Coercable\n \n @value : Int32\n \n def initialize(value : String)\n @value = value.to_i32\n end\n \n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed\n arg.processed\n new(arg.value)\n \n end\n \n def self.coerce(arg : String)\n new(arg)\n end\n end\nend\n```\n\n\nCoercable Method:\n-----------------\n```crystal\n def self.coerce(arg : String)\n new(arg)\n end\n```\n\nThe coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type. \n\nThis should only be used in the case you need a simple datatype that can be learned from a single string.\n\nParsable Method:\n----------------\n```crystal\n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed (required)\n arg.processed\n new(arg.value)\n end\n```\n\nThis method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.\n\nThis gives the framework a way to allow you to extend the parser in your own custom way to allow for a \"custom\" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.\n\n## Development\n\n```bash\n# Type-cheLine truncated
|
||||
{"repository_name":"CliGenerator","body":"# cligen\n\nA Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.\n\n## How It Works\n\nSubclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n ```yaml\n dependencies:\n cligen:\n git: https://git.arcanium.tech/tristan/cligen\n ```\n\n2. Run `shards install`\n\n## Usage\n\n```crystal\nrequire \"cligen\"\n\n@[CliGen::CommandInfo(description: \"Greet someone\")]\nclass Greet < CliGen::Command\n @[CliGen::Argument(short: \"-n\", long: \"--name VALUE\", description: \"Name to greet\")]\n @name : String = \"world\"\n \n argument(otherval : String = \"abc\",\n long: \"--other\",\n short: \"-o\",\n options: %w[ abc def ghi ],\n description: \"This provides a way of setting the second string taht is printed\"\n )\n \n argument(myvars : Array(String) = [ \"a\" ],\n short: \"-m\",\n options: %w[ a b c ],\n description: \"Provide multiple things to be printed out in the main function\"\n )\n\n def main\n puts \"1) Hello, #{@name}!\"\n puts \"2) #{@otherval}\"\n @myvars.each_with_index do |var, index|\n puts \"%d) %s\" % [ 3 + index, var ]\n end\n end\nend\n\nCliGen::App.process\n```\n\n```\n$ myapp greet --name Alice -m a a -m a,a,b\n1) Hello, Alice!\n2) abc\n3) a \n4) a \n5) a \n6) a \n7) b\n```\n\nFull API documentation and design notes are in [`design.adoc`](design.adoc).\n\n## Architecture\n\nAs a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.\n\nSubclassing to `CliGen::Command` injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library `src/cligen/app/generate.cr` to generate a object graph of your commands and all annotated \"arguments/flags\" and stores them in a tree from the App object itself.\n\nThis allows the project to \"learn\" your project & generate a command tree from the defined data.\n\nThe MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with `CliGen::Coercable` && `CliGen::Parsable` modules and define the `self.parse_args(args : Array(CliGen::Arg)` and `self.coerce(arg : String)` class methods.\n\nEX:\n```crystal\nmodule MyModule\n class MyData\n extend CliGen::Parsable\n extend CliGen::Coercable\n \n @value : Int32\n \n def initialize(value : String)\n @value = value.to_i32\n end\n \n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed\n arg.processed\n new(arg.value)\n \n end\n \n def self.coerce(arg : String)\n new(arg)\n end\n end\nend\n```\n\n\nCoercable Method:\n-----------------\n```crystal\n def self.coerce(arg : String)\n new(arg)\n end\n```\n\nThe coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type. \n\nThis should only be used in the case you need a simple datatype that can be learned from a single string.\n\nParsable Method:\n----------------\n```crystal\n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed (required)\n arg.processed\n new(arg.value)\n end\n```\n\nThis method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.\n\nThis gives the framework a way to allow you to extend the parser in your own custom way to allow for a \"custom\" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.\n\n## Development\n\n```bash\n# Type-check without running\ncrystaLine truncated
|
||||
@@ -1 +1 @@
|
||||
crystal_doc_search_index_callback({"repository_name":"CliGenerator","body":"# cligen\n\nA Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.\n\n## How It Works\n\nSubclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]` or `@[CliGen::Selection]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n ```yaml\n dependencies:\n cligen:\n git: https://git.arcanium.tech/tristan/cligen\n ```\n\n2. Run `shards install`\n\n## Usage\n\n```crystal\nrequire \"cligen\"\n\n@[CliGen::CommandInfo(description: \"Greet someone\")]\nclass Greet < CliGen::Command\n @[CliGen::Argument(short: \"-n\", long: \"--name VALUE\", description: \"Name to greet\")]\n @name : String = \"world\"\n \n argument(otherval : String = \"abc\",\n long: \"--other\",\n short: \"-o\",\n options: %w[ abc def ghi ],\n description: \"This provides a way of setting the second string taht is printed\"\n )\n \n argument(myvars : Array(String) = [ \"a\" ],\n short: \"-m\",\n options: %w[ a b c ],\n description: \"Provide multiple things to be printed out in the main function\"\n )\n\n def main\n puts \"1) Hello, #{@name}!\"\n puts \"2) #{@otherval}\"\n @myvars.each_with_index do |var, index|\n puts \"%d) %s\" % [ 3 + index, var ]\n end\n end\nend\n\nCliGen::App.process\n```\n\n```\n$ myapp greet --name Alice -m a a -m a,a,b\n1) Hello, Alice!\n2) abc\n3) a \n4) a \n5) a \n6) a \n7) b\n```\n\nFull API documentation and design notes are in [`design.adoc`](design.adoc).\n\n## Architecture\n\nAs a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.\n\nSubclassing to `CliGen::Command` injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library `src/cligen/app/generate.cr` to generate a object graph of your commands and all annotated \"arguments/flags\" and stores them in a tree from the App object itself.\n\nThis allows the project to \"learn\" your project & generate a command tree from the defined data.\n\nThe MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with `CliGen::Coercable` && `CliGen::Parsable` modules and define the `self.parse_args(args : Array(CliGen::Arg)` and `self.coerce(arg : String)` class methods.\n\nEX:\n```crystal\nmodule MyModule\n class MyData\n extend CliGen::Parsable\n extend CliGen::Coercable\n \n @value : Int32\n \n def initialize(value : String)\n @value = value.to_i32\n end\n \n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed\n arg.processed\n new(arg.value)\n \n end\n \n def self.coerce(arg : String)\n new(arg)\n end\n end\nend\n```\n\n\nCoercable Method:\n-----------------\n```crystal\n def self.coerce(arg : String)\n new(arg)\n end\n```\n\nThe coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type. \n\nThis should only be used in the case you need a simple datatype that can be learned from a single string.\n\nParsable Method:\n----------------\n```crystal\n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed (required)\n arg.processed\n new(arg.value)\n end\n```\n\nThis method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.\n\nThis gives the framework a way to allow you to extend the parser in your own custom way to allow for a \"custom\" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.\n\n##
Line truncated
|
||||
crystal_doc_search_index_callback({"repository_name":"CliGenerator","body":"# cligen\n\nA Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.\n\n## How It Works\n\nSubclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n ```yaml\n dependencies:\n cligen:\n git: https://git.arcanium.tech/tristan/cligen\n ```\n\n2. Run `shards install`\n\n## Usage\n\n```crystal\nrequire \"cligen\"\n\n@[CliGen::CommandInfo(description: \"Greet someone\")]\nclass Greet < CliGen::Command\n @[CliGen::Argument(short: \"-n\", long: \"--name VALUE\", description: \"Name to greet\")]\n @name : String = \"world\"\n \n argument(otherval : String = \"abc\",\n long: \"--other\",\n short: \"-o\",\n options: %w[ abc def ghi ],\n description: \"This provides a way of setting the second string taht is printed\"\n )\n \n argument(myvars : Array(String) = [ \"a\" ],\n short: \"-m\",\n options: %w[ a b c ],\n description: \"Provide multiple things to be printed out in the main function\"\n )\n\n def main\n puts \"1) Hello, #{@name}!\"\n puts \"2) #{@otherval}\"\n @myvars.each_with_index do |var, index|\n puts \"%d) %s\" % [ 3 + index, var ]\n end\n end\nend\n\nCliGen::App.process\n```\n\n```\n$ myapp greet --name Alice -m a a -m a,a,b\n1) Hello, Alice!\n2) abc\n3) a \n4) a \n5) a \n6) a \n7) b\n```\n\nFull API documentation and design notes are in [`design.adoc`](design.adoc).\n\n## Architecture\n\nAs a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.\n\nSubclassing to `CliGen::Command` injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library `src/cligen/app/generate.cr` to generate a object graph of your commands and all annotated \"arguments/flags\" and stores them in a tree from the App object itself.\n\nThis allows the project to \"learn\" your project & generate a command tree from the defined data.\n\nThe MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with `CliGen::Coercable` && `CliGen::Parsable` modules and define the `self.parse_args(args : Array(CliGen::Arg)` and `self.coerce(arg : String)` class methods.\n\nEX:\n```crystal\nmodule MyModule\n class MyData\n extend CliGen::Parsable\n extend CliGen::Coercable\n \n @value : Int32\n \n def initialize(value : String)\n @value = value.to_i32\n end\n \n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed\n arg.processed\n new(arg.value)\n \n end\n \n def self.coerce(arg : String)\n new(arg)\n end\n end\nend\n```\n\n\nCoercable Method:\n-----------------\n```crystal\n def self.coerce(arg : String)\n new(arg)\n end\n```\n\nThe coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type. \n\nThis should only be used in the case you need a simple datatype that can be learned from a single string.\n\nParsable Method:\n----------------\n```crystal\n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed (required)\n arg.processed\n new(arg.value)\n end\n```\n\nThis method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.\n\nThis gives the framework a way to allow you to extend the parser in your own custom way to allow for a \"custom\" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.\n\n## Development\n\n```bash\n#
Line truncated
|
||||
@@ -1,5 +1,5 @@
|
||||
name: cligen
|
||||
version: 0.1.0
|
||||
version: 0.2.0
|
||||
|
||||
authors:
|
||||
- Tristan Ancelet <[email protected]>
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
require "../spec_helper"
|
||||
|
||||
@[CliGen::CommandInfo(description: "Abc", singleton_init: true)]
|
||||
class MyCmd < CliGen::Command
|
||||
|
||||
argument(abcdef : String = "123",
|
||||
description: "This is a thing"
|
||||
)
|
||||
argument(ghijkl : Int32 = 666,
|
||||
description: "The number of the devil"
|
||||
)
|
||||
argument(badvar : String,
|
||||
description: "This will fail on init"
|
||||
)
|
||||
|
||||
def main
|
||||
puts "abc"
|
||||
end
|
||||
|
||||
def get_badvar
|
||||
resolve_value badvar, default: "was unset"
|
||||
end
|
||||
end
|
||||
|
||||
@[CliGen::CommandInfo(description: "Def", parent: ::MyCmd, singleton_init: true)]
|
||||
class MySubCmd < CliGen::Command
|
||||
argument(dfdfdf : String = "abc",
|
||||
description: "ALKJSDFLSKDFJ"
|
||||
)
|
||||
def main
|
||||
resolve_value abcdef
|
||||
end
|
||||
end
|
||||
|
||||
@[CliGen::CommandInfo(description: "Def", parent: ::MySubCmd, singleton_init: true)]
|
||||
class MySubSubCmd < CliGen::Command
|
||||
def main
|
||||
resolve_value ghijkl
|
||||
end
|
||||
|
||||
def main2
|
||||
resolve_value badvar, default: "unset"
|
||||
end
|
||||
end
|
||||
|
||||
def get_handler_for(cls : String)
|
||||
if handler = CliGen::App.get.all_commands.find(&.meta.cls.== cls)
|
||||
handler
|
||||
else
|
||||
raise "ERROR"
|
||||
end
|
||||
end
|
||||
|
||||
describe CliGen::Command do
|
||||
before_each do
|
||||
ENV.delete("MYCMD_BADVAR")
|
||||
end
|
||||
|
||||
describe "#resolve_value" do
|
||||
it "does work 1 level deep" do
|
||||
MySubCmd.new.main.should eq("123")
|
||||
end
|
||||
|
||||
it "works 2 levels deep" do
|
||||
MySubSubCmd.new.main.should eq(666)
|
||||
end
|
||||
|
||||
it "If a argument is without a default value it will fall back to the default" do
|
||||
MySubSubCmd.new.main2.should eq("unset")
|
||||
end
|
||||
|
||||
it "will return the provided value if the Flag(T) has an ENVVAR to match" do
|
||||
ENV["MYCMD_BADVAR"]="ABC"
|
||||
MySubSubCmd.new.main2.should eq("ABC")
|
||||
end
|
||||
|
||||
it "works on instance variables" do
|
||||
a = "the cake was a lie"
|
||||
ENV["MYCMD_BADVAR"] = a
|
||||
handler = get_handler_for("MyCmd")
|
||||
MyCmd.new(handler: handler).get_badvar.should eq(a)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#initialize" do
|
||||
it "will raise CliGen::MissingRequiredFlagError on handler initialize if no flag value is set for badvar" do
|
||||
handler = get_handler_for("MyCmd")
|
||||
expect_raises(CliGen::MissingRequiredFlagError) do
|
||||
MyCmd.new(handler: handler)
|
||||
end
|
||||
end
|
||||
|
||||
it "will not raise if badvar is set via ENV VAR" do
|
||||
ENV["MYCMD_BADVAR"]="the cake was a lie"
|
||||
handler = get_handler_for("MyCmd")
|
||||
MyCmd.new(handler: handler).get_badvar.should eq("the cake was a lie")
|
||||
end
|
||||
end
|
||||
|
||||
describe ".get" do
|
||||
it "will raise CliGen::AppNotProcessedError if a user attempts to use .get before CliGen::App has processed commandline arguments" do
|
||||
expect_raises(CliGen::AppNotProcessedError) do
|
||||
MySubCmd.get
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -104,21 +104,21 @@ describe CliGen::Flag do
|
||||
before_each { ENV.delete("TEST") }
|
||||
|
||||
describe "#check!" do
|
||||
it "will throw CliGen::ReservedFlagError if -h is used as short" do
|
||||
expect_raises(CliGen::ReservedFlagError) do
|
||||
make_flag(type: Bool, short: "-h", long: "--not-help").check!
|
||||
it "will throw CliGen::ConfigurationError if a short is provided as a long" do
|
||||
expect_raises(CliGen::ConfigurationError) do
|
||||
make_flag(type: Bool, short: nil, long: "-n").check!
|
||||
end
|
||||
end
|
||||
|
||||
it "will throw CliGen::ReservedFlagError if --help is used in long" do
|
||||
expect_raises(CliGen::ReservedFlagError) do
|
||||
make_flag(type: Bool, short: "-b", long: "--help TOPIC").check!
|
||||
it "will throw CliGen::ConfigurationError if a long is provided as a short" do
|
||||
expect_raises(CliGen::ConfigurationError) do
|
||||
make_flag(type: Bool, short: "--b", long: "--help TOPIC").check!
|
||||
end
|
||||
end
|
||||
|
||||
it "will throw CliGen::ReservedFlagError if --help is used as long_key" do
|
||||
expect_raises(CliGen::ReservedFlagError) do
|
||||
make_flag(type: Bool, short: "-b", long: "--help").check!
|
||||
it "will throw CliGen::ConfigurationError if long flag does not have enough characters" do
|
||||
expect_raises(CliGen::ConfigurationError) do
|
||||
make_flag(type: Bool, short: "-b", long: "--h").check!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
require "../spec_helper"
|
||||
|
||||
|
||||
macro get_match(a, b, &work)
|
||||
match = CliGen::Regex::{{a}}.match({{b}}).not_nil!
|
||||
{{work.body}}
|
||||
end
|
||||
|
||||
macro does_match(a, b)
|
||||
CliGen::Regex::{{a}}.matches?({{b}}).should be_true
|
||||
end
|
||||
|
||||
macro doesnt_match(a, b)
|
||||
CliGen::Regex::{{a}}.matches?({{b}}).should be_false
|
||||
end
|
||||
|
||||
describe CliGen::Regex do
|
||||
describe "FLAG_REGEX" do
|
||||
it "will match LONG (--long) format" do
|
||||
does_match(FLAG_REGEX, "--long")
|
||||
end
|
||||
|
||||
it "will match a SHORT (-s) format" do
|
||||
does_match(FLAG_REGEX, "-s")
|
||||
end
|
||||
|
||||
it "will not match a LONG with an arg (--long=abc)" do
|
||||
doesnt_match(FLAG_REGEX, "--long=abc")
|
||||
end
|
||||
|
||||
it "will not match a SHORT with an arg (-s=abc)" do
|
||||
doesnt_match(FLAG_REGEX, "-s=abc")
|
||||
end
|
||||
end
|
||||
|
||||
describe "FLAG_WITH_ARG" do
|
||||
it "will match a LONG with arg without quotes (--long=arg)" do
|
||||
get_match(FLAG_WITH_ARG, "--long=arg") do
|
||||
match["flag"].should eq("--long")
|
||||
match["arg"].should eq("arg")
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a LONG with arg with quotes (--long=\"arg\")" do
|
||||
get_match(FLAG_WITH_ARG, "--long=\"arg\"") do
|
||||
match["flag"].should eq("--long")
|
||||
match["arg"].should eq("arg")
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a LONG with arg with quotes and spaces in the arg (--long=\"arg abcd ef\")" do
|
||||
get_match(FLAG_WITH_ARG, "--long=\"arg abcd ef\"") do
|
||||
match["flag"].should eq("--long")
|
||||
match["arg"].should eq("arg abcd ef")
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a LONG with arg without quotes and with spaces in the arg (--long=arg abcd ef)" do
|
||||
get_match(FLAG_WITH_ARG, "--long=arg abcd ef") do
|
||||
match["flag"].should eq("--long")
|
||||
match["arg"].should eq("arg abcd ef")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "FLAG_MULTIPLE_SHORT" do
|
||||
it "does match a valid multi-short flag (-abcdef)" do
|
||||
does_match(FLAG_MULTIPLE_SHORT, "-abcdef")
|
||||
end
|
||||
|
||||
it "does not match a singleshort flag (-a)" do
|
||||
doesnt_match(FLAG_MULTIPLE_SHORT, "-a")
|
||||
end
|
||||
|
||||
{% for int in (0..9) %}
|
||||
it "does not match a multi-short flag with a digit in it (-abc{{int}}) as -{{int}} is not a valid short" do
|
||||
doesnt_match(FLAG_MULTIPLE_SHORT, "-abc{{int}}")
|
||||
end
|
||||
{% end %}
|
||||
|
||||
it "does not match a long flag (--long)" do
|
||||
doesnt_match(FLAG_MULTIPLE_SHORT, "--long")
|
||||
end
|
||||
end
|
||||
|
||||
describe "FLAG_LONG" do
|
||||
it "matches a valid long flag (--long)" do
|
||||
does_match(FLAG_LONG, "--long")
|
||||
end
|
||||
|
||||
it "does not match a short flag (-s)" do
|
||||
doesnt_match(FLAG_LONG, "-s")
|
||||
end
|
||||
|
||||
it "doesn't match a long flag with an arg" do
|
||||
doesnt_match(FLAG_LONG, "--long=abc")
|
||||
end
|
||||
end
|
||||
|
||||
describe "FLAG_SHORT" do
|
||||
it "matches a valid short flag (-s)" do
|
||||
does_match(FLAG_SHORT, "-s")
|
||||
end
|
||||
|
||||
{% for int in (0..9) %}
|
||||
it "does not match a digit flag (-{{int}})" do
|
||||
doesnt_match(FLAG_SHORT, "-{{int}}")
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
|
||||
describe "TIMEZONE" do
|
||||
{% for sign in %w[ - + ] %}
|
||||
{% for i in [ 2, 4, 7 ] %}
|
||||
{% for j in [ 0, 7, 59 ] %}
|
||||
{% format = "%s%02d%02d".id %}
|
||||
it "will match a valid offset ({{format}})" % [ {{sign}}, {{i}}, {{j}} ] do
|
||||
does_match(TIMEZONE, {{format.stringify}} % [ {{sign}}, {{i}}, {{j}} ])
|
||||
end
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
it "won't accept any offsets above \"+2359\"" do
|
||||
doesnt_match(TIMEZONE, "-2400")
|
||||
end
|
||||
|
||||
it "won't accept any invalid minute values (+2361)" do
|
||||
doesnt_match(TIMEZONE, "-2361")
|
||||
end
|
||||
|
||||
it "able to parse fields out of the offset (-2330)" do
|
||||
get_match(TIMEZONE, "-2330") do
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("23")
|
||||
match["offset_minute"].should eq("30")
|
||||
match["timezone"].should eq("-2330")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "TIME" do
|
||||
it "should be able to match a valid time (22:23:24) and parse the fields" do
|
||||
does_match(TIME, "22:23:24")
|
||||
get_match(TIME, "22:23:24") do
|
||||
match["hour"].should eq("22")
|
||||
match["minute"].should eq("23")
|
||||
match["second"].should eq("24")
|
||||
match["time"].should eq("22:23:24")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "DATE" do
|
||||
it "should be able to match a valid date (2026-08-10) and parse the fields" do
|
||||
does_match(DATE, "2026-08-10")
|
||||
get_match(DATE, "2026-08-10") do
|
||||
match["date"].should eq("2026-08-10")
|
||||
match["year"].should eq("2026")
|
||||
match["month"].should eq("08")
|
||||
match["day"].should eq("10")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "EPOCH" do
|
||||
it "should match a valid epoch time, based on the pattern, and parse it's fields (@1788748305)" do
|
||||
does_match(EPOCH, "@1788748305")
|
||||
get_match(EPOCH, "@1788748305") do
|
||||
match["epoch"].should eq("1788748305")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "RELATIVE" do
|
||||
it "should match a valid operation" do
|
||||
{% for sign in %w[ - + ].map(&.id) %}
|
||||
{% for token in %w[ day days week weeks hour hours month months second seconds year years ].map(&.id) %}
|
||||
does_match(RELATIVE, "{{sign}}1 {{token}}")
|
||||
{% end %}
|
||||
{% end %}
|
||||
end
|
||||
it "should not match invalid units (taco, tuesday, misfit, really?)" do
|
||||
tokens = %w[ taco tuesday misfit really? ]
|
||||
tokens.each do |token|
|
||||
doesnt_match(RELATIVE, "+1 #{token}")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "RELATIVE_OPERATION" do
|
||||
it "should match a valid operation and we can parse the fields" do
|
||||
{% for sign in %w[ - + ].map(&.id) %}
|
||||
{% for int in %w[ 1 3 10 ].map(&.id) %}
|
||||
{% for token in %w[ day days week weeks hour hours month months second seconds year years ].map(&.id) %}
|
||||
get_match(RELATIVE_OPERATION, "{{sign}}{{int}} {{token}}") do
|
||||
match["sign"].should eq("{{sign}}")
|
||||
match["quantity"].should eq("{{int}}")
|
||||
match["unit"].should eq("{{token}}")
|
||||
end
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
|
||||
describe "INPUT_DATE_FULL" do
|
||||
it "will match a bounded full date with an offset (2024-08-13 22:23:24 -0700)" do
|
||||
get_match(INPUT_DATE_FULL, "2024-08-13 22:23:24 -0700") do
|
||||
match["date"].should eq("2024-08-13")
|
||||
match["year"].should eq("2024")
|
||||
match["month"].should eq("08")
|
||||
match["day"].should eq("13")
|
||||
match["time"].should eq("22:23:24")
|
||||
match["hour"].should eq("22")
|
||||
match["minute"].should eq("23")
|
||||
match["second"].should eq("24")
|
||||
match["timezone"].should eq("-0700")
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("07")
|
||||
match["offset_minute"].should eq("00")
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a bounded full date without an offset (2024-08-13 22:23:24)" do
|
||||
get_match(INPUT_DATE_FULL, "2024-08-13 22:23:24") do
|
||||
match["date"].should eq("2024-08-13")
|
||||
match["year"].should eq("2024")
|
||||
match["month"].should eq("08")
|
||||
match["day"].should eq("13")
|
||||
match["time"].should eq("22:23:24")
|
||||
match["hour"].should eq("22")
|
||||
match["minute"].should eq("23")
|
||||
match["second"].should eq("24")
|
||||
match["timezone"]?.should eq(nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "INPUT_DATE_SIMPLE" do
|
||||
it "will match a bounded simple date without an offset (2024-08-13)" do
|
||||
get_match(INPUT_DATE_SIMPLE, "2024-08-13") do
|
||||
match["date"].should eq("2024-08-13")
|
||||
match["year"].should eq("2024")
|
||||
match["month"].should eq("08")
|
||||
match["day"].should eq("13")
|
||||
match["timezone"]?.should eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a bounded simple date with an offset (2024-08-13 -0700)" do
|
||||
get_match(INPUT_DATE_SIMPLE, "2024-08-13 -0700") do
|
||||
match["date"].should eq("2024-08-13")
|
||||
match["year"].should eq("2024")
|
||||
match["month"].should eq("08")
|
||||
match["day"].should eq("13")
|
||||
match["timezone"].should eq("-0700")
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("07")
|
||||
match["offset_minute"].should eq("00")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "INPUT_DATE_EPOCH" do
|
||||
it "will match a bounded epoch time without an offset (@1788748305)" do
|
||||
get_match(INPUT_DATE_EPOCH, "@1788748305") do
|
||||
match["epoch"].should eq("1788748305")
|
||||
match["timezone"]?.should eq(nil)
|
||||
end
|
||||
end
|
||||
|
||||
it "will match a bounded simple date with an offset (@1788748305 -0700)" do
|
||||
get_match(INPUT_DATE_EPOCH, "@1788748305 -0700") do
|
||||
match["epoch"].should eq("1788748305")
|
||||
match["timezone"].should eq("-0700")
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("07")
|
||||
match["offset_minute"].should eq("00")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
describe "INPUT_RELATIVE_OPERATIONS" do
|
||||
it "matches a single relative operation without timzone (+1 day)" do
|
||||
get_match(INPUT_RELATIVE_OPERATIONS, "+1 day") do
|
||||
match["operations"].should eq("+1 day")
|
||||
match["timezone"]?.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it "matches a single relative operation with timzone (+1 day -0700)" do
|
||||
get_match(INPUT_RELATIVE_OPERATIONS, "+1 day -0700") do
|
||||
match["operations"].should eq("+1 day")
|
||||
match["timezone"].should eq("-0700")
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("07")
|
||||
match["offset_minute"].should eq("00")
|
||||
end
|
||||
end
|
||||
|
||||
it "matches multiple relative operations without timzone (+1 day -2 years)" do
|
||||
get_match(INPUT_RELATIVE_OPERATIONS, "+1 day -2 years") do
|
||||
match["operations"].should eq("+1 day -2 years")
|
||||
match["timezone"]?.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it "matches multiple relative operations without timzone (+1 day -2 years -0700)" do
|
||||
get_match(INPUT_RELATIVE_OPERATIONS, "+1 day -2 years -0700") do
|
||||
match["operations"].should eq("+1 day -2 years")
|
||||
match["timezone"].should eq("-0700")
|
||||
match["offset_sign"].should eq("-")
|
||||
match["offset_hour"].should eq("07")
|
||||
match["offset_minute"].should eq("00")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "FLOAT" do
|
||||
it "will match a traditional float (1.1)" do
|
||||
does_match(FLOAT, "1.1")
|
||||
end
|
||||
|
||||
it "will match an int (1)" do
|
||||
does_match(FLOAT, "1")
|
||||
end
|
||||
|
||||
it "will match a negative float (-1.1)" do
|
||||
does_match(FLOAT, "-1.1")
|
||||
end
|
||||
|
||||
it "will match a negative int (-1)" do
|
||||
does_match(FLOAT, "-1")
|
||||
end
|
||||
end
|
||||
|
||||
describe "INT" do
|
||||
end
|
||||
|
||||
describe "UINT" do
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,102 @@
|
||||
require "../spec_helper"
|
||||
|
||||
def get_ops(raw : String)
|
||||
CliGen::Timeparse::RelativeOperation.get_operations(raw)
|
||||
end
|
||||
|
||||
describe CliGen::Timeparse::RelativeOperation do
|
||||
describe ".get_operations" do
|
||||
it "will correctly parse a single relative operation & provide an array of 1" do
|
||||
op = "+1 seconds"
|
||||
ops = get_ops(op)
|
||||
ops.size.should eq(1)
|
||||
my_op = ops.first
|
||||
my_op.sign.should eq(1)
|
||||
my_op.quantity.should eq(1)
|
||||
my_op.unit.should eq(CliGen::Timeparse::OperationUnit::SECOND)
|
||||
end
|
||||
|
||||
it "will correctly parse multiple relative operations & provide an array of 2" do
|
||||
op = "+1 seconds -1 minute"
|
||||
ops = get_ops(op)
|
||||
ops.size.should eq(2)
|
||||
|
||||
op1 = ops.shift
|
||||
op1.sign.should eq(1)
|
||||
op1.quantity.should eq(1)
|
||||
op1.unit.should eq(CliGen::Timeparse::OperationUnit::SECOND)
|
||||
|
||||
op2 = ops.shift
|
||||
op2.sign.should eq(-1)
|
||||
op2.quantity.should eq(1)
|
||||
op2.unit.should eq(CliGen::Timeparse::OperationUnit::MINUTE)
|
||||
end
|
||||
|
||||
it "will parse every unit in both singular and plural form" do
|
||||
{
|
||||
"year" => CliGen::Timeparse::OperationUnit::YEAR,
|
||||
"month" => CliGen::Timeparse::OperationUnit::MONTH,
|
||||
"week" => CliGen::Timeparse::OperationUnit::WEEK,
|
||||
"day" => CliGen::Timeparse::OperationUnit::DAY,
|
||||
"hour" => CliGen::Timeparse::OperationUnit::HOUR,
|
||||
"minute" => CliGen::Timeparse::OperationUnit::MINUTE,
|
||||
"second" => CliGen::Timeparse::OperationUnit::SECOND,
|
||||
}.each do |word, unit|
|
||||
[word, "#{word}s"].each do |form|
|
||||
ops = get_ops("+1 #{form}")
|
||||
ops.size.should eq(1)
|
||||
ops.first.unit.should eq(unit)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it "will correctly parse a negative sign and a multi-digit quantity" do
|
||||
op = get_ops("-42 days").first
|
||||
op.sign.should eq(-1)
|
||||
op.quantity.should eq(42)
|
||||
op.unit.should eq(CliGen::Timeparse::OperationUnit::DAY)
|
||||
end
|
||||
end
|
||||
|
||||
describe "#apply" do
|
||||
it "will apply a single operation correctly" do
|
||||
time = Time.local
|
||||
atime = time + 2.minute
|
||||
get_ops("+2 minutes").each{|op| time = op.apply(time)}
|
||||
time.should eq(atime)
|
||||
end
|
||||
|
||||
it "will apply multiple operations correctly" do
|
||||
time = Time.local
|
||||
atime = time + 2.minute - 3.minute + 2.year
|
||||
get_ops("+2 minutes -3 minutes +2 years").each{|op| time = op.apply(time)}
|
||||
time.should eq(atime)
|
||||
end
|
||||
|
||||
it "will apply each Time::Span unit correctly" do
|
||||
time = Time.utc(2026, 4, 24, 10, 20, 30)
|
||||
get_ops("+3 weeks").first.apply(time).should eq(time + 3.weeks)
|
||||
get_ops("+3 days").first.apply(time).should eq(time + 3.days)
|
||||
get_ops("+3 hours").first.apply(time).should eq(time + 3.hours)
|
||||
get_ops("+3 minutes").first.apply(time).should eq(time + 3.minutes)
|
||||
get_ops("+3 seconds").first.apply(time).should eq(time + 3.seconds)
|
||||
end
|
||||
|
||||
it "will apply MONTH and YEAR as calendar spans, not fixed durations" do
|
||||
# Jan 31 + 1 month clamps to Feb 28 - a fixed 30.days span would give Mar 02
|
||||
jan31 = Time.utc(2026, 1, 31, 12, 0, 0)
|
||||
get_ops("+1 month").first.apply(jan31).should eq(Time.utc(2026, 2, 28, 12, 0, 0))
|
||||
get_ops("+1 year").first.apply(jan31).should eq(Time.utc(2027, 1, 31, 12, 0, 0))
|
||||
|
||||
# leap year: Feb 29 2028 exists, so +2 years from 2026-02-28 stays on the 28th
|
||||
feb28 = Time.utc(2026, 2, 28, 12, 0, 0)
|
||||
get_ops("+2 years").first.apply(feb28).should eq(Time.utc(2028, 2, 28, 12, 0, 0))
|
||||
end
|
||||
|
||||
it "will apply a negative operation correctly" do
|
||||
time = Time.utc(2026, 3, 15, 8, 0, 0)
|
||||
get_ops("-1 month").first.apply(time).should eq(Time.utc(2026, 2, 15, 8, 0, 0))
|
||||
get_ops("-10 days").first.apply(time).should eq(time - 10.days)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,139 @@
|
||||
require "../spec_helper"
|
||||
|
||||
module CliGen::Timeparse
|
||||
def self.test_get_location(raw : String)
|
||||
get_location(raw)
|
||||
end
|
||||
end
|
||||
|
||||
describe CliGen::Timeparse do
|
||||
describe ".parse" do
|
||||
it "accepts time in %Y-%m-%d format" do
|
||||
time = "2026-04-24"
|
||||
a = ::Time.parse_local(time, "%Y-%m-%d")
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "accepts time in %Y-%m-%d %z format and will respect the provided offset" do
|
||||
time = "2026-04-24 -0900"
|
||||
a = ::Time.parse!(time, "%Y-%m-%d %z")
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "strips surrounding whitespace before parsing" do
|
||||
a = ::Time.parse_local("2026-04-24", "%Y-%m-%d")
|
||||
CliGen::Timeparse.parse(" 2026-04-24 ").should eq(a)
|
||||
end
|
||||
|
||||
it "accepts time in %Y-%m-%d %H:%M:%S format and defaults to the local timezone" do
|
||||
time = "2026-04-24 10:20:30"
|
||||
a = ::Time.parse(time, "%Y-%m-%d %H:%M:%S", location: ::Time::Location.local)
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "accepts time in %Y-%m-%d %H:%M:%S %z format and will respect the provided offset" do
|
||||
time = "2026-04-24 10:20:30 -0900"
|
||||
a = ::Time.parse!(time, "%Y-%m-%d %H:%M:%S %z")
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "accepts epoch time in the @%s format and will default to UTC" do
|
||||
time = "@1788742653"
|
||||
a = ::Time.unix(time.lchop.to_i)
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "accepts epoch time in the @%s %z format and will set the timezone to match the offset provided" do
|
||||
time = "@1788742653 -0700"
|
||||
a = ::Time.unix(time.lchop.split(" ").first.to_i).in(Time::Location.fixed(-1 * (7 * 3600)))
|
||||
CliGen::Timeparse.parse(time).should eq(a)
|
||||
end
|
||||
|
||||
it "accepts a single relative operation and will return the time" do
|
||||
time = CliGen::Timeparse.parse("+10 minutes")
|
||||
b_time = Time.local + 9.minute
|
||||
a_time = Time.local + 11.minute
|
||||
|
||||
(b_time..a_time).includes?(time).should be_true
|
||||
end
|
||||
|
||||
it "accepts a single relative operation + offset and will return the time" do
|
||||
time = CliGen::Timeparse.parse("+10 minutes -0900")
|
||||
b_time = Time.local + 9.minute
|
||||
a_time = Time.local + 11.minute
|
||||
(b_time..a_time).includes?(time).should be_true
|
||||
time.location.should eq(Time::Location.fixed("-0900", -1 * (9 * 3600)))
|
||||
end
|
||||
|
||||
it "accepts multiple relative operations and will return the time" do
|
||||
time = CliGen::Timeparse.parse("+20 minutes +2 minute")
|
||||
b_time = Time.local + 21.minute
|
||||
a_time = Time.local + 23.minute
|
||||
(b_time..a_time).includes?(time).should be_true
|
||||
end
|
||||
|
||||
it "accepts a multiple relative operation + offset and will return the time" do
|
||||
time = CliGen::Timeparse.parse("+10 minutes +2 minutes -0900")
|
||||
b_time = Time.local + 11.minute
|
||||
a_time = Time.local + 13.minute
|
||||
(b_time..a_time).includes?(time).should be_true
|
||||
time.location.should eq(Time::Location.fixed("-0900", -1 * (9 * 3600)))
|
||||
end
|
||||
end
|
||||
|
||||
describe ".parse error handling" do
|
||||
it "raises CliGen::TimeParseError when the input matches no known format" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("not-a-date")
|
||||
end
|
||||
end
|
||||
|
||||
it "includes the offending input in the unknown-format message" do
|
||||
ex = expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("nonsense")
|
||||
end
|
||||
ex.message.to_s.should contain("nonsense")
|
||||
end
|
||||
|
||||
it "raises CliGen::TimeParseError for a shape-valid but out-of-range month/day" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("2026-13-45")
|
||||
end
|
||||
end
|
||||
|
||||
it "raises CliGen::TimeParseError for an out-of-range hour" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("2026-01-15 25:00:00")
|
||||
end
|
||||
end
|
||||
|
||||
it "raises CliGen::TimeParseError for a day that does not exist in that month" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("2026-02-30")
|
||||
end
|
||||
end
|
||||
|
||||
# Guards the catch-all rescue: this path raises OverflowError, not ArgumentError.
|
||||
# Narrowing the rescue back to specific stdlib types would let it escape
|
||||
# App#handle_command_raises and reach the user as a stack trace.
|
||||
it "raises CliGen::TimeParseError for an epoch large enough to overflow" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("@99999999999999999999")
|
||||
end
|
||||
end
|
||||
|
||||
it "raises CliGen::TimeParseError rather than an offset error for an out-of-range timezone" do
|
||||
expect_raises(CliGen::TimeParseError) do
|
||||
CliGen::Timeparse.parse("2026-01-15 -9999")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe ".get_location" do
|
||||
it "correctly generates an offest" do
|
||||
a = "-0900"
|
||||
b = Time::Location.fixed(a, (-1) * ((9 * 3600) + (0 * 60)))
|
||||
CliGen::Timeparse.test_get_location(a).should eq(b)
|
||||
end
|
||||
end
|
||||
end
|
||||
+32
-1
@@ -14,7 +14,38 @@ require "./cligen/command_node"
|
||||
require "./cligen/app"
|
||||
|
||||
module CliGen
|
||||
VERSION = "0.1.0"
|
||||
VERSION = "0.2.0"
|
||||
|
||||
macro finished
|
||||
{% unless CliGen.has_constant?("MAX_COMMAND_DEPTH") %}
|
||||
{% puts "DEBUG : CliGen : User did not override MAX_COMMAND_DEPTH. Setting to default of 32" if env("DEBUG") %}
|
||||
# # CliGen::MAX_COMMAND_DEPTH
|
||||
#
|
||||
# This exists to prevent the user from defining a command tree
|
||||
# that extends past the compile-time configured max via the
|
||||
# CliGen::MAX_COMMAND_DEPTH constant.
|
||||
#
|
||||
# The reason this is a thing is because crystal macros don't allow for
|
||||
# unbounded while's/until's in macros, meaning it always has to be
|
||||
# deterministic. SO to deal with this and still allow for subcommand
|
||||
# defining you need either go with the default (32 command depth) or
|
||||
# define your own larger max (understand this will affect compile-time
|
||||
# due to this directly affecting loops in the Command macros).
|
||||
#
|
||||
# So to still support this I had to make bounded for-loops usng
|
||||
#
|
||||
#
|
||||
# \{% for i in (1..CliGen::MAX_COMMAND_DEPTH) %}
|
||||
# ...do checks...
|
||||
# \{% end }
|
||||
#
|
||||
#
|
||||
MAX_COMMAND_DEPTH = 32
|
||||
{% else %}
|
||||
{% puts "DEBUG : CliGen : User override the MAX_COMMAND_DEPTH. Not overriding with default" if env("DEBUG") %}
|
||||
{% raise "ERROR : CliGen::MAX_COMMAND_DEPTH must be an integer" unless CliGen::MAX_COMMAND_DEPTH.is_a? NumberLiteral %}
|
||||
{% end %}
|
||||
end
|
||||
|
||||
APPNAME = File.basename(PROGRAM_NAME)
|
||||
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
# Copyright 2026 Tristan Ancelet
|
||||
|
||||
module CliGen
|
||||
annotation InternalVar
|
||||
end
|
||||
# (Not Implemented Yet)
|
||||
# In the future you would use this to annotate a "proxy command" that will allow you to defer execution
|
||||
# of a "subcommand" to an external method not located in the class itself.
|
||||
@@ -206,9 +208,6 @@ module CliGen
|
||||
annotation Trigger
|
||||
end
|
||||
|
||||
annotation Selection
|
||||
end
|
||||
|
||||
annotation PreRunCommand
|
||||
end
|
||||
|
||||
|
||||
+18
-5
@@ -11,6 +11,11 @@ module CliGen
|
||||
# for global-flag matching, then hands off to the matched child CommandNode.
|
||||
class App < CliGen::CommandNode(Nil)
|
||||
@@instance : self?
|
||||
@@processed : Bool = false
|
||||
|
||||
def self.processed?
|
||||
@@processed
|
||||
end
|
||||
|
||||
def initialize(@name, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand))
|
||||
super(name: @name, flags: flags, commands: commands, pre_run_commands: pre_run_commands, post_run_commands: post_run_commands)
|
||||
@@ -19,13 +24,13 @@ module CliGen
|
||||
|
||||
def check!
|
||||
super
|
||||
check_for_env_duplicates(all_flags + CliGen::GLOBAL_FLAGS)
|
||||
check_for_env_duplicates(all_flags.uniq + CliGen::GLOBAL_FLAGS)
|
||||
end
|
||||
|
||||
def check_for_env_duplicates(flags : Array(BaseFlag))
|
||||
flgs = flags.reject(&.env_var.empty?)
|
||||
flgs = flags.reject(&.env_var.nil?)
|
||||
|
||||
env_vars = flgs.group_by(&.env_var)
|
||||
env_vars = flgs.group_by(&.env_var.not_nil!)
|
||||
|
||||
failures = [] of Tuple(String, Array(BaseFlag))
|
||||
|
||||
@@ -68,11 +73,19 @@ module CliGen
|
||||
end
|
||||
end
|
||||
|
||||
def self.get
|
||||
generate if @@instance.nil?
|
||||
@@instance.not_nil!
|
||||
end
|
||||
|
||||
# Convenience entry point; defaults to ARGV
|
||||
def self.process(args : Array(String) = ARGV.to_a) : Nil
|
||||
generate if @@instance.nil?
|
||||
raise CliGen::AppAlreadyProcessedError.new("ERROR : CliGen::App.process : App has already processed CLI arguments. It is not allowed to be run again") if processed?
|
||||
handle_command_raises do
|
||||
@@instance.not_nil!.process(args)
|
||||
if app = get
|
||||
@@processed = true
|
||||
app.process(args)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,55 +5,25 @@ module CliGen
|
||||
macro finished
|
||||
class App
|
||||
private def self.generate
|
||||
app_flags = [] of BaseFlag
|
||||
app_commands = [] of BaseCommandNode
|
||||
|
||||
{% verbatim do %}
|
||||
{% for cmd in CliGen::Command.subclasses %}
|
||||
{% unless CliGen::Command.subclasses.reject(&.annotation(CliGen::CommandInfo)[:parent]).empty? %}
|
||||
{% for cmd in CliGen::Command.subclasses.reject(&.annotation(CliGen::CommandInfo)[:parent]) %}
|
||||
{% cmd_info = cmd.annotation(CliGen::CommandInfo) %}
|
||||
{% raise "ERROR : CliGen::App.generate : No CliGen::CommandInfo annotation made for #{cmd.name}" unless cmd_info %}
|
||||
{% raise "ERROR : CliGen::App.generate : Description must be provided for #{cmd.name}" unless cmd_info[:description].is_a? StringLiteral %}
|
||||
{% cmd_name = cmd.name.split("::").last.downcase %}
|
||||
{% cmd_flags = cmd.instance_vars.select{|v| v.annotation(CliGen::Argument) || v.annotation(CliGen::Selection) } %}
|
||||
|
||||
cmd_flags = [] of BaseFlag
|
||||
cmd_sub_commands = [] of BaseCommandNode
|
||||
cmd_pre_run_cmds = [] of Proc(Nil)
|
||||
cmd_post_run_cmds = [] of Proc(Nil)
|
||||
|
||||
{% for var in cmd_flags %}
|
||||
{% anno = var.annotation(CliGen::Argument) || var.annotation(CliGen::Selection) %}
|
||||
cmd_flags << Flag({{var.type}}).new(
|
||||
var: {{ var.name.stringify }},
|
||||
short: {% if anno[:short] %} {{anno[:short]}} {% else %} nil {% end %},
|
||||
long: {{ anno[:long] }},
|
||||
env_var: {% if anno[:env_var] %} {{anno[:env_var]}} {% else %} {{"#{cmd.name.split("::").last.upcase.id}_#{var.name.upcase}"}} {% end %},
|
||||
description: {{ anno[:description] }},
|
||||
default: {% unless var.default_value.nil? %} {{var.default_value}} {% else %} nil {% end %},
|
||||
validate: {% if anno[:validation] %} {{anno[:validation]}} {% else %} nil {% end %},
|
||||
on_match: {% if anno[:on_match] %} {{anno[:on_match]}} {% else %} nil {% end %},
|
||||
options: {% if anno[:options] %} {{anno[:options]}} {% else %} nil {% end %},
|
||||
delimiter: {% if anno[:delimiter] %} {{anno[:delimiter]}} {% else %} "," {% end %},
|
||||
format: {% if anno[:format] %} {{anno[:format]}} {% else %} nil {% end %}
|
||||
)
|
||||
{% debug if env("DEBUG") %}
|
||||
{{cmd}}.register_command(app_commands)
|
||||
{% end %}
|
||||
|
||||
app_commands << CommandNode({{cmd}}).new(
|
||||
name: {{cmd_name}},
|
||||
flags: cmd_flags,
|
||||
commands: cmd_sub_commands,
|
||||
pre_run_commands: cmd_pre_run_cmds,
|
||||
post_run_commands: cmd_post_run_cmds,
|
||||
description: {{cmd_info[:description]}}
|
||||
)
|
||||
{% debug if env("DEBUG") %}
|
||||
{% else %}
|
||||
{% raise "ERROR : CliGen::App.generate : No root commands were found for App.generate to index. Ensure that you have at least one CliGen::Command subclass with no parent in the CliGen::CommandInfo annotation" %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
|
||||
new(
|
||||
name: File.basename(::PROGRAM_NAME),
|
||||
flags: app_flags,
|
||||
flags: [] of BaseFlag,
|
||||
commands: app_commands,
|
||||
pre_run_commands: [] of Proc(Nil),
|
||||
post_run_commands: [] of Proc(Nil)
|
||||
|
||||
+37
-6
@@ -6,23 +6,54 @@ require "time"
|
||||
|
||||
require "./annotations"
|
||||
require "./command/argument"
|
||||
require "./command/selection"
|
||||
require "./command/help_template"
|
||||
require "./command/subcommand"
|
||||
require "./command/def_init"
|
||||
require "./command/define_singleton_init"
|
||||
require "./command/define_command_initializer"
|
||||
require "./command/generate_register_command"
|
||||
require "./command/generate_gather_handler"
|
||||
require "./command/resolve_value"
|
||||
require "./command/validate_command_tree"
|
||||
|
||||
module CliGen
|
||||
class Command
|
||||
@[CliGen::InternalVar]
|
||||
@handler : CliGen::BaseCommandNode?
|
||||
|
||||
def handler? : Bool
|
||||
! @handler.nil?
|
||||
end
|
||||
|
||||
macro inherited
|
||||
{% verbatim do %}
|
||||
macro finished
|
||||
{% anno = @type.annotation(CliGen::CommandInfo) %}
|
||||
{% raise "" unless anno %}
|
||||
{% if anno[:def_init] %}
|
||||
def_init
|
||||
{% if anno = @type.annotation(CliGen::CommandInfo) %}
|
||||
{% if anno[:singleton_init] == true %}
|
||||
define_singleton_init
|
||||
{% end %}
|
||||
{% else %}
|
||||
{% raise "ERROR : #{@type.name} < CliGen::Command : When creating a Command subclass you MUST have an (CliGen::CommandInfo) annotation. No if's and's or but's. OKAY?" %}
|
||||
{% end %}
|
||||
|
||||
# This validates that the Command doesn't have a circular dependency
|
||||
# chain which would cause a rcursive loop in the register_command
|
||||
# method at runtime
|
||||
validate_command_tree
|
||||
|
||||
# This defines the initializer that the CommandNode(T) uses to set the
|
||||
# values of this command object
|
||||
define_command_initializer
|
||||
|
||||
# Generate the command registration method to allow App to have this
|
||||
# command registered in the App.commands or another commands @commands
|
||||
# as a subcommand
|
||||
generate_register_command
|
||||
|
||||
# This generates the gather_handler method that allows a command (if
|
||||
# initialized via sources other than CliGen::CommandNode(T)) to get
|
||||
# it's related CliGen::CommandNode(T) handler to gather flag values
|
||||
# with the resolve_value macro or in the singleton init method
|
||||
generate_gather_handler
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
module CliGen
|
||||
class Command
|
||||
macro argument(variable, description, long = nil, short = nil, validation = nil, on_match = nil, def_setter = false, def_getter = false, options = nil, delimiter = ",", format = nil, allow_no_verification = false, env_var = nil)
|
||||
macro argument(variable, description, long = nil, short = nil, validation = nil, on_match = nil, def_setter = false, def_getter = false, options = nil, delimiter = ",", format = nil, allow_no_verification = false, env_var = "")
|
||||
{% raise "ERROR : CliGen::Command.argument : def_setter must be a Bool" unless def_setter.is_a? BoolLiteral %}
|
||||
{% raise "ERROR : CliGen::Command.argument : def_getter must be a Bool" unless def_getter.is_a? BoolLiteral %}
|
||||
{% raise "ERROR : CliGen::Command.argument : First argument (#{variable}) must be a TypeDeclaration (ex: '<var> : <type> [= val]')" unless variable.is_a? TypeDeclaration %}
|
||||
@@ -27,9 +27,9 @@ module CliGen
|
||||
)
|
||||
|
||||
{% if type.resolve < Array && ! options.nil? %}
|
||||
@[CliGen::Argument(short: {{short}}, long: {{long}}, description: {{description}}, validation: {{validation}}, on_match: {{on_match}}, options: [{{options}}], delimiter: {{delimiter}}, format: {{format}}, env_var: {{env_var}})]
|
||||
@[CliGen::Argument(short: {{short}}, long: {{long}}, description: {{description}}, validation: {{validation}}, on_match: {{on_match}}, options: [{{options}}], delimiter: {{delimiter}}, format: {{format}}, env_var: {{env_var}}, allow_no_verification: {{allow_no_verification}})]
|
||||
{% else %}
|
||||
@[CliGen::Argument(short: {{short}}, long: {{long}}, description: {{description}}, validation: {{validation}}, on_match: {{on_match}}, options: {{options}}, delimiter: {{delimiter}}, format: {{format}}, env_var: {{env_var}})]
|
||||
@[CliGen::Argument(short: {{short}}, long: {{long}}, description: {{description}}, validation: {{validation}}, on_match: {{on_match}}, options: {{options}}, delimiter: {{delimiter}}, format: {{format}}, env_var: {{env_var}}, allow_no_verification: {{allow_no_verification}})]
|
||||
{% end %}
|
||||
@{{variable}}
|
||||
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright 2026 Tristan Ancelet
|
||||
|
||||
module CliGen
|
||||
class Command
|
||||
macro def_init
|
||||
def initialize
|
||||
{% verbatim do %}
|
||||
{% for var in @type.instance_vars %}
|
||||
{% raise "ERROR : Can't define a default initializer if #{var.name} doesn't have a default" if var.default_value.nil? && !var.type.nilable? %}
|
||||
@{{var.name}} = {{var.default_value}}
|
||||
{% end %}
|
||||
{% end %}
|
||||
end
|
||||
|
||||
def after_initialize
|
||||
@@instance = self
|
||||
end
|
||||
|
||||
def self.get
|
||||
@@instance ||= new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,11 +5,13 @@ module CliGen
|
||||
class Command
|
||||
macro define_command_initializer
|
||||
def initialize(*, handler : CliGen::BaseCommandNode)
|
||||
@handler = handler
|
||||
|
||||
{% verbatim do %}
|
||||
Log.debug { "#{self.class.name}#initialize : Initializing class" }
|
||||
{% for var in @type.instance_vars %}
|
||||
Log.debug { "{{@type.name}}#initialize : Checking {{var.name}}" }
|
||||
{% anno = (var.annotation(CliGen::Argument) || var.annotation(CliGen::Selection)) %}
|
||||
{% anno = var.annotation(CliGen::Argument) %}
|
||||
{% if anno %}
|
||||
{% raise "ERROR : #{@type.name}#initialize : Argument '#{var.name}' cannot be a nilable type (#{var.type}) — flags always resolve to a concrete value" if var.type.union? %}
|
||||
Log.debug { "{{@type.name}}#initialize : {{var.name}} is a CliGen managed ivar. Will attempt to gather from associated CliGen::Flag" }
|
||||
@@ -21,6 +23,7 @@ module CliGen
|
||||
else
|
||||
raise CliGen::FlagNotFoundError.new("{{@type.name}}\#{{@def.name}} : No flag found for \"{{var.name}}\"")
|
||||
end
|
||||
{% elsif var.annotation(CliGen::InternalVar) %}
|
||||
{% else %}
|
||||
Log.debug { "{{@type.name}}#initialize : {{var.name}} is not a CliGen managed ivar. Will initialize to default defined in class" }
|
||||
{% raise "ERROR : #{@type.name}#{@def.name} : Instance Variable(#{var.name}) is not handled by CliGen and does not have a default value" if var.default_value.nil? %}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright 2026 Tristan Ancelet
|
||||
|
||||
module CliGen
|
||||
class Command
|
||||
# This macro simply provides a easy singleton initializer for your command
|
||||
# to allow for you do (if this class isn't the target of a command) to still
|
||||
# be able to gather a Command object without having to have it as the target.
|
||||
#
|
||||
# This will setup the default (no args) initializer to gather the handler from
|
||||
# CliGen::App and then resolve all of the ivar (CliGen managed) to the parsed
|
||||
# values from the associated Flag(T) object that (if the process itself is
|
||||
# being started by CliGen the provided flags will store the value to be
|
||||
# set here)
|
||||
macro define_singleton_init
|
||||
def initialize
|
||||
{% verbatim do %}
|
||||
gather_handler unless @handler
|
||||
if handler = @handler
|
||||
{% for var in @type.instance_vars %}
|
||||
{% raise "ERROR : Can't define a default initializer if #{var.name} doesn't have a default" if var.default_value.nil? && !var.type.nilable? %}
|
||||
{% if anno = var.annotation(CliGen::Argument) %}
|
||||
{% raise "ERROR : #{@type}#initialize : Can't define a default initializer for a cligen managed ivar if #{var.name} doesn't have a default" if var.default_value.nil? %}
|
||||
# If the variable is cligen managed we can define the value from the handler and resolve the setting from
|
||||
@{{var.name}} = handler.flags.find{|flg| flg.var == {{var.name.stringify}} && flg.long == {{anno[:long]}}}.not_nil!.as(CliGen::Flag({{var.type}})).value!
|
||||
{% elsif var.annotation(CliGen::InternalVar) %}
|
||||
{% else %}
|
||||
{% raise "ERROR : #{@type}#initialize : Can't define a default initializer if #{var.name} doesn't have a default" if var.default_value.nil? && !var.type.nilable? %}
|
||||
@{{var.name}} = {{var.default_value}}
|
||||
{% end %}
|
||||
{% end %}
|
||||
else
|
||||
raise "ERROR : Was unable to retrieve a handler from CliGen::App"
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
|
||||
def after_initialize
|
||||
@@instance = self
|
||||
end
|
||||
|
||||
def self.get
|
||||
raise CliGen::AppNotProcessedError.new("ERROR : {{@type.name}}#get : #{__FILE__}:#{__LINE__} : {{@type.name}}#get was called before CliGen::App has processed commandline arguments") unless CliGen::App.processed?
|
||||
@@instance ||= new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,13 @@
|
||||
module CliGen
|
||||
class Command
|
||||
macro generate_gather_handler
|
||||
def gather_handler
|
||||
unless @handler
|
||||
unless @handler = CliGen::App.get.all_commands.find(&.meta.cls.== {{ @type.name.stringify }})
|
||||
raise CliGen::ConfigurationError.new("ERROR : #{self.class}#gather_handler : Was unable to find handler for this instance")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,86 @@
|
||||
require "../flag"
|
||||
module CliGen
|
||||
class Command
|
||||
macro generate_register_command
|
||||
{% verbatim do %}
|
||||
def self.register_command(command_array : Array(CliGen::BaseCommandNode), parent : CliGen::BaseCommandNode? = nil)
|
||||
cmd_flags = [] of CliGen::BaseFlag
|
||||
cmd_subcommands = [] of CliGen::BaseCommandNode
|
||||
cmd_pre_run_cmds = [] of Proc(Nil)
|
||||
cmd_post_run_cmds = [] of Proc(Nil)
|
||||
|
||||
|
||||
{% for var in @type.instance_vars.select(&.annotation(CliGen::Argument)) %}
|
||||
{% anno = var.annotation(CliGen::Argument) %}
|
||||
CliGen::Common.check_flag_vars(
|
||||
raise_base: {{"CliGen::Command(#{@type.name}).generate_register_command"}},
|
||||
type: {{var.type}},
|
||||
long: {{anno[:long]}},
|
||||
env_var: {{anno[:env_var]}},
|
||||
short: {{anno[:short]}},
|
||||
validation: {{anno[:validation]}},
|
||||
on_match: {{anno[:on_match]}},
|
||||
options: {{anno[:options]}},
|
||||
description: {{anno[:description]}},
|
||||
allow_no_verification: {{anno[:allow_no_verification]}},
|
||||
format: {{anno[:format]}},
|
||||
delimiter: {{anno[:delimiter]}}
|
||||
)
|
||||
|
||||
cmd_flags << CliGen::Flag({{var.type}}).new(
|
||||
var: {{ var.name.stringify }},
|
||||
short: {% if anno[:short] %} {{anno[:short]}} {% else %} nil {% end %},
|
||||
long: {{ anno[:long] }},
|
||||
{% if anno[:env_var] == "" %}
|
||||
{% if @type.name.stringify =~ /::/ %}
|
||||
env_var: "{{@type.name.upcase.split("::").last.id}}_{{var.name.upcase}}",
|
||||
{% else %}
|
||||
env_var: "{{@type.name.upcase.id}}_{{var.name.upcase}}",
|
||||
{% end %}
|
||||
{% else %}
|
||||
env_var: {{anno[:env_var]}},
|
||||
{% end %}
|
||||
description: {{ anno[:description] }},
|
||||
default: {% unless var.default_value.nil? %} {{var.default_value}} {% else %} nil {% end %},
|
||||
validate: {% if anno[:validation] %} {{anno[:validation]}} {% else %} nil {% end %},
|
||||
on_match: {% if anno[:on_match] %} {{anno[:on_match]}} {% else %} nil {% end %},
|
||||
options: {% if anno[:options] %} {{anno[:options]}} {% else %} nil {% end %},
|
||||
delimiter: {% if anno[:delimiter] %} {{anno[:delimiter]}} {% else %} "," {% end %},
|
||||
format: {% if anno[:format] %} {{anno[:format]}} {% else %} nil {% end %}
|
||||
)
|
||||
{% end %}
|
||||
|
||||
{% begin %}
|
||||
{% cmd_anno = @type.annotation(CliGen::CommandInfo) %}
|
||||
command = CliGen::CommandNode({{@type}}).new(
|
||||
{% if @type.name.stringify =~ /::/ %}
|
||||
name: {{@type.name.stringify.split("::").last.downcase}},
|
||||
{% else %}
|
||||
name: {{@type.name.stringify.downcase}},
|
||||
{% end %}
|
||||
flags: cmd_flags,
|
||||
commands: cmd_subcommands,
|
||||
pre_run_commands: cmd_pre_run_cmds,
|
||||
post_run_commands: cmd_post_run_cmds,
|
||||
parent: parent,
|
||||
description: {{cmd_anno[:description]}}
|
||||
)
|
||||
command_array << command
|
||||
{% end %}
|
||||
|
||||
{% for cmd in CliGen::Command.subclasses %}
|
||||
{% cmd_anno = cmd.annotation(CliGen::CommandInfo) %}
|
||||
{% unless cmd.annotation(CliGen::CommandInfo) %}
|
||||
{% raise "ERROR : CliGen::Command(#{@type}).generate_register_command : #{cmd} must have an CliGen::CommandInfo annotation" %}
|
||||
{% end %}
|
||||
{% unless cmd_anno[:parent].nil? %}
|
||||
{% if cmd_anno[:parent].resolve == @type %}
|
||||
{{cmd}}.register_command(cmd_subcommands, parent: command)
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
end
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,132 @@
|
||||
module CliGen
|
||||
class Command
|
||||
# This macro is just meant to provide the user an ability to resolve instance
|
||||
# var/varibles from parent commands. Simply to allow subcommands to be able
|
||||
# to retrieve values from their parents
|
||||
#
|
||||
# As an aside, this (as written) can only be used for variables that have
|
||||
# a default defined (ex: @var : Int32 = 3)
|
||||
#
|
||||
# For variables that (in your parent class) isn't set with a default value,
|
||||
# you will need to provide the (default: <val>) kwarg to set your own
|
||||
# runtime default if the value itself cannot be ensured by the compiler.
|
||||
#
|
||||
# This is a requirement as this macro MUST always return a value without
|
||||
# rasing, and the only way to do that is force the user to provide a
|
||||
# default of their choosing.
|
||||
macro resolve_value(variable, *, default = nil)
|
||||
{% variable = variable.id %}
|
||||
{% commands = [] of TypeNode %}
|
||||
{% commands << @type %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Entered with #{variable}" if env("DEBUG") %}
|
||||
{% anno = @type.annotation(CliGen::CommandInfo) %}
|
||||
{% parent = nil %}
|
||||
{% current = nil %}
|
||||
{% var = nil %}
|
||||
# if this provided variable exists in the current clases space
|
||||
{% if v = @type.instance_vars.find(&.name.stringify.== variable.stringify) %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Looks like variable is a local one" if env("DEBUG") %}
|
||||
@{{v.name}}
|
||||
# in this case we have a command tree (annotation driven) and we're going
|
||||
# to try and iterate through them to see if we can find the variable name
|
||||
# that the user is trying to meet
|
||||
{% elsif p = anno[:parent] %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Looks we couldn't find it in the class itself. Checking parents" if env("DEBUG") %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Parent is defined as #{p}" if env("DEBUG") %}
|
||||
{% var = nil %}
|
||||
{% current = p.resolve %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Beginning iteration into parent chain to find an object with that variable" if env("DEBUG") %}
|
||||
{% for i in (1..CliGen::MAX_COMMAND_DEPTH) %}
|
||||
{% iteration = "#{i}/#{CliGen::MAX_COMMAND_DEPTH}".id %}
|
||||
{% unless current.nil? %}
|
||||
{% anno = current.annotation(CliGen::CommandInfo) %}
|
||||
{% puts "TRACE : #{@type.name}##{@def.name} : resolve_value : Iteration (#{iteration}) : var = #{var}" if env("TRACE") %}
|
||||
{% puts "TRACE : #{@type.name}##{@def.name} : resolve_value : Iteration (#{iteration}) : current = #{current}" if env("TRACE") %}
|
||||
{% puts "TRACE : #{@type.name}##{@def.name} : resolve_value : Iteration (#{iteration}) : anno = #{anno}" if env("TRACE") %}
|
||||
{% if commands.includes?(current) %}
|
||||
{% puts "ERROR : #{@type}##{@def} : resolve_value : #{current.name} has already been processed. Meaning we have detected a circular reference. " %}
|
||||
{% puts "Processed commands: " %}
|
||||
{% for cmd, i in commands %}
|
||||
{% puts "#{i}) #{cmd.name}" %}
|
||||
{% end %}
|
||||
{% raise "Circular Referfence detected. Please fix your annotations." %}
|
||||
{% else %}
|
||||
{% commands << current %}
|
||||
{% end %}
|
||||
{% if v = current.instance_vars.select(&.annotation(CliGen::Argument)).find(&.name.stringify.== variable.stringify) %}
|
||||
{% puts "DEBUG : #{@type.name}##{@def.name} : resolve_value : Iteration (#{iteration}) : found variable from current parent : v = #{v}" if env("DEBUG") %}
|
||||
{% var = v %}
|
||||
{% parent = current %}
|
||||
{% current = nil %}
|
||||
{% elsif p = anno[:parent] %}
|
||||
{% current = p.resolve %}
|
||||
{% else %}
|
||||
{% current = nil %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% unless current.nil? %}
|
||||
{% puts "ERROR : #{@type}##{@def.name} : resolve_value : It looks like your Commands tree either has a circular reference or extends past the max number of commands allowed. " %}
|
||||
{% puts "CliGen::MAX_COMMAND_DEPTH: #{CliGen::MAX_COMMAND_DEPTH}" %}
|
||||
{% puts "Last Recorded Command: #{current.name}" %}
|
||||
{% puts "Processed Command List:" %}
|
||||
{% for cmd, i in commands %}
|
||||
{% puts "#{i}: #{cmd}" %}
|
||||
{% end %}
|
||||
{% raise "Please fix this or up the MAX_COMMAND_DEPTH." %}
|
||||
{% end %}
|
||||
{% if var.nil? %}
|
||||
{% puts "ERROR : #{@type}##{@def.name} : resolve_value : Was not able to find a variable in the command tree that matched #{variable}." %}
|
||||
{% puts "Valid Options are: " %}
|
||||
{% for cmd in commands %}
|
||||
{% puts "Command(#{cmd.name}): " %}
|
||||
{% for ivar in cmd.instance_vars.select(&.annotation(CliGen::Argument)) %}
|
||||
{% anno = ivar.annotation(CliGen::Argument) %}
|
||||
{% puts "- #{ivar.name} : #{ivar.type} = #{ivar.default_value.nil? ? "!not set!" : ivar.default_value} (description: \"#{anno[:description]}\")" %}
|
||||
{% end %}
|
||||
{% puts "" %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% if var.default_value.nil? %}
|
||||
{% if default.nil? %}
|
||||
{% raise "ERROR : #{@type}##{@def.name} : resolve_value : #{var.name} is recorded to not have any default values. So in order to use this macro you must provide a default via the (default:) key in this macro" %}
|
||||
{% else %}
|
||||
%default : {{var.type}} = {{default}}
|
||||
{% end %}
|
||||
{% end %}
|
||||
gather_handler unless @handler
|
||||
%handler : CliGen::BaseCommandNode? = @handler
|
||||
|
||||
unless %handler
|
||||
raise "ERROR : No handler defined for this command"
|
||||
end
|
||||
|
||||
%parent : CliGen::BaseCommandNode? = %handler.parent?
|
||||
|
||||
until %parent.nil? || %parent.not_nil!.meta.cls == {{parent.name.stringify}}
|
||||
%parent = %parent.parent?
|
||||
end
|
||||
|
||||
if %parent.nil?
|
||||
raise "ERROR : {{@type}}\#{{@def.name}} : resolve_value : Was unable to find the parent for {{variable}}"
|
||||
else
|
||||
if %flg = %parent.flags.find(&.var.== {{variable.stringify}})
|
||||
{% unless default.nil? %}
|
||||
begin
|
||||
{% end %}
|
||||
%flg.as(CliGen::Flag({{var.type}})).value!
|
||||
{% unless default.nil? %}
|
||||
rescue e : CliGen::MissingRequiredFlagError
|
||||
%default
|
||||
end
|
||||
{% end %}
|
||||
else
|
||||
raise "ERROR : {{@type}}\#{{@def.name}} : resolve_value : Was unable to find the flag for {{variable}}"
|
||||
end
|
||||
end
|
||||
{% else %}
|
||||
{% raise "ERROR : #{@type}##{@def.name} : resolve_value : Wasn't able to find a source for #{variable}" %}
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,24 +0,0 @@
|
||||
# SPDX-License-Identifier: MIT
|
||||
# Copyright 2026 Tristan Ancelet
|
||||
|
||||
module CliGen
|
||||
class Command
|
||||
macro selection(variable, description, options, short = nil, long = nil, validation = nil, on_match = nil)
|
||||
{% raise "ERROR : CliGen::Command.selection : First selection must be a TypeDeclaration (ex: '<var> : <type> [= val]')" unless variable.is_a? TypeDeclaration %}
|
||||
{% if short %}
|
||||
{% raise "ERROR : CliGen::Command.selection : Provided short must be a string" unless short.is_a? StringLiteral %}
|
||||
{% end %}
|
||||
{% long = "--#{variable.var}" if long.nil? %}
|
||||
{% raise "ERROR : CliGen::Command.selection : Provided long must be a flag format" unless long =~ /^--[a-zA-Z0-9-_]+/ %}
|
||||
{% raise "ERROR : CliGen::Command.selection : Provided long must be a string" unless long.is_a? StringLiteral %}
|
||||
{% raise "ERROR : CliGen::Command.selection : You must provide a short or long" unless long || short %}
|
||||
{% raise "ERROR : CliGen::Command.selection : You must provide a description" unless description %}
|
||||
{% raise "ERROR : CliGen::Command.selection : Provided description must be a String" unless description.is_a? StringLiteral %}
|
||||
{% options = options.resolve if options.is_a? Path %}
|
||||
{% raise "ERROR : CliGen::Command.selection : Provided options must be an ArrayLiteral" unless options.is_a? ArrayLiteral %}
|
||||
|
||||
@[CliGen::Argument(short: {{short}}, long: {{long}}, description: {{description}}, validation: {{validation}}, on_match: {{on_match}}, options: {{options}}, delimiter: "-")]
|
||||
@{{variable}}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,68 @@
|
||||
module CliGen
|
||||
class Command
|
||||
# This macro serves as a compile-time checker of the command-tree to
|
||||
# validate that there is no recursive references of the command-list
|
||||
# that would possibly cause a recursive stack-overflow during App.generate
|
||||
# when App begins registering all user defined commands.
|
||||
#
|
||||
# However, while this does exist, due to the way that the App.generate method
|
||||
# handles gathering root commands it makes this edge-case impossible to hit
|
||||
# aside from manually running the
|
||||
# Command#register_command([] of CliGen::Command) method.
|
||||
#
|
||||
# However, with this in place this issue cannot be hit at runtime as this will
|
||||
# prevent compilation if a recursive/circular command tree exists.
|
||||
#
|
||||
# Additionally, this exists to prevent the user from defining a command tree
|
||||
# that extends past the compile-time configured max via the
|
||||
# CliGen::MAX_COMMAND_DEPTH constant.
|
||||
#
|
||||
# The reason this is a thing is because crystal macros don't allow for
|
||||
# unbounded while's/until's in macros, meaning it always has to be
|
||||
# deterministic. SO to deal with this and still allow for subcommand
|
||||
# defining you need either go with the default (32 command depth) or
|
||||
# define your own larger max (understand this will affect compile-time
|
||||
# due to this directly affecting loops in the Command macros).
|
||||
macro validate_command_tree
|
||||
# Checking if the current type's parent is itself
|
||||
{% if p = @type.annotation(CliGen::CommandInfo)[:parent] %}
|
||||
{% if p.resolve == @type %}
|
||||
{% raise "ERROR : #{@type.name} < CliGen::Command : Circular parent defined between #{@type.name} and itself" %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% commands = [] of TypeNode %}
|
||||
|
||||
# Checking if any other commands in the tree are circular with this one
|
||||
{% issue_topic = nil %}
|
||||
{% current = @type %}
|
||||
{% for i in (1..CliGen::MAX_COMMAND_DEPTH) %}
|
||||
{% unless current.nil? %}
|
||||
{% commands << current %}
|
||||
{% if parent = current.annotation(CliGen::CommandInfo)[:parent] %}
|
||||
{% parent = parent.resolve %}
|
||||
{% if parent == @type %}
|
||||
{% issue_topic = current %}
|
||||
{% else %}
|
||||
{% current = parent %}
|
||||
{% end %}
|
||||
{% else %}
|
||||
{% current = nil %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
||||
{% if issue_topic %}
|
||||
{% raise "ERROR : #{@type.name} < CliGen::Command : Circular parent defined between #{@type.name} and #{issue_topic.name}" %}
|
||||
{% end %}
|
||||
|
||||
{% unless current.nil? %}
|
||||
{% puts "ERROR : #{@type.name} < CliGen::Command : Discovered command-tree is either circular or larger than CliGen::MAX_COMMAND_DEPTH (which is set to #{CliGen::MAX_COMMAND_DEPTH}). Please address" %}
|
||||
{% puts "Processed Commands: " %}
|
||||
{% for cmd, i in commands %}
|
||||
{% puts "#{i}) #{cmd.name}" %}
|
||||
{% end %}
|
||||
{% raise "Please address this and retry" %}
|
||||
{% end %}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -18,12 +18,22 @@ module CliGen
|
||||
commands : Array(BaseCommandNode),
|
||||
pre_run_commands : Array(RunCommand),
|
||||
post_run_commands : Array(RunCommand),
|
||||
parent : BaseCommandNode? = nil,
|
||||
description : String? = nil
|
||||
)
|
||||
meta = CommandMeta.new(
|
||||
cls: {{T.name.stringify}}
|
||||
)
|
||||
super(name, flags, commands, pre_run_commands, post_run_commands, meta, description)
|
||||
super(
|
||||
name: name,
|
||||
flags: flags,
|
||||
commands: commands,
|
||||
pre_run_commands: pre_run_commands,
|
||||
post_run_commands: post_run_commands,
|
||||
meta: meta,
|
||||
parent: parent,
|
||||
description: description
|
||||
)
|
||||
end
|
||||
|
||||
def subcommands : Array(SubCommandInfo)
|
||||
@@ -137,10 +147,6 @@ module CliGen
|
||||
raise CliGen::InternalError.new("CommandNode(#{@name})#process : subcommand '#{matched_subcommand}' was already matched — duplicate subcommand token") if matched_subcommand
|
||||
matched_subcommand = arg.value
|
||||
|
||||
when MatchType::Help
|
||||
Log.trace { "CommandNode(#{@name})#process : Arg(#{arg.value}) is a help option. Raising to have App print out help output" }
|
||||
raise CliGen::HelpRequestedError.new(help)
|
||||
|
||||
when MatchType::FlagWithArg
|
||||
Log.debug { "CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be a flag with an arg <flag>=<arg>" }
|
||||
if regex_match = CliGen::Regex::FLAG_WITH_ARG.match(arg.value)
|
||||
@@ -163,7 +169,7 @@ module CliGen
|
||||
Log.debug { "CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be an combined short flag" }
|
||||
val = arg.value.lchop('-')
|
||||
|
||||
flg : BaseFlag? = flag?("#{val[0]}")
|
||||
flg : BaseFlag? = flag?("-#{val[0]}")
|
||||
unless flg
|
||||
raise CliGen::UnknownFlagError.new("#{CliGen::APPNAME}: unknown flag '-#{val[0]}'")
|
||||
end
|
||||
|
||||
@@ -16,6 +16,7 @@ module CliGen
|
||||
getter commands : Array(BaseCommandNode)
|
||||
getter description : String?
|
||||
getter meta : CommandMeta
|
||||
getter? parent : BaseCommandNode?
|
||||
@pre_run_commands : Array(RunCommand)
|
||||
@post_run_commands : Array(RunCommand)
|
||||
|
||||
@@ -28,6 +29,7 @@ module CliGen
|
||||
@pre_run_commands : Array(RunCommand),
|
||||
@post_run_commands : Array(RunCommand),
|
||||
@meta : CommandMeta,
|
||||
@parent : BaseCommandNode? = nil,
|
||||
@description : String? = nil
|
||||
)
|
||||
end
|
||||
@@ -36,6 +38,10 @@ module CliGen
|
||||
@flags + @commands.flat_map(&.all_flags)
|
||||
end
|
||||
|
||||
def all_commands : Array(BaseCommandNode)
|
||||
@commands + @commands.flat_map(&.all_commands)
|
||||
end
|
||||
|
||||
def check_for_duplicate_subcommands!
|
||||
failures = [] of Tuple(String, Array(BaseCommandNode))
|
||||
|
||||
@@ -121,9 +127,6 @@ module CliGen
|
||||
end
|
||||
|
||||
case arg
|
||||
when "-h", "--help"
|
||||
Log.debug { "CommandNode(#{@name})#find_match(#{arg}) : was found to be a help flag" }
|
||||
CliGen::MatchType::Help
|
||||
when CliGen::Regex::FLAG_REGEX
|
||||
Log.debug { "CommandNode(#{@name})#find_match(#{arg}) : arg found to match the format of a flag" }
|
||||
if flg = flag?(arg)
|
||||
|
||||
@@ -2,20 +2,33 @@
|
||||
# Copyright 2026 Tristan Ancelet
|
||||
|
||||
module CliGen::Common
|
||||
macro check_flag_vars(*, type, long, description, raise_base, short = nil, validation = nil, on_match = nil, options = nil, format = nil, env_var = nil, delimiter = ",", allow_no_verification = false)
|
||||
macro check_flag_vars(*, type, long, description, raise_base, short = nil, validation = nil, on_match = nil, options = nil, format = nil, env_var = nil, delimiter = ",", allow_no_verification = false, internal = false)
|
||||
{% raise_base = raise_base.id %}
|
||||
{% raise "ERROR : #{raise_base} : Provided type (#{type}) must resolve to a type" unless type.resolve.is_a? TypeNode %}
|
||||
{% if env_var %}
|
||||
{% unless env_var.nil? || env_var == "" %}
|
||||
{% raise "ERROR : #{raise_base} : Provided env_var must be a string" unless env_var.is_a? StringLiteral %}
|
||||
{% raise "ERROR : #{raise_base} : Provided env_var cannot contain a \"-\". Please fix and re-run" if env_var.includes?("-") %}
|
||||
{% end %}
|
||||
{% raise "ERROR : #{raise_base} : Provided delimiter must be a string" unless delimiter.is_a? StringLiteral %}
|
||||
{% if short %}
|
||||
{% unless short.nil? %}
|
||||
{% raise "ERROR : #{raise_base} : Provided short must be a string" unless short.is_a? StringLiteral %}
|
||||
{% raise "ERROR : #{raise_base} : Provided short(#{short}) must be in a valid short format (-[a-zA-Z])" unless short =~ /^-[A-Za-z]$/ %}
|
||||
{% raise "ERROR : #{raise_base} : Provided short(#{short}) must be in a valid short format #{::CliGen::Regex::FLAG_SHORT}" unless short =~ ::CliGen::Regex::FLAG_SHORT %}
|
||||
{% unless internal %}
|
||||
{% if %w[ -h -v ].includes?(short) %}
|
||||
{% raise "ERROR : #{raise_base} : Short(#{short}) is a reserved for internal usage. Please choose another short" %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% raise "ERROR : #{raise_base} : Provided long must be a string" unless long.is_a? StringLiteral %}
|
||||
{% raise "ERROR : #{raise_base} : Provided long must match --[a-zA-Z0-9-_]+" unless long =~ /^--[a-zA-Z0-9-_]+/ %}
|
||||
{% if long =~ /\s+|=+/ %}
|
||||
{% long = long.split(/\s+|=+/).first %}
|
||||
{% end %}
|
||||
{% raise "ERROR : #{raise_base} : Provided long (#{long}) must match #{::CliGen::Regex::FLAG_LONG.source}" unless long =~ ::CliGen::Regex::FLAG_LONG %}
|
||||
{% unless internal %}
|
||||
{% if %w[ --help --verbose ].includes?(long) %}
|
||||
{% raise "ERROR : #{raise_base} : Long(#{long}) is a reserved for internal usage. Please choose another long" %}
|
||||
{% end %}
|
||||
{% end %}
|
||||
{% raise "ERROR : #{raise_base} : You must provide a description" unless description %}
|
||||
{% raise "ERROR : #{raise_base} : Provided description must be a String" unless description.is_a? StringLiteral || description.is_a? StringInterpolation %}
|
||||
{% unless on_match.nil? %}
|
||||
|
||||
@@ -6,7 +6,7 @@ module CliGen
|
||||
class Error < Exception; end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Internal errors - framework invariant violations, should never reach users
|
||||
# Internal errors : framework invariant violations, should never reach users
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class InternalError < Error; end
|
||||
@@ -21,11 +21,19 @@ module CliGen
|
||||
class UnknownCommandNodeError < InternalError; end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Configuration errors - shard consumer wired something up incorrectly
|
||||
# Configuration errors : shard consumer wired something up incorrectly
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class ConfigurationError < Error; end
|
||||
|
||||
# Used when a user attempts to initialize a singleton class before
|
||||
# CliGen::App has processed any commandline arguments.
|
||||
class AppNotProcessedError < ConfigurationError; end
|
||||
|
||||
# Used when a user double-calls App#process. As we do not want to double process
|
||||
# thigns
|
||||
class AppAlreadyProcessedError < ConfigurationError; end
|
||||
|
||||
# -h or --help was used as a flag short/long (reserved for internal help)
|
||||
class ReservedFlagError < ConfigurationError; end
|
||||
|
||||
@@ -48,7 +56,7 @@ module CliGen
|
||||
class ParseableInvariantError < ConfigurationError; end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Runtime errors - bad user input at the CLI level
|
||||
# Runtime errors : bad user input at the CLI level
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
class RuntimeError < Error; end
|
||||
@@ -75,7 +83,7 @@ module CliGen
|
||||
class FlagBundleError < RuntimeError; end
|
||||
|
||||
# -------------------------------------------------------------------------
|
||||
# Help signal - not an error; exit 0 after printing
|
||||
# Help signal : not an error; exit 0 after printing
|
||||
# -------------------------------------------------------------------------
|
||||
|
||||
# Raised when -h/--help is matched; carries the rendered help string
|
||||
|
||||
+36
-8
@@ -19,7 +19,7 @@ module CliGen
|
||||
var : String,
|
||||
short : String?,
|
||||
long : String,
|
||||
env_var : String,
|
||||
env_var : String?,
|
||||
description : String,
|
||||
delimiter : String = ",",
|
||||
@default : T? = nil,
|
||||
@@ -200,10 +200,13 @@ module CliGen
|
||||
|
||||
# Priority: provided arg → env var → default → abort
|
||||
if v.nil?
|
||||
if raw = ENV[@env_var]?
|
||||
# Since ENVVAR is optional it can be nil
|
||||
if var = @env_var
|
||||
if raw = ENV[var]?
|
||||
v = coerce(raw)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
v ||= @default
|
||||
|
||||
@@ -228,7 +231,7 @@ module CliGen
|
||||
def satisfied? : Bool
|
||||
Log.trace { "Flag(long: #{@long}, type: #{@meta.type})#satisfied? : called" }
|
||||
return true if !@value.nil?
|
||||
return true if @env_var && ENV[@env_var]?
|
||||
return true if !@env_var.nil? && ENV[@env_var.not_nil!]?
|
||||
return true if !@default.nil?
|
||||
false
|
||||
end
|
||||
@@ -254,12 +257,37 @@ module CliGen
|
||||
|
||||
def check! : Nil
|
||||
Log.trace { "Flag(long: #{@long}, type: #{@meta.type})#check! : called" }
|
||||
unless @short.nil?
|
||||
raise CliGen::ConfigurationError.new("Flag({{T}}, long: #{@long})#check! : #{@short} flag short must start with '--'") unless @short.not_nil!.starts_with?("-")
|
||||
if short = @short
|
||||
unless short =~ CliGen::Regex::FLAG_SHORT
|
||||
raise CliGen::ConfigurationError.new(
|
||||
"Flag({{T}}, long: #{@long})#check! : #{short} must match be a single \"-\" followed by a single character [a-zA-Z]. " \
|
||||
"Valid pattern (#{CliGen::Regex::FLAG_SHORT.source})"
|
||||
)
|
||||
end
|
||||
end
|
||||
unless long_key =~ CliGen::Regex::FLAG_LONG
|
||||
raise CliGen::ConfigurationError.new(
|
||||
"Flag({{T}}, long: #{@long})#check! : flag long (#{long_key}) must begin with \"--\" followed by a series of alphanumeric " \
|
||||
"characters and/or \"-\". Valid pattern (#{CliGen::Regex::FLAG_LONG.source})"
|
||||
)
|
||||
end
|
||||
# If #check! is ever called on CliGen::GLOBAL_FLAGS this will die as the
|
||||
# internal flags are also included in there. However, since this isn't
|
||||
# called on them this check is safe and is only scoped for the class/command
|
||||
# authored ones
|
||||
if %w[ --verbose --help ].includes?(@long_key)
|
||||
raise CliGen::ReservedFlagError.new(
|
||||
"Flag({{T}}, long: #{@long})#check! : Long(#{@long_key}) is a reserved long flag. You will need to use another"
|
||||
)
|
||||
end
|
||||
|
||||
if short = @short
|
||||
if %w[ -v -h ].includes?(short)
|
||||
raise CliGen::ReservedFlagError.new(
|
||||
"Flag({{T}}, long: #{@long})#check! : Long(#{@short}) is a reserved short flag. You will need to use another"
|
||||
)
|
||||
end
|
||||
end
|
||||
raise CliGen::ConfigurationError.new("Flag({{T}}, long: #{@long})#check! : #{@long} flag long must start with '--'") unless @long.starts_with?("--")
|
||||
raise CliGen::ReservedFlagError.new("Flag({{T}}, long: #{@long})#check! : -h is reserved for internal help") if @short == "-h"
|
||||
raise CliGen::ReservedFlagError.new("Flag({{T}}, long: #{@long})#check! : --help is reserved for internal help") if @long_key == "--help"
|
||||
end
|
||||
|
||||
private def coerce(raw : String) : T
|
||||
|
||||
@@ -11,7 +11,7 @@ module CliGen
|
||||
getter short : String?
|
||||
getter long : String
|
||||
getter long_key : String
|
||||
getter env_var : String
|
||||
getter env_var : String?
|
||||
getter description : String
|
||||
getter delimiter : String
|
||||
getter meta : FlagMeta
|
||||
@@ -22,7 +22,7 @@ module CliGen
|
||||
@var : String,
|
||||
@short : String?,
|
||||
@long : String,
|
||||
@env_var : String,
|
||||
@env_var : String?,
|
||||
@description : String,
|
||||
@delimiter : String,
|
||||
@meta : FlagMeta
|
||||
@@ -38,7 +38,7 @@ module CliGen
|
||||
}
|
||||
# if the user provides just a "--long" I want the @long_key to match it
|
||||
if @long =~ /\s|=/
|
||||
@long_key = @long.split(/\s|=/).first
|
||||
@long_key = @long.split(/\s|=/).first.strip
|
||||
else
|
||||
@long_key = @long
|
||||
end
|
||||
|
||||
@@ -12,17 +12,30 @@ module CliGen
|
||||
long: "--verbose",
|
||||
env_var: "VERBOSE",
|
||||
default: false,
|
||||
description: "Enable verbose output from program & help output"
|
||||
description: "Enable verbose output from program & help output",
|
||||
internal: true
|
||||
)
|
||||
|
||||
add_global_flag(Bool,
|
||||
short: "-h",
|
||||
long: "--help",
|
||||
env_var: "",
|
||||
env_var: nil,
|
||||
default: false,
|
||||
description: "Print out this help output",
|
||||
internal: true,
|
||||
on_match: ->(v : Bool) do
|
||||
raise CliGen::
|
||||
raise CliGen::HelpRequestedError.new("")
|
||||
end
|
||||
)
|
||||
{% unless env("CLIGEN_VERSION") == "no" %}
|
||||
add_global_flag(Bool,
|
||||
long: "--cligen-version",
|
||||
env_var: nil,
|
||||
description: "Print out the version of cligen",
|
||||
on_match: ->(v : Bool) do
|
||||
puts CliGen::VERSION
|
||||
exit 0
|
||||
end
|
||||
)
|
||||
{% end %}
|
||||
end
|
||||
@@ -4,9 +4,250 @@
|
||||
require "../common/check_flag_vars"
|
||||
|
||||
module CliGen
|
||||
macro add_global_flag(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil, options = nil)
|
||||
# This macro provides a user-friendly way to define a global flag for your
|
||||
# project.
|
||||
#
|
||||
# ## What does this do?
|
||||
# This macro is used to help define & check a global flag to be used in the
|
||||
# all levels of commands.
|
||||
#
|
||||
# When provided it will parse your values & serialize them into a Flag(T)
|
||||
# object & insert it in the CliGen::GLOBAL_FLAGS array after checking if
|
||||
# a flag using it's `--long` is already in use. In the case that that long
|
||||
# is already used it will raise at runtime and you'll need to choose another
|
||||
# long.
|
||||
#
|
||||
# ## Arguments
|
||||
# ### type: TypeNode
|
||||
# **Required:** true
|
||||
#
|
||||
# This is the type of the flag (Bool, Int32, String, etc).
|
||||
#
|
||||
#
|
||||
# ### long: StringLiteral
|
||||
# **Required:** true
|
||||
#
|
||||
# This is the long form of the flag that will be matched at the command-line
|
||||
#
|
||||
#
|
||||
# ### description: StringLiteral
|
||||
# **Required:** true
|
||||
#
|
||||
# This is the full length description of the flag that will be presented in the
|
||||
# help text provided to the user.
|
||||
#
|
||||
#
|
||||
# ### env_var: StringLiteral
|
||||
# **Required:** false
|
||||
#
|
||||
# This is an ENV VAR that can be used to set this value without providing an
|
||||
# argument via the CLI. By default it will (unless explicitly disbled by
|
||||
# passing `env_var: nil` as an argument to disable the env_var entirely)
|
||||
# will parse your long flag and set the ENV VAR to the un "--" portion of it
|
||||
#
|
||||
# **Warning:** Incompatible ENV VAR formatting
|
||||
#
|
||||
# When providing ENV VARs manually you cannot provide any whitespace or "-"
|
||||
# characters internally to it. As thse are both incompatible with ENV VARs.
|
||||
#
|
||||
# If you provide an ENV VAR with these the framework will raise at
|
||||
# compile-time and tell you to change them.
|
||||
#
|
||||
# **Note:** Auto Generates ENV VAR from flag long
|
||||
#
|
||||
# If you did not provide a ENV VAR manually (or disable it via setting it to
|
||||
# nil), the macro will use the long flag to create a ENV VAR that can be
|
||||
# matched. In this case if the flag has any internal "-" chars they will
|
||||
# be replaced with "_" so "--long--flag--name"/"--long-flag-name" ->
|
||||
# "LONG_FLAG_NAME".
|
||||
#
|
||||
# When you provide a long: with a trailing ARGUMENT (ex: "--item ITEM",
|
||||
# "--item=ITEM") the flag will first be split on the whitespace or "="
|
||||
# prior to being used for the ENV_VAR.
|
||||
#
|
||||
#
|
||||
# ### short: StringLiteral
|
||||
# **Required:** false
|
||||
#
|
||||
# This is the short form of a flag ("--filename" -> "-f") that can be matched
|
||||
# during parsing.
|
||||
#
|
||||
# **Note:** Alphabetic characters only
|
||||
#
|
||||
# Unlike some other frameworks that might support numeric flags, due to the
|
||||
# issues around supporting them & being able to discern if these are arguments
|
||||
# (-1/signed int's) or short flags ("--one" -> "-1"), I've determined that I
|
||||
# will not be supporting numeric flags as this causes a number of
|
||||
# complications/complexities around ARGV parsing.
|
||||
#
|
||||
#
|
||||
# ### default: T
|
||||
# **Required:** ?false?
|
||||
#
|
||||
# This is the default value of the flag (String -> "abc", Int32 -> 0, etc)
|
||||
# that will be returned if no direct (via parsing CLI args) or indirect
|
||||
# (by parsing ENV VAR values) arguments are provided.
|
||||
#
|
||||
# While not technically required, it's advised to always set a default
|
||||
# when creating flags as if you don't and nothing is parsed/provided
|
||||
# when Flag(T)#value! is called it will raise a
|
||||
# CliGen::MissingRequiredFlagError exception at the call site.
|
||||
#
|
||||
#
|
||||
# ### options: ArrayLiteral(T)|Call
|
||||
# **Required:** false
|
||||
#
|
||||
# This argument sets a static list of accepted arguments to a specific subset
|
||||
# of values.
|
||||
#
|
||||
# EX: Output format
|
||||
#
|
||||
# CliGen.add_global_flag(String,
|
||||
# default: "ecr",
|
||||
# short: "-f",
|
||||
# long: "--format",
|
||||
# description: "Provide the preferred output format",
|
||||
# options: %w[ json yaml ecr ]
|
||||
# )
|
||||
#
|
||||
#
|
||||
# **Note:** Support for runtime resolution
|
||||
#
|
||||
# While the primary value of this is static arrays of values, you can also
|
||||
# delegate the discovery of values to a global method or helper method in
|
||||
# your codebase.
|
||||
#
|
||||
# HOWEVER, when doing so ALWAYS ensure that you are providing a full path
|
||||
# to your method, as the the macro has no way of determining relative paths
|
||||
# in your modules. While, provided you are doing this in the same context as
|
||||
# the method you are running, this shouldn't be an issue, however best
|
||||
# practices dictate you provide a full path just to be careful.
|
||||
#
|
||||
# EX: Delegated resolution
|
||||
#
|
||||
# module ABC
|
||||
# def self.items
|
||||
# %w[ a b c d e f g taco ]
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# CliGen.add_global_flag(String,
|
||||
# default: "a",
|
||||
# short: "-i",
|
||||
# long: "--item",
|
||||
# description: "Provide an item to print",
|
||||
# options: ::ABC.items
|
||||
# )
|
||||
#
|
||||
#
|
||||
# ### format: RegexLiteral
|
||||
# **Required:** false
|
||||
#
|
||||
# This exists to handle (for String & Custom Data Types) filtering & checking
|
||||
# that an argument being provided by a user is being given in a specific
|
||||
# format.
|
||||
#
|
||||
# This is something you use when you're only wanting to validate formatting,
|
||||
# if you plan to do more specific/extensive validation you should use the
|
||||
# validation: field.
|
||||
#
|
||||
# EX: Hostname matching
|
||||
#
|
||||
# CliGen.add_global_flag(Array(String),
|
||||
# default: [] of String,
|
||||
# short: "-H",
|
||||
# long: "--hostname",
|
||||
# description: "Provide a hostname to do remote work on",
|
||||
# format: /^[a-zA-Z]{3}[0-9]+node[0-9]$/
|
||||
# )
|
||||
#
|
||||
#
|
||||
# ### validation: ProcLiteral(T, Bool)
|
||||
# **Required:** false
|
||||
#
|
||||
# Here you can provide a ad-hoc proc for doing validations of a provided
|
||||
# argument that can't easily be done by providing a static `options:` value.
|
||||
#
|
||||
# **Note:** Explicit input & return type requirement
|
||||
#
|
||||
# The explicit input `: T` & return `: Bool` turn types are required as the
|
||||
# macros I setup are trying to enforce that both the input & return types
|
||||
# are explicity to avoid truthy & falsey semantics.
|
||||
#
|
||||
# EX: checking int range
|
||||
#
|
||||
# CliGen.add_global_flag(Int32,
|
||||
# short: "-p",
|
||||
# long: "--port",
|
||||
# description: "Provide a single port to test against",
|
||||
# validation: ->(port : Int32) : Bool do
|
||||
# (UInt16::MIN..UInt16::MAX).includes?(port)
|
||||
# end
|
||||
# )
|
||||
#
|
||||
#
|
||||
# EX: file existance check
|
||||
#
|
||||
# CliGen.add_global_flag(String,
|
||||
# short: "-i",
|
||||
# long: "--filename",
|
||||
# description: "Provide a file that will serve as the input for this program",
|
||||
# validation: ->(file : String) : Bool do
|
||||
# if File.exists?(file)
|
||||
# true
|
||||
# else
|
||||
# STDERR.puts "ERROR : --filename : Provided file (#{file}) does not exist"
|
||||
# false
|
||||
# end
|
||||
# end
|
||||
# )
|
||||
#
|
||||
#
|
||||
# ### on_match: ProcLiteral(T, Nil)
|
||||
# **Required:** false
|
||||
#
|
||||
# This option is where you provide the proc for handling ad-hoc
|
||||
#
|
||||
# EX: Configuring the stdlib log level
|
||||
#
|
||||
# CliGen.add_global_flag(String,
|
||||
# long: "--log-level LEVEL",
|
||||
# short: "-l",
|
||||
# description: "Set the current log level of the stdlib Log library",
|
||||
# options: %w[ trace debug notice info warn error fatal ],
|
||||
# on_match: ->(level : String) do
|
||||
# ::Log.setup(level: ::Log::Severity.parse(level))
|
||||
# end
|
||||
# )
|
||||
#
|
||||
# EX: Collecting arguments in a global array
|
||||
#
|
||||
#
|
||||
# module MyModule
|
||||
# MY_ARRAY = [] of String
|
||||
# CliGen.add_global_flag(String,
|
||||
# long: "--filename FILE",
|
||||
# short: "-i",
|
||||
# description: "Provide a single file to check against (repeatable)",
|
||||
# validation: ->(file : String) : Bool do
|
||||
# if File.exists?(file)
|
||||
# true
|
||||
# else
|
||||
# STDERR.puts "ERROR : --filename : #{file} does not exist"
|
||||
# false
|
||||
# end
|
||||
# end,
|
||||
# on_match: ->(file : String) do
|
||||
# ::MyModule::MY_ARRAY << file
|
||||
# end
|
||||
# )
|
||||
# end
|
||||
#
|
||||
#
|
||||
# For more detailed documentation please visit the wiki in the repo. All topics are covered there in much greater detail than inline documentation here
|
||||
macro add_global_flag(type, *, long, description, env_var = "", short = nil, validation = nil, default = nil, on_match = nil, options = nil, format = nil, internal = false)
|
||||
{% raise "ERROR : CliGen.add_global_flag : Provided long must be a string" unless long.is_a? StringLiteral %}
|
||||
{% env_var = long.gsub(/^--/,"").gsub(/-+/,"_").upcase if env_var.nil? %}
|
||||
{% env_var = long.split(/=|\s+/).first.gsub(/^--/,"").gsub(/-+/,"_").upcase if env_var == "" %}
|
||||
|
||||
CliGen::Common.check_flag_vars(
|
||||
raise_base: {{"CliGen.add_global_flag(#{long.id})"}},
|
||||
@@ -17,10 +258,12 @@ module CliGen
|
||||
validation: {{validation}},
|
||||
on_match: {{on_match}},
|
||||
options: {{options}},
|
||||
description: {{description}}
|
||||
format: {{format}},
|
||||
description: {{description}},
|
||||
internal: {{internal}}
|
||||
)
|
||||
|
||||
::CliGen::GLOBAL_FLAGS << ::CliGen::Flag({{type}}).new(
|
||||
%flg = ::CliGen::Flag({{type}}).new(
|
||||
var: "",
|
||||
short: {{short}},
|
||||
long: {{long}},
|
||||
@@ -31,5 +274,42 @@ module CliGen
|
||||
on_match: {% unless on_match.nil? %} {{on_match}} {% else %} nil {% end %},
|
||||
validate: {% unless validation.nil? %} {{validation}} {% else %} nil {% end %}
|
||||
)
|
||||
|
||||
# If the user is defining a global flag check to make sure that long
|
||||
# isn't already defined
|
||||
if %oflg = ::CliGen::GLOBAL_FLAGS.find(&.long_key.== %flg.long_key)
|
||||
abort <<-EOF
|
||||
ERROR : CliGen.add_global_flag : Flag({{type}}, long: "{{long.id}}") : at #{__FILE__}:#{__LINE__}
|
||||
|
||||
Provided long flag (#{%flg.long_key}) is in conflict with another flag in CliGen::GLOBAL_FLAGS.
|
||||
|
||||
You will need to choose another long.
|
||||
|
||||
Conflicted Flag:
|
||||
Flag(#{%oflg.meta.type}, long: "#{%oflg.long}", description: "#{%oflg.description}")
|
||||
\n
|
||||
EOF
|
||||
end
|
||||
|
||||
{% unless short.nil? %}
|
||||
# If the user is defining a global flag check to make sure that short
|
||||
# isn't already defined
|
||||
if %oflg = ::CliGen::GLOBAL_FLAGS.find(&.short.== %flg.short)
|
||||
abort <<-EOF
|
||||
ERROR : CliGen.add_global_flag : Flag({{type}}, long: "{{long.id}}") : at #{__FILE__}:#{__LINE__}
|
||||
|
||||
Provided short flag (#{%flg.short}) is in conflict with another flag in CliGen::GLOBAL_FLAGS.
|
||||
|
||||
You will need to choose another short.
|
||||
|
||||
Conflicted Flag:
|
||||
Flag(#{%oflg.meta.type}, long: "#{%oflg.long}", description: "#{%oflg.description}")
|
||||
\n
|
||||
EOF
|
||||
end
|
||||
{% end %}
|
||||
|
||||
# if they didn't fail completely add it to the global flags
|
||||
::CliGen::GLOBAL_FLAGS << %flg
|
||||
end
|
||||
end
|
||||
+4
-2
@@ -3,8 +3,10 @@
|
||||
|
||||
module CliGen::Regex
|
||||
FLAG_REGEX=/^(-[a-zA-Z]|--[a-zA-Z-_0-9]+)$/
|
||||
FLAG_WITH_ARG=/^(?<flag>(-[a-zA-Z]|--[a-zA-Z-_]+))="?(?<arg>\S+?)"?$/
|
||||
FLAG_MULTIPLE_SHORT=/^-[a-zA-Z][a-zA-Z0-9]+$/
|
||||
FLAG_WITH_ARG=/^(?<flag>(-[a-zA-Z]|--[a-zA-Z0-9][a-zA-Z0-9-_]+))="?(?<arg>.+?)"?$/
|
||||
FLAG_MULTIPLE_SHORT=/^-[a-zA-Z][a-zA-Z]+$/
|
||||
FLAG_LONG = /^--[a-zA-Z0-9][a-zA-Z0-9-_]+$/
|
||||
FLAG_SHORT = /^-[a-zA-Z]$/
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Date/time components.
|
||||
|
||||
@@ -2,6 +2,9 @@ Command: <%= @name %>
|
||||
<%- unless @description.nil? -%>
|
||||
Description: <%= @description %>
|
||||
<%- end -%>
|
||||
<%- if p = parent? -%>
|
||||
Parent Command: <%= p.name %>
|
||||
<%- end -%>
|
||||
|
||||
<%- unless @flags.empty? -%>
|
||||
<%- len = @flags.map{|f| f.short.nil? ? f.long.size : "#{f.short},#{f.long}".size}.max + 5 -%>
|
||||
@@ -17,7 +20,9 @@ Flags:
|
||||
<%= "%-#{len}s %s" % [flags.join(","), flag.description.strip] %><%= flag.meta.options.nil? ? "" : " (valid: #{flag.meta.options.not_nil!.join(", ")})" %><%= flag.meta.default.empty? ? "" : " (default: #{flag.meta.default.not_nil!})" %>
|
||||
<%- if verbose? -%>
|
||||
<%= "%-#{len}s %s" % ["", "Type: #{flag.meta.type}"] %>
|
||||
<%- unless flag.env_var.nil? -%>
|
||||
<%= "%-#{len}s %s" % ["", "ENV VAR: #{flag.env_var}"] %>
|
||||
<%- end -%>
|
||||
<%- unless flag.meta.format.nil? -%>
|
||||
<%= "%-#{len}s %s" % ["", "Valid Format: #{flag.meta.format}"] %>
|
||||
<%- end -%>
|
||||
@@ -42,7 +47,9 @@ Global Flags
|
||||
<%= "%-#{len}s %s" % [flags.join(","), flag.description.strip] %><%= flag.meta.options.nil? ? "" : " (valid: #{flag.meta.options.not_nil!.join(", ")})" %><%= flag.meta.default.empty? ? "" : " (default: #{flag.meta.default.not_nil!})" %>
|
||||
<%- if verbose? -%>
|
||||
<%= "%-#{len}s %s" % ["", "Type: #{flag.meta.type}"] %>
|
||||
<%- unless flag.env_var.nil? -%>
|
||||
<%= "%-#{len}s %s" % ["", "ENV VAR: #{flag.env_var}"] %>
|
||||
<%- end -%>
|
||||
<%- unless flag.meta.format.nil? -%>
|
||||
<%= "%-#{len}s %s" % ["", "Valid Format: #{flag.meta.format}"] %>
|
||||
<%- end -%>
|
||||
|
||||
@@ -90,5 +90,9 @@ module CliGen::Timeparse
|
||||
EOF
|
||||
)
|
||||
end
|
||||
rescue e : CliGen::Error
|
||||
raise e
|
||||
rescue e : Exception
|
||||
raise CliGen::TimeParseError.new("invalid date/time \"#{raw}\" : #{e.message}")
|
||||
end
|
||||
end
|
||||
Reference in new issue
Block a user