Modified a few things:

- Finished implementing relative date parsing and migrated date parsing
  from Flag(T) to it's own dedicated module. Additionally added a
  the ability to do "recursive" relative operations for time searching.
- Additionally made a Struct & Enum for containing relative operations
  around dates.
- Added additional checks in App & CommandNode(T) around checking
  env_vars of flags & checking for duplicate commands
- Added a CommandMeta record to contain the classname of the
  CommandNode(T)
- Seperated out all of the monolitic files (command_node.cr & file.cr).
  Moved the base classes and records into their own files in the dir
  with the same name of their generic counterparts.
- Fixed a number of macro related bugs around Command.argument &
  CliGen.add_global_flag
- My ass hurts from sitting here for hours and doing these changes and
  arguing with claude over what needs to be done. Fun tho.
This commit is contained in:
2026-08-30 22:13:39 -05:00
parent f2d5c84f2b
commit 4cce5cc45c
42 changed files with 1576 additions and 988 deletions
+56
View File
@@ -0,0 +1,56 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright 2026 Tristan Ancelet
#
# Manual harness for flag resolution + validation across every source a value
# can arrive from. Driven by ./utils/flag_matrix.sh; see that script for the expected
# results. Kept out of spec/ because each case needs its own process (env vars
# must be set before startup).
#
# ENV VAR NAMING - the two kinds of flag derive their names differently:
#
# global flag add_global_flag(..., long: "--retries") -> RETRIES
# derived from the long flag, minus the leading dashes
#
# command arg class Greet; argument(level : Int32 ...) -> GREET_LEVEL
# derived as <COMMAND>_<VAR>, see app/generate.cr
#
# The asymmetry is easy to trip over: exporting LEVEL=9 does nothing at all,
# because the command argument is bound to GREET_LEVEL.
require "cligen"
CliGen.add_global_flag(Int32,
long: "--retries",
short: "-r",
description: "retry count (global, validated 0..10, env: RETRIES)",
default: 3,
validation: ->(v : Int32) : Bool { v >= 0 && v <= 10 }
)
@[CliGen::CommandInfo(description: "flag resolution matrix")]
class Greet < CliGen::Command
argument(name : String = "world",
long: "--name",
description: "plain string, no validation (env: GREET_NAME)"
)
argument(level : Int32 = 1,
long: "--level",
description: "validated < 5 (env: GREET_LEVEL)",
validation: ->(v : Int32) : Bool { v < 5 }
)
private def retries : Int32
CliGen::GLOBAL_FLAGS
.find { |f| f.long_key == "--retries" }
.not_nil!
.as(CliGen::Flag(Int32))
.value!
end
def main
puts "retries=#{retries} level=#{@level} name=#{@name}"
end
end
CliGen::App.process