diff --git a/shard.yml b/shard.yml index cf78d70..19be6f5 100644 --- a/shard.yml +++ b/shard.yml @@ -1,5 +1,5 @@ name: optarg -version: 0.5.4 +version: 0.5.5 authors: - mosop diff --git a/spec/internal/unknown_spec.cr b/spec/internal/unknown_spec.cr new file mode 100644 index 0000000..58eda10 --- /dev/null +++ b/spec/internal/unknown_spec.cr @@ -0,0 +1,26 @@ +require "../spec_helper" + +module OptargInternalSpec::Unknown + class Model < Optarg::Model + string "-s" + unknown + end + + describe name do + it "with option" do + result = Model.parse(%w(-s foo bar)) + result.s?.should eq "foo" + result.unparsed_args.should eq %w(bar) + end + + it "without different option" do + result = Model.parse(%w(-b foo bar)) + result.unparsed_args.should eq %w(-b foo bar) + end + + it "without option" do + result = Model.parse(%w(foo bar)) + result.unparsed_args.should eq %w(foo bar) + end + end +end diff --git a/src/lib/completion_generators/base.cr b/src/lib/completion_generators/base.cr index 4d84d22..2196c4f 100644 --- a/src/lib/completion_generators/base.cr +++ b/src/lib/completion_generators/base.cr @@ -100,6 +100,7 @@ module Optarg::CompletionGenerators end def make_definition(df) + return if df.is_a?(Definitions::Unknown) @keymap[df.key] = @keymap.size add_key df add_act df diff --git a/src/lib/definition_set.cr b/src/lib/definition_set.cr index 7e679f7..1aa25bd 100644 --- a/src/lib/definition_set.cr +++ b/src/lib/definition_set.cr @@ -36,6 +36,7 @@ module Optarg __set Definitions::Terminator, terminators __set DefinitionMixins::Value, values __set Definitions::StringArrayArgument, string_array_arguments + __set Definitions::Unknown, unknowns end getter all = {} of String => Definitions::Base @@ -44,6 +45,7 @@ module Optarg getter value_options = {} of String => DefinitionMixins::ValueOption getter handlers = {} of String => Definitions::Handler getter terminators = {} of String => Definitions::Terminator + getter unknowns = {} of String => Definitions::Unknown getter values = {} of String => DefinitionMixins::Value getter string_array_arguments = {} of String => Definitions::StringArrayArgument diff --git a/src/lib/definitions/base.cr b/src/lib/definitions/base.cr index 95f7b9d..31686fb 100644 --- a/src/lib/definitions/base.cr +++ b/src/lib/definitions/base.cr @@ -7,7 +7,7 @@ module Optarg::Definitions getter names : Array(String) getter metadata : Metadata - def initialize(names : String | Array(String), metadata : Metadata? = nil, stop : Bool? = nil, terminate : Bool? = nil, complete : String | Symbol | Array(String) | Nil = nil) + def initialize(names : String | Array(String), metadata : Metadata? = nil, stop : Bool? = nil, terminate : Bool? = nil, complete : String | Symbol | Array(String) | Nil = nil, unknown : Bool? = nil) @names = case names when String [names] @@ -18,6 +18,7 @@ module Optarg::Definitions @metadata.definition = self @stops = !!stop @terminates = !!terminate + @unknown = !!unknown initialize_completion complete: (complete || "") end @@ -31,6 +32,11 @@ module Optarg::Definitions @terminates.as(Bool) end + @unknown : Bool? + def unknown? + @unknown.as(Bool) + end + def key @names[0] end diff --git a/src/lib/definitions/unknown.cr b/src/lib/definitions/unknown.cr new file mode 100644 index 0000000..6307122 --- /dev/null +++ b/src/lib/definitions/unknown.cr @@ -0,0 +1,15 @@ +module Optarg::Definitions + class Unknown < Base + def initialize(metadata = nil) + super "@unknown", metadata: metadata, unknown: true + end + + def completion_length(gen) + 1 + end + + def completion_max_occurs(gen) + 1 + end + end +end diff --git a/src/lib/model/dsl/unknown.cr b/src/lib/model/dsl/unknown.cr new file mode 100644 index 0000000..efd7203 --- /dev/null +++ b/src/lib/model/dsl/unknown.cr @@ -0,0 +1,9 @@ +module Optarg + class Model + # Defines an unknown model item. + macro unknown(metadata = nil) + %unknown = ::Optarg::Definitions::Unknown.new(metadata: {{metadata}}) + @@__klass.definitions << %unknown + end + end +end diff --git a/src/lib/parser.cr b/src/lib/parser.cr index f62dc35..549bbfa 100644 --- a/src/lib/parser.cr +++ b/src/lib/parser.cr @@ -60,7 +60,7 @@ module Optarg # :nodoc: def stopped? return false if parsed_nodes.size == 0 - return parsed_nodes.last[:definitions].any?{|i| i.stops? || i.terminates?} + return parsed_nodes.last[:definitions].any?{|i| i.stops? || i.terminates? || i.unknown?} end on_validate do |o| @@ -101,13 +101,21 @@ module Optarg def visit arg = self[0] if visit_terminator - elsif arg =~ /^-\w\w/ + return + end + if arg =~ /^-\w\w/ visit_concatenated_options - elsif arg =~ /^-/ - visit_option - else - visit_argument + return end + if arg =~ /^-/ + begin + visit_option + return + rescue ex : UnknownOption + raise ex if definitions.unknowns.empty? + end + end + visit_argument end # :nodoc: @@ -157,6 +165,15 @@ module Optarg # :nodoc: def visit_argument + if definitions.unknowns.empty? + visit_argument2 + else + visit_unknown + end + end + + # :nodoc: + def visit_argument2 while @argument_index < definitions.arguments.size df = definitions.argument_list[@argument_index] unless df.visitable?(self) @@ -175,6 +192,12 @@ module Optarg @index += 1 end + # :nodoc: + def visit_unknown + node = Parser.new_node(%w(), definitions.unknowns.first[1]) + @parsed_nodes << node + end + # :nodoc: def [](*args) input_args[@index..-1][*args] diff --git a/src/version.cr b/src/version.cr index 6c72d14..51c3010 100644 --- a/src/version.cr +++ b/src/version.cr @@ -1,3 +1,3 @@ module Optarg - VERSION = "0.5.4" + VERSION = "0.5.5" end