From 8fab6912fc6f259a501371648bd7365bcb570f3e Mon Sep 17 00:00:00 2001 From: Tristan Ancelet Date: Mon, 7 Sep 2026 16:40:02 -0500 Subject: [PATCH] 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 --- CLAUDE.md | 113 ++++- DESIGN.md | 10 +- README.md | 2 +- docs/404.html | 15 +- docs/CliGen.html | 301 +++++++++++- docs/CliGen/App.html | 52 +- docs/CliGen/Arg.html | 15 +- docs/CliGen/ArgReprocessedError.html | 15 +- docs/CliGen/Argument.html | 17 +- docs/CliGen/BaseCommandNode.html | 61 ++- docs/CliGen/BaseFlag.html | 31 +- docs/CliGen/Coercable.html | 15 +- docs/CliGen/Command.html | 244 ++++++++-- docs/CliGen/CommandInfo.html | 15 +- docs/CliGen/CommandMeta.html | 15 +- docs/CliGen/CommandNode.html | 37 +- docs/CliGen/Common.html | 444 ++++++++++++++++++ docs/CliGen/ConfigurationError.html | 15 +- docs/CliGen/DuplicateCommandError.html | 15 +- docs/CliGen/DuplicateFlagError.html | 15 +- docs/CliGen/Error.html | 15 +- docs/CliGen/Flag.html | 31 +- docs/CliGen/FlagArgumentError.html | 15 +- docs/CliGen/FlagBundleError.html | 15 +- docs/CliGen/FlagMeta.html | 15 +- docs/CliGen/FlagMissingArgumentError.html | 15 +- docs/CliGen/FlagNotFoundError.html | 15 +- docs/CliGen/Format.html | 15 +- docs/CliGen/HelpRequestedError.html | 15 +- docs/CliGen/InternalError.html | 15 +- docs/CliGen/InternalVar.html | 403 ++++++++++++++++ docs/CliGen/InvalidFlagValueError.html | 15 +- docs/CliGen/InvalidOptionError.html | 15 +- docs/CliGen/MatchType.html | 15 +- docs/CliGen/MissingDispatchError.html | 15 +- docs/CliGen/MissingRequiredFlagError.html | 15 +- docs/CliGen/Parsable.html | 15 +- docs/CliGen/ParseableInvariantError.html | 15 +- docs/CliGen/PreRunCommand.html | 15 +- docs/CliGen/ProxyCommand.html | 15 +- docs/CliGen/Regex.html | 29 +- docs/CliGen/RegexInvariantError.html | 15 +- docs/CliGen/ReservedFlagError.html | 15 +- docs/CliGen/RunCommand.html | 15 +- docs/CliGen/RuntimeError.html | 15 +- docs/CliGen/SubCommand.html | 15 +- docs/CliGen/SubCommandInfo.html | 15 +- docs/CliGen/TimeParseError.html | 15 +- docs/CliGen/Timeparse.html | 15 +- docs/CliGen/Timeparse/OperationUnit.html | 15 +- docs/CliGen/Timeparse/RelativeOperation.html | 15 +- docs/CliGen/Trigger.html | 15 +- docs/CliGen/UnknownCommandNodeError.html | 15 +- docs/CliGen/UnknownFlagError.html | 15 +- docs/CliGen/ValidationError.html | 15 +- docs/index.html | 17 +- docs/index.json | 2 +- docs/search-index.js | 2 +- shard.yml | 2 +- spec/cligen/command_spec.cr | 107 +++++ spec/cligen/flag_spec.cr | 18 +- spec/cligen/regex_spec.cr | 344 ++++++++++++++ spec/cligen/relative_operation_spec.cr | 102 ++++ spec/cligen/timeparse_spec.cr | 139 ++++++ src/cligen.cr | 33 +- src/cligen/annotations.cr | 5 +- src/cligen/app.cr | 23 +- src/cligen/app/generate.cr | 52 +- src/cligen/command.cr | 43 +- src/cligen/command/argument.cr | 6 +- src/cligen/command/def_init.cr | 25 - .../command/define_command_initializer.cr | 5 +- src/cligen/command/define_singleton_init.cr | 48 ++ src/cligen/command/generate_gather_handler.cr | 13 + .../command/generate_register_command.cr | 86 ++++ src/cligen/command/resolve_value.cr | 132 ++++++ src/cligen/command/selection.cr | 24 - src/cligen/command/validate_command_tree.cr | 68 +++ src/cligen/command_node.cr | 18 +- src/cligen/command_node/base.cr | 9 +- src/cligen/common/check_flag_vars.cr | 23 +- src/cligen/exceptions.cr | 16 +- src/cligen/flag.cr | 48 +- src/cligen/flag/base.cr | 6 +- src/cligen/global_flag.cr | 19 +- src/cligen/global_flag/add_global_flag.cr | 288 +++++++++++- src/cligen/regex.cr | 6 +- src/cligen/template/cmd_help.ecr | 7 + src/cligen/timeparse.cr | 4 + 89 files changed, 3615 insertions(+), 515 deletions(-) create mode 100644 docs/CliGen/Common.html create mode 100644 docs/CliGen/InternalVar.html create mode 100644 spec/cligen/command_spec.cr create mode 100644 spec/cligen/regex_spec.cr create mode 100644 spec/cligen/relative_operation_spec.cr create mode 100644 spec/cligen/timeparse_spec.cr delete mode 100644 src/cligen/command/def_init.cr create mode 100644 src/cligen/command/define_singleton_init.cr create mode 100644 src/cligen/command/generate_gather_handler.cr create mode 100644 src/cligen/command/generate_register_command.cr create mode 100644 src/cligen/command/resolve_value.cr delete mode 100644 src/cligen/command/selection.cr create mode 100644 src/cligen/command/validate_command_tree.cr diff --git a/CLAUDE.md b/CLAUDE.md index d2ddbbf..355ac0d 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -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=` 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 diff --git a/DESIGN.md b/DESIGN.md index 3f69868..1837215 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -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 diff --git a/README.md b/README.md index 2898ea7..3dcd4ed 100644 --- a/README.md +++ b/README.md @@ -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 diff --git a/docs/404.html b/docs/404.html index a50a38a..70d069b 100644 --- a/docs/404.html +++ b/docs/404.html @@ -117,6 +117,11 @@ +
  • + Common + +
  • +
  • ConfigurationError @@ -182,6 +187,11 @@
  • +
  • + InternalVar + +
  • +
  • InvalidFlagValueError @@ -252,11 +262,6 @@
  • -
  • - Selection - -
  • -
  • SubCommand diff --git a/docs/CliGen.html b/docs/CliGen.html index 46f3b70..251e2c9 100644 --- a/docs/CliGen.html +++ b/docs/CliGen.html @@ -117,6 +117,11 @@
  • +
  • + Common + +
  • +
  • ConfigurationError @@ -182,6 +187,11 @@
  • +
  • + InternalVar + +
  • +
  • InvalidFlagValueError @@ -252,11 +262,6 @@
  • -
  • - Selection - -
  • -
  • SubCommand @@ -396,12 +401,22 @@
    - cligen/command/def_init.cr + cligen/command/define_command_initializer.cr
    - cligen/command/define_command_initializer.cr + cligen/command/define_singleton_init.cr + +
    + + + cligen/command/generate_gather_handler.cr + +
    + + + cligen/command/generate_register_command.cr
    @@ -411,7 +426,7 @@
    - cligen/command/selection.cr + cligen/command/resolve_value.cr
    @@ -421,6 +436,11 @@
    + cligen/command/validate_command_tree.cr + +
    + + cligen/command_node.cr
    @@ -500,8 +520,33 @@ +
    + MAX_COMMAND_DEPTH = 32 +
    + +
    +

    +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 }
    +
    + +
    - VERSION = "0.1.0" + VERSION = "0.2.0"
    @@ -525,7 +570,9 @@
    • - add_global_flag(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil) + add_global_flag(type, *, long, description, env_var = "", short = nil, validation = nil, default = nil, on_match = nil, options = nil, format = nil, internal = false) + +

      This macro provides a user-friendly way to define a global flag for your project.

    • @@ -558,14 +605,242 @@ Macro Detail -
      +
      - macro add_global_flag(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil) + macro add_global_flag(type, *, long, description, env_var = "", short = nil, validation = nil, default = nil, on_match = nil, options = nil, format = nil, internal = false) - # + #
      +
      + +

      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

      +
      +
      diff --git a/docs/CliGen/App.html b/docs/CliGen/App.html index 51e16d3..0c60807 100644 --- a/docs/CliGen/App.html +++ b/docs/CliGen/App.html @@ -117,6 +117,11 @@ +
    • + Common + +
    • +
    • ConfigurationError @@ -182,6 +187,11 @@
    • +
    • + InternalVar + +
    • +
    • InvalidFlagValueError @@ -252,11 +262,6 @@
    • -
    • - Selection - -
    • -
    • SubCommand @@ -419,6 +424,11 @@ for global-flag matching, then hands off to the matched child CommandNode.

        +
      • + .get + +
      • +
      • .handle_command_raises(&) : Nil @@ -500,8 +510,8 @@ for global-flag matching, then hands off to the matched child CommandNode.

        Constructor methods inherited from class CliGen::CommandNode(Nil)

        - - new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil) + + 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) new @@ -519,6 +529,11 @@ for global-flag matching, then hands off to the matched child CommandNode.

        Instance methods inherited from class CliGen::BaseCommandNode

        + + all_commands : Array(BaseCommandNode) + all_commands, + + all_flags : Array(BaseFlag) all_flags, @@ -584,6 +599,11 @@ for global-flag matching, then hands off to the matched child CommandNode.

        name, + + parent? : BaseCommandNode | Nil + parent?, + + process(args : Array(String)) : Nil
        process(args : Array(CliGen::Arg)) : Nil
        process
        , @@ -611,8 +631,8 @@ for global-flag matching, then hands off to the matched child CommandNode.

        Constructor methods inherited from class CliGen::BaseCommandNode

        - - 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) + + 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) new @@ -689,6 +709,20 @@ for global-flag matching, then hands off to the matched child CommandNode.

        Class Method Detail +
        +
        + + def self.get + + # +
        + +
        +
        + +
        +
        +
        diff --git a/docs/CliGen/Arg.html b/docs/CliGen/Arg.html index 3100dcc..f787eaf 100644 --- a/docs/CliGen/Arg.html +++ b/docs/CliGen/Arg.html @@ -117,6 +117,11 @@
      • +
      • + Common + +
      • +
      • ConfigurationError @@ -182,6 +187,11 @@
      • +
      • + InternalVar + +
      • +
      • InvalidFlagValueError @@ -252,11 +262,6 @@
      • -
      • - Selection - -
      • -
      • SubCommand diff --git a/docs/CliGen/ArgReprocessedError.html b/docs/CliGen/ArgReprocessedError.html index 9fe3b6b..0a80644 100644 --- a/docs/CliGen/ArgReprocessedError.html +++ b/docs/CliGen/ArgReprocessedError.html @@ -117,6 +117,11 @@
      • +
      • + Common + +
      • +
      • ConfigurationError @@ -182,6 +187,11 @@
      • +
      • + InternalVar + +
      • +
      • InvalidFlagValueError @@ -252,11 +262,6 @@
      • -
      • - Selection - -
      • -
      • SubCommand diff --git a/docs/CliGen/Argument.html b/docs/CliGen/Argument.html index 469f3a1..98d1815 100644 --- a/docs/CliGen/Argument.html +++ b/docs/CliGen/Argument.html @@ -117,6 +117,11 @@
      • +
      • + Common + +
      • +
      • ConfigurationError @@ -182,6 +187,11 @@
      • +
      • + InternalVar + +
      • +
      • InvalidFlagValueError @@ -252,11 +262,6 @@
      • -
      • - Selection - -
      • -
      • SubCommand @@ -346,7 +351,7 @@

        This is used for annotating instance variables for the CliGen framework can know how to create your CliGen::Flag(T) objects

        -

        WHILE this is usually being handled by the CliGen::Command.argument macro +

        WHILE this is usually being handled by the CliGen::Command.argument macro inside of the class body.

        EX:

        class MyCmd < CliGen::Command
        diff --git a/docs/CliGen/BaseCommandNode.html b/docs/CliGen/BaseCommandNode.html
        index fce7cc5..9a5cad2 100644
        --- a/docs/CliGen/BaseCommandNode.html
        +++ b/docs/CliGen/BaseCommandNode.html
        @@ -117,6 +117,11 @@
               
             
      • +
      • + Common + +
      • +
      • ConfigurationError @@ -182,6 +187,11 @@
      • +
      • + InternalVar + +
      • +
      • InvalidFlagValueError @@ -252,11 +262,6 @@
      • -
      • - Selection - -
      • -
      • SubCommand @@ -429,7 +434,7 @@ Everything that doesn't depend on T lives here.

        • - .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) + .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)
        • @@ -451,6 +456,11 @@ Everything that doesn't depend on T lives here.

            +
          • + #all_commands : Array(BaseCommandNode) + +
          • +
          • #all_flags : Array(BaseFlag) @@ -521,6 +531,11 @@ Everything that doesn't depend on T lives here.

          • +
          • + #parent? : BaseCommandNode | Nil + +
          • +
          • #process(args : Array(String)) : Nil @@ -592,12 +607,12 @@ Everything that doesn't depend on T lives here.

            Constructor Detail -
            +
            - def self.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) + def self.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) - # + #

            @@ -622,6 +637,20 @@ Everything that doesn't depend on T lives here.

            Instance Method Detail +
            +
            + + def all_commands : Array(BaseCommandNode) + + # +
            + +
            +
            + +
            +
            +
            @@ -818,6 +847,20 @@ Everything that doesn't depend on T lives here.

            +
            +
            + + def parent? : BaseCommandNode | Nil + + # +
            + +
            +
            + +
            +
            +
            diff --git a/docs/CliGen/BaseFlag.html b/docs/CliGen/BaseFlag.html index 9f71ef7..4dbff17 100644 --- a/docs/CliGen/BaseFlag.html +++ b/docs/CliGen/BaseFlag.html @@ -117,6 +117,11 @@
          • +
          • + Common + +
          • +
          • ConfigurationError @@ -182,6 +187,11 @@
          • +
          • + InternalVar + +
          • +
          • InvalidFlagValueError @@ -252,11 +262,6 @@
          • -
          • - Selection - -
          • -
          • SubCommand @@ -417,7 +422,7 @@
            • - .new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta) + .new(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : FlagMeta)
            • @@ -455,7 +460,7 @@
            • - #env_var : String + #env_var : String | Nil
            • @@ -548,12 +553,12 @@ Constructor Detail -
              +
              - def self.new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta) + def self.new(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : FlagMeta) - # + #

              @@ -620,12 +625,12 @@
              -
              +
              - def env_var : String + def env_var : String | Nil - # + #

              diff --git a/docs/CliGen/Coercable.html b/docs/CliGen/Coercable.html index bec5a16..f5d5e45 100644 --- a/docs/CliGen/Coercable.html +++ b/docs/CliGen/Coercable.html @@ -117,6 +117,11 @@ +
            • + Common + +
            • +
            • ConfigurationError @@ -182,6 +187,11 @@
            • +
            • + InternalVar + +
            • +
            • InvalidFlagValueError @@ -252,11 +262,6 @@
            • -
            • - Selection - -
            • -
            • SubCommand diff --git a/docs/CliGen/Command.html b/docs/CliGen/Command.html index 116a1cc..e4e96c9 100644 --- a/docs/CliGen/Command.html +++ b/docs/CliGen/Command.html @@ -117,6 +117,11 @@
            • +
            • + Common + +
            • +
            • ConfigurationError @@ -182,6 +187,11 @@
            • +
            • + InternalVar + +
            • +
            • InvalidFlagValueError @@ -252,11 +262,6 @@
            • -
            • - Selection - -
            • -
            • SubCommand @@ -373,12 +378,22 @@
              - cligen/command/def_init.cr + cligen/command/define_command_initializer.cr
              - cligen/command/define_command_initializer.cr + cligen/command/define_singleton_init.cr + +
              + + + cligen/command/generate_gather_handler.cr + +
              + + + cligen/command/generate_register_command.cr
              @@ -388,7 +403,7 @@
              - cligen/command/selection.cr + cligen/command/resolve_value.cr
              @@ -397,6 +412,11 @@
              + + cligen/command/validate_command_tree.cr + +
              + @@ -418,12 +438,7 @@ +

              + + + + Instance Method Summary +

              + +
              @@ -497,26 +555,12 @@ Macro Detail -
              +
              - 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 = "") - # -
              - -
              -
              - -
              -
              - -
              -
              - - macro def_init - - # + #

              @@ -539,6 +583,60 @@
              +
              +
              + + macro define_singleton_init + + # +
              + +
              + +

              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 generate_gather_handler + + # +
              + +
              +
              + +
              +
              + +
              +
              + + macro generate_register_command + + # +
              + +
              +
              + +
              +
              +
              @@ -553,14 +651,29 @@
              -
              +
              - macro selection(variable, description, options, short = nil, long = nil, validation = nil, on_match = nil) + macro resolve_value(variable, *, default = nil) - # + #
              +
              + +

              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: ) 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.

              +
              +
              @@ -581,9 +694,70 @@
              +
              +
              + + macro validate_command_tree + + # +
              + +
              + +

              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).

              +
              + +
              +
              + +
              +
              + +

              + + + + Instance Method Detail +

              + +
              +
              + + def handler? : Bool + + # +
              + +
              +
              + +
              +
              + +
              diff --git a/docs/CliGen/CommandInfo.html b/docs/CliGen/CommandInfo.html index 7c53059..42c8bc1 100644 --- a/docs/CliGen/CommandInfo.html +++ b/docs/CliGen/CommandInfo.html @@ -117,6 +117,11 @@
            • +
            • + Common + +
            • +
            • ConfigurationError @@ -182,6 +187,11 @@
            • +
            • + InternalVar + +
            • +
            • InvalidFlagValueError @@ -252,11 +262,6 @@
            • -
            • - Selection - -
            • -
            • SubCommand diff --git a/docs/CliGen/CommandMeta.html b/docs/CliGen/CommandMeta.html index ef09ad8..9d1c07c 100644 --- a/docs/CliGen/CommandMeta.html +++ b/docs/CliGen/CommandMeta.html @@ -117,6 +117,11 @@
            • +
            • + Common + +
            • +
            • ConfigurationError @@ -182,6 +187,11 @@
            • +
            • + InternalVar + +
            • +
            • InvalidFlagValueError @@ -252,11 +262,6 @@
            • -
            • - Selection - -
            • -
            • SubCommand diff --git a/docs/CliGen/CommandNode.html b/docs/CliGen/CommandNode.html index ffc6917..503111b 100644 --- a/docs/CliGen/CommandNode.html +++ b/docs/CliGen/CommandNode.html @@ -117,6 +117,11 @@
            • +
            • + Common + +
            • +
            • ConfigurationError @@ -182,6 +187,11 @@
            • +
            • + InternalVar + +
            • +
            • InvalidFlagValueError @@ -252,11 +262,6 @@
            • -
            • - Selection - -
            • -
            • SubCommand @@ -398,7 +403,7 @@
              • - .new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil) + .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)
              • @@ -456,6 +461,11 @@

                Instance methods inherited from class CliGen::BaseCommandNode

                + + all_commands : Array(BaseCommandNode) + all_commands, + + all_flags : Array(BaseFlag) all_flags, @@ -521,6 +531,11 @@ name, + + parent? : BaseCommandNode | Nil + parent?, + + process(args : Array(String)) : Nil
                process(args : Array(CliGen::Arg)) : Nil
                process
                , @@ -548,8 +563,8 @@

                Constructor methods inherited from class CliGen::BaseCommandNode

                - - 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) + + 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) new @@ -600,12 +615,12 @@ Constructor Detail -
                +
                - def self.new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil) + def self.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) - # + #

                diff --git a/docs/CliGen/Common.html b/docs/CliGen/Common.html new file mode 100644 index 0000000..880487d --- /dev/null +++ b/docs/CliGen/Common.html @@ -0,0 +1,444 @@ + + + + + + + + + + + + + + + + + CliGen::Common - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + module + CliGen::Common + +

                + + + + + + + + + + + + + + + + + + + + +

                + + + + Defined in: +

                + + + cligen/common/check_flag_vars.cr + +
                + + + + + + + + + + + +

                + + + + Macro Summary +

                + + + + + + +
                + +
                + + + + + + +

                + + + + Macro Detail +

                + +
                +
                + + 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) + + # +
                + +
                +
                + +
                +
                + + + + + + +
                + + + diff --git a/docs/CliGen/ConfigurationError.html b/docs/CliGen/ConfigurationError.html index 17abf44..29bf63c 100644 --- a/docs/CliGen/ConfigurationError.html +++ b/docs/CliGen/ConfigurationError.html @@ -117,6 +117,11 @@ +
              • + Common + +
              • +
              • ConfigurationError @@ -182,6 +187,11 @@
              • +
              • + InternalVar + +
              • +
              • InvalidFlagValueError @@ -252,11 +262,6 @@
              • -
              • - Selection - -
              • -
              • SubCommand diff --git a/docs/CliGen/DuplicateCommandError.html b/docs/CliGen/DuplicateCommandError.html index 04d27a6..3804c43 100644 --- a/docs/CliGen/DuplicateCommandError.html +++ b/docs/CliGen/DuplicateCommandError.html @@ -117,6 +117,11 @@
              • +
              • + Common + +
              • +
              • ConfigurationError @@ -182,6 +187,11 @@
              • +
              • + InternalVar + +
              • +
              • InvalidFlagValueError @@ -252,11 +262,6 @@
              • -
              • - Selection - -
              • -
              • SubCommand diff --git a/docs/CliGen/DuplicateFlagError.html b/docs/CliGen/DuplicateFlagError.html index be18b69..3545d1b 100644 --- a/docs/CliGen/DuplicateFlagError.html +++ b/docs/CliGen/DuplicateFlagError.html @@ -117,6 +117,11 @@
              • +
              • + Common + +
              • +
              • ConfigurationError @@ -182,6 +187,11 @@
              • +
              • + InternalVar + +
              • +
              • InvalidFlagValueError @@ -252,11 +262,6 @@
              • -
              • - Selection - -
              • -
              • SubCommand diff --git a/docs/CliGen/Error.html b/docs/CliGen/Error.html index 598ffcb..ee11279 100644 --- a/docs/CliGen/Error.html +++ b/docs/CliGen/Error.html @@ -117,6 +117,11 @@
              • +
              • + Common + +
              • +
              • ConfigurationError @@ -182,6 +187,11 @@
              • +
              • + InternalVar + +
              • +
              • InvalidFlagValueError @@ -252,11 +262,6 @@
              • -
              • - Selection - -
              • -
              • SubCommand diff --git a/docs/CliGen/Flag.html b/docs/CliGen/Flag.html index e71f59e..9c2fdee 100644 --- a/docs/CliGen/Flag.html +++ b/docs/CliGen/Flag.html @@ -117,6 +117,11 @@
              • +
              • + Common + +
              • +
              • ConfigurationError @@ -182,6 +187,11 @@
              • +
              • + InternalVar + +
              • +
              • InvalidFlagValueError @@ -252,11 +262,6 @@
              • -
              • - Selection - -
              • -
              • SubCommand @@ -384,7 +389,7 @@
                • - .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) + .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)
                • @@ -467,8 +472,8 @@ description, - - env_var : String + + env_var : String | Nil env_var, @@ -524,8 +529,8 @@

                  Constructor methods inherited from class CliGen::BaseFlag

                  - - new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta) + + new(var : String, short : String | Nil, long : String, env_var : String | Nil, description : String, delimiter : String, meta : FlagMeta) new @@ -576,12 +581,12 @@ Constructor Detail -
                  +
                  - def self.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) + def self.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) - # + #

                  diff --git a/docs/CliGen/FlagArgumentError.html b/docs/CliGen/FlagArgumentError.html index 1b92aed..e85c0a4 100644 --- a/docs/CliGen/FlagArgumentError.html +++ b/docs/CliGen/FlagArgumentError.html @@ -117,6 +117,11 @@ +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/FlagBundleError.html b/docs/CliGen/FlagBundleError.html index aa222ff..1032949 100644 --- a/docs/CliGen/FlagBundleError.html +++ b/docs/CliGen/FlagBundleError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/FlagMeta.html b/docs/CliGen/FlagMeta.html index 2a873e4..c6f7c82 100644 --- a/docs/CliGen/FlagMeta.html +++ b/docs/CliGen/FlagMeta.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/FlagMissingArgumentError.html b/docs/CliGen/FlagMissingArgumentError.html index 2d5a1a8..5bbff96 100644 --- a/docs/CliGen/FlagMissingArgumentError.html +++ b/docs/CliGen/FlagMissingArgumentError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/FlagNotFoundError.html b/docs/CliGen/FlagNotFoundError.html index a6bbdcc..1c89e06 100644 --- a/docs/CliGen/FlagNotFoundError.html +++ b/docs/CliGen/FlagNotFoundError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Format.html b/docs/CliGen/Format.html index 69165fe..b8dedd0 100644 --- a/docs/CliGen/Format.html +++ b/docs/CliGen/Format.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/HelpRequestedError.html b/docs/CliGen/HelpRequestedError.html index 5280aab..885be4c 100644 --- a/docs/CliGen/HelpRequestedError.html +++ b/docs/CliGen/HelpRequestedError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/InternalError.html b/docs/CliGen/InternalError.html index c2706c5..a9a8d26 100644 --- a/docs/CliGen/InternalError.html +++ b/docs/CliGen/InternalError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/InternalVar.html b/docs/CliGen/InternalVar.html new file mode 100644 index 0000000..dc3e97f --- /dev/null +++ b/docs/CliGen/InternalVar.html @@ -0,0 +1,403 @@ + + + + + + + + + + + + + + + + + CliGen::InternalVar - CliGenerator object_rework-dev + + + + + + + + + + +
                  +

                  + + + annotation + CliGen::InternalVar + +

                  + + + + + + + + + + + + + + + + + + + + +

                  + + + + Defined in: +

                  + + + cligen/annotations.cr + +
                  + + + + + + + + + + + + + + + +
                  + +
                  + + + + + + + + + + +
                  + + + diff --git a/docs/CliGen/InvalidFlagValueError.html b/docs/CliGen/InvalidFlagValueError.html index 7415b1e..b2e4906 100644 --- a/docs/CliGen/InvalidFlagValueError.html +++ b/docs/CliGen/InvalidFlagValueError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/InvalidOptionError.html b/docs/CliGen/InvalidOptionError.html index 8364397..f5a828e 100644 --- a/docs/CliGen/InvalidOptionError.html +++ b/docs/CliGen/InvalidOptionError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/MatchType.html b/docs/CliGen/MatchType.html index 57f52ff..a76a53d 100644 --- a/docs/CliGen/MatchType.html +++ b/docs/CliGen/MatchType.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/MissingDispatchError.html b/docs/CliGen/MissingDispatchError.html index f9f1b70..32c0bfa 100644 --- a/docs/CliGen/MissingDispatchError.html +++ b/docs/CliGen/MissingDispatchError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/MissingRequiredFlagError.html b/docs/CliGen/MissingRequiredFlagError.html index 072a185..ce6f984 100644 --- a/docs/CliGen/MissingRequiredFlagError.html +++ b/docs/CliGen/MissingRequiredFlagError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Parsable.html b/docs/CliGen/Parsable.html index ca89daa..4db80a3 100644 --- a/docs/CliGen/Parsable.html +++ b/docs/CliGen/Parsable.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/ParseableInvariantError.html b/docs/CliGen/ParseableInvariantError.html index b52b82d..15695e3 100644 --- a/docs/CliGen/ParseableInvariantError.html +++ b/docs/CliGen/ParseableInvariantError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/PreRunCommand.html b/docs/CliGen/PreRunCommand.html index 811d3e2..60a2f3b 100644 --- a/docs/CliGen/PreRunCommand.html +++ b/docs/CliGen/PreRunCommand.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/ProxyCommand.html b/docs/CliGen/ProxyCommand.html index 84cff51..3844b7d 100644 --- a/docs/CliGen/ProxyCommand.html +++ b/docs/CliGen/ProxyCommand.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Regex.html b/docs/CliGen/Regex.html index 2c465d9..cf5f839 100644 --- a/docs/CliGen/Regex.html +++ b/docs/CliGen/Regex.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand @@ -390,8 +395,13 @@ +
                  + FLAG_LONG = /^--[a-zA-Z0-9][a-zA-Z0-9-_]+$/ +
                  + +
                  - FLAG_MULTIPLE_SHORT = /^-[a-zA-Z0-9]+$/ + FLAG_MULTIPLE_SHORT = /^-[a-zA-Z][a-zA-Z]+$/
                  @@ -400,8 +410,13 @@ +
                  + FLAG_SHORT = /^-[a-zA-Z]$/ +
                  + +
                  - FLAG_WITH_ARG = /^(?<flag>(-[a-zA-Z]|--[a-zA-Z-_]+))="?(?<arg>\S+?)"?$/ + FLAG_WITH_ARG = /^(?<flag>(-[a-zA-Z]|--[a-zA-Z0-9][a-zA-Z0-9-_]+))="?(?<arg>.+?)"?$/
                  diff --git a/docs/CliGen/RegexInvariantError.html b/docs/CliGen/RegexInvariantError.html index 77b6061..9b14afc 100644 --- a/docs/CliGen/RegexInvariantError.html +++ b/docs/CliGen/RegexInvariantError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/ReservedFlagError.html b/docs/CliGen/ReservedFlagError.html index 0ec2436..6eac1b3 100644 --- a/docs/CliGen/ReservedFlagError.html +++ b/docs/CliGen/ReservedFlagError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/RunCommand.html b/docs/CliGen/RunCommand.html index b24ffb0..97410f5 100644 --- a/docs/CliGen/RunCommand.html +++ b/docs/CliGen/RunCommand.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/RuntimeError.html b/docs/CliGen/RuntimeError.html index 859967b..5ae5ff9 100644 --- a/docs/CliGen/RuntimeError.html +++ b/docs/CliGen/RuntimeError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/SubCommand.html b/docs/CliGen/SubCommand.html index 988ab21..037cc0c 100644 --- a/docs/CliGen/SubCommand.html +++ b/docs/CliGen/SubCommand.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/SubCommandInfo.html b/docs/CliGen/SubCommandInfo.html index 552ebab..da972d7 100644 --- a/docs/CliGen/SubCommandInfo.html +++ b/docs/CliGen/SubCommandInfo.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/TimeParseError.html b/docs/CliGen/TimeParseError.html index 5dfaee9..f4506f9 100644 --- a/docs/CliGen/TimeParseError.html +++ b/docs/CliGen/TimeParseError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Timeparse.html b/docs/CliGen/Timeparse.html index 56049c0..1e8ea7d 100644 --- a/docs/CliGen/Timeparse.html +++ b/docs/CliGen/Timeparse.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Timeparse/OperationUnit.html b/docs/CliGen/Timeparse/OperationUnit.html index 52e052f..15b6d24 100644 --- a/docs/CliGen/Timeparse/OperationUnit.html +++ b/docs/CliGen/Timeparse/OperationUnit.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Timeparse/RelativeOperation.html b/docs/CliGen/Timeparse/RelativeOperation.html index 1d6cbfb..9e18b5c 100644 --- a/docs/CliGen/Timeparse/RelativeOperation.html +++ b/docs/CliGen/Timeparse/RelativeOperation.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/Trigger.html b/docs/CliGen/Trigger.html index c356657..907d9ac 100644 --- a/docs/CliGen/Trigger.html +++ b/docs/CliGen/Trigger.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/UnknownCommandNodeError.html b/docs/CliGen/UnknownCommandNodeError.html index c583027..c835ff2 100644 --- a/docs/CliGen/UnknownCommandNodeError.html +++ b/docs/CliGen/UnknownCommandNodeError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/UnknownFlagError.html b/docs/CliGen/UnknownFlagError.html index b01e41c..fb1d9dd 100644 --- a/docs/CliGen/UnknownFlagError.html +++ b/docs/CliGen/UnknownFlagError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/CliGen/ValidationError.html b/docs/CliGen/ValidationError.html index 864725e..5ed7ed1 100644 --- a/docs/CliGen/ValidationError.html +++ b/docs/CliGen/ValidationError.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand diff --git a/docs/index.html b/docs/index.html index 3f33642..b619e70 100644 --- a/docs/index.html +++ b/docs/index.html @@ -117,6 +117,11 @@
                • +
                • + Common + +
                • +
                • ConfigurationError @@ -182,6 +187,11 @@
                • +
                • + InternalVar + +
                • +
                • InvalidFlagValueError @@ -252,11 +262,6 @@
                • -
                • - Selection - -
                • -
                • SubCommand @@ -334,7 +339,7 @@ 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.

                  nil, short = nil, validation = nil, default = nil, on_match = nil)","location":{"filename":"src/cligen/global_flag/add_global_flag.cr","line_number":5,"url":null},"def":{"name":"add_global_flag","args":[{"name":"type","external_name":"type","restriction":""},{"name":"","external_name":"","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"env_var","default_value":"nil","external_name":"env_var","restriction":""},{"name":"short","default_value":"nil","external_name":"short","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""},{"name":"default","default_value":"nil","external_name":"default","restriction":""},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":""}],"splat_index":1,"visibility":"Public","body":" \n{% unless type.resolve.is_a?(TypeNode)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : type must be a TypeNode\")\nend %}\n\n \n{% unless long.is_a?(StringLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : long must begin a StringLiteral\")\nend %}\n\n \n{% unless long =~ (/^--/)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : long must begin with --\")\nend %}\n\n \n{% if short %}\n {% unless short.is_a?(StringLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : Short must be a StringLiteral\")\nend %}\n {% unless short =~ (/^-[a-zA-Z]/)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : Short must be a - with single char (ex: -a)\")\nend %}\n {% end %}\n\n \n{% unless validation.nil? %}\n {% unless validation.is_a?(ProcLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : validation must be a Proc\")\nend %}\n {% unless validation.return_type.resolve == Bool\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : validation proc return type must be Bool \\\"->(...) : Bool {...}\\\"\")\nend %}\n {% unless validation.args.size == 1\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : validation proc must have a single input variable\")\nend %}\n {% arg = validation.args.first %}\n {% unless arg.restriction == type\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : validation proc input variable MUST be typed to match the flag type \\\"->(#{arg.name} : #{type}) : Bool { ... }\\\"\")\nend %}\n {% end %}\n\n \n{% unless on_match.nil? %}\n {% unless on_match.is_a?(ProcLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : Provided on_match must be a Proc\")\nend %}\n {% if on_match.args.empty?\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : You must have arguments for on_match\")\nend %}\n {% unless on_match.args.first.restriction\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : Your input argument must have a type\")\nend %}\n {% unless on_match.args.first.restriction == type\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : Your input argument must be the same type as your argument (#{type})\")\nend %}\n {% end %}\n\n \n{% unless description.is_a?(StringLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : decription must be a StringLiteral\")\nend %}\n\n \n{% if env_var %}\n {% unless env_var.is_a?(StringLiteral)\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : env_var must be a StringLiteral\")\nend %}\n {% if env_var.includes?(\"-\")\n raise(\"ERROR : CliGen.add_global_flag(#{long}) : env_var cannot contain \\\"-\\\"'s please fix this\")\nend %}\n {% else %}\n {% env_var = ((long.gsub(/--/, \"\")).gsub(/-/, \"_\")).upcase %}\n {% end %}\n\n ::CliGen::GLOBAL_FLAGS << ::CliGen::Flag(\n{{ type }}\n).new(\n var: \"\",\n short: \n{{ short }}\n,\n long: \n{{ long }}\n,\n description: \n{{ description }}\n,\n \nenv_var: \n{{ env_var }}\n,\n default: \n{{ default }}\n,\n on_match: \n{% if on_match %} {{ on_match }} {% else %} nil {% end %}\n,\n validate: \n{% if validation %} {{ validation }} {% else %} nil {% end %}\n\n )\n \n"}},{"html_id":"override_help_template(filepath)-macro","name":"override_help_template","abstract":false,"args":[{"name":"filepath","external_name":"filepath","restriction":""}],"args_string":"(filepath)","args_html":"(filepath)","location":{"filename":"src/cligen.cr","line_number":21,"url":null},"def":{"name":"override_help_template","args":[{"name":"filepath","external_name":"filepath","restriction":""}],"visibility":"Public","body":" \n{% unless file_exists?(filepath)\n raise(\"ERROR : CliGen.override_help_template : File(#{filepath}) doesn't exist\")\nend %}\n\n CliGen::HELP_OVERRIDE_TEMPLATE = \n{{ (`readlink -f #{filepath}`).strip.stringify }}\n\n \n"}}],"types":[{"html_id":"CliGenerator/CliGen/App","path":"CliGen/App.html","kind":"class","full_name":"CliGen::App","name":"App","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/CommandNode","kind":"class","full_name":"CliGen::CommandNode","name":"CommandNode"},"ancestors":[{"html_id":"CliGenerator/CliGen/CommandNode","kind":"class","full_name":"CliGen::CommandNode","name":"CommandNode"},{"html_id":"CliGenerator/CliGen/BaseCommandNode","kind":"class","full_name":"CliGen::BaseCommandNode","name":"BaseCommandNode"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/app.cr","line_number":12,"url":null},{"filename":"src/cligen/app/generate.cr","line_number":5,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Root entry point. Holds a flattened copy of all flags from every command\nfor global-flag matching, then hands off to the matched child CommandNode.","summary":"

                  Root entry point.

                  ","class_methods":[{"html_id":"handle_command_raises(&):Nil-class-method","name":"handle_command_raises","abstract":false,"location":{"filename":"src/cligen/app.cr","line_number":51,"url":null},"def":{"name":"handle_command_raises","yields":0,"block_arity":0,"return_type":"Nil","visibility":"Public","body":"begin\n yield\nrescue e : CliGen::RuntimeError\n Fiber.yield\n abort(e.message)\nrescue e : CliGen::ConfigurationError\n Fiber.yield\n abort(e.message)\nrescue e : CliGen::HelpRequestedError\n Fiber.yield\n puts(e.message)\n exit(0)\nend"},"external_var":false},{"html_id":"process(args:Array(String)=ARGV.to_a):Nil-class-method","name":"process","doc":"Convenience entry point; defaults to ARGV","summary":"

                  Convenience entry point; defaults to ARGV

                  ","abstract":false,"args":[{"name":"args","default_value":"ARGV.to_a","external_name":"args","restriction":"Array(String)"}],"args_string":"(args : Array(String) = ARGV.to_a) : Nil","args_html":"(args : Array(String) = ARGV.to_a) : Nil","location":{"filename":"src/cligen/app.cr","line_number":72,"url":null},"def":{"name":"process","args":[{"name":"args","default_value":"ARGV.to_a","external_name":"args","restriction":"Array(String)"}],"return_type":"Nil","visibility":"Public","body":"if @@instance.nil?\n generate\nend\nhandle_command_raises do\n @@instance.not_nil!.process(args)\nend\n"},"external_var":false}],"constructors":[{"html_id":"new(name,flags:Array(BaseFlag),commands:Array(BaseCommandNode),pre_run_commands:Array(RunCommand),post_run_commands:Array(RunCommand))-class-method","name":"new","abstract":false,"args":[{"name":"name","external_name":"name","restriction":""},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"}],"args_string":"(name, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand))","args_html":"(name, flags : Array(
                  BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand))","location":{"filename":"src/cligen/app.cr","line_number":15,"url":null},"def":{"name":"new","args":[{"name":"name","external_name":"name","restriction":""},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(name, flags, commands, pre_run_commands, post_run_commands)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"check!-instance-method","name":"check!","abstract":false,"location":{"filename":"src/cligen/app.cr","line_number":20,"url":null},"def":{"name":"check!","visibility":"Public","body":"super()\ncheck_for_env_duplicates(all_flags + CliGen::GLOBAL_FLAGS)\n"},"external_var":false},{"html_id":"check_for_env_duplicates(flags:Array(BaseFlag))-instance-method","name":"check_for_env_duplicates","abstract":false,"args":[{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"}],"args_string":"(flags : Array(BaseFlag))","args_html":"(flags : Array(BaseFlag))","location":{"filename":"src/cligen/app.cr","line_number":25,"url":null},"def":{"name":"check_for_env_duplicates","args":[{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"}],"visibility":"Public","body":"flgs = flags.reject() do |__arg0| __arg0.env_var.empty? end\n\nenv_vars = flgs.group_by(&.env_var)\n\nfailures = [] of Tuple(String, Array(BaseFlag))\n\nenv_vars.each do |env_var, flg_group|\n if flg_group.size > 1\n failures << (Tuple.new(env_var, flg_group))\n end\nend\n\nif failures.empty?\nelse\n error_buffer = \"ERROR : App(%s)#check! : Found ENV VAR Duplicates \\n%s\"\n format = \"\\n%s:\\n%s\\n\\n\"\n buffer = \"\"\n\n failures.each do |env_var, flgs|\n buffer = buffer + (format % [env_var, flgs.map do |f| \"- #{f.long_key}\" end.join(\"\\n\")])\n end\n\n raise(CliGen::DuplicateFlagError.new(error_buffer % [@name, buffer]))\nend\n"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/Arg","path":"CliGen/Arg.html","kind":"class","full_name":"CliGen::Arg","name":"Arg","abstract":false,"superclass":{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/arg.cr","line_number":18,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"This class serves as a \"argument wrapper\" to force a fail-fast approach to\narg-parsing. \n\nIt wraps around the argument + index of the argument to do state tracking\nand ensure that each argument is only processed once (plus allows for\neasier filtering of processed arguments to avoid having to do index math)\n\n args.reject(&.processed?) # returns the args that haven't been processed yet\n\nIt expects each argument to only be processed once and will force a raise\nif the argument has Arg#processed called a second time. This is to force \nthe developer (me) to fix any processing issues during the development of\nthis framework.","summary":"

                  This class serves as a "argument wrapper" to force a fail-fast approach to arg-parsing.

                  ","class_methods":[{"html_id":"flag?(val:String):Bool-class-method","name":"flag?","abstract":false,"args":[{"name":"val","external_name":"val","restriction":"String"}],"args_string":"(val : String) : Bool","args_html":"(val : String) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":30,"url":null},"def":{"name":"flag?","args":[{"name":"val","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"if val =~ CliGen::Regex::FLAG_REGEX\n true\nelse\n false\nend"},"external_var":false},{"html_id":"float?(val:String):Bool-class-method","name":"float?","abstract":false,"args":[{"name":"val","external_name":"val","restriction":"String"}],"args_string":"(val : String) : Bool","args_html":"(val : String) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":66,"url":null},"def":{"name":"float?","args":[{"name":"val","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"if val =~ CliGen::Regex::FLOAT\n true\nelse\n false\nend"},"external_var":false},{"html_id":"int?(val:String):Bool-class-method","name":"int?","abstract":false,"args":[{"name":"val","external_name":"val","restriction":"String"}],"args_string":"(val : String) : Bool","args_html":"(val : String) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":42,"url":null},"def":{"name":"int?","args":[{"name":"val","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"if val =~ CliGen::Regex::INT\n true\nelse\n false\nend"},"external_var":false},{"html_id":"uint?(val:String):Bool-class-method","name":"uint?","abstract":false,"args":[{"name":"val","external_name":"val","restriction":"String"}],"args_string":"(val : String) : Bool","args_html":"(val : String) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":54,"url":null},"def":{"name":"uint?","args":[{"name":"val","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"if val =~ CliGen::Regex::UINT\n true\nelse\n false\nend"},"external_var":false}],"constructors":[{"html_id":"new(value:String,index:Int32)-class-method","name":"new","abstract":false,"args":[{"name":"value","external_name":"value","restriction":"::String"},{"name":"index","external_name":"index","restriction":"::Int32"}],"args_string":"(value : String, index : Int32)","args_html":"(value : String, index : Int32)","location":{"filename":"src/cligen/arg.cr","line_number":27,"url":null},"def":{"name":"new","args":[{"name":"value","external_name":"value","restriction":"::String"},{"name":"index","external_name":"index","restriction":"::Int32"}],"visibility":"Public","body":"_ = allocate\n_.initialize(value, index)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"flag?(val:String=@value):Bool-instance-method","name":"flag?","abstract":false,"args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"args_string":"(val : String = @value) : Bool","args_html":"(val : String = @value) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":38,"url":null},"def":{"name":"flag?","args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Arg.flag?(val)"},"external_var":false},{"html_id":"float?(val:String=@value):Bool-instance-method","name":"float?","abstract":false,"args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"args_string":"(val : String = @value) : Bool","args_html":"(val : String = @value) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":74,"url":null},"def":{"name":"float?","args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Arg.float?(val)"},"external_var":false},{"html_id":"index:Int32-instance-method","name":"index","doc":"The index of the argument in the array it was in","summary":"

                  The index of the argument in the array it was in

                  ","abstract":false,"location":{"filename":"src/cligen/arg.cr","line_number":23,"url":null},"def":{"name":"index","return_type":"Int32","visibility":"Public","body":"@index"},"external_var":false},{"html_id":"int?(val:String=@value):Bool-instance-method","name":"int?","abstract":false,"args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"args_string":"(val : String = @value) : Bool","args_html":"(val : String = @value) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":50,"url":null},"def":{"name":"int?","args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Arg.int?(val)"},"external_var":false},{"html_id":"processed-instance-method","name":"processed","doc":"This serves as a trigger that tells the object that it has been processed\n\nThis will raise an exception if it is re-called after already having been\nprocessed.","summary":"

                  This serves as a trigger that tells the object that it has been processed

                  ","abstract":false,"location":{"filename":"src/cligen/arg.cr","line_number":82,"url":null},"def":{"name":"processed","visibility":"Public","body":"if @processed\n raise(CliGen::ArgReprocessedError.new(\"CliGen::Arg(index: #{@index}, value: #{@value})#processed : This arg was re-processed\"))\nend\n@processed = true\n"},"external_var":false},{"html_id":"processed?:Bool-instance-method","name":"processed?","doc":"The \"flag\"/variable that tracks is the Arg has been processed yet","summary":"

                  The "flag"/variable that tracks is the Arg has been processed yet

                  ","abstract":false,"location":{"filename":"src/cligen/arg.cr","line_number":25,"url":null},"def":{"name":"processed?","return_type":"Bool","visibility":"Public","body":"@processed"},"external_var":false},{"html_id":"uint?(val:String=@value):Bool-instance-method","name":"uint?","abstract":false,"args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"args_string":"(val : String = @value) : Bool","args_html":"(val : String = @value) : Bool","location":{"filename":"src/cligen/arg.cr","line_number":62,"url":null},"def":{"name":"uint?","args":[{"name":"val","default_value":"@value","external_name":"val","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Arg.uint?(val)"},"external_var":false},{"html_id":"value:String-instance-method","name":"value","doc":"The raw string argument provided from the user","summary":"

                  The raw string argument provided from the user

                  ","abstract":false,"location":{"filename":"src/cligen/arg.cr","line_number":21,"url":null},"def":{"name":"value","return_type":"String","visibility":"Public","body":"@value"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/ArgReprocessedError","path":"CliGen/ArgReprocessedError.html","kind":"class","full_name":"CliGen::ArgReprocessedError","name":"ArgReprocessedError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/InternalError","kind":"class","full_name":"CliGen::InternalError","name":"InternalError"},"ancestors":[{"html_id":"CliGenerator/CliGen/InternalError","kind":"class","full_name":"CliGen::InternalError","name":"InternalError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":15,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Arg#processed was called a second time on the same Arg","summary":"

                  Arg#processed was called a second time on the same Arg

                  "},{"html_id":"CliGenerator/CliGen/Argument","path":"CliGen/Argument.html","kind":"annotation","full_name":"CliGen::Argument","name":"Argument","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":203,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"This is used for annotating instance variables for the CliGen framework can know how to create your `CliGen::Flag(T)` objects\n\nWHILE this is usually being handled by the `CliGen::Command.argument` macro\ninside of the class body.\n\nEX:\n\n class MyCmd < CliGen::Command\n argument(myvar : String = \"test\",\n short: \"-m\",\n long: \"--myvar\",\n description: \"This is my test flag\",\n options: %w[ test test2 test3 ]\n )\n\n def main \n puts \"@myvar was #{@myvar}\"\n end\n end\n\n\nHowever, this can also be done manually if you don't want to use the macros\nyou will make me sad, but otherwise it's understandable if you want do it\nmanually. Just understand that the macros are there for doing all of the\nvalidations for user-friendly implementation.\n\n## Expected Metadata:\n\n### short:\nType: StringLiteral\n\nRequired: false\n\nThis represents the short form of the flag bring provided. it is optional as \nnot all flags have to have a short form flag. \n\n\n### long:\nType: StringLiteral\n\nRequired: true\n\nThis represents the long-form of the flag. It is required in order to generate\nthe `Flag(T)`.\n\n\n### description:\nType: StringLiteral\nRequired: true\n\nThis is the description of your flag and is required for `Flag(T)` creation\n\n\n### delimiter: \nType: StringLiteral\n\nRequired: false\n\nFor `Flag`(Array(T)) flags this is the delimiter that will seperate any inline \nargs (ex: \",\" will split \"a,b,c\") provided at the commandline. If nil/not \nprovided, the framework will default to ',' as this is the usual choice.\n\n\n### env_var:\nType: StringLiteral\n\nRequired: false\n\nThis is the ENV VAR that can be used to specify your flag value when not \nprovided by the user.\n\n\n### validation:\nType: ProcLiteral\n\nRequired: false\n\nThis is a proc that can be used to provide an ad-hoc way of verifying the\nvalue provided by a user.\n\n EX: Int Validator\n\n\n validation: ->(i : Int32) : Bool do\n (1..23).includes?(i)\n end\n\n\n This is used as a fallback to where the options: key doesn't cleanly \n provide enough of a check for the provided values.\n\n Note: \n The input value MUST be the same as the value type as the instance \n variable. Otherwise CliGen will not compile. IF requested I can \n add a raw_validation: key as well to do the same but for just the\n String variable provided by the user.\n\n### on_match:\nType: ProcLiteral\n\nRequired: false\n\nMuch like validation, this is used as a hook for doing arbitrary actions\nwith the parsed value from the user (very useful for global flags).\n\nEX: Log level setter\n\n on_match: ->(arg : String) do\n begin\n ::Log.setup(level: ::Log::Severity.parse(arg))\n rescue e : ArgumentError\n STDERR.puts \"ERROR : Failed to set to #{arg} log level: (#{e.class}: #{e.message})\"\n end\n end\n\nIn this way you can use on_match: to hook a global flag and have it call some\narbitrary method elsewhere in the codebase to help setup the environment \nbefore the main command is run.\n\n### options:\nType: ArrayLiteral(T)|Call\n\nRequired: false\n\nCURRENTLY this is being as a way of providing a static set of values that we \nare to use when doing a provided argument. \n\nEX: Options for string var\n \n options: %w[ a b c ]\n\n\nHowver, this currently also \nsupports delegating the retrieval of values (in array format) to be learned\nat runtime by providing a call to a global methods/class method/util \nmethod/etc\n\nEX: Deletgating to runtime\n \n\n module MyModule\n def self.my_method : Array(String)\n if File.exists?(\"/etc/valid_things.txt\")\n File.read(\"/etc/valid_things.txt\").split(\",\")\n else\n %w[ a b c ]\n end\n end\n\n CliGen.add_global_flag(String, \n short: \"-t\",\n long: \"--test\",\n description: \"This does things. I promise\",\n options: ::MyModule.my_method,\n on_match: ->(t : String) do \n puts \"Matched #{t}\"\n end\n )\n end\n\n\nDoing things this way gives you some runtime flexibility, but makes you \nresponsible for ensuring that it doesn't crash or provide incorrect data\nat runtime. As (unfortunately) the framework doesn't account for developer\nerror at runtime like it can at compile-time with a static array of\nvalues.\n\n\n### format: \nType: RegexLiteral\n\nRequired: false\n\nThis metadata is used to provide (mostly for strings when you don't have a\nstatically known list of values that can be provided at runtime, but you \nwant to filter out invalid options.\n\nEX: filtering for csv formatted info\n\n format: /^([a-z0-9]+)(,?[a-z0-9]+)+$/\n\n","summary":"

                  This is used for annotating instance variables for the CliGen framework can know how to create your CliGen::Flag(T) objects

                  "},{"html_id":"CliGenerator/CliGen/BaseCommandNode","path":"CliGen/BaseCommandNode.html","kind":"class","full_name":"CliGen::BaseCommandNode","name":"BaseCommandNode","abstract":true,"superclass":{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/command_node/base.cr","line_number":13,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"Log","name":"Log","value":"::Log.for(CliGen::CommandNode)"}],"subclasses":[{"html_id":"CliGenerator/CliGen/CommandNode","kind":"class","full_name":"CliGen::CommandNode(T)","name":"CommandNode"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Non-generic base that lets the tree hold heterogeneous CommandNode(T) children.\nEverything that doesn't depend on T lives here.","summary":"

                  Non-generic base that lets the tree hold heterogeneous CommandNode(T) children.

                  ","constructors":[{"html_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","name":"new","abstract":false,"args":[{"name":"name","external_name":"name","restriction":"String"},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"},{"name":"meta","external_name":"meta","restriction":"CommandMeta"},{"name":"description","default_value":"nil","external_name":"description","restriction":"String | ::Nil"}],"args_string":"(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, description : String | Nil = nil)","args_html":"(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), meta : CommandMeta, description : String | Nil = nil)","location":{"filename":"src/cligen/command_node/base.cr","line_number":24,"url":null},"def":{"name":"new","args":[{"name":"name","external_name":"name","restriction":"String"},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"},{"name":"meta","external_name":"meta","restriction":"CommandMeta"},{"name":"description","default_value":"nil","external_name":"description","restriction":"String | ::Nil"}],"visibility":"Public","body":"_ = allocate\n_.initialize(name, flags, commands, pre_run_commands, post_run_commands, meta, description)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"all_flags:Array(BaseFlag)-instance-method","name":"all_flags","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":35,"url":null},"def":{"name":"all_flags","return_type":"Array(BaseFlag)","visibility":"Public","body":"@flags + @commands.flat_map(&.all_flags)"},"external_var":false},{"html_id":"check!:Nil-instance-method","name":"check!","abstract":true,"location":{"filename":"src/cligen/command_node/base.cr","line_number":174,"url":null},"def":{"name":"check!","return_type":"Nil","visibility":"Public","body":""},"external_var":false},{"html_id":"check_for_duplicate_flags!(flags:Array(BaseFlag)):Nil-instance-method","name":"check_for_duplicate_flags!","abstract":false,"args":[{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"}],"args_string":"(flags : Array(BaseFlag)) : Nil","args_html":"(flags : Array(BaseFlag)) : Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":61,"url":null},"def":{"name":"check_for_duplicate_flags!","args":[{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"}],"return_type":"Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#check_for_duplicate_flags! : entered with #{flags.map(&.long_key)}\" end\nshorts = flags.compact_map(&.short)\nshort_duplicates = [] of String\nlongs = flags.compact_map do |f| if f.long_key.empty?\nelse\n f.long_key\nend end\nlong_duplicates = [] of String\n\nlast_short : String = \"\"\nshorts.sort.each do |short|\n if last_short == short\n short_duplicates << short\n end\n last_short = short\nend\n\nlast_long : String = \"\"\nlongs.sort.each do |long|\n if last_long == long\n long_duplicates << long\n end\n last_long = long\nend\n\nif long_duplicates.empty? && short_duplicates.empty?\nelse\n error_buffer = \"ERROR : CommandNode(%s)#check! : Found Duplicates : %s\"\n\n message = \"\"\n if long_duplicates.empty?\n else\n message = message + (\"\\nLong:\\n%s\\n\" % (long_duplicates.map do |f| \"- #{f}\" end.join(\"\\n\")))\n end\n\n if short_duplicates.empty?\n else\n message = message + (\"\\nShort:\\n%s\" % (short_duplicates.map do |f| \"- #{f}\" end.join(\"\\n\")))\n end\n\n raise(CliGen::DuplicateFlagError.new(error_buffer % [@name, message]))\nend\n"},"external_var":false},{"html_id":"check_for_duplicate_subcommands!-instance-method","name":"check_for_duplicate_subcommands!","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":39,"url":null},"def":{"name":"check_for_duplicate_subcommands!","visibility":"Public","body":"failures = [] of Tuple(String, Array(BaseCommandNode))\n\n@commands.group_by(&.name).each do |command, cmd_group|\n if cmd_group.size > 1\n failures << (Tuple.new(command, cmd_group))\n end\nend\n\nif failures.empty?\nelse\n error_buffer = \"ERROR : #{self.class}(%s)#check! : Found Command Name Duplicates \\n%s\"\n format = \"\\n%s:\\n%s\\n\\n\"\n buffer = \"\"\n\n failures.each do |name, cmds|\n buffer = buffer + (format % [name, cmds.map do |c| \"- #{c.meta.cls} (#{c.description})\" end.join(\"\\n\")])\n end\n\n raise(CliGen::DuplicateCommandError.new(error_buffer % [@name, buffer]))\nend\n"},"external_var":false},{"html_id":"commands:Array(BaseCommandNode)-instance-method","name":"commands","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":16,"url":null},"def":{"name":"commands","return_type":"Array(BaseCommandNode)","visibility":"Public","body":"@commands"},"external_var":false},{"html_id":"description:String|Nil-instance-method","name":"description","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":17,"url":null},"def":{"name":"description","return_type":"String | ::Nil","visibility":"Public","body":"@description"},"external_var":false},{"html_id":"find_match(arg:String)-instance-method","name":"find_match","abstract":false,"args":[{"name":"arg","external_name":"arg","restriction":"String"}],"args_string":"(arg : String)","args_html":"(arg : String)","location":{"filename":"src/cligen/command_node/base.cr","line_number":114,"url":null},"def":{"name":"find_match","args":[{"name":"arg","external_name":"arg","restriction":"String"}],"visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#find_match(#{arg}) : Entered\" end\nif subcommand?(arg)\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found to be subcommand\" end\n return CliGen::MatchType::SubCommand\nend\n\ncase arg\nwhen \"-h\", \"--help\"\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : was found to be a help flag\" end\n CliGen::MatchType::Help\nwhen CliGen::Regex::FLAG_REGEX\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found to match the format of a flag\" end\n if flg = flag?(arg)\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found to be a Flag(long: #{flg.long_key})\" end\n flg\n else\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found not to have a flag associated with it\" end\n CliGen::MatchType::NoMatch\n end\nwhen CliGen::Regex::FLAG_WITH_ARG\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found to match the format of a flag with an arg =\" end\n CliGen::MatchType::FlagWithArg\nwhen CliGen::Regex::FLAG_MULTIPLE_SHORT\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : arg found to match the clumped flag format\" end\n CliGen::MatchType::FlagMultipleShort\nelse\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : Found no obvious match format wise. Checking if arg is a command\" end\n if cmd = @commands.find() do |__arg10| __arg10.name == arg end\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : Looks like the arg matched a defined command\" end\n cmd\n else\n Log.debug do \"CommandNode(#{@name})#find_match(#{arg}) : No match found for arg\" end\n CliGen::MatchType::NoMatch\n end\nend\n"},"external_var":false},{"html_id":"flag?(arg:String):BaseFlag|Nil-instance-method","name":"flag?","abstract":false,"args":[{"name":"arg","external_name":"arg","restriction":"String"}],"args_string":"(arg : String) : BaseFlag | Nil","args_html":"(arg : String) : BaseFlag | Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":161,"url":null},"def":{"name":"flag?","args":[{"name":"arg","external_name":"arg","restriction":"String"}],"return_type":"BaseFlag | ::Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#flag?(#{arg}) : Entered\" end\nget(short: arg) || get(long: arg)\n"},"external_var":false},{"html_id":"flags:Array(BaseFlag)-instance-method","name":"flags","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":15,"url":null},"def":{"name":"flags","return_type":"Array(BaseFlag)","visibility":"Public","body":"@flags"},"external_var":false},{"html_id":"get(*,long:String):BaseFlag|Nil-instance-method","name":"get","abstract":false,"args":[{"name":"","external_name":"","restriction":""},{"name":"long","external_name":"long","restriction":"String"}],"args_string":"(*, long : String) : BaseFlag | Nil","args_html":"(*, long : String) : BaseFlag | Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":96,"url":null},"def":{"name":"get","args":[{"name":"","external_name":"","restriction":""},{"name":"long","external_name":"long","restriction":"String"}],"splat_index":0,"return_type":"BaseFlag | ::Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#get(long: #{long}) : entered\" end\n(@flags.find do |f| f.long_key == long end || @commands.find(&.flag?(long)).try(&.get(long: long))) || CliGen::GLOBAL_FLAGS.find() do |__arg6| __arg6.long_key == long end\n"},"external_var":false},{"html_id":"get(*,short:String):BaseFlag|Nil-instance-method","name":"get","abstract":false,"args":[{"name":"","external_name":"","restriction":""},{"name":"short","external_name":"short","restriction":"String"}],"args_string":"(*, short : String) : BaseFlag | Nil","args_html":"(*, short : String) : BaseFlag | Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":101,"url":null},"def":{"name":"get","args":[{"name":"","external_name":"","restriction":""},{"name":"short","external_name":"short","restriction":"String"}],"splat_index":0,"return_type":"BaseFlag | ::Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#get(short: #{short}) : entered\" end\n(@flags.find do |f| f.short == short end || @commands.find(&.flag?(short)).try(&.get(short: short))) || CliGen::GLOBAL_FLAGS.find() do |__arg9| __arg9.short == short end\n"},"external_var":false},{"html_id":"handle_flag_raises(&):Nil-instance-method","name":"handle_flag_raises","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":106,"url":null},"def":{"name":"handle_flag_raises","yields":0,"block_arity":0,"return_type":"Nil","visibility":"Public","body":"begin\n yield\nrescue e : CliGen::RuntimeError\n abort(e.message)\nend"},"external_var":false},{"html_id":"meta:CommandMeta-instance-method","name":"meta","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":18,"url":null},"def":{"name":"meta","return_type":"CommandMeta","visibility":"Public","body":"@meta"},"external_var":false},{"html_id":"name:String-instance-method","name":"name","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":14,"url":null},"def":{"name":"name","return_type":"String","visibility":"Public","body":"@name"},"external_var":false},{"html_id":"process(args:Array(String)):Nil-instance-method","name":"process","doc":"Converts String array to Arg array and hands off to the typed process method","summary":"

                  Converts String array to Arg array and hands off to the typed process method

                  ","abstract":false,"args":[{"name":"args","external_name":"args","restriction":"Array(String)"}],"args_string":"(args : Array(String)) : Nil","args_html":"(args : Array(String)) : Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":167,"url":null},"def":{"name":"process","args":[{"name":"args","external_name":"args","restriction":"Array(String)"}],"return_type":"Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#process(#{args}) : Entered\" end\nnew_args = args.each_with_index.map do |arg, i| CliGen::Arg.new(value: arg, index: i) end.to_a\nprocess(new_args)\n"},"external_var":false},{"html_id":"process(args:Array(CliGen::Arg)):Nil-instance-method","name":"process","abstract":true,"args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"args_string":"(args : Array(CliGen::Arg)) : Nil","args_html":"(args : Array(CliGen::Arg)) : Nil","location":{"filename":"src/cligen/command_node/base.cr","line_number":175,"url":null},"def":{"name":"process","args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"return_type":"Nil","visibility":"Public","body":""},"external_var":false},{"html_id":"subcommand?(arg:String):Bool-instance-method","name":"subcommand?","abstract":false,"args":[{"name":"arg","external_name":"arg","restriction":"String"}],"args_string":"(arg : String) : Bool","args_html":"(arg : String) : Bool","location":{"filename":"src/cligen/command_node/base.cr","line_number":156,"url":null},"def":{"name":"subcommand?","args":[{"name":"arg","external_name":"arg","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#subcommand?(#{arg}) : Entered\" end\nsubcommands.any?() do |__arg11| __arg11.name == arg end\n"},"external_var":false},{"html_id":"subcommands:Array(SubCommandInfo)-instance-method","name":"subcommands","abstract":true,"location":{"filename":"src/cligen/command_node/base.cr","line_number":173,"url":null},"def":{"name":"subcommands","return_type":"Array(SubCommandInfo)","visibility":"Public","body":""},"external_var":false},{"html_id":"subcommands?:Bool-instance-method","name":"subcommands?","abstract":false,"location":{"filename":"src/cligen/command_node/base.cr","line_number":152,"url":null},"def":{"name":"subcommands?","return_type":"Bool","visibility":"Public","body":"subcommands.size > 0"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/BaseFlag","path":"CliGen/BaseFlag.html","kind":"class","full_name":"CliGen::BaseFlag","name":"BaseFlag","abstract":true,"superclass":{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/flag/base.cr","line_number":9,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"Log","name":"Log","value":"::Log.for(CliGen::Flag)"}],"subclasses":[{"html_id":"CliGenerator/CliGen/Flag","kind":"class","full_name":"CliGen::Flag(T)","name":"Flag"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"constructors":[{"html_id":"new(var:String,short:String|Nil,long:String,env_var:String,description:String,delimiter:String,meta:FlagMeta)-class-method","name":"new","abstract":false,"args":[{"name":"var","external_name":"var","restriction":"String"},{"name":"short","external_name":"short","restriction":"String | ::Nil"},{"name":"long","external_name":"long","restriction":"String"},{"name":"env_var","external_name":"env_var","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"delimiter","external_name":"delimiter","restriction":"String"},{"name":"meta","external_name":"meta","restriction":"FlagMeta"}],"args_string":"(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta)","args_html":"(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta)","location":{"filename":"src/cligen/flag/base.cr","line_number":21,"url":null},"def":{"name":"new","args":[{"name":"var","external_name":"var","restriction":"String"},{"name":"short","external_name":"short","restriction":"String | ::Nil"},{"name":"long","external_name":"long","restriction":"String"},{"name":"env_var","external_name":"env_var","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"delimiter","external_name":"delimiter","restriction":"String"},{"name":"meta","external_name":"meta","restriction":"FlagMeta"}],"visibility":"Public","body":"_ = allocate\n_.initialize(var, short, long, env_var, description, delimiter, meta)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"check!:Nil-instance-method","name":"check!","abstract":true,"location":{"filename":"src/cligen/flag/base.cr","line_number":55,"url":null},"def":{"name":"check!","return_type":"Nil","visibility":"Public","body":""},"external_var":false},{"html_id":"delimiter:String-instance-method","name":"delimiter","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":16,"url":null},"def":{"name":"delimiter","return_type":"String","visibility":"Public","body":"@delimiter"},"external_var":false},{"html_id":"description:String-instance-method","name":"description","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":15,"url":null},"def":{"name":"description","return_type":"String","visibility":"Public","body":"@description"},"external_var":false},{"html_id":"env_var:String-instance-method","name":"env_var","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":14,"url":null},"def":{"name":"env_var","return_type":"String","visibility":"Public","body":"@env_var"},"external_var":false},{"html_id":"long:String-instance-method","name":"long","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":12,"url":null},"def":{"name":"long","return_type":"String","visibility":"Public","body":"@long"},"external_var":false},{"html_id":"long_key:String-instance-method","name":"long_key","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":13,"url":null},"def":{"name":"long_key","return_type":"String","visibility":"Public","body":"@long_key"},"external_var":false},{"html_id":"matches?(token:String):Bool-instance-method","name":"matches?","abstract":false,"args":[{"name":"token","external_name":"token","restriction":"String"}],"args_string":"(token : String) : Bool","args_html":"(token : String) : Bool","location":{"filename":"src/cligen/flag/base.cr","line_number":47,"url":null},"def":{"name":"matches?","args":[{"name":"token","external_name":"token","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"Log.trace do \"Flag(#{@long})#matches?(#{token}) : entered\" end\n(token == @short) || (!@long_key.empty? && (token == @long_key))\n"},"external_var":false},{"html_id":"meta:FlagMeta-instance-method","name":"meta","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":17,"url":null},"def":{"name":"meta","return_type":"FlagMeta","visibility":"Public","body":"@meta"},"external_var":false},{"html_id":"raw_value:String|Nil-instance-method","name":"raw_value","abstract":true,"location":{"filename":"src/cligen/flag/base.cr","line_number":54,"url":null},"def":{"name":"raw_value","return_type":"String | ::Nil","visibility":"Public","body":""},"external_var":false},{"html_id":"satisfied?:Bool-instance-method","name":"satisfied?","abstract":true,"location":{"filename":"src/cligen/flag/base.cr","line_number":52,"url":null},"def":{"name":"satisfied?","return_type":"Bool","visibility":"Public","body":""},"external_var":false},{"html_id":"short:String|Nil-instance-method","name":"short","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":11,"url":null},"def":{"name":"short","return_type":"String | ::Nil","visibility":"Public","body":"@short"},"external_var":false},{"html_id":"validate!:Nil-instance-method","name":"validate!","abstract":true,"location":{"filename":"src/cligen/flag/base.cr","line_number":53,"url":null},"def":{"name":"validate!","return_type":"Nil","visibility":"Public","body":""},"external_var":false},{"html_id":"var:String-instance-method","name":"var","abstract":false,"location":{"filename":"src/cligen/flag/base.cr","line_number":10,"url":null},"def":{"name":"var","return_type":"String","visibility":"Public","body":"@var"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/Coercable","path":"CliGen/Coercable.html","kind":"module","full_name":"CliGen::Coercable","name":"Coercable","abstract":false,"locations":[{"filename":"src/cligen/coercable.cr","line_number":4,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"instance_methods":[{"html_id":"coerce(arg:String)-instance-method","name":"coerce","abstract":true,"args":[{"name":"arg","external_name":"arg","restriction":"String"}],"args_string":"(arg : String)","args_html":"(arg : String)","location":{"filename":"src/cligen/coercable.cr","line_number":5,"url":null},"def":{"name":"coerce","args":[{"name":"arg","external_name":"arg","restriction":"String"}],"visibility":"Public","body":""},"external_var":false}]},{"html_id":"CliGenerator/CliGen/Command","path":"CliGen/Command.html","kind":"class","full_name":"CliGen::Command","name":"Command","abstract":false,"superclass":{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},"ancestors":[{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/command.cr","line_number":16,"url":null},{"filename":"src/cligen/command/argument.cr","line_number":5,"url":null},{"filename":"src/cligen/command/def_init.cr","line_number":5,"url":null},{"filename":"src/cligen/command/define_command_initializer.cr","line_number":5,"url":null},{"filename":"src/cligen/command/help_template.cr","line_number":5,"url":null},{"filename":"src/cligen/command/selection.cr","line_number":5,"url":null},{"filename":"src/cligen/command/subcommand.cr","line_number":5,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"macros":[{"html_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","name":"argument","abstract":false,"args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"long","default_value":"nil","external_name":"long","restriction":""},{"name":"short","default_value":"nil","external_name":"short","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":""},{"name":"def_setter","default_value":"false","external_name":"def_setter","restriction":""},{"name":"def_getter","default_value":"false","external_name":"def_getter","restriction":""},{"name":"options","default_value":"nil","external_name":"options","restriction":""},{"name":"delimiter","default_value":"\",\"","external_name":"delimiter","restriction":""},{"name":"format","default_value":"nil","external_name":"format","restriction":""},{"name":"allow_no_verification","default_value":"false","external_name":"allow_no_verification","restriction":""},{"name":"env_var","default_value":"nil","external_name":"env_var","restriction":""}],"args_string":"(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)","args_html":"(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)","location":{"filename":"src/cligen/command/argument.cr","line_number":6,"url":null},"def":{"name":"argument","args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"long","default_value":"nil","external_name":"long","restriction":""},{"name":"short","default_value":"nil","external_name":"short","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":""},{"name":"def_setter","default_value":"false","external_name":"def_setter","restriction":""},{"name":"def_getter","default_value":"false","external_name":"def_getter","restriction":""},{"name":"options","default_value":"nil","external_name":"options","restriction":""},{"name":"delimiter","default_value":"\",\"","external_name":"delimiter","restriction":""},{"name":"format","default_value":"nil","external_name":"format","restriction":""},{"name":"allow_no_verification","default_value":"false","external_name":"allow_no_verification","restriction":""},{"name":"env_var","default_value":"nil","external_name":"env_var","restriction":""}],"visibility":"Public","body":" \n{% unless def_setter.is_a?(BoolLiteral)\n raise(\"ERROR : CliGen::Command.argument : def_setter must be a Bool\")\nend %}\n\n \n{% unless variable.is_a?(TypeDeclaration)\n raise(\"ERROR : CliGen::Command.argument : First argument (#{variable}) must be a TypeDeclaration (ex: ' : [= val]')\")\nend %}\n\n \n{% name = variable.var %}\n\n \n{% type = variable.type %}\n\n \n{% if env_var %}\n {% unless env_var.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided env_var must be a string\")\nend %}\n {% if env_var.includes?(\"-\")\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided env_var cannot contain a \\\"-\\\". Please fix and re-run\")\nend %}\n {% end %}\n\n \n{% unless delimiter.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided delimiter must be a string\")\nend %}\n\n \n{% if short %}\n {% unless short.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided short must be a string\")\nend %}\n {% end %}\n\n \n{% if long %}\n {% unless long.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided long must be a string\")\nend %}\n {% unless long =~ (/^--[a-zA-Z0-9-_]+/)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided long must match --[a-zA-Z0-9-_]+\")\nend %}\n {% else %}\n {% long = \"--#{name.downcase}\" %}\n {% end %}\n\n \n{% unless description\n raise(\"ERROR : CliGen::Command.argument(#{name}) : You must provide a description\")\nend %}\n\n \n{% unless description.is_a?(StringLiteral) || description.is_a?(StringInterpolation)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided description must be a String\")\nend %}\n\n \n{% unless on_match.nil? %}\n {% if env(\"DEBUG\")\n puts(\"DEBUG : #{@type.name}.argument(#{name}) : OnMatch:\\n\\tid: #{on_match}\\n\\treturn_type: #{on_match.return_type}\\n\\tinput_vars: #{on_match.args}\")\nend %}\n {% unless on_match.is_a?(ProcLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided on_match must be a Proc\")\nend %}\n {% if on_match.args.empty?\n raise(\"ERROR : CliGen::Command.argument(#{name}) : You must have arguments for on_match\")\nend %}\n {% unless on_match.args.first.restriction\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Your input argument must have a type\")\nend %}\n {% unless on_match.args.first.restriction == type\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Your input argument must be the same type as your argument (#{type})\")\nend %}\n {% end %}\n\n \n{% unless validation.nil? %}\n {% if env(\"DEBUG\")\n puts(\"DEBUG : #{@type.name}.argument(#{name}) : Validation:\\n\\tid: #{validation}\\n\\treturn_type: #{validation.return_type}\\n\\tinput_vars: #{validation.args}\")\nend %}\n {% unless validation.is_a?(ProcLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided validation must be a Proc\")\nend %}\n {% unless validation.return_type.resolve == Bool\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided validation return type must be a Bool\")\nend %}\n {% if validation.args.empty?\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided validation provided validation must have an input variable\")\nend %}\n {% arg = validation.args.first %}\n {% unless arg.restriction == type %}\n {% example = \"->(#{arg.name} : #{type}) : Bool { #{validation.body} }\" %}\n {% raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided validation input value must be #{type}. EX: #{example}\") %}\n {% end %}\n {% end %}\n\n \n{% if options %}\n {% if options.is_a?(Path)\n options = options.resolve\nend %}\n {% if options.is_a?(Call) %}\n {% elsif options.is_a?(ArrayLiteral) %}\n {% else %}\n {% raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided options must be an ArrayLiteral or a runtime method call to retrieve data\") %}\n {% end %}\n {% end %}\n\n \n{% if format %}\n {% if format.is_a?(Path)\n format = format.resolve\nend %}\n {% unless format.is_a?(RegexLiteral)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided format must be a RegexLiteral\")\nend %}\n {% end %}\n\n \n{% if type.resolve <= Array && (!allow_no_verification) %}\n {% elem = type.resolve.type_vars.first %}\n {% unless elem < Int || elem < Float %}\n {% if format.nil? && options.nil? %}\n {% raise(\"ERROR : CliGen::Command.argument(#{name}) : When providing custom data types for Array(T) or using Array(String) you must provide a format or options for argument filtering so that parsing can be done deterministically\") %}\n {% end %}\n {% end %}\n {% end %}\n\n\n \n{% if type.resolve < Array && !options.nil? %}\n @[CliGen::Argument(short: {{ short }}, long: {{ long }}, description: {{ description }}, validation: {{ validation }}, on_match: {{ on_match }}, options: [{{ options }}], delimiter: {{ delimiter }}, format: {{ format }}, env_var: {{ env_var }})]\n {% else %}\n @[CliGen::Argument(short: {{ short }}, long: {{ long }}, description: {{ description }}, validation: {{ validation }}, on_match: {{ on_match }}, options: {{ options }}, delimiter: {{ delimiter }}, format: {{ format }}, env_var: {{ env_var }})]\n {% end %}\n\n @\n{{ variable }}\n\n\n \n{% if def_getter %}\n def {{ variable.var }}\n @{{ name }}\n end\n {% end %}\n\n\n \n{% if def_setter %}\n def {{ variable.var }}= (value : {{ type }})\n {% unless validation.nil? %}\n raise CliGen::ValidationError.new(\"#{@type.name}##{@def.name} : Provided value #{value} failed validation\") unless {{ validation }}.call(value)\n {% end %}\n @{{ name }} = value\n end\n {% end %}\n\n \n"}},{"html_id":"def_init-macro","name":"def_init","abstract":false,"location":{"filename":"src/cligen/command/def_init.cr","line_number":6,"url":null},"def":{"name":"def_init","visibility":"Public","body":" def initialize\n \n{% verbatim do %}\n {% for var in @type.instance_vars %}\n {% if var.default_value.nil? && !var.type.nilable?\n raise(\"ERROR : Can't define a default initializer if #{var.name} doesn't have a default\")\n end %}\n @{{ var.name }} = {{ var.default_value }}\n {% end %}\n {% end %}\n\n \nend\n\n def after_initialize\n @@instance = self\n \nend\n\n def self.get \n @@instance ||= new\n \nend\n \n"}},{"html_id":"define_command_initializer-macro","name":"define_command_initializer","abstract":false,"location":{"filename":"src/cligen/command/define_command_initializer.cr","line_number":6,"url":null},"def":{"name":"define_command_initializer","visibility":"Public","body":" def initialize(*, handler : CliGen::BaseCommandNode)\n \n{% verbatim do %}\n Log.debug { \"#{self.class.name}#initialize : Initializing class\" }\n {% for var in @type.instance_vars %}\n Log.debug { \"{{ @type.name }}#initialize : Checking {{ var.name }}\" }\n {% anno = ((var.annotation(CliGen::Argument)) || (var.annotation(CliGen::Selection))) %}\n {% if anno %}\n {% if var.type.union?\n raise(\"ERROR : #{@type.name}#initialize : Argument '#{var.name}' cannot be a nilable type (#{var.type}) — flags always resolve to a concrete value\")\n end %}\n Log.debug { \"{{ @type.name }}#initialize : {{ var.name }} is a CliGen managed ivar. Will attempt to gather from associated CliGen::Flag\" }\n if flg = handler.flags.find{|f| f.var == {{ var.name.stringify }} && f.long == {{ anno[:long] }}}\n Log.debug { \"{{ @type.name }}#initialize : {{ var.name }} : Found Flag(long: #{flg.long}). Calling validate! to make sure data provided (in whatever format) is valid\" }\n flg.validate!\n Log.debug { \"{{ @type.name }}#initialize : {{ var.name }} : Found Flag(long: #{flg.long}). Data was valid seems like (or at least a default was set)\" }\n @{{ var.id }} = flg.as(CliGen::Flag({{ var.type }})).value!\n else\n raise CliGen::FlagNotFoundError.new(\"{{ @type.name }}\\#{{@def.name}} : No flag found for \\\"{{ var.name }}\\\"\")\n end\n {% else %}\n Log.debug { \"{{ @type.name }}#initialize : {{ var.name }} is not a CliGen managed ivar. Will initialize to default defined in class\" }\n {% if var.default_value.nil?\n raise(\"ERROR : #{@type.name}#{@def.name} : Instance Variable(#{var.name}) is not handled by CliGen and does not have a default value\")\n end %}\n @{{ var.id }} = {{ var.default_value }}\n {% end %}\n {% end %}\n\n {% if @type.has_method?(:after_initialize) %}\n Log.debug { \"{{ @type.name }}#initialize : Developer defined 'after_initialize' so going to call it\" }\n after_initialize\n {% end %}\n {% end %}\n\n \nend\n \n"}},{"html_id":"help_template(filepath)-macro","name":"help_template","abstract":false,"args":[{"name":"filepath","external_name":"filepath","restriction":""}],"args_string":"(filepath)","args_html":"(filepath)","location":{"filename":"src/cligen/command/help_template.cr","line_number":6,"url":null},"def":{"name":"help_template","args":[{"name":"filepath","external_name":"filepath","restriction":""}],"visibility":"Public","body":" \n{% unless file_exists?(filepath)\n raise(\"ERROR : CliGen::Command.help_template : #{filepath} does not exist\")\nend %}\n\n HELP_TEMPLATE = \n{{ (`readlink -f #{filepath}`).strip.stringify }}\n\n \n{% if env(\"DEBUG\")\n puts(\"DEBUG : #{@type.name} : Set HELP_TEMPLATE to #{filepath}\")\nend %}\n\n \n{% if env(\"DEBUG\")\n debug\nend %}\n\n \n"}},{"html_id":"selection(variable,description,options,short=nil,long=nil,validation=nil,on_match=nil)-macro","name":"selection","abstract":false,"args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"options","external_name":"options","restriction":""},{"name":"short","default_value":"nil","external_name":"short","restriction":""},{"name":"long","default_value":"nil","external_name":"long","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":""}],"args_string":"(variable, description, options, short = nil, long = nil, validation = nil, on_match = nil)","args_html":"(variable, description, options, short = nil, long = nil, validation = nil, on_match = nil)","location":{"filename":"src/cligen/command/selection.cr","line_number":6,"url":null},"def":{"name":"selection","args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"options","external_name":"options","restriction":""},{"name":"short","default_value":"nil","external_name":"short","restriction":""},{"name":"long","default_value":"nil","external_name":"long","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":""}],"visibility":"Public","body":" \n{% unless variable.is_a?(TypeDeclaration)\n raise(\"ERROR : CliGen::Command.selection : First selection must be a TypeDeclaration (ex: ' : [= val]')\")\nend %}\n\n \n{% if short %}\n {% unless short.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.selection : Provided short must be a string\")\nend %}\n {% end %}\n\n \n{% if long.nil?\n long = \"--#{variable.var}\"\nend %}\n\n \n{% unless long =~ (/^--[a-zA-Z0-9-_]+/)\n raise(\"ERROR : CliGen::Command.selection : Provided long must be a flag format\")\nend %}\n\n \n{% unless long.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.selection : Provided long must be a string\")\nend %}\n\n \n{% unless long || short\n raise(\"ERROR : CliGen::Command.selection : You must provide a short or long\")\nend %}\n\n \n{% unless description\n raise(\"ERROR : CliGen::Command.selection : You must provide a description\")\nend %}\n\n \n{% unless description.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.selection : Provided description must be a String\")\nend %}\n\n \n{% if options.is_a?(Path)\n options = options.resolve\nend %}\n\n \n{% unless options.is_a?(ArrayLiteral)\n raise(\"ERROR : CliGen::Command.selection : Provided options must be an ArrayLiteral\")\nend %}\n\n\n @[CliGen::Argument(short: \n{{ short }}\n, long: \n{{ long }}\n, description: \n{{ description }}\n, validation: \n{{ validation }}\n, on_match: \n{{ on_match }}\n, options: \n{{ options }}\n, delimiter: \"-\")]\n @\n{{ variable }}\n\n \n"}},{"html_id":"subcommand(func,description,examples=nil,&block)-macro","name":"subcommand","abstract":false,"args":[{"name":"func","external_name":"func","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"examples","default_value":"nil","external_name":"examples","restriction":""}],"args_string":"(func, description, examples = nil, &block)","args_html":"(func, description, examples = nil, &block)","location":{"filename":"src/cligen/command/subcommand.cr","line_number":6,"url":null},"def":{"name":"subcommand","args":[{"name":"func","external_name":"func","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"examples","default_value":"nil","external_name":"examples","restriction":""}],"block_arg":{"name":"block","external_name":"block","restriction":""},"visibility":"Public","body":" \n{% unless func.is_a?(TypeDeclaration) || func.is_a?(Call)\n raise(\"ERROR : CliGen::Command.subcommand : First argument must be a TypeDeclaration, or Call (ex: ' : ' or )\")\nend %}\n\n \n{% unless description\n raise(\"ERROR : CliGen::Command.subcommand : You must provide a description\")\nend %}\n\n \n{% unless description.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.subcommand : Provided description must be a String\")\nend %}\n\n \n{% unless examples.nil? %}\n {% if examples.is_a?(Path)\n examples = examples.resolve\nend %}\n {% unless examples.is_a?(ArrayLiteral)\n raise(\"ERROR : CliGen::Command.subcommand : Provided example must be an Array\")\nend %}\n {% end %}\n\n \n{% unless block\n raise(\"ERROR : CliGen::Command.subcommand : You MUST provide a function body\")\nend %}\n\n\n @[CliGen::SubCommand(description: \n{{ description }}\n, \nexamples: \n{{ examples }}\n)]\n def \n{{ func }}\n\n \n{{ block.body }}\n\n \nend\n \n"}}]},{"html_id":"CliGenerator/CliGen/CommandInfo","path":"CliGen/CommandInfo.html","kind":"annotation","full_name":"CliGen::CommandInfo","name":"CommandInfo","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":18,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"This is used to annotate a CliGen::Command subclass to define the description and other possible information in the future\n\nThe CliGen Framework uses this to store metadata for the creation of the associated CliGen::CommandNode(T) objects.\n\nKeys:\n description: StringLiteral\n This is what you use to define the short blurb of what this command is and does","summary":"

                  This is used to annotate a CliGen::Command subclass to define the description and other possible information in the future

                  "},{"html_id":"CliGenerator/CliGen/CommandMeta","path":"CliGen/CommandMeta.html","kind":"struct","full_name":"CliGen::CommandMeta","name":"CommandMeta","abstract":false,"superclass":{"html_id":"CliGenerator/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"CliGenerator/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"CliGenerator/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/command_node/command_meta.cr","line_number":5,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"constructors":[{"html_id":"new(cls:String)-class-method","name":"new","abstract":false,"args":[{"name":"cls","external_name":"cls","restriction":"String"}],"args_string":"(cls : String)","args_html":"(cls : String)","location":{"filename":"src/cligen/command_node/command_meta.cr","line_number":5,"url":null},"def":{"name":"new","args":[{"name":"cls","external_name":"cls","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(cls)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"clone-instance-method","name":"clone","abstract":false,"location":{"filename":"src/cligen/command_node/command_meta.cr","line_number":5,"url":null},"def":{"name":"clone","visibility":"Public","body":"self.class.new(@cls.clone)"},"external_var":false},{"html_id":"cls:String-instance-method","name":"cls","abstract":false,"def":{"name":"cls","return_type":"String","visibility":"Public","body":"@cls"},"external_var":false},{"html_id":"copy_with(cls_cls=@cls)-instance-method","name":"copy_with","abstract":false,"args":[{"name":"_cls","default_value":"@cls","external_name":"cls","restriction":""}],"args_string":"(cls _cls = @cls)","args_html":"(cls _cls = @cls)","location":{"filename":"src/cligen/command_node/command_meta.cr","line_number":5,"url":null},"def":{"name":"copy_with","args":[{"name":"_cls","default_value":"@cls","external_name":"cls","restriction":""}],"visibility":"Public","body":"self.class.new(_cls)"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/CommandNode","path":"CliGen/CommandNode.html","kind":"class","full_name":"CliGen::CommandNode(T)","name":"CommandNode","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/BaseCommandNode","kind":"class","full_name":"CliGen::BaseCommandNode","name":"BaseCommandNode"},"ancestors":[{"html_id":"CliGenerator/CliGen/BaseCommandNode","kind":"class","full_name":"CliGen::BaseCommandNode","name":"BaseCommandNode"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/command_node.cr","line_number":14,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"CliGenerator/CliGen/App","kind":"class","full_name":"CliGen::App","name":"App"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"constructors":[{"html_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","name":"new","abstract":false,"args":[{"name":"name","external_name":"name","restriction":"String"},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"},{"name":"description","default_value":"nil","external_name":"description","restriction":"String | ::Nil"}],"args_string":"(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil)","args_html":"(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil)","location":{"filename":"src/cligen/command_node.cr","line_number":15,"url":null},"def":{"name":"new","args":[{"name":"name","external_name":"name","restriction":"String"},{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"Array(BaseCommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"Array(RunCommand)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"Array(RunCommand)"},{"name":"description","default_value":"nil","external_name":"description","restriction":"String | ::Nil"}],"visibility":"Public","body":"_ = CommandNode(T).allocate\n_.initialize(name, flags, commands, pre_run_commands, post_run_commands, description)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"check!:Nil-instance-method","name":"check!","abstract":false,"location":{"filename":"src/cligen/command_node.cr","line_number":70,"url":null},"def":{"name":"check!","return_type":"Nil","visibility":"Public","body":"@flags.each(&.check!)\ncheck_for_duplicate_flags!(@flags + CliGen::GLOBAL_FLAGS)\n@commands.each(&.check!)\ncheck_for_duplicate_subcommands!\n\n{% unless T == Nil %}\n raise CliGen::MissingDispatchError.new(\"CommandNode(#{@name})#check! : {{ T }} has no subcommands and no #main defined\") \\\n if subcommands.empty? && !{{ T.has_method?(:main) }}\n {% end %}\n"},"external_var":false},{"html_id":"help:String-instance-method","name":"help","abstract":false,"location":{"filename":"src/cligen/command_node.cr","line_number":54,"url":null},"def":{"name":"help","return_type":"String","visibility":"Public","body":"{% if true %}\n {% if T.has_constant?(\"HELP_TEMPLATE\") %}\n {% if env(\"DEBUG\")\n puts(\"#{T} was found to have HELP_TEMPLATE defined using this instead\")\nend %}\n ECR.render({{ T.constant(\"HELP_TEMPLATE\") }})\n {% elsif CliGen.has_constant?(\"HELP_OVERRIDE_TEMPLATE\") %} # If we have a global override use it\n {% if env(\"DEBUG\")\n puts(\"Global override found. Using\")\nend %}\n ECR.render({{ CliGen::HELP_OVERRIDE_TEMPLATE }})\n {% else %}\n {% if env(\"DEBUG\")\n puts(\"No type overrided help output. Using default\")\nend %}\n ECR.render(\"lib/cligen/src/cligen/template/cmd_help.ecr\")\n {% end %} # otherwise\n {% if env(\"DEBUG\")\n debug\nend %}\n {% end %}"},"external_var":false},{"html_id":"process(args:Array(CliGen::Arg)):Nil-instance-method","name":"process","abstract":false,"args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"args_string":"(args : Array(CliGen::Arg)) : Nil","args_html":"(args : Array(CliGen::Arg)) : Nil","location":{"filename":"src/cligen/command_node.cr","line_number":82,"url":null},"def":{"name":"process","args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"return_type":"Nil","visibility":"Public","body":"Log.trace do \"CommandNode(#{@name})#process(#{args.map(&.value)}) : Entered\" end\ncheck!\npassed_execution = false\nmatched_subcommand : String | ::Nil = nil\n\n@pre_run_commands.each(&.call)\n\nargs.each do |arg|\n Log.trace do \"CommandNode(#{@name})#process : Iterating with arg Arg(index: #{arg.index}, value: #{arg.value})\" end\n if arg.processed?\n Log.debug do \"CommandNode(#{@name})#process : Arg(#{arg.value}) was already processed. Skipping\" end\n next\n end\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) wasn't processed yet. Continuing and marking arg as processed\" end\n arg.processed\n\n case match = find_match(arg.value)\n when BaseCommandNode\n Log.trace do\n \"CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be a child command. Handing off rest of execution & parsing to it\"\n end\n\n {% if true %}\n case match\n {% for cls in CliGen::Command.subclasses %}\n when CliGen::CommandNode({{ cls.name }})\n match.as(CommandNode({{ cls }})).process(args.reject(&.processed?))\n exit 0\n {% end %}\n else\n raise CliGen::UnknownCommandNodeError.new(\"CommandNode(#{@name})#process : matched a BaseCommandNode that isn't a known CommandNode(T)\")\n end\n {% end %}\n passed_execution = true\n when BaseFlag\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be a flag\" end\n\n\n handle_flag_raises do\n if match.requires_arg?\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) flag requires values so handing it the data without a match or that matches it's valid options\" end\n match.process(args.reject(&.processed?).take_while do |v|\n ((find_match(v.value)) == CliGen::MatchType::NoMatch) || (!!match.meta.options.try(&.includes?(v.value)))\n end)\n else\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) flag does not require an argument so just calling process\" end\n match.process\n end\n end\n when MatchType::SubCommand\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be a subcomand. Marking it as the matched sub-command\" end\n if matched_subcommand\n raise(CliGen::InternalError.new(\"CommandNode(#{@name})#process : subcommand '#{matched_subcommand}' was already matched — duplicate subcommand token\"))\n end\n matched_subcommand = arg.value\n when MatchType::Help\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) is a help option. Raising to have App print out help output\" end\n raise(CliGen::HelpRequestedError.new(help))\n when MatchType::FlagWithArg\n Log.debug do \"CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be a flag with an arg =\" end\n if regex_match = CliGen::Regex::FLAG_WITH_ARG.match(arg.value)\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) flag: #{regex_match[\"flag\"]} & arg: #{regex_match[\"arg\"]}\" end\n case flag_match = find_match(regex_match[\"flag\"])\n when BaseFlag\n Log.debug do \"CommandNode(#{@name})#process : Arg(#{arg.value}) flag: #{regex_match[\"flag\"]} is actually a flag\" end\n handle_flag_raises do\n flag_match.process([CliGen::Arg.new(value: regex_match[\"arg\"], index: arg.index)])\n end\n else\n Log.debug do \"CommandNode(#{@name})#process : Arg(#{arg.value}) flag: #{regex_match[\"flag\"]} had no flag matches\" end\n raise(CliGen::UnknownCommandNodeError.new(\"CommandNode(#{@name}).process : No flag matched '#{regex_match[\"flag\"]}'\"))\n end\n else\n raise(CliGen::RegexInvariantError.new(\"CommandNode(#{@name})#process : FLAG_WITH_ARG matched in find_match but failed on re-match — this is a framework bug\"))\n end\n when MatchType::FlagMultipleShort\n Log.debug do \"CommandNode(#{@name})#process : Arg(#{arg.value}) was found to be an combined short flag\" end\n val = arg.value.gsub(/^-/, \"\")\n\n\n if flag?(\"-#{val[1]}\")\n chars = val.chars\n chars.map do |c| \"-#{c}\" end.each_with_index do |flag, index|\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) : char(flag: #{flag}, index: #{index}) being processed\" end\n case match = find_match(flag)\n when BaseFlag\n Log.trace do \"CommandNode(#{@name})#process : Arg(#{arg.value}) : char(flag: #{flag}, index: #{index}) was actually found to be a flag\" end\n\n handle_flag_raises do\n\n if index == (chars.size - 1)\n if match.requires_arg?\n match.process(args.reject(&.processed?).take_while do |v|\n ((find_match(v.value)) == CliGen::MatchType::NoMatch) || (!!match.meta.options.try(&.includes?(v.value)))\n end)\n else\n match.process\n end\n else\n if match.requires_arg?\n raise(CliGen::FlagBundleError.new(\"#{CliGen::APPNAME}: cannot bundle '#{flag}' — it requires an argument\"))\n end\n match.process\n end\n end\n when MatchType::NoMatch\n raise(CliGen::UnknownFlagError.new(\"#{CliGen::APPNAME}: unknown flag '#{flag}'\"))\n end\n end\n else\n raise(CliGen::FlagArgumentError.new(\"#{CliGen::APPNAME}: inline flag arguments are not supported — did you mean '-#{val[0]} #{val[1..]}'?\"))\n end\n when MatchType::NoMatch\n raise(CliGen::HelpRequestedError.new(\"#{CliGen::APPNAME}: unknown token '#{arg.value}'\\n\\n#{help}\"))\n end\nend\n\n@post_run_commands.each(&.call)\n\n{% unless T == Nil %}\n unless passed_execution\n cls = T.new(handler: self.as(CliGen::BaseCommandNode))\n {% for cmd in T.methods.select(&.annotation(CliGen::PreRunCommand)) %}\n cls.{{ cmd.name }}\n {% end %}\n {% subcmds = T.methods.select(&.annotation(CliGen::SubCommand)) %}\n {% if true %}\n case matched_subcommand\n {% for cmd in subcmds %}\n when {{ cmd.name.stringify }}\n cls.{{ cmd.name }}\n {% end %}\n else\n {% if T.has_method?(:main) %}\n cls.main\n {% else %}\n puts \"ERROR : CommandNode(#{@name})#process : No subcommand matched and no #main defined\"\n puts help\n {% end %}\n exit 0\n end\n {% end %}\n end\n {% else %}\n puts help\n exit 0\n {% end %}\n"},"external_var":false},{"html_id":"subcommands:Array(SubCommandInfo)-instance-method","name":"subcommands","abstract":false,"location":{"filename":"src/cligen/command_node.cr","line_number":29,"url":null},"def":{"name":"subcommands","return_type":"Array(SubCommandInfo)","visibility":"Public","body":"{% if true %}\n {% subcmds = T.methods.select(&.annotation(CliGen::SubCommand)) %}\n {% if subcmds.empty? %}\n [] of SubCommandInfo\n {% else %}\n [\n {% for cmd in subcmds %}\n {% anno = cmd.annotation(CliGen::SubCommand) %}\n SubCommandInfo.new(\n name: {{ cmd.name.stringify }},\n description: {{ anno[:description] }},\n examples: {% if anno[:examples] %} {{ anno[:examples] }} {% else %} nil {% end %}\n ),\n {% end %}\n ]\n {% end %}\n {% end %}"},"external_var":false},{"html_id":"verbose?:Bool-instance-method","name":"verbose?","abstract":false,"location":{"filename":"src/cligen/command_node.cr","line_number":49,"url":null},"def":{"name":"verbose?","return_type":"Bool","visibility":"Public","body":"@verbose_flag || (@verbose_flag = get(long: \"--verbose\").not_nil!.as(Flag(Bool)))\n@verbose_flag.not_nil!.value!\n"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/ConfigurationError","path":"CliGen/ConfigurationError.html","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},"ancestors":[{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":27,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"CliGenerator/CliGen/DuplicateCommandError","kind":"class","full_name":"CliGen::DuplicateCommandError","name":"DuplicateCommandError"},{"html_id":"CliGenerator/CliGen/DuplicateFlagError","kind":"class","full_name":"CliGen::DuplicateFlagError","name":"DuplicateFlagError"},{"html_id":"CliGenerator/CliGen/FlagMissingArgumentError","kind":"class","full_name":"CliGen::FlagMissingArgumentError","name":"FlagMissingArgumentError"},{"html_id":"CliGenerator/CliGen/FlagNotFoundError","kind":"class","full_name":"CliGen::FlagNotFoundError","name":"FlagNotFoundError"},{"html_id":"CliGenerator/CliGen/MissingDispatchError","kind":"class","full_name":"CliGen::MissingDispatchError","name":"MissingDispatchError"},{"html_id":"CliGenerator/CliGen/ParseableInvariantError","kind":"class","full_name":"CliGen::ParseableInvariantError","name":"ParseableInvariantError"},{"html_id":"CliGenerator/CliGen/ReservedFlagError","kind":"class","full_name":"CliGen::ReservedFlagError","name":"ReservedFlagError"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"}},{"html_id":"CliGenerator/CliGen/DuplicateCommandError","path":"CliGen/DuplicateCommandError.html","kind":"class","full_name":"CliGen::DuplicateCommandError","name":"DuplicateCommandError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":36,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Duplicate command names detected during check!","summary":"

                  Duplicate command names detected during check!

                  "},{"html_id":"CliGenerator/CliGen/DuplicateFlagError","path":"CliGen/DuplicateFlagError.html","kind":"class","full_name":"CliGen::DuplicateFlagError","name":"DuplicateFlagError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":33,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Duplicate short or long flags detected during check!","summary":"

                  Duplicate short or long flags detected during check!

                  "},{"html_id":"CliGenerator/CliGen/Error","path":"CliGen/Error.html","kind":"class","full_name":"CliGen::Error","name":"Error","abstract":false,"superclass":{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},"ancestors":[{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":6,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/HelpRequestedError","kind":"class","full_name":"CliGen::HelpRequestedError","name":"HelpRequestedError"},{"html_id":"CliGenerator/CliGen/InternalError","kind":"class","full_name":"CliGen::InternalError","name":"InternalError"},{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Base for all CliGen exceptions","summary":"

                  Base for all CliGen exceptions

                  "},{"html_id":"CliGenerator/CliGen/Flag","path":"CliGen/Flag.html","kind":"class","full_name":"CliGen::Flag(T)","name":"Flag","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/BaseFlag","kind":"class","full_name":"CliGen::BaseFlag","name":"BaseFlag"},"ancestors":[{"html_id":"CliGenerator/CliGen/BaseFlag","kind":"class","full_name":"CliGen::BaseFlag","name":"BaseFlag"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/flag.cr","line_number":10,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"constructors":[{"html_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","name":"new","abstract":false,"args":[{"name":"var","external_name":"var","restriction":"String"},{"name":"short","external_name":"short","restriction":"String | ::Nil"},{"name":"long","external_name":"long","restriction":"String"},{"name":"env_var","external_name":"env_var","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"delimiter","default_value":"\",\"","external_name":"delimiter","restriction":"String"},{"name":"default","default_value":"nil","external_name":"default","restriction":"T | ::Nil"},{"name":"options","default_value":"nil","external_name":"options","restriction":"Array(T) | ::Nil"},{"name":"validate","default_value":"nil","external_name":"validate","restriction":"(T -> Bool) | ::Nil"},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":"Proc(T, Nil) | ::Nil"},{"name":"format","default_value":"nil","external_name":"format","restriction":"::Regex | ::Nil"}],"args_string":"(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)","args_html":"(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)","location":{"filename":"src/cligen/flag.cr","line_number":18,"url":null},"def":{"name":"new","args":[{"name":"var","external_name":"var","restriction":"String"},{"name":"short","external_name":"short","restriction":"String | ::Nil"},{"name":"long","external_name":"long","restriction":"String"},{"name":"env_var","external_name":"env_var","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"delimiter","default_value":"\",\"","external_name":"delimiter","restriction":"String"},{"name":"default","default_value":"nil","external_name":"default","restriction":"T | ::Nil"},{"name":"options","default_value":"nil","external_name":"options","restriction":"Array(T) | ::Nil"},{"name":"validate","default_value":"nil","external_name":"validate","restriction":"(T -> Bool) | ::Nil"},{"name":"on_match","default_value":"nil","external_name":"on_match","restriction":"Proc(T, Nil) | ::Nil"},{"name":"format","default_value":"nil","external_name":"format","restriction":"::Regex | ::Nil"}],"visibility":"Public","body":"_ = Flag(T).allocate\n_.initialize(var, short, long, env_var, description, delimiter, default, options, validate, on_match, format)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"check!:Nil-instance-method","name":"check!","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":255,"url":null},"def":{"name":"check!","return_type":"Nil","visibility":"Public","body":"Log.trace do \"Flag(long: #{@long}, type: #{@meta.type})#check! : called\" end\nif @short.nil?\nelsif @short.not_nil!.starts_with?(\"-\")\nelse\n raise(CliGen::ConfigurationError.new(\"Flag({{T}}, long: #{@long})#check! : #{@short} flag short must start with '--'\"))\nend\nif @long.starts_with?(\"--\")\nelse\n raise(CliGen::ConfigurationError.new(\"Flag({{T}}, long: #{@long})#check! : #{@long} flag long must start with '--'\"))\nend\nif @short == \"-h\"\n raise(CliGen::ReservedFlagError.new(\"Flag({{T}}, long: #{@long})#check! : -h is reserved for internal help\"))\nend\nif @long_key == \"--help\"\n raise(CliGen::ReservedFlagError.new(\"Flag({{T}}, long: #{@long})#check! : --help is reserved for internal help\"))\nend\n"},"external_var":false},{"html_id":"process(argv:Array(Arg)=[]ofArg):Nil-instance-method","name":"process","abstract":false,"args":[{"name":"argv","default_value":"[] of Arg","external_name":"argv","restriction":"Array(Arg)"}],"args_string":"(argv : Array(Arg) = [] of Arg) : Nil","args_html":"(argv : Array(Arg) = [] of Arg) : Nil","location":{"filename":"src/cligen/flag.cr","line_number":61,"url":null},"def":{"name":"process","args":[{"name":"argv","default_value":"[] of Arg","external_name":"argv","restriction":"Array(Arg)"}],"return_type":"Nil","visibility":"Public","body":"Log.trace do \"Flag(#{@long}, type: #{@meta.type})#process : entered with args #{argv.map(&.value)}\" end\nif requires_arg?\n if argv.empty?\n raise(CliGen::FlagMissingArgumentError.new(\"Flag(#{T}, long: #{@long_key}) : requires an argument but provided array is empty\"))\n end\n if argv.first.flag?\n raise(CliGen::FlagArgumentError.new(\"Flag(#{T}, long: #{@long_key}) : a flag token was provided where a value was expected (got: #{argv.first.value})\"))\n end\nend\n\n{% if T == Bool %}\n @value = true\n {% elsif T < Array %}\n {% if T.type_vars.size > 1\n raise(\"ERROR : Flag(#{T}) : You cannot define multiple types of array entries\")\nend %}\n {% elem = T.type_vars.first %}\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type})#process : Beginning iteration of arguments\" }\n argv.each do |arg|\n Log.trace { \"Flag(long: #{@long}, type: #{@meta.type})#process : Iterating with Arg(index: #{arg.index}, value: #{arg.value})\" }\n if arg.flag?\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) was a flag. Breaking loop\" }\n break \n end\n unless @format.nil?\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type}) : Arg(index: #{arg.index}, value: #{arg.value}) format regex was provided. Going to check argument value against it\" }\n unless arg.value.includes?(@delimiter)\n unless arg.value =~ @format\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type}) : Arg(index: #{arg.index}, value: #{arg.value}) was not found to be matching the defined filter #{@format}. So breaking from parse loop\" }\n break\n end\n end\n end\n {% if elem < Int %}\n {% int_case = elem.stringify =~ (/^UInt/) ? \"uint?\".id : \"int?\".id %}\n if arg.value.includes?(@delimiter)\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) argument provided is delimited with provided delimiter . Splitting and parsing individual values\" }\n @value = (@value || T.new) + arg.value.split(@delimiter).map do |val|\n Log.trace { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) : Indexing with Value(#{val})\" }\n val = val.strip\n unless arg.{{ int_case }}(val)\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{val}' is not a valid {{ elem }}\")\n end\n {{ elem }}.new(val)\n end\n else\n unless arg.{{ int_case }}\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{arg.value}' is not a valid {{ T }}\") \n end\n (@value ||= T.new) << {{ elem }}.new(arg.value)\n end\n {% elsif elem < Float %}\n if arg.value.includes?(@delimiter)\n @value = (@value || T.new) + arg.value.split(@delimiter).map do |val|\n val = val.strip\n unless CliGen::Arg.float?(val)\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{val}' is not a valid {{ T }}\")\n end\n {{ elem }}.new(val)\n end\n else\n unless arg.float?\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{arg.value}' is not a float\") \n end\n (@value ||= T.new) << {{ elem }}.new(arg.value)\n end\n {% elsif elem == String %}\n if arg.value.includes?(@delimiter)\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) argument provided is delimited with provided delimiter . Splitting and parsing individual values\" }\n @value = (@value || [] of String) + arg.value.split(@delimiter).map { |v|\n Log.trace { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) : Indexing with Value(#{v})\" }\n unless @format.nil?\n Log.debug { \"Flag(long: #{@long}, type: #{@meta.type})#process : Arg(index: #{arg.index}, value: #{arg.value}) format regex (#{@format.not_nil!.source}) was provided. Checking value against it\" }\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{v}' does not match required format /#{@format.not_nil!.source}/\") unless v =~ @format\n end\n v\n }\n else\n if ! @format.nil? && arg.value !~ @format\n raise CliGen::InvalidFlagValueError.new(\"Flag({{ T }}, long: #{@long_key}) : '#{arg.value}' does not match required format /#{@format.not_nil!.source}/\") \n end\n (@value ||= [] of String) << arg.value\n end\n {% elsif elem.class < CliGen::Coercable %}\n if arg.value.includes?(@delimiter)\n @value = (@value || [] of {{ elem }}) + arg.value.split(@delimiter).map { |i| {{ elem }}.coerce(i) }\n else\n @value = (@value || [] of {{ elem }}) + [({{ elem }}.coerce(arg.value))]\n end\n {% else %}\n {% raise(\"ERROR : Flag(#{T}) : #{elem} is not a coercable type. If you wish to coerce it from a bare string extend with CliGen::Coercable & implement the class method\") %}\n {% end %}\n arg.processed\n end\n {% elsif T < Int %}\n {% int_case = T.stringify =~ (/^UInt/) ? \"uint?\".id : \"int?\".id %}\n unless argv.first.{{ int_case }}\n raise CliGen::InvalidFlagValueError.new(\"Flag(#{T}, long: #{@long_key}) : '#{argv.first.value}' is not a valid {{ T }}\") \n end\n @value = T.new(argv.first.value)\n argv.first.processed\n {% elsif T < Float %}\n unless argv.first.float?\n raise CliGen::InvalidFlagValueError.new(\"Flag(#{T}, long: #{@long_key}) : '#{argv.first.value}' is not a valid {{ T }}\") \n end\n @value = T.new(argv.first.value)\n argv.first.processed\n {% elsif T == Time %}\n begin\n @value = ::CliGen::Timeparse.parse(argv.first.value)\n argv.first.processed\n rescue e : ::CliGen::TimeParseError\n raise CliGen::InvalidFlagValueError.new(\"Flag(#{T}, long: #{@long_key}) : #{e.message}\") \n end\n {% elsif T == String %} # String\n if ! @format.nil? && argv.first.value !~ @format\n raise CliGen::InvalidFlagValueError.new(\"Flag(#{T}, long: #{@long_key}) : '#{argv.first.value}' does not match required format /#{@format.not_nil!.source}/\") \n end\n\n @value = argv.first.value\n argv.first.processed\n {% elsif T.class < CliGen::Parsable %}\n unprocessed = argv.reject(&.processed?)\n Log.trace { \"Flag(long: #{@long}, type: #{@meta.type})#process : unprocessed before : #{unprocessed.map(&.value)}\" }\n @value = T.parse_args(argv)\n Log.trace { \"Flag(long: #{@long}, type: #{@meta.type})#process : unprocessed after : #{unprocessed.reject(&.processed?).map(&.value)}\" }\n # Essentially if the unprocessed array stays the same (aka if it shows the same number of unprocessed\n # arguments it will complain and raise. Only possible because the array holds references to the objects\n # in case the user (for some reason) shifts/pops options out when getting/parsing data from argv)\n if unprocessed.size == unprocessed.reject(&.processed?).size\n raise CliGen::ParseableInvariantError.new(\"Flag({{ T }}, long: #{@long_key})#process : {{ T }}#parse_args did not mark any args as processed\")\n end\n {% else %}\n {% raise(\"ERROR : Flag({{T}}#process : Generic Type #{T} is not supported. To add support you must extend with CliGen::Parsable & implement the class method\") %}\n {% end %}\n\nvalidate!\n@on_match.try(&.call(value!))\n"},"external_var":false},{"html_id":"raw_value:String|Nil-instance-method","name":"raw_value","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":217,"url":null},"def":{"name":"raw_value","return_type":"String | ::Nil","visibility":"Public","body":"Log.trace do \"Flag(long: #{@long}, type: #{@meta.type})#raw_value : called\" end\n{% if T == Bool %}\n @value.try(&.to_s)\n {% elsif T <= Array %}\n @value.try(&.join(\",\"))\n {% else %}\n @value.try(&.to_s)\n {% end %}\n"},"external_var":false},{"html_id":"requires_arg?:Bool-instance-method","name":"requires_arg?","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":57,"url":null},"def":{"name":"requires_arg?","return_type":"Bool","visibility":"Public","body":"({{ T }}) != Bool"},"external_var":false},{"html_id":"satisfied?:Bool-instance-method","name":"satisfied?","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":228,"url":null},"def":{"name":"satisfied?","return_type":"Bool","visibility":"Public","body":"Log.trace do \"Flag(long: #{@long}, type: #{@meta.type})#satisfied? : called\" end\nif !@value.nil?\n return true\nend\nif @env_var && ENV[@env_var]?\n return true\nend\nif !@default.nil?\n return true\nend\nfalse\n"},"external_var":false},{"html_id":"validate!(v:T|Nil=nil):Nil-instance-method","name":"validate!","abstract":false,"args":[{"name":"v","default_value":"nil","external_name":"v","restriction":"T | ::Nil"}],"args_string":"(v : T | Nil = nil) : Nil","args_html":"(v : T | Nil = nil) : Nil","location":{"filename":"src/cligen/flag.cr","line_number":236,"url":null},"def":{"name":"validate!","args":[{"name":"v","default_value":"nil","external_name":"v","restriction":"T | ::Nil"}],"return_type":"Nil","visibility":"Public","body":"Log.trace do \"Flag(long: #{@long}, type: #{@meta.type})#validate! : called\" end\nif v.nil?\n v = value!\nend\n\nif opts = @options\n {% if T < Array %}\n v.each do |v2|\n raise CliGen::InvalidOptionError.new(\"#{CliGen::APPNAME}: '#{v2}' is not a valid value for #{@long_key} (valid: #{opts.first.join(\", \")})\") unless opts.first.includes?(v2)\n end\n {% else %}\n raise CliGen::InvalidOptionError.new(\"#{CliGen::APPNAME}: '#{v}' is not a valid value for #{@long_key} (valid: #{opts.join(\", \")})\") unless opts.includes?(v)\n {% end %}\nend\n\nif check = @validate\n if check.call(v)\n else\n raise(CliGen::ValidationError.new(\"#{CliGen::APPNAME}: validation failed for #{@long_key} (got: #{v})\"))\n end\nend\n"},"external_var":false},{"html_id":"value!:T-instance-method","name":"value!","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":196,"url":null},"def":{"name":"value!","return_type":"T","visibility":"Public","body":"Log.trace do \"Flag(long: #{@long}, type: #{@meta.type})#value! : called\" end\n\nv = @value\n\n\nif v.nil?\n if raw = ENV[@env_var]?\n v = coerce(raw)\n end\nend\n\nv || (v = @default)\n\nif v.nil?\n raise(CliGen::MissingRequiredFlagError.new(\"#{CliGen::APPNAME}: required flag #{@long_key} was not provided\"))\nend\n\nvalidate!(v)\n\nv.not_nil!\n"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/FlagArgumentError","path":"CliGen/FlagArgumentError.html","kind":"class","full_name":"CliGen::FlagArgumentError","name":"FlagArgumentError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},"ancestors":[{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":63,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A flag token was provided where a value argument was expected","summary":"

                  A flag token was provided where a value argument was expected

                  "},{"html_id":"CliGenerator/CliGen/FlagBundleError","path":"CliGen/FlagBundleError.html","kind":"class","full_name":"CliGen::FlagBundleError","name":"FlagBundleError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},"ancestors":[{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":75,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A flag that requires an argument was included in a short-flag bundle","summary":"

                  A flag that requires an argument was included in a short-flag bundle

                  "},{"html_id":"CliGenerator/CliGen/FlagMeta","path":"CliGen/FlagMeta.html","kind":"struct","full_name":"CliGen::FlagMeta","name":"FlagMeta","abstract":false,"superclass":{"html_id":"CliGenerator/Struct","kind":"struct","full_name":"Struct","name":"Struct"},"ancestors":[{"html_id":"CliGenerator/Struct","kind":"struct","full_name":"Struct","name":"Struct"},{"html_id":"CliGenerator/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/flag/meta.cr","line_number":6,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"To be able to store metadata for use in the help output","summary":"

                  To be able to store metadata for use in the help output

                  ","constructors":[{"html_id":"new(type:String,array:Bool,format:String|Nil,default:String,options:Array(String)|Nil)-class-method","name":"new","abstract":false,"args":[{"name":"type","external_name":"type","restriction":"String"},{"name":"array","external_name":"array","restriction":"Bool"},{"name":"format","external_name":"format","restriction":"String | ::Nil"},{"name":"default","external_name":"default","restriction":"String"},{"name":"options","external_name":"options","restriction":"Array(String) | ::Nil"}],"args_string":"(type : String, array : Bool, format : String | Nil, default : String, options : Array(String) | Nil)","args_html":"(type : String, array : Bool, format : String | Nil, default : String, options : Array(String) | Nil)","location":{"filename":"src/cligen/flag/meta.cr","line_number":6,"url":null},"def":{"name":"new","args":[{"name":"type","external_name":"type","restriction":"String"},{"name":"array","external_name":"array","restriction":"Bool"},{"name":"format","external_name":"format","restriction":"String | ::Nil"},{"name":"default","external_name":"default","restriction":"String"},{"name":"options","external_name":"options","restriction":"Array(String) | ::Nil"}],"visibility":"Public","body":"_ = allocate\n_.initialize(type, array, format, default, options)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"array:Bool-instance-method","name":"array","abstract":false,"def":{"name":"array","return_type":"Bool","visibility":"Public","body":"@array"},"external_var":false},{"html_id":"clone-instance-method","name":"clone","abstract":false,"location":{"filename":"src/cligen/flag/meta.cr","line_number":6,"url":null},"def":{"name":"clone","visibility":"Public","body":"self.class.new(@type.clone, @array.clone, @format.clone, @default.clone, @options.clone)"},"external_var":false},{"html_id":"copy_with(type_type=@type,array_array=@array,format_format=@format,default_default=@default,options_options=@options)-instance-method","name":"copy_with","abstract":false,"args":[{"name":"_type","default_value":"@type","external_name":"type","restriction":""},{"name":"_array","default_value":"@array","external_name":"array","restriction":""},{"name":"_format","default_value":"@format","external_name":"format","restriction":""},{"name":"_default","default_value":"@default","external_name":"default","restriction":""},{"name":"_options","default_value":"@options","external_name":"options","restriction":""}],"args_string":"(type _type = @type, array _array = @array, format _format = @format, default _default = @default, options _options = @options)","args_html":"(type _type = @type, array _array = @array, format _format = @format, default _default = @default, options _options = @options)","location":{"filename":"src/cligen/flag/meta.cr","line_number":6,"url":null},"def":{"name":"copy_with","args":[{"name":"_type","default_value":"@type","external_name":"type","restriction":""},{"name":"_array","default_value":"@array","external_name":"array","restriction":""},{"name":"_format","default_value":"@format","external_name":"format","restriction":""},{"name":"_default","default_value":"@default","external_name":"default","restriction":""},{"name":"_options","default_value":"@options","external_name":"options","restriction":""}],"visibility":"Public","body":"self.class.new(_type, _array, _format, _default, _options)"},"external_var":false},{"html_id":"default:String-instance-method","name":"default","abstract":false,"def":{"name":"default","return_type":"String","visibility":"Public","body":"@default"},"external_var":false},{"html_id":"format:String|Nil-instance-method","name":"format","abstract":false,"def":{"name":"format","return_type":"String | ::Nil","visibility":"Public","body":"@format"},"external_var":false},{"html_id":"options:Array(String)|Nil-instance-method","name":"options","abstract":false,"def":{"name":"options","return_type":"Array(String) | ::Nil","visibility":"Public","body":"@options"},"external_var":false},{"html_id":"type:String-instance-method","name":"type","abstract":false,"def":{"name":"type","return_type":"String","visibility":"Public","body":"@type"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/FlagMissingArgumentError","path":"CliGen/FlagMissingArgumentError.html","kind":"class","full_name":"CliGen::FlagMissingArgumentError","name":"FlagMissingArgumentError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":45,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A flag that requires an argument was processed with an empty argv","summary":"

                  A flag that requires an argument was processed with an empty argv

                  "},{"html_id":"CliGenerator/CliGen/FlagNotFoundError","path":"CliGen/FlagNotFoundError.html","kind":"class","full_name":"CliGen::FlagNotFoundError","name":"FlagNotFoundError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":42,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"No flag was found in the handler for a Command ivar during initialize","summary":"

                  No flag was found in the handler for a Command ivar during initialize

                  "},{"html_id":"CliGenerator/CliGen/Format","path":"CliGen/Format.html","kind":"module","full_name":"CliGen::Format","name":"Format","abstract":false,"locations":[{"filename":"src/cligen/format.cr","line_number":5,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"INPUT_DATE_FULL","name":"INPUT_DATE_FULL","value":"\"%Y-%m-%d %H:%M:%S %z\""},{"id":"INPUT_DATE_PARTIAL","name":"INPUT_DATE_PARTIAL","value":"\"%Y-%m-%d %H:%M:%S\""},{"id":"INPUT_DATE_SIMPLE","name":"INPUT_DATE_SIMPLE","value":"\"%Y-%m-%d\""},{"id":"INPUT_DATE_SIMPLE_WITH_TIMEZONE","name":"INPUT_DATE_SIMPLE_WITH_TIMEZONE","value":"\"%Y-%m-%d %z\""},{"id":"INPUT_EPOCH","name":"INPUT_EPOCH","value":"\"@%s\""}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"This module just holds time formats to be used with ::Time.parse!/.parse/.parse_local","summary":"

                  This module just holds time formats to be used with ::Time.parse!/.parse/.parse_local

                  "},{"html_id":"CliGenerator/CliGen/HelpRequestedError","path":"CliGen/HelpRequestedError.html","kind":"class","full_name":"CliGen::HelpRequestedError","name":"HelpRequestedError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},"ancestors":[{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":82,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"Raised when -h/--help is matched; carries the rendered help string","summary":"

                  Raised when -h/--help is matched; carries the rendered help string

                  "},{"html_id":"CliGenerator/CliGen/InternalError","path":"CliGen/InternalError.html","kind":"class","full_name":"CliGen::InternalError","name":"InternalError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},"ancestors":[{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":12,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"subclasses":[{"html_id":"CliGenerator/CliGen/ArgReprocessedError","kind":"class","full_name":"CliGen::ArgReprocessedError","name":"ArgReprocessedError"},{"html_id":"CliGenerator/CliGen/RegexInvariantError","kind":"class","full_name":"CliGen::RegexInvariantError","name":"RegexInvariantError"},{"html_id":"CliGenerator/CliGen/UnknownCommandNodeError","kind":"class","full_name":"CliGen::UnknownCommandNodeError","name":"UnknownCommandNodeError"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"}},{"html_id":"CliGenerator/CliGen/InvalidFlagValueError","path":"CliGen/InvalidFlagValueError.html","kind":"class","full_name":"CliGen::InvalidFlagValueError","name":"InvalidFlagValueError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},"ancestors":[{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":66,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A provided value doesn't satisfy type or format requirements (wrong type, bad format, invalid bool/date string)","summary":"

                  A provided value doesn't satisfy type or format requirements (wrong type, bad format, invalid bool/date string)

                  "},{"html_id":"CliGenerator/CliGen/InvalidOptionError","path":"CliGen/InvalidOptionError.html","kind":"class","full_name":"CliGen::InvalidOptionError","name":"InvalidOptionError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},"ancestors":[{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":69,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A provided value is not in the flag's allowed options list","summary":"

                  A provided value is not in the flag's allowed options list

                  "},{"html_id":"CliGenerator/CliGen/MatchType","path":"CliGen/MatchType.html","kind":"enum","full_name":"CliGen::MatchType","name":"MatchType","abstract":false,"ancestors":[{"html_id":"CliGenerator/Enum","kind":"struct","full_name":"Enum","name":"Enum"},{"html_id":"CliGenerator/Comparable","kind":"module","full_name":"Comparable","name":"Comparable"},{"html_id":"CliGenerator/Value","kind":"struct","full_name":"Value","name":"Value"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/match_type.cr","line_number":5,"url":null}],"repository_name":"CliGenerator","program":false,"enum":true,"alias":false,"const":false,"constants":[{"id":"FlagWithArg","name":"FlagWithArg","value":"0"},{"id":"FlagMultipleShort","name":"FlagMultipleShort","value":"1"},{"id":"ShortWithInlineArg","name":"ShortWithInlineArg","value":"2"},{"id":"SubCommand","name":"SubCommand","value":"3"},{"id":"Help","name":"Help","value":"4"},{"id":"NoMatch","name":"NoMatch","value":"5"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"instance_methods":[{"html_id":"flag_multiple_short?-instance-method","name":"flag_multiple_short?","doc":"Returns `true` if this enum value equals `FlagMultipleShort`","summary":"

                  Returns true if this enum value equals FlagMultipleShort

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":7,"url":null},"def":{"name":"flag_multiple_short?","visibility":"Public","body":"self == FlagMultipleShort"},"external_var":false},{"html_id":"flag_with_arg?-instance-method","name":"flag_with_arg?","doc":"Returns `true` if this enum value equals `FlagWithArg`","summary":"

                  Returns true if this enum value equals FlagWithArg

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":6,"url":null},"def":{"name":"flag_with_arg?","visibility":"Public","body":"self == FlagWithArg"},"external_var":false},{"html_id":"help?-instance-method","name":"help?","doc":"Returns `true` if this enum value equals `Help`","summary":"

                  Returns true if this enum value equals Help

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":10,"url":null},"def":{"name":"help?","visibility":"Public","body":"self == Help"},"external_var":false},{"html_id":"no_match?-instance-method","name":"no_match?","doc":"Returns `true` if this enum value equals `NoMatch`","summary":"

                  Returns true if this enum value equals NoMatch

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":11,"url":null},"def":{"name":"no_match?","visibility":"Public","body":"self == NoMatch"},"external_var":false},{"html_id":"short_with_inline_arg?-instance-method","name":"short_with_inline_arg?","doc":"Returns `true` if this enum value equals `ShortWithInlineArg`","summary":"

                  Returns true if this enum value equals ShortWithInlineArg

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":8,"url":null},"def":{"name":"short_with_inline_arg?","visibility":"Public","body":"self == ShortWithInlineArg"},"external_var":false},{"html_id":"sub_command?-instance-method","name":"sub_command?","doc":"Returns `true` if this enum value equals `SubCommand`","summary":"

                  Returns true if this enum value equals SubCommand

                  ","abstract":false,"location":{"filename":"src/cligen/match_type.cr","line_number":9,"url":null},"def":{"name":"sub_command?","visibility":"Public","body":"self == SubCommand"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/MissingDispatchError","path":"CliGen/MissingDispatchError.html","kind":"class","full_name":"CliGen::MissingDispatchError","name":"MissingDispatchError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":39,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A CommandNode(T) has no subcommands and no #main defined","summary":"

                  A CommandNode(T) has no subcommands and no #main defined

                  "},{"html_id":"CliGenerator/CliGen/MissingRequiredFlagError","path":"CliGen/MissingRequiredFlagError.html","kind":"class","full_name":"CliGen::MissingRequiredFlagError","name":"MissingRequiredFlagError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},"ancestors":[{"html_id":"CliGenerator/CliGen/RuntimeError","kind":"class","full_name":"CliGen::RuntimeError","name":"RuntimeError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":57,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A required flag was not provided and has no env var or default to fall back on","summary":"

                  A required flag was not provided and has no env var or default to fall back on

                  "},{"html_id":"CliGenerator/CliGen/Parsable","path":"CliGen/Parsable.html","kind":"module","full_name":"CliGen::Parsable","name":"Parsable","abstract":false,"locations":[{"filename":"src/cligen/parsable.cr","line_number":4,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"instance_methods":[{"html_id":"parse_args(args:Array(CliGen::Arg))-instance-method","name":"parse_args","abstract":true,"args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"args_string":"(args : Array(CliGen::Arg))","args_html":"(args : Array(CliGen::Arg))","location":{"filename":"src/cligen/parsable.cr","line_number":5,"url":null},"def":{"name":"parse_args","args":[{"name":"args","external_name":"args","restriction":"Array(CliGen::Arg)"}],"visibility":"Public","body":""},"external_var":false}]},{"html_id":"CliGenerator/CliGen/ParseableInvariantError","path":"CliGen/ParseableInvariantError.html","kind":"class","full_name":"CliGen::ParseableInvariantError","name":"ParseableInvariantError","abstract":false,"superclass":{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},"ancestors":[{"html_id":"CliGenerator/CliGen/ConfigurationError","kind":"class","full_name":"CliGen::ConfigurationError","name":"ConfigurationError"},{"html_id":"CliGenerator/CliGen/Error","kind":"class","full_name":"CliGen::Error","name":"Error"},{"html_id":"CliGenerator/Exception","kind":"class","full_name":"Exception","name":"Exception"},{"html_id":"CliGenerator/Reference","kind":"class","full_name":"Reference","name":"Reference"},{"html_id":"CliGenerator/Object","kind":"class","full_name":"Object","name":"Object"}],"locations":[{"filename":"src/cligen/exceptions.cr","line_number":48,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"A Parsable type's parse_args did not mark any args as processed","summary":"

                  A Parsable type's parse_args did not mark any args as processed

                  "},{"html_id":"CliGenerator/CliGen/PreRunCommand","path":"CliGen/PreRunCommand.html","kind":"annotation","full_name":"CliGen::PreRunCommand","name":"PreRunCommand","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":212,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"}},{"html_id":"CliGenerator/CliGen/ProxyCommand","path":"CliGen/ProxyCommand.html","kind":"annotation","full_name":"CliGen::ProxyCommand","name":"ProxyCommand","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":8,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"},"doc":"(Not Implemented Yet)\nIn the future you would use this to annotate a \"proxy command\" that will allow you to defer execution\nof a \"subcommand\" to an external method not located in the class itself.","summary":"

                  (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.

                  "},{"html_id":"CliGenerator/CliGen/Regex","path":"CliGen/Regex.html","kind":"module","full_name":"CliGen::Regex","name":"Regex","abstract":false,"locations":[{"filename":"src/cligen/regex.cr","line_number":4,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"DATE","name":"DATE","value":"/(?(?[0-9]{4})-(?[0-9]{2})-(?[0-9]{2}))/"},{"id":"EPOCH","name":"EPOCH","value":"/@(?[0-9]+)/"},{"id":"FLAG_MULTIPLE_SHORT","name":"FLAG_MULTIPLE_SHORT","value":"/^-[a-zA-Z0-9]+$/"},{"id":"FLAG_REGEX","name":"FLAG_REGEX","value":"/^(-[a-zA-Z]|--[a-zA-Z-_0-9]+)$/"},{"id":"FLAG_WITH_ARG","name":"FLAG_WITH_ARG","value":"/^(?(-[a-zA-Z]|--[a-zA-Z-_]+))=\"?(?\\S+?)\"?$/"},{"id":"FLOAT","name":"FLOAT","value":"/^[-+]?[[:digit:]]+(\\.[[:digit:]]+)?$/"},{"id":"INPUT_DATE_EPOCH","name":"INPUT_DATE_EPOCH","value":"/^#{EPOCH}(\\s+#{TIMEZONE})?$/"},{"id":"INPUT_DATE_FULL","name":"INPUT_DATE_FULL","value":"/^#{DATE}\\s+#{TIME}(\\s+#{TIMEZONE})?$/","doc":"---------------------------------------------------------------------------\nDate/time matchers - fully anchored so a partial match can't slip through.\n---------------------------------------------------------------------------","summary":"

                  --------------------------------------------------------------------------- Date/time matchers - fully anchored so a partial match can't slip through.

                  "},{"id":"INPUT_DATE_SIMPLE","name":"INPUT_DATE_SIMPLE","value":"/^#{DATE}(\\s+#{TIMEZONE})?$/"},{"id":"INPUT_RELATIVE_OPERATIONS","name":"INPUT_RELATIVE_OPERATIONS","value":"/^(?(#{RELATIVE}\\s*)+)(\\s+#{TIMEZONE})?$/"},{"id":"INT","name":"INT","value":"/^[-+]?[[:digit:]]+$/"},{"id":"RELATIVE","name":"RELATIVE","value":"/[+-][0-9]+\\s+(seconds?|minutes?|hours?|days?|weeks?|months?|years?)/"},{"id":"RELATIVE_OPERATION","name":"RELATIVE_OPERATION","value":"/(?[+-])(?[0-9]+)\\s+(?seconds?|minutes?|hours?|days?|weeks?|months?|years?)/","doc":"---------------------------------------------------------------------------\nRelative Operation matcher - For use with CliGen::Timeparse::RelativeOperation\n---------------------------------------------------------------------------","summary":"

                  --------------------------------------------------------------------------- Relative Operation matcher - For use with CliGen::Timeparse::RelativeOperation ---------------------------------------------------------------------------

                  "},{"id":"TIME","name":"TIME","value":"/(?