diff --git a/.gitignore b/.gitignore index b5f6d08..36e5b28 100644 --- a/.gitignore +++ b/.gitignore @@ -11,11 +11,12 @@ !docs/** !Makefile !LICENSE -!NOTICE !spec/ !spec/** !utils/ !utils/** +!wiki/ +!wiki/** # ...but not the binary utils/flag_matrix.sh builds (later rules win). utils/flag_matrix diff --git a/CLAUDE.md b/CLAUDE.md index 4596e57..d2ddbbf 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -5,72 +5,307 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co ## Commands ```bash -# Run all specs +# Run all specs. `make` / `make spec` is the same thing with -v; +# `make spec_silent` is the bare form. crystal spec # Run a single spec file -crystal spec spec/command_spec.cr +crystal spec spec/cligen/flag_spec.cr -# Type-check without running +# Type-check without codegen — fastest way to validate macro expansion crystal build src/cligen.cr --no-codegen -# Install dependencies -shards install +# End-to-end flag resolution matrix (default/env/CLI, 16 cases) +./utils/flag_matrix.sh + +# API docs +make doc && make doc_show ``` +Setting `DEBUG=1` in the environment turns on `{% debug %}` / `{% puts %}` macro tracing +in `app/generate.cr`, `command/argument.cr`, `command/help_template.cr`, and +`command_node.cr#help`. Very noisy, but it's the only way to see generated code. + ## What This Is -`cligen` is a Crystal **shard (library)** — not a standalone application. It wraps Crystal's built-in `OptionParser` with an annotation- and macro-driven system that auto-generates CLI parsers from class definitions. Users of the shard subclass `CliGen::Command` and annotate methods; the library generates the `OptionParser` wiring at compile time via Crystal macros. +`cligen` is a Crystal **shard (library)** — not a standalone application. Consumers +subclass `CliGen::Command`, declare flags with the `argument` macro and subcommands with +the `subcommand` macro, and the library builds the whole CLI tree at compile time. There +is **no runtime registration and no `OptionParser`** — `cligen` implements its own +argument scanner. + +`lib/cligen` is a symlink back to the repo root so that `require "cligen"` resolves in +this project's own test programs. ## Architecture +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`. + ### Entry point: `src/cligen.cr` -Defines the `CliGen` module. The `macro finished` hook calls `define_root_parser`, which scans all `CliGen::Command` subclasses at compile time and registers each as a subcommand on the root `OptionParser`. `CliGen.parse` runs the root parser. +Requires everything and defines `CliGen::VERSION`, `CliGen::APPNAME` +(`File.basename(PROGRAM_NAME)`), and `override_help_template` (sets +`CliGen::HELP_OVERRIDE_TEMPLATE` to an absolute path, checked with `file_exists?`). -`ADDITIONAL_DEFAULT_FLAGS` / `add_default_flag` let users inject extra flags into every parser (root and subcommand). +### Object model -### Command definition: `src/cligen/command.cr` +The runtime tree is built from four object families. Two of them have a **non-generic +abstract base** so heterogeneous children can live in one array — this is load-bearing +and comes up constantly: -`CliGen::Command` is the base class. When subclassed, `macro inherited` installs a `macro finished` block that triggers four code-generation macros in order: - -1. `define_actions` — collects all `@[SubCommand]`-annotated class methods into `ACTIONS : Array(String)` and `@@action : String`. -2. `define_header` — builds the `HEADER` string (banner + examples) from `@[SubCommand]` and `@[CommandSelection]` annotation metadata. -3. `define_runner` (skipped if `@[CommandInfo(def_runner: false)]`) — generates a `self.run` method that dispatches on `@@action` or a selection variable via a `case` statement. -4. `define_action_setter` — generates `self.action=` with bounds-checking against `ACTIONS`. - -#### Key macros on `Command` - -- **`define_argument`** — declares a class-level variable (`@@`) and an annotated setter method (`@[CommandArgument]`). Handles `String`, `Bool`, `Int32`, `Array(String|Int32)`, and `Time`. Optional `check:` proc, `logger:` method, and `def_getter:` flag. -- **`define_selection`** — like `define_argument` but validates against a fixed list of values; annotated with `@[CommandArgument]` and participates in selection-based dispatch. - -### Parser generation: `src/cligen/command/parser.cr` - -`CliGen::Parser` is `extend`ed by `Command`. It provides `define_parser`, which generates `self.make_parser(parent_parser)`. That method: - -1. Creates a subparser `OptionParser` with the command's `HEADER` as banner. -2. Wires `@[CommandSelection]`-annotated methods as `parser.on(name, description)` that set the selection variable. -3. Wires `@[SubCommand]`-annotated methods as subcommand strings that set `@@action`. -4. Wires `@[CommandArgument]`-annotated methods as `parser.on(short, long, description)` flag handlers. -5. Calls `CliGen.define_default_flags` (adds `-h`/`--help`, error handlers). -6. Registers the whole subparser on `parent_parser` under the command's lowercase class name. - -### Annotations - -| Annotation | Applied to | Purpose | +| Generic | Base | Why the base exists | |---|---|---| -| `@[CommandInfo(description:, def_runner:)]` | Command subclass | Required; provides the description shown in root help; `def_runner: false` skips auto-generating `run` | -| `@[SubCommand(description:, examples:)]` | class method on Command | Marks a method as a dispatachable subcommand | -| `@[CommandArgument(short:, long:, description:, type:)]` | class method on Command | Generated automatically by `define_argument`/`define_selection`; drives parser wiring | -| `@[CommandSelection(selector:, description:, examples:)]` | class method on Command | Alternative to `SubCommand`; dispatches via a named selector variable instead of `@@action` | -| `@[CommandPreRun]` | class method on Command | Methods run unconditionally before dispatch inside `self.run` | -| `@[DefaultFlag]` | (reserved) | Defined but not currently used in generation | +| `Flag(T)` | `BaseFlag` | `Array(BaseFlag)` holds flags of mixed `T` | +| `CommandNode(T)` | `BaseCommandNode` | `Array(BaseCommandNode)` holds the command tree | -### Supporting files +- **`src/cligen/flag.cr`** — `Flag(T)`. Owns `@value`, `@default`, `@options`, `@validate`, + `@on_match`, `@format`. Its `process`, `coerce`, and `validate!` are giant compile-time + `{% if %}` chains over `T`. Supported `T`: `Bool`, `String`, `Int*` (signed and unsigned), + `Float*`, `Time`, `Array(Int*|Float*|String|Coercable)`, plus any type that + `extend`s `CliGen::Coercable` or `CliGen::Parsable`. Unsupported `T` is a `{% raise %}`. +- **`src/cligen/flag/base.cr`** — `BaseFlag`: `var`, `short`, `long`, `long_key`, + `env_var`, `description`, `delimiter`, `meta`. `@long_key` is `@long` split on `\s|=`, + so a declaration like `long: "--help TOPIC"` still keys off `--help`. +- **`src/cligen/flag/meta.cr`** — `FlagMeta` record (type/array/format/default/options), + stringified metadata used solely by the ECR help template. +- **`src/cligen/command_node/base.cr`** — `BaseCommandNode`: the tree walk, `find_match`, + `get(long:)`/`get(short:)`, `all_flags`, and the duplicate checks. +- **`src/cligen/command_node.cr`** — `CommandNode(T)`: `subcommands`, `help`, `check!`, + and the main `process(Array(Arg))` loop, all of which need `T`. +- **`src/cligen/app.cr`** — `App < CommandNode(Nil)`. Singleton (`@@instance`), root of + the tree, adds env-var collision detection and the error boundary. -- `src/cligen/format.cr` — date/datetime format strings used by `Time` argument parsing. -- `src/cligen/regex.cr` — regexes for validating date/datetime input strings. +### Argument scanning: `src/cligen/arg.cr` + +`CliGen::Arg` wraps `(value, index)` and tracks a one-way `processed?` flag. Calling +`#processed` twice raises `ArgReprocessedError` — a deliberate fail-fast so double-consumption +bugs surface during development rather than silently eating an argument. The parser +never does index math; it filters with `args.reject(&.processed?)`. + +`Arg` also holds the class-level predicates `flag?`, `int?`, `uint?`, `float?`, which +delegate to `CliGen::Regex`. + +### The dispatch loop: `CommandNode(T)#process` + +`find_match(token)` returns a `BaseCommandNode`, a `BaseFlag`, or a `MatchType` enum +member. `process` `case`s over that: + +- **`BaseCommandNode`** — a child command matched. Hands the unprocessed args off to the + child and `exit 0`. The cast back to a concrete `CommandNode(T)` is done by a + macro-generated `case` over `CliGen::Command.subclasses`; falling through raises + `UnknownCommandNodeError`. +- **`BaseFlag`** — if `requires_arg?` (i.e. `T != Bool`), it is handed the run of following + args that either match nothing or are in the flag's `options`; otherwise `process` with no args. +- **`MatchType::SubCommand`** — records `matched_subcommand`; a second one raises. +- **`MatchType::Help`** — raises `HelpRequestedError` carrying the rendered help. +- **`MatchType::FlagWithArg`** — `--flag=value`, re-split and dispatched. +- **`MatchType::FlagMultipleShort`** — `-abc` bundles. Only the last flag in a bundle may + take an argument; otherwise `FlagBundleError`. If the second char isn't a known flag, + raises `FlagArgumentError` (inline short args like `-n5` are not supported). +- **`MatchType::NoMatch`** — raises `HelpRequestedError` with an "unknown token" preamble. + +After the loop, if no child command took over: instantiate `T`, run its +`@[PreRunCommand]` methods, then dispatch to the matched `@[SubCommand]` method or `main`. +`App` itself (`T == Nil`) just prints help. + +### Value resolution + +`Flag(T)#value!` resolves in strict priority order — **CLI arg → env var → default → +raise `MissingRequiredFlagError`** — and then runs `validate!(v)` on whatever it got, so +env-var and default values are validated on exactly the same path as CLI input. + +Two footguns here, both previously live bugs: + +- `validate!(v : T? = nil)` must use `v = value! if v.nil?`, **not** `v ||= value!`. + With `Flag(Bool)` and `default: false`, `||=` treats `false` as absent and recurses + into `value!` forever. +- The `MissingRequiredFlagError` raise must stay **above** the `validate!(v)` call in + `value!`, or the same infinite recursion occurs when nothing resolved. + +Env vars for command arguments are **namespaced** `_` (e.g. `GREET_LEVEL`, +not `LEVEL`) unless an explicit `env_var:` is given. Global flags are un-namespaced, +derived as `long.gsub(/--/,"").gsub(/-/,"_").upcase`. Both macros reject an explicit +`env_var:` containing `-`. + +### Validation: `check!` + +Run at the top of every `process`, so misconfiguration fails on first invocation: + +- `Flag#check!` — rejects `-h` / `--help` (`ReservedFlagError`). +- `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. + +### Errors: `src/cligen/exceptions.cr` + +Everything derives from `CliGen::Error`, in three buckets plus a signal: + +- **`InternalError`** — framework invariant broken; should never reach a user + (`ArgReprocessedError`, `RegexInvariantError`, `UnknownCommandNodeError`). +- **`ConfigurationError`** — the shard *consumer* wired something wrong + (`ReservedFlagError`, `DuplicateFlagError`, `DuplicateCommandError`, + `MissingDispatchError`, `FlagNotFoundError`, `FlagMissingArgumentError`, + `ParseableInvariantError`). +- **`RuntimeError`** — bad end-user input (`MissingRequiredFlagError`, `ValidationError`, + `FlagArgumentError`, `InvalidFlagValueError`, `InvalidOptionError`, `UnknownFlagError`, + `FlagBundleError`, `TimeParseError`). +- **`HelpRequestedError`** — not an error; carries rendered help, caught and `exit 0`. + +`App.handle_command_raises` is the single error boundary: `RuntimeError` and +`ConfigurationError` `abort` with the message, `HelpRequestedError` prints and exits 0. +Each `rescue` does `Fiber.yield` first to let buffered `Log` output flush — a known-fragile +workaround, not a design. + +**Never let a non-`CliGen` exception escape.** The whole point of the typed hierarchy is +that `handle_command_raises` catches everything; a stray stdlib exception (e.g. +`Time::Location::InvalidTimezoneOffsetError`) reaches the user as a stack trace. Wrap and +re-raise at the boundary — `Flag(Time)` does exactly this, translating +`TimeParseError` into `InvalidFlagValueError`. + +### Time parsing: `src/cligen/timeparse.cr` + +`CliGen::Timeparse.parse(raw) : Time` is a single `case` over four anchored matchers from +`CliGen::Regex`, each branching on whether `match["timezone"]?` is present (offset-aware +vs. `parse_local`). Supported: `%Y-%m-%d %H:%M:%S [%z]`, `%Y-%m-%d [%z]`, `@ [%z]`, +and one-or-more relative operations (`"+1 day -2 hours"`). + +`timeparse/relative_operation.cr` — `RelativeOperation` struct. `get_operations` `scan`s +with `RELATIVE_OPERATION` and applies each in sequence. `apply` is macro-generated from +`OperationUnit.constants` using `case ... in` (exhaustive, so no `else` and the return +type collapses to `Time`). + +### Regex: `src/cligen/regex.cr` + +Two tiers, and the distinction matters: + +- **Components** (`TIMEZONE`, `TIME`, `DATE`, `EPOCH`, `RELATIVE`) are **unanchored** and + exist only to be interpolated. Interpolating a Crystal `Regex` renders it as + `(?-imsx:...)`, so an anchor here would end up buried mid-pattern in the composite and + could never match. +- **Matchers** (`INPUT_DATE_FULL`, `INPUT_DATE_SIMPLE`, `INPUT_DATE_EPOCH`, + `INPUT_RELATIVE_OPERATIONS`) are fully `^...$` anchored. Match user input only against these. + +`TIMEZONE`'s offset is deliberately bounded to `23:59` so it can't produce an offset +outside `Time::Location.fixed`'s ±24h limit. + +Also here: `FLAG_REGEX`, `FLAG_WITH_ARG`, `FLAG_MULTIPLE_SHORT`, `INT`, `UINT`, `FLOAT`. + +### Help output + +`CommandNode#help` picks a template at compile time, in priority order: the command's own +`HELP_TEMPLATE` (set by the `help_template` macro) → `CliGen::HELP_OVERRIDE_TEMPLATE` +(set by `CliGen.override_help_template`) → the bundled default. + +The default path is **hardcoded relative to the CWD**: +`ECR.render("lib/cligen/src/cligen/template/cmd_help.ecr")`. Anything that runs a cligen +binary must therefore run from a directory with a `lib/cligen` — which is why +`utils/flag_matrix.sh` `cd`s to the project root. + +The template renders per-flag detail (type, env var, format, delimiter) only when +`verbose?`, which reads the `--verbose` global flag. + +## Public macro API + +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 | +| `help_template(filepath)` | `command/help_template.cr` | Per-command ECR override | + +Module-level: + +| Macro | File | Purpose | +|---|---|---| +| `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`. + +### Extension points + +| Module | Contract | Used for | +|---|---|---| +| `CliGen::Coercable` | `self.coerce(arg : String)` | Building `T` from a single string (also used for env vars and array elements) | +| `CliGen::Parsable` | `self.parse_args(args : Array(CliGen::Arg))` | Multi-arg consumption; **must** mark at least one `Arg` as `processed` or `ParseableInvariantError` is raised | + +Both are `extend`ed, not `include`d — hence the metaclass checks `T.class < CliGen::Parsable` +in `flag.cr`. + +## Annotations + +`src/cligen/annotations.cr` declares seven; only five 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` | +| `@[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 | + +## Crystal macro gotchas + +These have each caused real bugs in this codebase — check for them before touching a macro: + +- **Macro *arguments* arrive as unresolved AST** (`Path`, `Generic`), not `TypeNode`. + `==` 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. +- **`{% 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`). +- 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. ## Spec structure -`spec/command_spec.cr` uses Crystal's macro system heavily: most `it` blocks are generated at compile time by inspecting `CommandSubclass` via `@type` introspection. The `macro finished` wrapper around the entire `describe` block is required because `make_parser` and `run` don't exist until all `macro finished` hooks have fired. +- `spec/cligen/arg_spec.cr` — plain specs for `Arg`. +- `spec/cligen/flag_spec.cr` — reopens `CliGen::Flag(T)` to expose `test_coerce` and a + `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. + +`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 +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`). + +Known gaps, all deliberate: + +- **Enum support** — deferred to v0.2.1; requires reworking five type-dispatch chains. + 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. + +## Repo conventions + +- Every `.cr` file starts with `# SPDX-License-Identifier: MIT` and + `# Copyright 2026 Tristan Ancelet`. Add these to new files. +- **`.gitignore` is a deny-all allowlist** (`*` followed by `!` exceptions). New top-level + files and directories are ignored silently and fail closed — add an explicit `!` entry + when creating one. This has bitten `DESIGN.md` and `spec/`. +- `Log` is stdlib (`::Log.for(...)` on `BaseFlag` and `BaseCommandNode`), deliberately + chosen over a dependency. Always use the block form — it's zero-cost when the level is disabled. +- Licensed MIT. diff --git a/DESIGN.md b/DESIGN.md index 7c5ce54..3f69868 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -472,6 +472,41 @@ Implementation notes: +### Converter Objects + +Currently a custom type is wired in by reopening it and extending `CliGen::Coercable` (or `CliGen::Parsable`). That works, but it requires *owning* the type — you cannot use `Flag(SomeShardType)` without monkey-patching another shard. A converter object, modelled on `JSON::Serializable`'s `converter:`, moves the conversion logic outside the type. + +```crystal +abstract class CliGen::Converter(T) + abstract def convert(raw : String) : T + abstract def to_s(value : T) : String +end + +class PointConverter < CliGen::Converter(Point) + def convert(raw : String) : Point + a, b = raw.split("x", 2) + Point.new(a.to_i, b.to_i) + end + + def to_s(value : Point) : String + "#{value.x}x#{value.y}" + end +end + +argument(origin : Point, description: "origin", converter: PointConverter) +``` + +Implementation notes: + +* Threading is the usual four hops: `converter:` on `argument`/`add_global_flag` → validated in `check_flag_vars` → `@[CliGen::Argument(converter:)]` → `generate.cr` → `Flag.new` +* The converter/flag type match is checkable at compile time — `PointConverter.ancestors` contains the *instantiated* `CliGen::Converter(Point)`, so a mismatched converter is rejected with a real message rather than failing inside array construction +* `Converter(T)#convert` has a declared return type, which `Coercable#coerce` does not — this turns a class of user error into a definition-site compile error +* Being bidirectional, a converter supplies the rendering half too, so the `T.class.has_method? :to_s` constraint in `Flag(T)#initialize` can be dropped for converted types +* A subclass instance (rather than a module) can carry state — a date format, a locale, a delimiter — and is what makes the generic parameter available for the ancestor check above +* This does **not** replace `CliGen::Parsable`, which has a different shape (`Array(Arg) -> T` plus the mark-something-processed invariant). Converter is the `String -> T` path; `Parsable` stays the multi-arg path. An explicit converter should take precedence over an implicit `Coercable` +* Open question for `Array(T)`: whether `converter:` means a `Converter(T)` applied per-element after the delimiter split, or a `Converter(Array(T))` that splits itself. Per-element composes with `delimiter:` and `format:` and is more reusable; the ancestor check can distinguish the two, so both could be supported +* Payoff beyond the feature itself: `flag.cr` has three separate compile-time chains over `T` (`process`, `coerce`, and the array-element branches). A converter short-circuits all three with a single `if conv = @converter`. It is also a route to Enum support — a macro-generated `EnumConverter(T)` calling `T.parse(raw)`, with `options` derived from `T.names`, would land enums without touching those dispatch chains + ### JSON-RPC like execution This is a LATE (post v1.0) feature. It takes the same format and instead of a CLI argument diff --git a/LICENSE b/LICENSE index d645695..d03ed56 100644 --- a/LICENSE +++ b/LICENSE @@ -1,202 +1,21 @@ +MIT License - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ +Copyright (c) 2026 Tristan Ancelet - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: - 1. Definitions. +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/Makefile b/Makefile index 614ef80..626ab68 100644 --- a/Makefile +++ b/Makefile @@ -18,5 +18,5 @@ doc: crystal doc --project-name "$(PROJECT_NAME)" --output "$(DOC_DIR)" echo "Done Generating docs" -doc_show: +show: doc cd "$(DOC_DIR)"; python -m http.server diff --git a/NOTICE b/NOTICE deleted file mode 100644 index 72b9e5e..0000000 --- a/NOTICE +++ /dev/null @@ -1,5 +0,0 @@ -cligen -Copyright 2026 Tristan Ancelet - -This product includes software developed by Tristan Ancelet -(https://git.arcanium.tech/tristan/cligen). diff --git a/docs/404.html b/docs/404.html index 46e67d4..a50a38a 100644 --- a/docs/404.html +++ b/docs/404.html @@ -62,11 +62,6 @@ diff --git a/docs/CliGen.html b/docs/CliGen.html index 812004f..46f3b70 100644 --- a/docs/CliGen.html +++ b/docs/CliGen.html @@ -62,11 +62,6 @@ @@ -211,6 +376,11 @@
+ cligen/app/generate.cr + +
+ + cligen/arg.cr
@@ -226,6 +396,21 @@
+ cligen/command/def_init.cr + +
+ + + cligen/command/define_command_initializer.cr + +
+ + + cligen/command/help_template.cr + +
+ + cligen/command/selection.cr
@@ -236,12 +421,27 @@
- cligen/command/trigger.cr + cligen/command_node.cr
- cligen/command_node.cr + cligen/command_node/base.cr + +
+ + + cligen/command_node/command_meta.cr + +
+ + + cligen/command_node/subcommand_meta.cr + +
+ + + cligen/exceptions.cr
@@ -251,7 +451,22 @@
- cligen/generate.cr + cligen/flag/base.cr + +
+ + + cligen/flag/meta.cr + +
+ + + cligen/global_flag.cr + +
+ + + cligen/global_flag/add_global_flag.cr
@@ -275,13 +490,13 @@
-
- ADDITIONAL_DEFAULT_FLAGS = [] of AdditionalDefaultFlag +
+ APPNAME = File.basename(PROGRAM_NAME)
-
- APPNAME = File.basename(PROGRAM_NAME) +
+ GLOBAL_FLAGS = [] of BaseFlag
@@ -297,18 +512,25 @@ + +

- + - Class Method Summary + Macro Summary

  • - .add_default_flag(short : String = "", long : String = "", description : String = "", &work : String -> ) + add_global_flag(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil) + +
  • + +
  • + override_help_template(filepath)
  • @@ -317,8 +539,6 @@ - -
    @@ -327,21 +547,37 @@ + +

    - + - Class Method Detail + Macro Detail

    -
    +
    - def self.add_default_flag(short : String = "", long : String = "", description : String = "", &work : String -> ) + macro add_global_flag(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil) - # + # +
    + +
    +
    + +
    +
    + +
    +
    + + macro override_help_template(filepath) + + #

    @@ -354,8 +590,6 @@ - -
    diff --git a/docs/CliGen/App.html b/docs/CliGen/App.html index 3b7600b..51e16d3 100644 --- a/docs/CliGen/App.html +++ b/docs/CliGen/App.html @@ -62,11 +62,6 @@ @@ -168,7 +333,7 @@ - + @@ -182,8 +347,8 @@ Overview -

    This serves as the default App object, that holds a copy of all flags & -handles flag processing until it hands off to the user defined commands

    +

    Root entry point. Holds a flattened copy of all flags from every command +for global-flag matching, then hands off to the matched child CommandNode.

    @@ -214,6 +379,11 @@ handles flag processing until it hands off to the user defined commands


    + + cligen/app/generate.cr + +
    + @@ -231,7 +401,7 @@ handles flag processing until it hands off to the user defined commands

    • - .new(name, flags, commands, pre_run_commands, post_run_commands) + .new(name, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand))
    • @@ -250,9 +420,14 @@ handles flag processing until it hands off to the user defined commands

      @@ -285,38 +465,154 @@ handles flag processing until it hands off to the user defined commands

      -

      Instance methods inherited from class CliGen::CommandNode

      +

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

      - - check! + + check! : Nil check!, - - check_for_duplicates!(flags : Array(BaseFlag)) - check_for_duplicates!, + + help : String + help, - - find_match(arg : String) - find_match, + + process(args : Array(CliGen::Arg)) : Nil + process, - - process(args : Array(String))
      process(args : Array(Arg)) : Nil
      - process
      + + subcommands : Array(SubCommandInfo) + subcommands, + + + + verbose? : Bool + verbose? -

      Constructor methods inherited from class CliGen::CommandNode

      +

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

      - - new(name : String, flags : Array(CliGen::BaseFlag), commands : Array(CliGen::CommandNode), pre_run_commands : Array(_), post_run_commands : Array(_)) + + new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil) + new + + + + + + + + + + + + + +

      Instance methods inherited from class CliGen::BaseCommandNode

      + + + + all_flags : Array(BaseFlag) + all_flags, + + + + check! : Nil + check!, + + + + check_for_duplicate_flags!(flags : Array(BaseFlag)) : Nil + check_for_duplicate_flags!, + + + + check_for_duplicate_subcommands! + check_for_duplicate_subcommands!, + + + + commands : Array(BaseCommandNode) + commands, + + + + description : String | Nil + description, + + + + find_match(arg : String) + find_match, + + + + flag?(arg : String) : BaseFlag | Nil + flag?, + + + + flags : Array(BaseFlag) + flags, + + + + get(*, long : String) : BaseFlag | Nil
      get(*, short : String) : BaseFlag | Nil
      + get
      , + + + + handle_flag_raises(&) : Nil + handle_flag_raises, + + + + meta : CommandMeta + meta, + + + + name : String + name, + + + + process(args : Array(String)) : Nil
      process(args : Array(CliGen::Arg)) : Nil
      + process
      , + + + + subcommand?(arg : String) : Bool + subcommand?, + + + + subcommands : Array(SubCommandInfo) + subcommands, + + + + subcommands? : Bool + subcommands? + + + + + + +

      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 @@ -367,12 +663,12 @@ handles flag processing until it hands off to the user defined commands

      Constructor Detail -
      +
      - def self.new(name, flags, commands, pre_run_commands, post_run_commands) + def self.new(name, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand)) - # + #

      @@ -393,19 +689,31 @@ handles flag processing until it hands off to the user defined commands

      Class Method Detail -
      +
      - def self.process(args : Array(String) = ARGV) + def self.handle_command_raises(&) : Nil - # + # +
      + +
      +
      + +
      +
      + +
      +
      + + def self.process(args : Array(String) = ARGV.to_a) : Nil + + #
      -

      Serves as a convinence method for the user to call to begin processing an -argument array provided by the user.

      -

      This defaults to ARGV for convinence if no arguments are passed through

      +

      Convenience entry point; defaults to ARGV


      @@ -442,6 +750,20 @@ argument array provided by the user.

      +
      +
      + + def check_for_env_duplicates(flags : Array(BaseFlag)) + + # +
      + +
      +
      + +
      +
      + diff --git a/docs/CliGen/Arg.html b/docs/CliGen/Arg.html index ce837ff..3100dcc 100644 --- a/docs/CliGen/Arg.html +++ b/docs/CliGen/Arg.html @@ -62,11 +62,6 @@ @@ -247,6 +412,38 @@ this framework.

      +

      + + + + Class Method Summary +

      + + @@ -261,6 +458,16 @@ this framework.

        +
      • + #flag?(val : String = @value) : Bool + +
      • + +
      • + #float?(val : String = @value) : Bool + +
      • +
      • #index : Int32 @@ -268,6 +475,11 @@ this framework.

      • +
      • + #int?(val : String = @value) : Bool + +
      • +
      • #processed @@ -282,6 +494,11 @@ this framework.

      • +
      • + #uint?(val : String = @value) : Bool + +
      • +
      • #value : String @@ -350,6 +567,72 @@ this framework.

        +

        + + + + Class Method Detail +

        + +
        +
        + + def self.flag?(val : String) : Bool + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def self.float?(val : String) : Bool + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def self.int?(val : String) : Bool + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def self.uint?(val : String) : Bool + + # +
        + +
        +
        + +
        +
        + + @@ -363,6 +646,34 @@ this framework.

        Instance Method Detail +
        +
        + + def flag?(val : String = @value) : Bool + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def float?(val : String = @value) : Bool + + # +
        + +
        +
        + +
        +
        +
        @@ -382,6 +693,20 @@ this framework.

        +
        +
        + + def int?(val : String = @value) : Bool + + # +
        + +
        +
        + +
        +
        +
        @@ -422,6 +747,20 @@ processed.

        +
        +
        + + def uint?(val : String = @value) : Bool + + # +
        + +
        +
        + +
        +
        +
        diff --git a/docs/CliGen/ArgReprocessedError.html b/docs/CliGen/ArgReprocessedError.html new file mode 100644 index 0000000..9fe3b6b --- /dev/null +++ b/docs/CliGen/ArgReprocessedError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::ArgReprocessedError - CliGenerator object_rework-dev + + + + + + + + + + +
        +

        + + + class + CliGen::ArgReprocessedError + +

        + + + + + + + +

        + + + + Overview +

        + +

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

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

        + + + + Defined in: +

        + + + cligen/exceptions.cr + +
        + + + + + + + + + + + + + + + +
        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        + + + + + + + + + + +
        + + + diff --git a/docs/CliGen/Argument.html b/docs/CliGen/Argument.html index 94dea09..469f3a1 100644 --- a/docs/CliGen/Argument.html +++ b/docs/CliGen/Argument.html @@ -62,11 +62,6 @@ @@ -171,6 +336,178 @@ +

        + + + + Overview +

        + +

        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 +inside of the class body.

        +

        EX:

        +
        class MyCmd < CliGen::Command
        +  argument(myvar : String = "test",
        +          short: "-m",
        +          long: "--myvar",
        +          description: "This is my test flag",
        +          options: %w[ test test2 test3 ]
        +  )
        +
        +  def main 
        +    puts "@myvar was #{@myvar}"
        +  end
        +end
        +

        However, this can also be done manually if you don't want to use the macros +you will make me sad, but otherwise it's understandable if you want do it +manually. Just understand that the macros are there for doing all of the +validations for user-friendly implementation.

        +

        + +Expected Metadata:

        +

        + +short:

        +

        Type: StringLiteral

        +

        Required: false

        +

        This represents the short form of the flag bring provided. it is optional as +not all flags have to have a short form flag.

        +

        + +long:

        +

        Type: StringLiteral

        +

        Required: true

        +

        This represents the long-form of the flag. It is required in order to generate +the Flag(T).

        +

        + +description:

        +

        Type: StringLiteral +Required: true

        +

        This is the description of your flag and is required for Flag(T) creation

        +

        + +delimiter:

        +

        Type: StringLiteral

        +

        Required: false

        +

        For Flag(Array(T)) flags this is the delimiter that will seperate any inline +args (ex: "," will split "a,b,c") provided at the commandline. If nil/not +provided, the framework will default to ',' as this is the usual choice.

        +

        + +env_var:

        +

        Type: StringLiteral

        +

        Required: false

        +

        This is the ENV VAR that can be used to specify your flag value when not +provided by the user.

        +

        + +validation:

        +

        Type: ProcLiteral

        +

        Required: false

        +

        This is a proc that can be used to provide an ad-hoc way of verifying the +value provided by a user.

        +

        EX: Int Validator

        +
        validation: ->(i : Int32) : Bool do
        +  (1..23).includes?(i)
        +end
        +

        This is used as a fallback to where the options: key doesn't cleanly +provide enough of a check for the provided values.

        +

        Note: +The input value MUST be the same as the value type as the instance +variable. Otherwise CliGen will not compile. IF requested I can +add a raw_validation: key as well to do the same but for just the +String variable provided by the user.

        +

        + +on_match:

        +

        Type: ProcLiteral

        +

        Required: false

        +

        Much like validation, this is used as a hook for doing arbitrary actions +with the parsed value from the user (very useful for global flags).

        +

        EX: Log level setter

        +
        on_match: ->(arg : String) do
        +  begin
        +    ::Log.setup(level: ::Log::Severity.parse(arg))
        +  rescue e : ArgumentError
        +    STDERR.puts "ERROR : Failed to set to #{arg} log level: (#{e.class}: #{e.message})"
        +  end
        +end
        +

        In this way you can use on_match: to hook a global flag and have it call some +arbitrary method elsewhere in the codebase to help setup the environment +before the main command is run.

        +

        + +options:

        +

        Type: ArrayLiteral(T)|Call

        +

        Required: false

        +

        CURRENTLY this is being as a way of providing a static set of values that we +are to use when doing a provided argument.

        +

        EX: Options for string var

        +
        options: %w[ a b c ]
        +

        Howver, this currently also +supports delegating the retrieval of values (in array format) to be learned +at runtime by providing a call to a global methods/class method/util +method/etc

        +

        EX: Deletgating to runtime

        +
        module MyModule
        +  def self.my_method : Array(String)
        +    if File.exists?("/etc/valid_things.txt")
        +      File.read("/etc/valid_things.txt").split(",")
        +    else
        +      %w[ a b c ]
        +    end
        +  end
        +
        +  CliGen.add_global_flag(String, 
        +                         short: "-t",
        +                         long: "--test",
        +                         description: "This does things. I promise",
        +                         options: ::MyModule.my_method,
        +                         on_match: ->(t : String) do 
        +                           puts "Matched #{t}"
        +                         end
        +  )
        +end
        +

        Doing things this way gives you some runtime flexibility, but makes you +responsible for ensuring that it doesn't crash or provide incorrect data +at runtime. As (unfortunately) the framework doesn't account for developer +error at runtime like it can at compile-time with a static array of +values.

        +

        + +format:

        +

        Type: RegexLiteral

        +

        Required: false

        +

        This metadata is used to provide (mostly for strings when you don't have a +statically known list of values that can be provided at runtime, but you +want to filter out invalid options.

        +

        EX: filtering for csv formatted info

        +
        format: /^([a-z0-9]+)(,?[a-z0-9]+)+$/
        + diff --git a/docs/CliGen/BaseCommandNode.html b/docs/CliGen/BaseCommandNode.html new file mode 100644 index 0000000..fce7cc5 --- /dev/null +++ b/docs/CliGen/BaseCommandNode.html @@ -0,0 +1,902 @@ + + + + + + + + + + + + + + + + + CliGen::BaseCommandNode - CliGenerator object_rework-dev + + + + + + + + + + +
        +

        + + + abstract class + CliGen::BaseCommandNode + +

        + + + + + + + +

        + + + + Overview +

        + +

        Non-generic base that lets the tree hold heterogeneous CommandNode(T) children. +Everything that doesn't depend on T lives here.

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

        + + + + Direct Known Subclasses +

        + + + + + + + +

        + + + + Defined in: +

        + + + cligen/command_node/base.cr + +
        + + + + + +

        + + + + Constant Summary +

        + +
        + +
        + Log = ::Log.for(CliGen::CommandNode) +
        + + +
        + + + + +

        + + + + Constructors +

        + + + + + + + + +

        + + + + Instance Method Summary +

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

        + + + + 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) + + # +
        + +
        +
        + +
        +
        + + + + + + + + +

        + + + + Instance Method Detail +

        + +
        +
        + + def all_flags : Array(BaseFlag) + + # +
        + +
        +
        + +
        +
        + +
        +
        + abstract + def check! : Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def check_for_duplicate_flags!(flags : Array(BaseFlag)) : Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def check_for_duplicate_subcommands! + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def commands : Array(BaseCommandNode) + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def description : String | Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def find_match(arg : String) + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def flag?(arg : String) : BaseFlag | Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def flags : Array(BaseFlag) + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def get(*, long : String) : BaseFlag | Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def get(*, short : String) : BaseFlag | Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def handle_flag_raises(&) : Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def meta : CommandMeta + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def name : String + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def process(args : Array(String)) : Nil + + # +
        + +
        + +

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

        +
        + +
        +
        + +
        +
        + +
        +
        + abstract + def process(args : Array(CliGen::Arg)) : Nil + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def subcommand?(arg : String) : Bool + + # +
        + +
        +
        + +
        +
        + +
        +
        + abstract + def subcommands : Array(SubCommandInfo) + + # +
        + +
        +
        + +
        +
        + +
        +
        + + def subcommands? : Bool + + # +
        + +
        +
        + +
        +
        + + + + +
        + + + diff --git a/docs/CliGen/BaseFlag.html b/docs/CliGen/BaseFlag.html index e9d3ae9..9f71ef7 100644 --- a/docs/CliGen/BaseFlag.html +++ b/docs/CliGen/BaseFlag.html @@ -62,11 +62,6 @@ @@ -212,13 +377,32 @@ - cligen/flag.cr + cligen/flag/base.cr
        + +

        + + + + Constant Summary +

        + +
        + +
        + Log = ::Log.for(CliGen::Flag) +
        + + +
        + @@ -233,7 +417,7 @@
        • - .new(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String) + .new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta)
        • @@ -255,18 +439,28 @@
            +
          • + #check! : Nil + +
          • + +
          • + #delimiter : String + +
          • +
          • #description : String
          • - #env_var : String | Nil + #env_var : String
          • - #long : String | Nil + #long : String
          • @@ -280,6 +474,11 @@ +
          • + #meta : FlagMeta + +
          • +
          • #raw_value : String | Nil @@ -349,12 +548,12 @@ Constructor Detail -
            +
            - def self.new(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String) + def self.new(var : String, short : String | Nil, long : String, env_var : String, description : String, delimiter : String, meta : FlagMeta) - # + #

            @@ -379,6 +578,34 @@ Instance Method Detail +
            +
            + abstract + def check! : Nil + + # +
            + +
            +
            + +
            +
            + +
            +
            + + def delimiter : String + + # +
            + +
            +
            + +
            +
            +
            @@ -393,12 +620,12 @@
            -
            +
            - def env_var : String | Nil + def env_var : String - # + #

            @@ -407,12 +634,12 @@
            -
            +
            - def long : String | Nil + def long : String - # + #

            @@ -449,6 +676,20 @@
            +
            +
            + + def meta : FlagMeta + + # +
            + +
            +
            + +
            +
            +
            abstract diff --git a/docs/CliGen/Coercable.html b/docs/CliGen/Coercable.html new file mode 100644 index 0000000..bec5a16 --- /dev/null +++ b/docs/CliGen/Coercable.html @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + CliGen::Coercable - CliGenerator object_rework-dev + + + + + + + + + + +
            +

            + + + module + CliGen::Coercable + +

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

            + + + + Defined in: +

            + + + cligen/coercable.cr + +
            + + + + + + + + + + + + + +

            + + + + Instance Method Summary +

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

            + + + + Instance Method Detail +

            + +
            +
            + abstract + def coerce(arg : String) + + # +
            + +
            +
            + +
            +
            + + + + +
            + + + diff --git a/docs/CliGen/Command.html b/docs/CliGen/Command.html index 6368b1c..116a1cc 100644 --- a/docs/CliGen/Command.html +++ b/docs/CliGen/Command.html @@ -62,11 +62,6 @@ @@ -208,6 +373,21 @@
            + cligen/command/def_init.cr + +
            + + + cligen/command/define_command_initializer.cr + +
            + + + cligen/command/help_template.cr + +
            + + cligen/command/selection.cr
            @@ -217,11 +397,6 @@
            - - cligen/command/trigger.cr - -
            - @@ -243,12 +418,27 @@ @@ -312,12 +497,12 @@ Macro Detail -
            +
            - macro argument(variable, short, long, description, validation = 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 = nil) - # + #

            @@ -326,12 +511,54 @@
            -
            +
            - macro selection(variable, short, long, description, options) + macro def_init - # + # +
            + +
            +
            + +
            +
            + +
            +
            + + macro define_command_initializer + + # +
            + +
            +
            + +
            +
            + +
            +
            + + macro help_template(filepath) + + # +
            + +
            +
            + +
            +
            + +
            +
            + + macro selection(variable, description, options, short = nil, long = nil, validation = nil, on_match = nil) + + #

            @@ -354,20 +581,6 @@
            -
            -
            - - macro trigger(short, long, argument = nil, &on_match) - - # -
            - -
            -
            - -
            -
            - diff --git a/docs/CliGen/CommandInfo.html b/docs/CliGen/CommandInfo.html index 7d596a8..7c53059 100644 --- a/docs/CliGen/CommandInfo.html +++ b/docs/CliGen/CommandInfo.html @@ -62,11 +62,6 @@ @@ -171,6 +336,21 @@ +

            + + + + Overview +

            + +

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

            +

            The CliGen Framework uses this to store metadata for the creation of the associated CliGen::CommandNode(T) objects.

            +

            Keys: +description: StringLiteral +This is what you use to define the short blurb of what this command is and does

            + diff --git a/docs/CliGen/CommandMeta.html b/docs/CliGen/CommandMeta.html new file mode 100644 index 0000000..ef09ad8 --- /dev/null +++ b/docs/CliGen/CommandMeta.html @@ -0,0 +1,559 @@ + + + + + + + + + + + + + + + + + CliGen::CommandMeta - CliGenerator object_rework-dev + + + + + + + + + + +
            +

            + + + struct + CliGen::CommandMeta + +

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

            + + + + Defined in: +

            + + + cligen/command_node/command_meta.cr + +
            + + + + + + + +

            + + + + Constructors +

            + + + + + + + + +

            + + + + Instance Method Summary +

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

            + + + + Constructor Detail +

            + +
            +
            + + def self.new(cls : String) + + # +
            + +
            +
            + +
            +
            + + + + + + + + +

            + + + + Instance Method Detail +

            + +
            +
            + + def clone + + # +
            + +
            +
            + +
            +
            + +
            +
            + + def cls : String + + # +
            + +
            +
            + +
            +
            + +
            +
            + + def copy_with(cls _cls = @cls) + + # +
            + +
            +
            + +
            +
            + + + + +
            + + + diff --git a/docs/CliGen/CommandNode.html b/docs/CliGen/CommandNode.html index 7e323d5..ffc6917 100644 --- a/docs/CliGen/CommandNode.html +++ b/docs/CliGen/CommandNode.html @@ -14,7 +14,7 @@ - CliGen::CommandNode - CliGenerator object_rework-dev + CliGen::CommandNode(T) - CliGenerator object_rework-dev @@ -62,11 +62,6 @@ @@ -163,12 +328,12 @@ class - CliGen::CommandNode + CliGen::CommandNode(T) - + @@ -233,7 +398,7 @@
            • - .new(name : String, flags : Array(CliGen::BaseFlag), commands : Array(CliGen::CommandNode), pre_run_commands : Array(_), post_run_commands : Array(_)) + .new(name : String, flags : Array(BaseFlag), commands : Array(BaseCommandNode), pre_run_commands : Array(RunCommand), post_run_commands : Array(RunCommand), description : String | Nil = nil)
            • @@ -256,29 +421,27 @@
              • - #check! + #check! : Nil
              • - #check_for_duplicates!(flags : Array(BaseFlag)) + #help : String
              • - #find_match(arg : String) + #process(args : Array(CliGen::Arg)) : Nil
              • - #process(args : Array(String)) - -

                This serves to just convert the arguments into a usable Array(Arg) format and pass it to the ACTUAL CommandNode#process method

                + #subcommands : Array(SubCommandInfo)
              • - #process(args : Array(Arg)) : Nil + #verbose? : Bool
              • @@ -290,6 +453,117 @@ +

                Instance methods inherited from class CliGen::BaseCommandNode

                + + + + all_flags : Array(BaseFlag) + all_flags, + + + + check! : Nil + check!, + + + + check_for_duplicate_flags!(flags : Array(BaseFlag)) : Nil + check_for_duplicate_flags!, + + + + check_for_duplicate_subcommands! + check_for_duplicate_subcommands!, + + + + commands : Array(BaseCommandNode) + commands, + + + + description : String | Nil + description, + + + + find_match(arg : String) + find_match, + + + + flag?(arg : String) : BaseFlag | Nil + flag?, + + + + flags : Array(BaseFlag) + flags, + + + + get(*, long : String) : BaseFlag | Nil
                get(*, short : String) : BaseFlag | Nil
                + get
                , + + + + handle_flag_raises(&) : Nil + handle_flag_raises, + + + + meta : CommandMeta + meta, + + + + name : String + name, + + + + process(args : Array(String)) : Nil
                process(args : Array(CliGen::Arg)) : Nil
                + process
                , + + + + subcommand?(arg : String) : Bool + subcommand?, + + + + subcommands : Array(SubCommandInfo) + subcommands, + + + + subcommands? : Bool + subcommands? + + + + + + +

                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 + + + + + + + + + + + + + @@ -326,12 +600,12 @@ Constructor Detail -
                +
                - def self.new(name : String, flags : Array(CliGen::BaseFlag), commands : Array(CliGen::CommandNode), pre_run_commands : Array(_), post_run_commands : Array(_)) + 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) - # + #

                @@ -356,12 +630,12 @@ Instance Method Detail -
                +
                - def check! + def check! : Nil - # + #

                @@ -370,12 +644,12 @@
                -
                +
                - def check_for_duplicates!(flags : Array(BaseFlag)) + def help : String - # + #

                @@ -384,12 +658,12 @@
                -
                +
                - def find_match(arg : String) + def process(args : Array(CliGen::Arg)) : Nil - # + #

                @@ -398,32 +672,26 @@
                -
                +
                - def process(args : Array(String)) + def subcommands : Array(SubCommandInfo) - # + #
                -
                - -

                This serves to just convert the arguments into a usable Array(Arg) format -and pass it to the ACTUAL CommandNode#process method

                -
                -
                -
                +
                - def process(args : Array(Arg)) : Nil + def verbose? : Bool - # + #

                diff --git a/docs/CliGen/ConfigurationError.html b/docs/CliGen/ConfigurationError.html new file mode 100644 index 0000000..17abf44 --- /dev/null +++ b/docs/CliGen/ConfigurationError.html @@ -0,0 +1,478 @@ + + + + + + + + + + + + + + + + + CliGen::ConfigurationError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::ConfigurationError + +

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

                + + + + Direct Known Subclasses +

                + + + + + + + +

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/DuplicateCommandError.html b/docs/CliGen/DuplicateCommandError.html new file mode 100644 index 0000000..04d27a6 --- /dev/null +++ b/docs/CliGen/DuplicateCommandError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::DuplicateCommandError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::DuplicateCommandError + +

                + + + + + + + +

                + + + + Overview +

                + +

                Duplicate command names detected during check!

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/DuplicateFlagError.html b/docs/CliGen/DuplicateFlagError.html new file mode 100644 index 0000000..be18b69 --- /dev/null +++ b/docs/CliGen/DuplicateFlagError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::DuplicateFlagError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::DuplicateFlagError + +

                + + + + + + + +

                + + + + Overview +

                + +

                Duplicate short or long flags detected during check!

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/Error.html b/docs/CliGen/Error.html new file mode 100644 index 0000000..598ffcb --- /dev/null +++ b/docs/CliGen/Error.html @@ -0,0 +1,470 @@ + + + + + + + + + + + + + + + + + CliGen::Error - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::Error + +

                + + + + + + + +

                + + + + Overview +

                + +

                Base for all CliGen exceptions

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

                + + + + Direct Known Subclasses +

                + + + + + + + +

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/Flag.html b/docs/CliGen/Flag.html index 7e7e6e6..e71f59e 100644 --- a/docs/CliGen/Flag.html +++ b/docs/CliGen/Flag.html @@ -62,11 +62,6 @@ @@ -219,7 +384,7 @@
                +
                +
                + + def help? + + # +
                + +
                + +

                Returns true if this enum value equals Help

                +
                + +
                +
                + +
                +
                +
                @@ -436,6 +644,25 @@
                +
                +
                + + def sub_command? + + # +
                + +
                + +

                Returns true if this enum value equals SubCommand

                +
                + +
                +
                + +
                +
                + diff --git a/docs/CliGen/MissingDispatchError.html b/docs/CliGen/MissingDispatchError.html new file mode 100644 index 0000000..f9f1b70 --- /dev/null +++ b/docs/CliGen/MissingDispatchError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::MissingDispatchError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::MissingDispatchError + +

                + + + + + + + +

                + + + + Overview +

                + +

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

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/MissingRequiredFlagError.html b/docs/CliGen/MissingRequiredFlagError.html new file mode 100644 index 0000000..072a185 --- /dev/null +++ b/docs/CliGen/MissingRequiredFlagError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::MissingRequiredFlagError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::MissingRequiredFlagError + +

                + + + + + + + +

                + + + + Overview +

                + +

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

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/Parsable.html b/docs/CliGen/Parsable.html new file mode 100644 index 0000000..ca89daa --- /dev/null +++ b/docs/CliGen/Parsable.html @@ -0,0 +1,439 @@ + + + + + + + + + + + + + + + + + CliGen::Parsable - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + module + CliGen::Parsable + +

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

                + + + + Defined in: +

                + + + cligen/parsable.cr + +
                + + + + + + + + + + + + + +

                + + + + Instance Method Summary +

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

                + + + + Instance Method Detail +

                + +
                +
                + abstract + def parse_args(args : Array(CliGen::Arg)) + + # +
                + +
                +
                + +
                +
                + + + + +
                + + + diff --git a/docs/CliGen/ParseableInvariantError.html b/docs/CliGen/ParseableInvariantError.html new file mode 100644 index 0000000..b52b82d --- /dev/null +++ b/docs/CliGen/ParseableInvariantError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::ParseableInvariantError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::ParseableInvariantError + +

                + + + + + + + +

                + + + + Overview +

                + +

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

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/PreRunCommand.html b/docs/CliGen/PreRunCommand.html new file mode 100644 index 0000000..811d3e2 --- /dev/null +++ b/docs/CliGen/PreRunCommand.html @@ -0,0 +1,398 @@ + + + + + + + + + + + + + + + + + CliGen::PreRunCommand - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + annotation + CliGen::PreRunCommand + +

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

                + + + + Defined in: +

                + + + cligen/annotations.cr + +
                + + + + + + + + + + + + + + + +
                + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/ProxyCommand.html b/docs/CliGen/ProxyCommand.html index bab043a..84cff51 100644 --- a/docs/CliGen/ProxyCommand.html +++ b/docs/CliGen/ProxyCommand.html @@ -62,11 +62,6 @@ @@ -171,6 +336,19 @@ +

                + + + + Overview +

                + +

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

                + diff --git a/docs/CliGen/Regex.html b/docs/CliGen/Regex.html index 59b2ff4..2c465d9 100644 --- a/docs/CliGen/Regex.html +++ b/docs/CliGen/Regex.html @@ -62,11 +62,6 @@ @@ -215,13 +380,23 @@
                +
                + DATE = /(?<date>(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2}))/ +
                + + +
                + EPOCH = /@(?<epoch>[0-9]+)/ +
                + +
                - FLAG_MULTIPLE_SHORT = /^-[a-zA-Z]+$/ + FLAG_MULTIPLE_SHORT = /^-[a-zA-Z0-9]+$/
                - FLAG_REGEX = /^(-[a-zA-Z]|--[a-zA-Z-_]+)$/ + FLAG_REGEX = /^(-[a-zA-Z]|--[a-zA-Z-_0-9]+)$/
                @@ -230,18 +405,96 @@ -
                - INPUT_DATE_REGEX = /^[0-9]{4}-[0-9]{2}-[0-9]{2}$/ +
                + FLOAT = /^[-+]?[[:digit:]]+(\.[[:digit:]]+)?$/
                -
                - INPUT_DATETIME_REGEX = /^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/ +
                + INPUT_DATE_EPOCH = /^#{EPOCH}(\s+#{TIMEZONE})?$/
                -
                - SHORT_WITH_INLINE_ARG = /^-[a-zA-Z][a-zA-Z0-9]+$/ +
                + INPUT_DATE_FULL = /^#{DATE}\s+#{TIME}(\s+#{TIMEZONE})?$/ +
                + +
                +
                +

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

                +
                + + +
                + INPUT_DATE_SIMPLE = /^#{DATE}(\s+#{TIMEZONE})?$/ +
                + + +
                + INPUT_RELATIVE_OPERATIONS = /^(?<operations>(#{RELATIVE}\s*)+)(\s+#{TIMEZONE})?$/ +
                + + +
                + INT = /^[-+]?[[:digit:]]+$/ +
                + + +
                + RELATIVE = /[+-][0-9]+\s+(seconds?|minutes?|hours?|days?|weeks?|months?|years?)/ +
                + + +
                + RELATIVE_OPERATION = /(?<sign>[+-])(?<quantity>[0-9]+)\s+(?<unit>seconds?|minutes?|hours?|days?|weeks?|months?|years?)/ +
                + +
                +
                +

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

                +
                + + +
                + TIME = /(?<time>(?<hour>[0-9]{2}):(?<minute>[0-9]{2}):(?<second>[0-9]{2}))/ +
                + + +
                + TIMEZONE = /(?<timezone>(?<offset_sign>[-+])(?<offset_hour>[01][0-9]|2[0-3])(?<offset_minute>[0-5][0-9]))/ +
                + +
                +
                +

                Date/time components.

                +

                These are building blocks ONLY — they are interpolated into the anchored +matchers below and must stay unanchored. Interpolating a Regex renders it +as (?-imsx:...), so an anchor here would end up buried mid-pattern in the +composites (^(?-imsx:^...$)\s+...$) and could never match.

                +

                + +Never match user input against these directly — use the INPUT_DATE_* +matchers, which are anchored.

                +

                Hour is bounded 00-23 and minute 00-59 so the largest representable offset +is 23:59 (86340s), which stays inside Time::Location.fixed's +/-24h limit. +Without these bounds an offset like -9999 passes the match and then raises +Time::Location::InvalidTimezoneOffsetError - a non-CliGen exception that +escapes App#handle_command_raises and reaches the user as a stack trace.

                +
                + + +
                + UINT = /^[[:digit:]]+$/
                diff --git a/docs/CliGen/RegexInvariantError.html b/docs/CliGen/RegexInvariantError.html new file mode 100644 index 0000000..77b6061 --- /dev/null +++ b/docs/CliGen/RegexInvariantError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::RegexInvariantError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::RegexInvariantError + +

                + + + + + + + +

                + + + + Overview +

                + +

                A token matched FLAG_WITH_ARG in find_match but the regex failed on re-match

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/ReservedFlagError.html b/docs/CliGen/ReservedFlagError.html new file mode 100644 index 0000000..0ec2436 --- /dev/null +++ b/docs/CliGen/ReservedFlagError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::ReservedFlagError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::ReservedFlagError + +

                + + + + + + + +

                + + + + Overview +

                + +

                -h or --help was used as a flag short/long (reserved for internal help)

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/RunCommand.html b/docs/CliGen/RunCommand.html new file mode 100644 index 0000000..b24ffb0 --- /dev/null +++ b/docs/CliGen/RunCommand.html @@ -0,0 +1,408 @@ + + + + + + + + + + + + + + + + + CliGen::RunCommand - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + alias + CliGen::RunCommand + +

                + + + + + + + +

                + + + + Alias Definition +

                + -> Nil + + + + + + + + + + + + + + +

                + + + + Defined in: +

                + + + cligen/command_node/base.cr + +
                + + + + + + + + + + + + + + + +
                + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/RuntimeError.html b/docs/CliGen/RuntimeError.html new file mode 100644 index 0000000..859967b --- /dev/null +++ b/docs/CliGen/RuntimeError.html @@ -0,0 +1,480 @@ + + + + + + + + + + + + + + + + + CliGen::RuntimeError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::RuntimeError + +

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

                + + + + Direct Known Subclasses +

                + + + + + + + +

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/Selection.html b/docs/CliGen/Selection.html index e10af63..b9a59e1 100644 --- a/docs/CliGen/Selection.html +++ b/docs/CliGen/Selection.html @@ -62,11 +62,6 @@ diff --git a/docs/CliGen/SubCommand.html b/docs/CliGen/SubCommand.html index c39fbfb..988ab21 100644 --- a/docs/CliGen/SubCommand.html +++ b/docs/CliGen/SubCommand.html @@ -62,11 +62,6 @@ diff --git a/docs/CliGen/SubCommandInfo.html b/docs/CliGen/SubCommandInfo.html new file mode 100644 index 0000000..552ebab --- /dev/null +++ b/docs/CliGen/SubCommandInfo.html @@ -0,0 +1,597 @@ + + + + + + + + + + + + + + + + + CliGen::SubCommandInfo - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + struct + CliGen::SubCommandInfo + +

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

                + + + + Defined in: +

                + + + cligen/command_node/subcommand_meta.cr + +
                + + + + + + + +

                + + + + Constructors +

                + + + + + + + + +

                + + + + Instance Method Summary +

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

                + + + + Constructor Detail +

                + +
                +
                + + def self.new(name : String, description : String, examples : Array(String) | Nil) + + # +
                + +
                +
                + +
                +
                + + + + + + + + +

                + + + + Instance Method Detail +

                + +
                +
                + + def clone + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def copy_with(name _name = @name, description _description = @description, examples _examples = @examples) + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def description : String + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def examples : Array(String) | Nil + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def name : String + + # +
                + +
                +
                + +
                +
                + + + + +
                + + + diff --git a/docs/CliGen/TimeParseError.html b/docs/CliGen/TimeParseError.html new file mode 100644 index 0000000..5dfaee9 --- /dev/null +++ b/docs/CliGen/TimeParseError.html @@ -0,0 +1,481 @@ + + + + + + + + + + + + + + + + + CliGen::TimeParseError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::TimeParseError + +

                + + + + + + + +

                + + + + Overview +

                + +
                +

                + +CliGen::Timeparse Errors

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/Timeparse.html b/docs/CliGen/Timeparse.html new file mode 100644 index 0000000..56049c0 --- /dev/null +++ b/docs/CliGen/Timeparse.html @@ -0,0 +1,449 @@ + + + + + + + + + + + + + + + + + CliGen::Timeparse - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + module + CliGen::Timeparse + +

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

                + + + + Defined in: +

                + + + cligen/timeparse.cr + +
                + + + cligen/timeparse/operation_unit.cr + +
                + + + cligen/timeparse/relative_operation.cr + +
                + + + + + + + + + +

                + + + + Class Method Summary +

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

                + + + + Class Method Detail +

                + +
                +
                + + def self.parse(raw : String) : Time + + # +
                + +
                +
                + +
                +
                + + + + + + + + +
                + + + diff --git a/docs/CliGen/Timeparse/OperationUnit.html b/docs/CliGen/Timeparse/OperationUnit.html new file mode 100644 index 0000000..52e052f --- /dev/null +++ b/docs/CliGen/Timeparse/OperationUnit.html @@ -0,0 +1,703 @@ + + + + + + + + + + + + + + + + + CliGen::Timeparse::OperationUnit - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + enum + CliGen::Timeparse::OperationUnit + +

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

                + + + + Defined in: +

                + + + cligen/timeparse/operation_unit.cr + +
                + + + + + +

                + + + + Enum Members +

                + +
                + +
                + YEAR = 0 +
                + + +
                + MONTH = 1 +
                + + +
                + WEEK = 2 +
                + + +
                + DAY = 3 +
                + + +
                + HOUR = 4 +
                + + +
                + MINUTE = 5 +
                + + +
                + SECOND = 6 +
                + + +
                + + + + + + + + + + +

                + + + + Instance Method Summary +

                +
                  + +
                • + #day? + +

                  Returns true if this enum value equals DAY

                  + +
                • + +
                • + #hour? + +

                  Returns true if this enum value equals HOUR

                  + +
                • + +
                • + #minute? + +

                  Returns true if this enum value equals MINUTE

                  + +
                • + +
                • + #month? + +

                  Returns true if this enum value equals MONTH

                  + +
                • + +
                • + #second? + +

                  Returns true if this enum value equals SECOND

                  + +
                • + +
                • + #week? + +

                  Returns true if this enum value equals WEEK

                  + +
                • + +
                • + #year? + +

                  Returns true if this enum value equals YEAR

                  + +
                • + +
                + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + +

                + + + + Instance Method Detail +

                + +
                +
                + + def day? + + # +
                + +
                + +

                Returns true if this enum value equals DAY

                +
                + +
                +
                + +
                +
                + +
                +
                + + def hour? + + # +
                + +
                + +

                Returns true if this enum value equals HOUR

                +
                + +
                +
                + +
                +
                + +
                +
                + + def minute? + + # +
                + +
                + +

                Returns true if this enum value equals MINUTE

                +
                + +
                +
                + +
                +
                + +
                +
                + + def month? + + # +
                + +
                + +

                Returns true if this enum value equals MONTH

                +
                + +
                +
                + +
                +
                + +
                +
                + + def second? + + # +
                + +
                + +

                Returns true if this enum value equals SECOND

                +
                + +
                +
                + +
                +
                + +
                +
                + + def week? + + # +
                + +
                + +

                Returns true if this enum value equals WEEK

                +
                + +
                +
                + +
                +
                + +
                +
                + + def year? + + # +
                + +
                + +

                Returns true if this enum value equals YEAR

                +
                + +
                +
                + +
                +
                + + + + +
                + + + diff --git a/docs/CliGen/Timeparse/RelativeOperation.html b/docs/CliGen/Timeparse/RelativeOperation.html new file mode 100644 index 0000000..1d6cbfb --- /dev/null +++ b/docs/CliGen/Timeparse/RelativeOperation.html @@ -0,0 +1,627 @@ + + + + + + + + + + + + + + + + + CliGen::Timeparse::RelativeOperation - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + struct + CliGen::Timeparse::RelativeOperation + +

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

                + + + + Defined in: +

                + + + cligen/timeparse/relative_operation.cr + +
                + + + + + + + +

                + + + + Constructors +

                + + + + +

                + + + + Class Method Summary +

                + + + + + + +

                + + + + Instance Method Summary +

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

                + + + + Constructor Detail +

                + +
                +
                + + def self.new(sign : Int32, quantity : Int32, unit : CliGen::Timeparse::OperationUnit) + + # +
                + +
                +
                + +
                +
                + + + + +

                + + + + Class Method Detail +

                + +
                +
                + + def self.get_operations(raw : String) : Array(RelativeOperation) + + # +
                + +
                + +

                Just handles retrieving the operations from a bare string and returning +an array of them for use in applying them in a row

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

                + + + + Instance Method Detail +

                + +
                +
                + + def apply(time : Time) : Time + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def quantity : Int32 + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def sign : Int32 + + # +
                + +
                +
                + +
                +
                + +
                +
                + + def unit : CliGen::Timeparse::OperationUnit + + # +
                + +
                +
                + +
                +
                + + + + +
                + + + diff --git a/docs/CliGen/Trigger.html b/docs/CliGen/Trigger.html index 9ff7dd2..c356657 100644 --- a/docs/CliGen/Trigger.html +++ b/docs/CliGen/Trigger.html @@ -62,11 +62,6 @@ diff --git a/docs/CliGen/UnknownCommandNodeError.html b/docs/CliGen/UnknownCommandNodeError.html new file mode 100644 index 0000000..c583027 --- /dev/null +++ b/docs/CliGen/UnknownCommandNodeError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::UnknownCommandNodeError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::UnknownCommandNodeError + +

                + + + + + + + +

                + + + + Overview +

                + +

                A BaseCommandNode was matched but couldn't be cast to any known CommandNode(T)

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/UnknownFlagError.html b/docs/CliGen/UnknownFlagError.html new file mode 100644 index 0000000..b01e41c --- /dev/null +++ b/docs/CliGen/UnknownFlagError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::UnknownFlagError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::UnknownFlagError + +

                + + + + + + + +

                + + + + Overview +

                + +

                An unrecognised flag token was encountered during parsing

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/CliGen/ValidationError.html b/docs/CliGen/ValidationError.html new file mode 100644 index 0000000..864725e --- /dev/null +++ b/docs/CliGen/ValidationError.html @@ -0,0 +1,476 @@ + + + + + + + + + + + + + + + + + CliGen::ValidationError - CliGenerator object_rework-dev + + + + + + + + + + +
                +

                + + + class + CliGen::ValidationError + +

                + + + + + + + +

                + + + + Overview +

                + +

                A setter's validation proc rejected the provided value

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

                + + + + Defined in: +

                + + + cligen/exceptions.cr + +
                + + + + + + + + + + + + + + + +
                + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
                + + + + + + + + + + +
                + + + diff --git a/docs/index.html b/docs/index.html index 1293fb3..3f33642 100644 --- a/docs/index.html +++ b/docs/index.html @@ -62,11 +62,6 @@ @@ -159,11 +324,17 @@
                -

                -CliGenerator

                -

                This is a crystal project to manage setting up OptionParser objects based around "Command" objects and arguments you define inside them.

                +cligen

                +

                A Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.

                +

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

                Usage

                -
                require "cligen"
                +
                require "cligen"
                +
                +@[CliGen::CommandInfo(description: "Greet someone")]
                +class Greet < CliGen::Command
                +  @[CliGen::Argument(short: "-n", long: "--name VALUE", description: "Name to greet")]
                +  @name : String = "world"
                +  
                +  argument(otherval : String = "abc",
                +    long: "--other",
                +    short: "-o",
                +    options: %w[ abc def ghi ],
                +    description: "This provides a way of setting the second string taht is printed"
                +  )
                +  
                +  argument(myvars : Array(String) = [ "a" ],
                +    short: "-m",
                +    options: %w[ a b c ],
                +    description: "Provide multiple things to be printed out in the main function"
                +  )
                +
                +  def main
                +    puts "1) Hello, #{@name}!"
                +    puts "2) #{@otherval}"
                +    @myvars.each_with_index do |var, index|
                +      puts "%d) %s" % [ 3 + index, var ]
                +    end
                +  end
                +end
                +
                +CliGen::App.process
                +
                $ myapp greet --name Alice -m a a -m a,a,b
                +1) Hello, Alice!
                +2) abc
                +3) a 
                +4) a 
                +5) a 
                +6) a 
                +7) b
                +

                Full API documentation and design notes are in design.adoc.

                +

                + +Architecture

                +

                As a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.

                +

                Subclassing to CliGen::Command injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library src/cligen/app/generate.cr to generate a object graph of your commands and all annotated "arguments/flags" and stores them in a tree from the App object itself.

                +

                This allows the project to "learn" your project & generate a command tree from the defined data.

                +

                The MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with CliGen::Coercable && CliGen::Parsable modules and define the self.parse_args(args : Array(CliGen::Arg) and self.coerce(arg : String) class methods.

                +

                EX:

                +
                module MyModule
                +  class MyData
                +    extend CliGen::Parsable
                +    extend CliGen::Coercable
                +    
                +    @value : Int32
                +    
                +    def initialize(value : String)
                +      @value = value.to_i32
                +    end
                +    
                +    def self.parse_args(args : Array(CliGen::Arg))
                +      arg = args.first
                +      # Mark the argument as processed
                +      arg.processed
                +      new(arg.value)
                +      
                +    end
                +    
                +    def self.coerce(arg : String)
                +      new(arg)
                +    end
                +  end
                +end
                +

                + +Coercable Method:

                +
                  def self.coerce(arg : String)
                +    new(arg)
                +  end
                +

                The coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type.

                +

                This should only be used in the case you need a simple datatype that can be learned from a single string.

                +

                + +Parsable Method:

                +
                  def self.parse_args(args : Array(CliGen::Arg))
                +    arg = args.first
                +    # Mark the argument as processed (required)
                +    arg.processed
                +    new(arg.value)
                +  end
                +

                This method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.

                +

                This gives the framework a way to allow you to extend the parser in your own custom way to allow for a "custom" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.

                +

                + +Development

                +
                # Type-check without running
                +crystal build src/cligen.cr --no-codegen
                +
                +# Run specs
                +crystal spec
                +

                + +AI Assistance Disclosure

                +

                This project uses Claude Code as a development aid — specifically for catching bugs, spotting typos, reviewing implementations, and talking through design decisions. All architecture decisions, code, and design are written by the author. Claude is used the way one might use a second pair of eyes on a diff, not as a code generator.

                +

                CLAUDE.md at the repo root documents the project structure for Claude's context. .claude/ holds project-level Claude Code settings.

                "", long : String = "", description : String = "", &work : String -> )","location":{"filename":"src/cligen.cr","line_number":23,"url":null},"def":{"name":"add_default_flag","args":[{"name":"short","default_value":"\"\"","external_name":"short","restriction":"String"},{"name":"long","default_value":"\"\"","external_name":"long","restriction":"String"},{"name":"description","default_value":"\"\"","external_name":"description","restriction":"String"}],"yields":1,"block_arity":1,"block_arg":{"name":"work","external_name":"work","restriction":"(String ->)"},"visibility":"Public","body":"if description.empty?\n raise(\"ERROR : add_default_flag : You must provide a description\")\nend\nADDITIONAL_DEFAULT_FLAGS << AdditionalDefaultFlag.new(short: short, long: long, description: description, work: work)\n"},"external_var":false}],"types":[{"html_id":"CliGenerator/CliGen/AdditionalDefaultFlag","path":"CliGen/AdditionalDefaultFlag.html","kind":"struct","full_name":"CliGen::AdditionalDefaultFlag","name":"AdditionalDefaultFlag","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.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"},"constructors":[{"html_id":"new(short:String,long:String,description:String,work:String->)-class-method","name":"new","abstract":false,"args":[{"name":"short","external_name":"short","restriction":"String"},{"name":"long","external_name":"long","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"work","external_name":"work","restriction":"(String ->)"}],"args_string":"(short : String, long : String, description : String, work : String -> )","args_html":"(short : String, long : String, description : String, work : String -> )","location":{"filename":"src/cligen.cr","line_number":15,"url":null},"def":{"name":"new","args":[{"name":"short","external_name":"short","restriction":"String"},{"name":"long","external_name":"long","restriction":"String"},{"name":"description","external_name":"description","restriction":"String"},{"name":"work","external_name":"work","restriction":"(String ->)"}],"visibility":"Public","body":"_ = allocate\n_.initialize(short, long, description, work)\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.cr","line_number":15,"url":null},"def":{"name":"clone","visibility":"Public","body":"self.class.new(@short.clone, @long.clone, @description.clone, @work.clone)"},"external_var":false},{"html_id":"copy_with(short_short=@short,long_long=@long,description_description=@description,work_work=@work)-instance-method","name":"copy_with","abstract":false,"args":[{"name":"_short","default_value":"@short","external_name":"short","restriction":""},{"name":"_long","default_value":"@long","external_name":"long","restriction":""},{"name":"_description","default_value":"@description","external_name":"description","restriction":""},{"name":"_work","default_value":"@work","external_name":"work","restriction":""}],"args_string":"(short _short = @short, long _long = @long, description _description = @description, work _work = @work)","args_html":"(short _short = @short, long _long = @long, description _description = @description, work _work = @work)","location":{"filename":"src/cligen.cr","line_number":15,"url":null},"def":{"name":"copy_with","args":[{"name":"_short","default_value":"@short","external_name":"short","restriction":""},{"name":"_long","default_value":"@long","external_name":"long","restriction":""},{"name":"_description","default_value":"@description","external_name":"description","restriction":""},{"name":"_work","default_value":"@work","external_name":"work","restriction":""}],"visibility":"Public","body":"self.class.new(_short, _long, _description, _work)"},"external_var":false},{"html_id":"description:String-instance-method","name":"description","abstract":false,"def":{"name":"description","return_type":"String","visibility":"Public","body":"@description"},"external_var":false},{"html_id":"long:String-instance-method","name":"long","abstract":false,"def":{"name":"long","return_type":"String","visibility":"Public","body":"@long"},"external_var":false},{"html_id":"short:String-instance-method","name":"short","abstract":false,"def":{"name":"short","return_type":"String","visibility":"Public","body":"@short"},"external_var":false},{"html_id":"work:String->-instance-method","name":"work","abstract":false,"def":{"name":"work","return_type":"(String ->)","visibility":"Public","body":"@work"},"external_var":false}]},{"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/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":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":"This serves as the default App object, that holds a copy of all flags & \nhandles flag processing until it hands off to the user defined commands","summary":"

                This serves as the default App object, that holds a copy of all flags & handles flag processing until it hands off to the user defined commands

                ","class_methods":[{"html_id":"process(args:Array(String)=ARGV)-class-method","name":"process","doc":"Serves as a convinence method for the user to call to begin processing an\nargument array provided by the user.\n\nThis defaults to ARGV for convinence if no arguments are passed through","summary":"

                Serves as a convinence method for the user to call to begin processing an argument array provided by the user.

                ","abstract":false,"args":[{"name":"args","default_value":"ARGV","external_name":"args","restriction":"Array(String)"}],"args_string":"(args : Array(String) = ARGV)","args_html":"(args : Array(String) = ARGV)","location":{"filename":"src/cligen/app.cr","line_number":28,"url":null},"def":{"name":"process","args":[{"name":"args","default_value":"ARGV","external_name":"args","restriction":"Array(String)"}],"visibility":"Public","body":"if @@instance.nil?\n raise(\"ERROR : CliGen::App.process was called before an instance of App was defined\")\nend\n@@instance.process(args)\n"},"external_var":false}],"constructors":[{"html_id":"new(name,flags,commands,pre_run_commands,post_run_commands)-class-method","name":"new","abstract":false,"args":[{"name":"name","external_name":"name","restriction":""},{"name":"flags","external_name":"flags","restriction":""},{"name":"commands","external_name":"commands","restriction":""},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":""},{"name":"post_run_commands","external_name":"post_run_commands","restriction":""}],"args_string":"(name, flags, commands, pre_run_commands, post_run_commands)","args_html":"(name, flags, commands, pre_run_commands, post_run_commands)","location":{"filename":"src/cligen/app.cr","line_number":12,"url":null},"def":{"name":"new","args":[{"name":"name","external_name":"name","restriction":""},{"name":"flags","external_name":"flags","restriction":""},{"name":"commands","external_name":"commands","restriction":""},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":""},{"name":"post_run_commands","external_name":"post_run_commands","restriction":""}],"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":16,"url":null},"def":{"name":"check!","visibility":"Public","body":"CliGen::GLOBAL_FLAGS.each(&.check!)\n\n\ncheck_for_duplicates!([CliGen::GLOBAL_FLAGS, @flags].flatten)\n@commands.each(&.check!)\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":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":"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.

                ","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":24,"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":"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":20,"url":null},"def":{"name":"index","return_type":"Int32","visibility":"Public","body":"@index"},"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":31,"url":null},"def":{"name":"processed","visibility":"Public","body":"if @processed\n raise(\"ERROR : 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":22,"url":null},"def":{"name":"processed?","return_type":"Bool","visibility":"Public","body":"@processed"},"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":18,"url":null},"def":{"name":"value","return_type":"String","visibility":"Public","body":"@value"},"external_var":false}]},{"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":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"}},{"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.cr","line_number":4,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"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|Nil,env_var:String|Nil,description:String)-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 | ::Nil"},{"name":"env_var","external_name":"env_var","restriction":"String | ::Nil"},{"name":"description","external_name":"description","restriction":"String"}],"args_string":"(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String)","args_html":"(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String)","location":{"filename":"src/cligen/flag.cr","line_number":12,"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 | ::Nil"},{"name":"env_var","external_name":"env_var","restriction":"String | ::Nil"},{"name":"description","external_name":"description","restriction":"String"}],"visibility":"Public","body":"_ = allocate\n_.initialize(var, short, long, env_var, description)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"description:String-instance-method","name":"description","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":10,"url":null},"def":{"name":"description","return_type":"String","visibility":"Public","body":"@description"},"external_var":false},{"html_id":"env_var:String|Nil-instance-method","name":"env_var","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":9,"url":null},"def":{"name":"env_var","return_type":"String | ::Nil","visibility":"Public","body":"@env_var"},"external_var":false},{"html_id":"long:String|Nil-instance-method","name":"long","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":7,"url":null},"def":{"name":"long","return_type":"String | ::Nil","visibility":"Public","body":"@long"},"external_var":false},{"html_id":"long_key:String-instance-method","name":"long_key","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":8,"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.cr","line_number":22,"url":null},"def":{"name":"matches?","args":[{"name":"token","external_name":"token","restriction":"String"}],"return_type":"Bool","visibility":"Public","body":"(token == @short) || (!@long_key.empty? && (token == @long_key))"},"external_var":false},{"html_id":"raw_value:String|Nil-instance-method","name":"raw_value","abstract":true,"location":{"filename":"src/cligen/flag.cr","line_number":28,"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.cr","line_number":26,"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.cr","line_number":6,"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.cr","line_number":27,"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.cr","line_number":5,"url":null},"def":{"name":"var","return_type":"String","visibility":"Public","body":"@var"},"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":11,"url":null},{"filename":"src/cligen/command/argument.cr","line_number":2,"url":null},{"filename":"src/cligen/command/selection.cr","line_number":2,"url":null},{"filename":"src/cligen/command/subcommand.cr","line_number":2,"url":null},{"filename":"src/cligen/command/trigger.cr","line_number":2,"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,short,long,description,validation=nil)-macro","name":"argument","abstract":false,"args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""}],"args_string":"(variable, short, long, description, validation = nil)","args_html":"(variable, short, long, description, validation = nil)","location":{"filename":"src/cligen/command/argument.cr","line_number":3,"url":null},"def":{"name":"argument","args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"validation","default_value":"nil","external_name":"validation","restriction":""}],"visibility":"Public","body":" \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.name %}\n\n \n{% type = variable.type %}\n\n \n{% unless short.is_a?(StringLiteral) || (string == nil)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided short must be a string\")\nend %}\n\n \n{% unless long.is_a?(StringLiteral) || (long == nil)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided long must be a string\")\nend %}\n\n \n{% unless long || short\n raise(\"ERROR : CliGen::Command.argument(#{name}) : You must provide a short or long\")\nend %}\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)\n raise(\"ERROR : CliGen::Command.argument(#{name}) : Provided description must be a String\")\nend %}\n\n \n{% unless validation.nil? %}\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 == 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}) : #{type} { #{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 @[CliGen::Argument(short: \n{{ short }}\n, long: \n{{ long }}\n, description: \n{{ description }}\n, validation: \n{{ validation }}\n, on_match: \n{{ on_match }}\n)]\n @\n{{ variable }}\n\n\n def \n{{ variable.name }}\n= (value : \n{{ type }}\n)\n \n{% unless validation.nil? %}\n raise \"ERROR : #{@type.name}##{@def.name} : Provided value #{value} is not passing validation\" unless {{ validation }}.call(value)\n {% end %}\n\n @\n{{ name }}\n = value\n \nend\n \n"}},{"html_id":"selection(variable,short,long,description,options)-macro","name":"selection","abstract":false,"args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"options","external_name":"options","restriction":""}],"args_string":"(variable, short, long, description, options)","args_html":"(variable, short, long, description, options)","location":{"filename":"src/cligen/command/selection.cr","line_number":3,"url":null},"def":{"name":"selection","args":[{"name":"variable","external_name":"variable","restriction":""},{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"description","external_name":"description","restriction":""},{"name":"options","external_name":"options","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{% unless short.is_a?(StringLiteral) || (string == nil)\n raise(\"ERROR : CliGen::Command.selection : Provided short must be a string\")\nend %}\n\n \n{% unless long.is_a?(StringLiteral) || (long == nil)\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{% unless options\n raise(\"ERROR : CliGen::Command.selection : You must provide options\")\nend %}\n\n \n{% unless options\n raise(\"ERROR : CliGen::Command.selection : Provided options must be \")\nend %}\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":3,"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 variable.is_a?(TypeDeclaration)\n raise(\"ERROR : CliGen::Command.subcommand : First argument must be a TypeDeclaration (ex: ' : ')\")\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":"trigger(short,long,argument=nil,&on_match)-macro","name":"trigger","abstract":false,"args":[{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"argument","default_value":"nil","external_name":"argument","restriction":""}],"args_string":"(short, long, argument = nil, &on_match)","args_html":"(short, long, argument = nil, &on_match)","location":{"filename":"src/cligen/command/trigger.cr","line_number":3,"url":null},"def":{"name":"trigger","args":[{"name":"short","external_name":"short","restriction":""},{"name":"long","external_name":"long","restriction":""},{"name":"argument","default_value":"nil","external_name":"argument","restriction":""}],"block_arg":{"name":"on_match","external_name":"on_match","restriction":""},"visibility":"Public","body":" \n{% unless short.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.trigger : Provided short must be a string\")\nend %}\n\n \n{% unless long.is_a?(StringLiteral)\n raise(\"ERROR : CliGen::Command.trigger : Provided long must be a string\")\nend %}\n\n \n{% unless on_match\n raise(\"ERROR : CliGen::Command.trigger : Must provide a block for on_match trigger\")\nend %}\n\n \n{% name = long.gsub(/--/, \"\") %}\n\n\n @[CliGen::Trigger(short: \n{{ short }}\n, long: \n{{ long }}\n, argument: \n{{ argument }}\n)]\n \n{% if argument %}\n def self.__cligen_trigger__{{ name }}__({{ name }} : {{ argument }}) : Nil\n {{ on_match.body }}\n end\n {% else %}\n def self.__cligen_trigger__{{ name }}__ : Nil\n {{ on_match.body }}\n end\n {% end %}\n\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":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"}},{"html_id":"CliGenerator/CliGen/CommandNode","path":"CliGen/CommandNode.html","kind":"class","full_name":"CliGen::CommandNode","name":"CommandNode","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_node.cr","line_number":5,"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(CliGen::BaseFlag),commands:Array(CliGen::CommandNode),pre_run_commands:Array(_),post_run_commands:Array(_))-class-method","name":"new","abstract":false,"args":[{"name":"name","external_name":"name","restriction":"::String"},{"name":"flags","external_name":"flags","restriction":"::Array(::CliGen::BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"::Array(::CliGen::CommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"::Array(_)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"::Array(_)"}],"args_string":"(name : String, flags : Array(CliGen::BaseFlag), commands : Array(CliGen::CommandNode), pre_run_commands : Array(_), post_run_commands : Array(_))","args_html":"(name : String, flags : Array(
                CliGen::BaseFlag), commands : Array(CliGen::CommandNode), pre_run_commands : Array(_), post_run_commands : Array(_))","location":{"filename":"src/cligen/command_node.cr","line_number":12,"url":null},"def":{"name":"new","args":[{"name":"name","external_name":"name","restriction":"::String"},{"name":"flags","external_name":"flags","restriction":"::Array(::CliGen::BaseFlag)"},{"name":"commands","external_name":"commands","restriction":"::Array(::CliGen::CommandNode)"},{"name":"pre_run_commands","external_name":"pre_run_commands","restriction":"::Array(_)"},{"name":"post_run_commands","external_name":"post_run_commands","restriction":"::Array(_)"}],"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/command_node.cr","line_number":49,"url":null},"def":{"name":"check!","visibility":"Public","body":"@flags.each(&.check!)\ncheck_for_duplicates!(@flags)\n@commands.each(&.check!)\n"},"external_var":false},{"html_id":"check_for_duplicates!(flags:Array(BaseFlag))-instance-method","name":"check_for_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/command_node.cr","line_number":15,"url":null},"def":{"name":"check_for_duplicates!","args":[{"name":"flags","external_name":"flags","restriction":"Array(BaseFlag)"}],"visibility":"Public","body":"shorts = 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(error_buffer % [@name, message])\nend\n"},"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.cr","line_number":55,"url":null},"def":{"name":"find_match","args":[{"name":"arg","external_name":"arg","restriction":"String"}],"visibility":"Public","body":"case arg\nwhen CliGen::Regex::FLAG_REGEX\n if flg = @flags.find(&.matches?(arg))\n flg\n else\n CliGen::MatchType::NoMatch\n end\nwhen CliGen::Regex::FLAG_WITH_ARG\n CliGen::MatchType::FlagWithArg\nwhen CliGen::Regex::SHORT_WITH_INLINE_ARG\n CliGen::MatchType::ShortWithInlineArg\nwhen CliGen::Regex::FLAG_MULTIPLE_SHORT\n CliGen::MatchType::FlagMultipleShort\nelse\n if cmd = @commands.find do |c| c.name == arg end\n cmd\n else\n CliGen::MatchType::NoMatch\n end\nend"},"external_var":false},{"html_id":"process(args:Array(String))-instance-method","name":"process","doc":"This serves to just convert the arguments into a usable Array(Arg) format\nand pass it to the ACTUAL CommandNode#process method","summary":"

                This serves to just convert the arguments into a usable Array(Arg) format and pass it to the ACTUAL CommandNode#process method

                ","abstract":false,"args":[{"name":"args","external_name":"args","restriction":"Array(String)"}],"args_string":"(args : Array(String))","args_html":"(args : Array(String))","location":{"filename":"src/cligen/command_node.cr","line_number":80,"url":null},"def":{"name":"process","args":[{"name":"args","external_name":"args","restriction":"Array(String)"}],"visibility":"Public","body":"new_args = [] of Arg\nargs.each_with_index do |arg, index|\n new_args << Arg.new(value: arg, index: index)\nend\n\n\nprocess(new_args)\n"},"external_var":false},{"html_id":"process(args:Array(Arg)):Nil-instance-method","name":"process","abstract":false,"args":[{"name":"args","external_name":"args","restriction":"Array(Arg)"}],"args_string":"(args : Array(Arg)) : Nil","args_html":"(args : Array(Arg)) : Nil","location":{"filename":"src/cligen/command_node.cr","line_number":90,"url":null},"def":{"name":"process","args":[{"name":"args","external_name":"args","restriction":"Array(Arg)"}],"return_type":"Nil","visibility":"Public","body":"check!\n\n@pre_run_commands.each(&.call)\n\nargs.each do |arg|\n if arg.processed?\n next\n end\n arg.processed\n\n case match = find_match(arg.value)\n when CommandNode\n match.process(args.reject(&.processed?))\n when BaseFlag\n if match.requires_arg?\n match.process(args.reject(&.processed?))\n else\n match.process\n end\n when MatchType::FlagWithArg\n if regex_match = CliGen::Regex::FLAG_WITH_ARG.match(arg.value)\n case flag_match = find_match(regex_match[\"flag\"])\n when BaseFlag\n flag_match.process([Arg.new(value: regex_match[\"arg\"], index: arg.index)])\n else\n raise(\"ERROR : CommandNode(#{@name}).run : There was no match for #{regex_match[\"flag\"]}\")\n end\n else\n raise(\"Oh good, you broke regex. How the hell did it match in find_match but not above? What the hell is going on\")\n end\n when MatchType::ShortWithInlineArg\n abort(\"#{CliGen::APPNAME}: invalid flag '#{arg.value}' — inline values are not supported. Did you mean '#{arg.value[0..1]} #{arg.value[2..]}' ?\")\n when MatchType::FlagMultipleShort\n (arg.value.gsub(/^-/, \"\")).chars.map do |c| \"-#{c}\" end.each do |flag|\n case match = find_match(flag)\n when BaseFlag\n if match.requires_arg?\n abort(\"#{CliGen::APPNAME}: cannot bundle flag that requires an argument: #{flag}\")\n end\n match.process\n when MatchType::NoMatch\n raise(\"ERROR : CommandNode(#{@name}).run : There was no match for #{flag}\")\n end\n end\n when MatchType::NoMatch\n raise(\"ERROR : CommandNode(#{@name}).run : There was no match for #{arg.value}\")\n end\nend\n\n@post_run_commands.each(&.call)\n"},"external_var":false}]},{"html_id":"CliGenerator/CliGen/DefaultFlag","path":"CliGen/DefaultFlag.html","kind":"annotation","full_name":"CliGen::DefaultFlag","name":"DefaultFlag","abstract":false,"locations":[{"filename":"src/cligen.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"}},{"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":31,"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|Nil,env_var:String|Nil,description:String,default:T|Nil=nil,options:Array(String)|Nil=nil,validate:T->Bool|Nil=nil,on_match:Proc(Nil)|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 | ::Nil"},{"name":"env_var","external_name":"env_var","restriction":"String | ::Nil"},{"name":"description","external_name":"description","restriction":"String"},{"name":"default","default_value":"nil","external_name":"default","restriction":"T | ::Nil"},{"name":"options","default_value":"nil","external_name":"options","restriction":"Array(String) | ::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(Nil) | ::Nil"}],"args_string":"(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String, default : T | Nil = nil, options : Array(String) | Nil = nil, validate : T -> Bool | Nil = nil, on_match : Proc(Nil) | Nil = nil)","args_html":"(var : String, short : String | Nil, long : String | Nil, env_var : String | Nil, description : String, default : T | Nil = nil, options : Array(String) | Nil = nil, validate : T -> Bool | Nil = nil, on_match : Proc(Nil) | Nil = nil)","location":{"filename":"src/cligen/flag.cr","line_number":38,"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 | ::Nil"},{"name":"env_var","external_name":"env_var","restriction":"String | ::Nil"},{"name":"description","external_name":"description","restriction":"String"},{"name":"default","default_value":"nil","external_name":"default","restriction":"T | ::Nil"},{"name":"options","default_value":"nil","external_name":"options","restriction":"Array(String) | ::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(Nil) | ::Nil"}],"visibility":"Public","body":"_ = Flag(T).allocate\n_.initialize(var, short, long, env_var, description, default, options, validate, on_match)\nif _.responds_to?(:finalize)\n ::GC.add_finalizer(_)\nend\n_\n"},"external_var":false}],"instance_methods":[{"html_id":"process(argv:Array(Arg)=[]ofArray(Arg)):Nil-instance-method","name":"process","abstract":false,"args":[{"name":"argv","default_value":"[] of Array(Arg)","external_name":"argv","restriction":"Array(Arg)"}],"args_string":"(argv : Array(Arg) = [] of Array(Arg)) : Nil","args_html":"(argv : Array(Arg) = [] of Array(Arg)) : Nil","location":{"filename":"src/cligen/flag.cr","line_number":56,"url":null},"def":{"name":"process","args":[{"name":"argv","default_value":"[] of Array(Arg)","external_name":"argv","restriction":"Array(Arg)"}],"return_type":"Nil","visibility":"Public","body":"if requires_arg?\n if argv.empty?\n raise(\"ERROR : Flag({{T}}) : Array requires an argument but provided array is empty\")\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 argv.each do |arg|\n break if arg.value.starts_with('-')\n {% if elem == Int32 %}\n (@value ||= [] of Int32) << arg.value.to_i\n {% else %}\n (@value ||= [] of String) << arg.value\n {% end %}\n arg.processed\n end\n {% elsif T == Int32 %}\n @value = argv.first.value.to_i\n argv.first.processed\n {% elsif T == Time %}\n @value = parse_time(argv.first.value)\n argv.first.processed\n {% else %} # String\n @value = argv.first.value\n argv.first.processed\n {% end %}\n@on_match.try(&.call)\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":104,"url":null},"def":{"name":"raw_value","return_type":"String | ::Nil","visibility":"Public","body":"{% 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 %}"},"external_var":false},{"html_id":"requires_arg?:Bool-instance-method","name":"requires_arg?","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":52,"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":114,"url":null},"def":{"name":"satisfied?","return_type":"Bool","visibility":"Public","body":"if !@value.nil?\n return true\nend\nif @env_var && ENV[@env_var.not_nil!]?\n return true\nend\nif !@default.nil?\n return true\nend\nfalse\n"},"external_var":false},{"html_id":"validate!:Nil-instance-method","name":"validate!","abstract":false,"location":{"filename":"src/cligen/flag.cr","line_number":121,"url":null},"def":{"name":"validate!","return_type":"Nil","visibility":"Public","body":"v = value!\n\nif opts = @options\n str_v = v.to_s\n if opts.includes?(str_v)\n else\n abort(\"#{CliGen::APPNAME}: '#{str_v}' is not a valid value for #{@long_key.empty? ? @short : @long_key} (valid: #{opts.join(\", \")})\")\n end\nend\n\nif check = @validate\n if check.call(v)\n else\n abort(\"#{CliGen::APPNAME}: validation failed for #{@long_key.empty? ? @short : @long_key}\")\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":88,"url":null},"def":{"name":"value!","return_type":"T","visibility":"Public","body":"v = @value\n\n\nif v.nil? && @env_var\n if raw = ENV[@env_var.not_nil!]?\n v = coerce(raw)\n end\nend\n\nv || (v = @default)\n\nif v.nil?\n abort(\"#{CliGen::APPNAME}: required flag #{@long_key.empty? ? @short : @long_key} was not provided\")\nend\nv.not_nil!\n"},"external_var":false}]},{"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":1,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"INPUT_DATE_FORMAT","name":"INPUT_DATE_FORMAT","value":"\"%Y-%m-%d\""},{"id":"INPUT_DATETIME_FORMAT","name":"INPUT_DATETIME_FORMAT","value":"\"%Y-%m-%d %H:%M:%S\""}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"}},{"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":2,"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":"NoMatch","name":"NoMatch","value":"3"}],"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":4,"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":3,"url":null},"def":{"name":"flag_with_arg?","visibility":"Public","body":"self == FlagWithArg"},"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":6,"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":5,"url":null},"def":{"name":"short_with_inline_arg?","visibility":"Public","body":"self == ShortWithInlineArg"},"external_var":false}]},{"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":2,"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/Regex","path":"CliGen/Regex.html","kind":"module","full_name":"CliGen::Regex","name":"Regex","abstract":false,"locations":[{"filename":"src/cligen/regex.cr","line_number":1,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"FLAG_MULTIPLE_SHORT","name":"FLAG_MULTIPLE_SHORT","value":"/^-[a-zA-Z]+$/"},{"id":"FLAG_REGEX","name":"FLAG_REGEX","value":"/^(-[a-zA-Z]|--[a-zA-Z-_]+)$/"},{"id":"FLAG_WITH_ARG","name":"FLAG_WITH_ARG","value":"/^(?(-[a-zA-Z]|--[a-zA-Z-_]+))=\"?(?\\S+?)\"?$/"},{"id":"INPUT_DATE_REGEX","name":"INPUT_DATE_REGEX","value":"/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/"},{"id":"INPUT_DATETIME_REGEX","name":"INPUT_DATETIME_REGEX","value":"/^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$/"},{"id":"SHORT_WITH_INLINE_ARG","name":"SHORT_WITH_INLINE_ARG","value":"/^-[a-zA-Z][a-zA-Z0-9]+$/"}],"namespace":{"html_id":"CliGenerator/CliGen","kind":"module","full_name":"CliGen","name":"CliGen"}},{"html_id":"CliGenerator/CliGen/Selection","path":"CliGen/Selection.html","kind":"annotation","full_name":"CliGen::Selection","name":"Selection","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":14,"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/SubCommand","path":"CliGen/SubCommand.html","kind":"annotation","full_name":"CliGen::SubCommand","name":"SubCommand","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":17,"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/Trigger","path":"CliGen/Trigger.html","kind":"annotation","full_name":"CliGen::Trigger","name":"Trigger","abstract":false,"locations":[{"filename":"src/cligen/annotations.cr","line_number":11,"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"}}]}]}} \ No newline at end of file +{"repository_name":"CliGenerator","body":"# cligen\n\nA Crystal shard that generates CLI parsers from class definitions using annotations and macros. Define your commands as classes; cligen builds the runtime parse tree.\n\n## How It Works\n\nSubclass `CliGen::Command`, annotate your instance variables with `@[CliGen::Argument]` or `@[CliGen::Selection]`, and register the command with an `CliGen::App`. At compile time, macros inspect the annotations and generate typed `Flag(T)` objects; at runtime, `CliGen::App.process` walks the `CommandNode` tree to route arguments, populate your command instance, and dispatch to the right method.\n\n## Installation\n\n1. Add the dependency to your `shard.yml`:\n\n ```yaml\n dependencies:\n cligen:\n git: https://git.arcanium.tech/tristan/cligen\n ```\n\n2. Run `shards install`\n\n## Usage\n\n```crystal\nrequire \"cligen\"\n\n@[CliGen::CommandInfo(description: \"Greet someone\")]\nclass Greet < CliGen::Command\n @[CliGen::Argument(short: \"-n\", long: \"--name VALUE\", description: \"Name to greet\")]\n @name : String = \"world\"\n \n argument(otherval : String = \"abc\",\n long: \"--other\",\n short: \"-o\",\n options: %w[ abc def ghi ],\n description: \"This provides a way of setting the second string taht is printed\"\n )\n \n argument(myvars : Array(String) = [ \"a\" ],\n short: \"-m\",\n options: %w[ a b c ],\n description: \"Provide multiple things to be printed out in the main function\"\n )\n\n def main\n puts \"1) Hello, #{@name}!\"\n puts \"2) #{@otherval}\"\n @myvars.each_with_index do |var, index|\n puts \"%d) %s\" % [ 3 + index, var ]\n end\n end\nend\n\nCliGen::App.process\n```\n\n```\n$ myapp greet --name Alice -m a a -m a,a,b\n1) Hello, Alice!\n2) abc\n3) a \n4) a \n5) a \n6) a \n7) b\n```\n\nFull API documentation and design notes are in [`design.adoc`](design.adoc).\n\n## Architecture\n\nAs a short overview, this projects makes HEAVY use of Crystal macros to learn the shape of your project & command subclasses.\n\nSubclassing to `CliGen::Command` injects macros into your class that provides you user friendly DSLs/Macros for defining arguments/flags & subcommands. This is later used in the library `src/cligen/app/generate.cr` to generate a object graph of your commands and all annotated \"arguments/flags\" and stores them in a tree from the App object itself.\n\nThis allows the project to \"learn\" your project & generate a command tree from the defined data.\n\nThe MAJORITY of stdlib types (Int*, Float*, String, Bool & Time) are all supported in-place (as these are the primary data-types you might try to comsume from the CLI. However, custom data types are supported provided you extend the class's metaclass with `CliGen::Coercable` && `CliGen::Parsable` modules and define the `self.parse_args(args : Array(CliGen::Arg)` and `self.coerce(arg : String)` class methods.\n\nEX:\n```crystal\nmodule MyModule\n class MyData\n extend CliGen::Parsable\n extend CliGen::Coercable\n \n @value : Int32\n \n def initialize(value : String)\n @value = value.to_i32\n end\n \n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed\n arg.processed\n new(arg.value)\n \n end\n \n def self.coerce(arg : String)\n new(arg)\n end\n end\nend\n```\n\n\nCoercable Method:\n-----------------\n```crystal\n def self.coerce(arg : String)\n new(arg)\n end\n```\n\nThe coerce method provides you the ability to parse a single string value into your class/datatype. This is generally only used when parsing from ENV VAR and when being used by parsing from an Array(T) type. \n\nThis should only be used in the case you need a simple datatype that can be learned from a single string.\n\nParsable Method:\n----------------\n```crystal\n def self.parse_args(args : Array(CliGen::Arg))\n arg = args.first\n # Mark the argument as processed (required)\n arg.processed\n new(arg.value)\n end\n```\n\nThis method is used the most and is used for when using the bare class as the generic type in the Flag(T). With this the Flag(T) will collect all provided arguments (cli arguments that weren't determined to be flags or subcommands) and pass them to your parse_args method so that you can parse them how you see fit and determine if the args provided by the user are enough and to be able to raise if data is not provided correctly/in the right format.\n\nThis gives the framework a way to allow you to extend the parser in your own custom way to allow for a \"custom\" format to be procesed. However, it's very strict and you MUST properly mark the arguments as processed so that the mainloop won't double-process arguments passed to your custom parser. However, this won't happen as in the Flag(T) I am doing a check to ensure that args were processed after passing it to your code.\n\n## Development\n\n```bash\n# Type-check without running\ncrystal build src/cligen.cr --no-codegen\n\n# Run specs\ncrystal spec\n```\n\n## AI Assistance Disclosure\n\nThis project uses [Claude Code](https://claude.ai/code) as a development aid — specifically for catching bugs, spotting typos, reviewing implementations, and talking through design decisions. All architecture decisions, code, and design are written by the author. Claude is used the way one might use a second pair of eyes on a diff, not as a code generator.\n\n`CLAUDE.md` at the repo root documents the project structure for Claude's context. `.claude/` holds project-level Claude Code settings.\n\n## Contributors\n\n- [Tristan Ancelet](https://git.arcanium.tech/tristan) - creator and maintainer\n","program":{"html_id":"CliGenerator/toplevel","path":"toplevel.html","kind":"module","full_name":"Top Level Namespace","name":"Top Level Namespace","abstract":false,"locations":[],"repository_name":"CliGenerator","program":true,"enum":false,"alias":false,"const":false,"types":[{"html_id":"CliGenerator/CliGen","path":"CliGen.html","kind":"module","full_name":"CliGen","name":"CliGen","abstract":false,"locations":[{"filename":"src/cligen.cr","line_number":16,"url":null},{"filename":"src/cligen/annotations.cr","line_number":4,"url":null},{"filename":"src/cligen/app.cr","line_number":9,"url":null},{"filename":"src/cligen/app/generate.cr","line_number":4,"url":null},{"filename":"src/cligen/arg.cr","line_number":4,"url":null},{"filename":"src/cligen/command.cr","line_number":15,"url":null},{"filename":"src/cligen/command/argument.cr","line_number":4,"url":null},{"filename":"src/cligen/command/def_init.cr","line_number":4,"url":null},{"filename":"src/cligen/command/define_command_initializer.cr","line_number":4,"url":null},{"filename":"src/cligen/command/help_template.cr","line_number":4,"url":null},{"filename":"src/cligen/command/selection.cr","line_number":4,"url":null},{"filename":"src/cligen/command/subcommand.cr","line_number":4,"url":null},{"filename":"src/cligen/command_node.cr","line_number":13,"url":null},{"filename":"src/cligen/command_node/base.cr","line_number":8,"url":null},{"filename":"src/cligen/command_node/command_meta.cr","line_number":4,"url":null},{"filename":"src/cligen/command_node/subcommand_meta.cr","line_number":4,"url":null},{"filename":"src/cligen/exceptions.cr","line_number":4,"url":null},{"filename":"src/cligen/flag.cr","line_number":9,"url":null},{"filename":"src/cligen/flag/base.cr","line_number":8,"url":null},{"filename":"src/cligen/flag/meta.cr","line_number":4,"url":null},{"filename":"src/cligen/global_flag.cr","line_number":7,"url":null},{"filename":"src/cligen/global_flag/add_global_flag.cr","line_number":4,"url":null},{"filename":"src/cligen/match_type.cr","line_number":4,"url":null}],"repository_name":"CliGenerator","program":false,"enum":false,"alias":false,"const":false,"constants":[{"id":"APPNAME","name":"APPNAME","value":"File.basename(PROGRAM_NAME)"},{"id":"GLOBAL_FLAGS","name":"GLOBAL_FLAGS","value":"[] of BaseFlag"},{"id":"VERSION","name":"VERSION","value":"\"0.1.0\""}],"macros":[{"html_id":"add_global_flag(type,*,long,description,env_var=nil,short=nil,validation=nil,default=nil,on_match=nil)-macro","name":"add_global_flag","abstract":false,"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":""}],"args_string":"(type, *, long, description, env_var = nil, short = nil, validation = nil, default = nil, on_match = nil)","args_html":"(type, *, long, description, env_var = 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":"/(?