Doing test

This commit is contained in:
Tristan Ancelet
2026-02-23 15:22:13 -06:00
parent 5a14063e1f
commit 21a2b0d972
3 changed files with 29 additions and 25 deletions

View File

@@ -3,17 +3,17 @@ require "option_parser"
module CliGen module CliGen
VERSION = "0.1.0" VERSION = "0.1.0"
APPNAME = File.basename(PROGRAM_NAME)
record AdditionalDefaultFlag, record AdditionalDefaultFlag,
short : String?, short : String,
long : String?, long : String,
description : String, description : String,
work : Proc(Nil) work : String ->
private ADDITIONAL_DEFAULT_FLAGS = [] of AdditionalDefaultFlag ADDITIONAL_DEFAULT_FLAGS = [] of AdditionalDefaultFlag
def self.add_default_flag(short : String? = nil, long : String? = nil, description : String? = nil, &work : -> ) def self.add_default_flag(short : String, long : String, description : String, &work : String -> )
raise "ERROR : add_default_flag : You must provide a description" unless description raise "ERROR : add_default_flag : You must provide a description" unless description
raise "ERROR : add_default_flag : You must provide at least long or short" unless [short, long].any?
ADDITIONAL_DEFAULT_FLAGS << AdditionalDefaultFlag.new( ADDITIONAL_DEFAULT_FLAGS << AdditionalDefaultFlag.new(
short: short, short: short,
long: long, long: long,
@@ -32,18 +32,19 @@ module CliGen
end end
alias OnType = Tuple(String, String) | Tuple(String, String, String)
macro define_default_flags(parser) macro define_default_flags(parser)
define_section("Misc Flags", {{parser}}) CliGen.define_section("Misc Flags", {{parser}})
{{parser}}.on("-h", "--help", "Print out this help output"){ abort {{parser}} } {{parser}}.on("-h", "--help", "Print out this help output"){ abort {{parser}} }
{{parser}}.invalid_option{|opt| {{parser}}.invalid_option{|opt|
abort "#{PROGRAM_NAME} : invalid_option : Inavlid option provided #{opt}" abort "#{CliGen::APPNAME} : invalid_option : Inavlid option provided #{opt}"
} }
{{parser}}.invalid_option{|opt| {{parser}}.invalid_option{|opt|
case opt case opt
when /^-+[a-z-]+/ when /^-+[a-z-]+/
Logger.debug "#{PROGRAM_NAME} : ERROR : {{parser}} : invalid_option : Inavlid option provided #{opt}" Logger.debug "#{CliGen::APPNAME} : ERROR : {{parser}} : invalid_option : Inavlid option provided #{opt}"
else else
abort "#{PROGRAM_NAME} : ERROR : {{parser}} : invalid_option : Inavlid option provided #{opt}" abort "#{CliGen::APPNAME} : ERROR : {{parser}} : invalid_option : Inavlid option provided #{opt}"
end end
} }
{{parser}}.missing_option{|opt| {{parser}}.missing_option{|opt|
@@ -60,23 +61,23 @@ module CliGen
end end
} }
ADDITIONAL_DEFAULT_FLAGS.each do |flag| CliGen::ADDITIONAL_DEFAULT_FLAGS.each do |flag|
args = [flag.short, flag.long, flag.description].reject(&.nil?) {{parser}}.on(flag.short, flag.long, flag.description){|var| flag.work.call(var) }
{{parser}}.on(*args) &flag.work
end end
end end
macro define_root_parser macro define_root_parser
ROOT_COMMAND = OptionParser.new do |parser| ROOT_COMMAND = OptionParser.new do |parser|
parser.banner = "#{PROGRAM_NAME} [command] [flags]" parser.banner = "#{CliGen::APPNAME} [command] [flags]"
{% commands = ::CliGen::Command.subclasses %} {% commands = ::CliGen::Command.subclasses %}
{% raise "ERROR : No commands defined (no subclasses of ::CliGen::Command were found)" if commands.empty? %} {% raise "ERROR : No commands defined (no subclasses of ::CliGen::Command were found)" if commands.empty? %}
CliGen.define_section("Commands", parser)
{% for command in commands %} {% for command in commands %}
{{command.name}}.make_parser(parser) {{command.name}}.make_parser(parser)
{% end %} {% end %}
define_default_flags(parser) CliGen.define_default_flags(parser)
abort parser if ARGV.empty? abort parser if ARGV.empty?
end end

View File

@@ -21,7 +21,6 @@ module CliGen
class Command class Command
extend CliGen::Parser extend CliGen::Parser
@@action : String = ""
macro inherited macro inherited
macro finished macro finished
@@ -29,10 +28,12 @@ module CliGen
define_header define_header
define_runner define_runner
define_parser define_parser
define_action_setter
end end
end end
macro define_actions macro define_actions
@@action : String = ""
ACTIONS = {{@type.class.methods.select(&.annotation(::CliGen::SubCommand)).map(&.name.stringify)}} of String ACTIONS = {{@type.class.methods.select(&.annotation(::CliGen::SubCommand)).map(&.name.stringify)}} of String
end end
@@ -42,7 +43,7 @@ module CliGen
{% examples = [] of StringLiteral %} {% examples = [] of StringLiteral %}
{% info_annos.select(&.[](:examples)).map(&.[](:examples).resolve).each(&.each{|example| examples << example}) %} {% info_annos.select(&.[](:examples)).map(&.[](:examples).resolve).each(&.each{|example| examples << example}) %}
HEADER = [ HEADER = [
"#{PROGRAM_NAME} {{name}} [[flags]]", "#{CliGen::APPNAME} {{name}} [[flags]]",
"", "",
{% unless examples.empty? %} {% unless examples.empty? %}
"Examples:".colorize(:green), "Examples:".colorize(:green),
@@ -140,15 +141,17 @@ module CliGen
{{method.name}} {{method.name}}
{% end %} {% end %}
else else
abort "ERROR : No action provided to command #{@type.name}" abort "ERROR : No action provided to command {{@type.name}}"
end end
{% end %} {% end %}
end end
end end
def self.action=(action : String) macro define_action_setter
abort "ERROR : Action(#{action}) is not valid. Only #{ACTIONS.join(", ")} are acceptable" unless ACTIONS.includes?(action) def self.action=(action : String)
@@action = action abort "ERROR : Action(#{action}) is not valid. Only #{ACTIONS.join(", ")} are acceptable" unless ACTIONS.includes?(action)
@@action = action
end
end end
end end

View File

@@ -3,12 +3,12 @@ module CliGen::Parser
macro extended macro extended
{% verbatim do %} {% verbatim do %}
macro define_parser macro define_parser
def self.make_parser(parent_parser : OptionParser) : OptionParser def self.make_parser(parent_parser : OptionParser) : Nil
{% puts "#{@type.name} OptionParser is being generated" %} {% puts "#{@type.name} OptionParser is being generated" %}
{% name = @type.name.split("::").last %} {% name = @type.name.split("::").last %}
{% var = name.downcase %} {% var = name.downcase %}
{% info = @type.annotation(::CliGen::CommandInfo) %} {% info = @type.annotation(::CliGen::CommandInfo) %}
{% raise "ERROR : No CommandInfo annotation provided to #{@type.name}" unless info %} {% raise "ERROR : No CommandInfo annotation provided to {{@type.name}}" unless info %}
subparser = OptionParser.new do |parser| subparser = OptionParser.new do |parser|
parser.banner = {{@type.name}}::HEADER parser.banner = {{@type.name}}::HEADER
{% subcommands = @type.class.methods.select(&.annotation(::CliGen::SubCommand)) %} {% subcommands = @type.class.methods.select(&.annotation(::CliGen::SubCommand)) %}
@@ -38,11 +38,11 @@ module CliGen::Parser
} }
{% end %} {% end %}
{% end %} {% end %}
define_default_flags(parser) CliGen.define_default_flags(parser)
end end
parent_parser.on({{var}}, {{info[:description]}}){ parent_parser.on({{var}}, {{info[:description]}}){
ARGV.delete({{var}}) ARGV.delete({{var}})
abort {{var.id}} if ARGV.empty? abort subparser if ARGV.empty?
subparser.parse subparser.parse
{{@type.name}}.run {{@type.name}}.run
} }