From 4929b03b8b7016780e4925670c0901ed01b9a9b2 Mon Sep 17 00:00:00 2001 From: mosop Date: Sun, 13 Nov 2016 22:40:53 +0900 Subject: [PATCH] Argument / Option Value Container --- README.md | 297 +++++++++++++++++- spec/classes/argument_value_container_spec.cr | 17 + spec/classes/argument_value_list_spec.cr | 17 - spec/classes/option_value_container_spec.cr | 13 + spec/features/accessor_spec.cr | 10 +- spec/features/arguments_spec.cr | 2 +- spec/features/array_spec.cr | 6 +- spec/features/boolean_spec.cr | 12 + spec/features/boolean_value_spec.cr | 14 - spec/features/concatenation_spec.cr | 10 +- spec/features/custom_initializer_spec.cr | 12 +- spec/features/default_value_spec.cr | 6 +- .../detail/argument_value_container_spec.cr | 15 + .../avoiding_overriding_methods_spec.cr | 13 + .../detail/bool_option_value_accessor_spec.cr | 17 + .../named_argument_value_accessor_spec.cr | 16 + .../detail/named_argument_value_hash_spec.cr | 13 + .../nameless_argument_value_hash_spec.cr | 13 + .../detail/option_value_container_spec.cr | 31 ++ .../parsed_argument_value_array_spec.cr | 13 + ...string_array_option_value_accessor_spec.cr | 13 + .../string_option_value_accessor_spec.cr | 19 ++ .../unparsed_argument_value_array_spec.cr | 13 + spec/features/handler_spec.cr | 10 +- spec/features/inheritance_spec.cr | 12 +- spec/features/minimum_length_of_array_spec.cr | 4 +- ...uments_spec.cr => named_arguments_spec.cr} | 10 +- spec/features/negation_spec.cr | 10 +- spec/features/nilable_accessor_spec.cr | 10 +- .../required_arguments_and_options_spec.cr | 16 +- spec/features/synonyms_spec.cr | 10 +- spec/internal/argument_display_name_spec.cr | 2 +- .../argument_has_default_setter_spec.cr | 2 +- spec/internal/array_default_spec.cr | 2 +- spec/internal/array_has_min_method_spec.cr | 4 +- spec/internal/bool_has_not_method_spec.cr | 4 +- spec/internal/definition_has_group_spec.cr | 2 +- spec/internal/no_accessor_spec.cr | 8 +- .../option_has_required_method_spec.cr | 2 +- ...f_concatenated_options_not_matched_spec.cr | 2 +- ...e_unknown_option_regardless_of_arg_spec.cr | 2 +- .../raise_unsupported_concatenation_spec.cr | 2 +- ...ed_argument_error_preserves_object_spec.cr | 2 +- spec/internal/stopper_spec.cr | 2 +- ...ator_does_not_affect_another_model_spec.cr | 2 +- spec/internal_spec.cr | 10 +- src/optarg.cr | 32 -- ...ue_list.cr => argument_value_container.cr} | 10 +- src/optarg/model.cr | 35 ++- src/optarg/model/dsl/arg.cr | 4 +- src/optarg/model/dsl/array.cr | 8 +- src/optarg/model/dsl/bool.cr | 8 +- src/optarg/model/dsl/string.cr | 12 +- src/optarg/model/macros/option.cr | 8 +- src/optarg/option_mixins/array.cr | 4 +- src/optarg/option_mixins/bool.cr | 4 +- src/optarg/option_mixins/string.cr | 4 +- src/optarg/option_value_container.cr | 37 +++ src/optarg/option_value_list.cr | 4 - src/optarg/parser.cr | 8 +- 60 files changed, 682 insertions(+), 218 deletions(-) create mode 100644 spec/classes/argument_value_container_spec.cr delete mode 100644 spec/classes/argument_value_list_spec.cr create mode 100644 spec/classes/option_value_container_spec.cr create mode 100644 spec/features/boolean_spec.cr delete mode 100644 spec/features/boolean_value_spec.cr create mode 100644 spec/features/detail/argument_value_container_spec.cr create mode 100644 spec/features/detail/avoiding_overriding_methods_spec.cr create mode 100644 spec/features/detail/bool_option_value_accessor_spec.cr create mode 100644 spec/features/detail/named_argument_value_accessor_spec.cr create mode 100644 spec/features/detail/named_argument_value_hash_spec.cr create mode 100644 spec/features/detail/nameless_argument_value_hash_spec.cr create mode 100644 spec/features/detail/option_value_container_spec.cr create mode 100644 spec/features/detail/parsed_argument_value_array_spec.cr create mode 100644 spec/features/detail/string_array_option_value_accessor_spec.cr create mode 100644 spec/features/detail/string_option_value_accessor_spec.cr create mode 100644 spec/features/detail/unparsed_argument_value_array_spec.cr rename spec/features/{accessible_arguments_spec.cr => named_arguments_spec.cr} (67%) rename src/optarg/{argument_value_list.cr => argument_value_container.cr} (86%) create mode 100644 src/optarg/option_value_container.cr delete mode 100644 src/optarg/option_value_list.cr diff --git a/README.md b/README.md index 9b082e7..b0cd21c 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ result = Model.parse(%w(foo -s string bar -b baz)) result.args # => ["foo", "bar", "baz"] ``` -### Named Argument +### Named Arguments ```crystal class Model < Optarg::Model @@ -140,8 +140,8 @@ result = Model.parse(%w(/path/to/src /path/to/build and more)) result.args.src_dir # => "/path/to/src" result.args.build_dir # => "/path/to/build" result.args # => ["/path/to/src", "/path/to/build", "and", "more"] -result.args.named # => {"src_dir" => "/path/to/src", "build_dir" => "/path/to/build"} -result.args.nameless # => ["and", "more"] +result.named_args # => {"src_dir" => "/path/to/src", "build_dir" => "/path/to/build"} +result.nameless_args # => ["and", "more"] ``` ### Inheritance (Reusable Model) @@ -260,8 +260,299 @@ require "optarg" and see [Features](#features). +## Accessing Parsed Values + +### Value Container + +A value container is an object for storing parsed values. A value container is one of the following types: + +* [Argument Value Container](#argument_value_container) +* [Option Value Container](#option_value_container) +* [Named Argument Value Hash](#named_argument_value_hash) +* [Nameless Argument Value Array](#nameless_argument_value_array) +* [Parsed Argument Value Array](#parsed_argument_value_array) +* [Unparsed Argument Value Array](#unparsed_argument_value_array) + +#### Argument Value Container + + + +An argument value container is an Array-like object that contains argument values of a model object. + +To access argument value containers, use the `Optarg::Model#args` method. + +```crystal +class Model < Optarg::Model +end + +result = Model.parse(%w(foo bar baz)) +result.args.size # => 3 +result.args[0] # => "foo" +result.args[1] # => "bar" +result.args[2] # => "baz" +result.args.map{|i| "#{i}!"} # => ["foo!", "bar!", "baz!"] +``` + +#### Option Value Container + + + +An option value container is a set of Hash objects that contains option values of a model object. + +Every option value container has 3 hashes. Each hash is one of the following types: + +* String +* Bool +* Array(String) + +To access option value container, use the `Optarg::Model#options` method. + +To access the hashes, use the option value container's `#[]` method with a target type. + +```crystal +class Model < Optarg::Model + string "-s" + bool "-b" + array "-a" +end + +result = Model.parse(%w(-s foo -b -a bar -a baz)) +result.options[String] # => {"-s" => "foo"} +result.options[Bool] # => {"-b" => true} +result.options[Array(String)] # => {"-a" => ["bar", "baz"]} +``` + +##### Key for Multiple Names + +If an option has multiple names, only the first name can be used as a hash key. + +```crystal +class Model < Optarg::Model + bool %w(-f --force) +end + +result = Model.parse(%w(--force)) +result.options[Bool]["-f"] # => true +result.options[Bool]["--force"] # raises KeyError +``` + +#### Named Argument Value Hash + + + +A named argument value hash is an Hash object that contains named argument values of a model object. + +To access named argument value hashes, use the `Optarg::Model#named_args` method. + +```crystal +class Model < Optarg::Model + arg "named" +end + +result = Model.parse(%w(foo bar baz)) +result.named_args # => {"named" => "foo"} +``` + +#### Nameless Argument Value Array + + + +A nameless argument value array is an Array object that contains nameless argument values of a model object. + +To access nameless argument value arrays, use the `Optarg::Model#nameless_args` method. + +```crystal +class Model < Optarg::Model + arg "named" +end + +result = Model.parse(%w(foo bar baz)) +result.nameless_args # => ["bar", "baz"] +``` + +#### Parsed Argument Value Array + + + +A parsed argument value array is an Array object that contains parsed argument values of a model object, regardless of named or nameless. + +To access parsed argument value arrays, use the `Optarg::Model#parsed_args` method. + +```crystal +class Model < Optarg::Model + arg "named" +end + +result = Model.parse(%w(foo bar baz)) +result.parsed_args # => ["foo", "bar", "baz"] +``` + +Parsed argument value arrays are very similar to argument value containers in enumeration functionality. They are different in that an argument value container is an Array-like object and provides value accessors, whereas a parsed argument value array is just an Array object. + +#### Unparsed Argument Value Array + + + +An unparsed argument value array is an Array object that contains unparsed argument values of a model object. + +To access unparsed argument value arrays, use the `Optarg::Model#unparsed_args` method. + +```crystal +class Model < Optarg::Model + arg "stopper", stop: true +end + +result = Model.parse(%w(foo bar baz)) +result.unparsed_args # => ["bar", "baz"] +``` + +### Value Accessor + +A value accessor is a method to get a named value. A named value is a value of either an option or a named argument. + +Value accessors are automatically defined in model objects and value containers. + +The name of a value accessor is determined by the name of a corresponding option or argument. Any leading dash signs (`-`) are eliminated and the other dashes are converted to underscore letters (`_`). For example, `--option-name` is converted to `option_name`. + +A value accessor is one of the following types: + +* [String Option Value Accessor](#string_option_value_accessor) +* [Bool Option Value Accessor](#bool_option_value_accessor) +* [String-Array Option Value Accessor](#string-array_option_value_accessor) +* [Named Argument Value Accessor](#named_argument_value_accessor) + +#### String Option Value Accessor + + + +A string option value accessor is a method to get a string option's value. + +For a string option, a nillable value accessor is also defined. If a value is not set, the nillable value accessor returns nil instead raises an exception. The name of a nillable value accessor has a trailing `?` character. + +String option value accessors are defined in model objects and option value containers. + +```crystal +class Model < Optarg::Model + string "-s" +end + +result = Model.parse(%w(-s value)) +result.s # => "value" +result.options.s # equivalent to result.s + +not_set = Model.parse(%w()) +not_set.s # raises KeyError +not_set.s? # => nil +not_set.options.s # equivalent to not_set.s +not_set.options.s? # equivalent to not_set.s? +``` + +#### Bool Option Value Accessor + + + +A bool option value accessor is a method to get a bool option's value. + +The name of a bool option value accessor has a trailing `?` character. + +If a value is not set, a bool option value accessor returns false. + +Bool option value accessors are defined in model objects and option value containers. + +```crystal +class Model < Optarg::Model + bool "-b" +end + +result = Model.parse(%w(-b)) +result.b? # => true +result.options.b? # equivalent to result.b? + +not_set = Model.parse(%w()) +not_set.b? # => false +not_set.options.b? # equivalent to not_set.b? +``` + +#### String-Array Option Value Accessor + + + +A string-array option value accessor is a method to get an string-array option's value. + +String-Array option value accessors are defined in model objects and option value containers. + +```crystal +class Model < Optarg::Model + array "-a" +end + +result = Model.parse(%w(-a foo -a bar -a baz)) +result.a # => ["foo", "bar", "baz"] +result.options.a # equivalent to result.a +``` + +#### Named Argument Value Accessor + + + +A named argument value accessor is a method to get a named argument's value. + +For a named argument, a nillable value accessor is also defined. If a value is not set, the nillable value accessor returns nil instead raises an exception. The name of a nillable value accessor has a trailing `?` character. + +Named argument value accessors are defined in model objects and argument value containers. + +```crystal +class Model < Optarg::Model + arg "arg1" + arg "arg2" +end + +result = Model.parse(%w(foo bar)) +result.arg1 # => "foo" +result.arg2 # => "bar" +result.args.arg1 # equivalent to result.arg1 +result.args.arg2 # equivalent to result.arg2 +``` + +#### Avoiding Overriding Methods + +If an accessor's name is used for any methods that are already defined, the accessor won't be defined and the predefined method won't be overridden. + +For model objects (`Optarg::Model`), all the methods of its ancestor classes (`Reference` and `Object`) and the following methods are not overridden: + +* args +* named_args +* nameless_args +* options +* parse +* parsed_args +* parser +* unparsed_args + +For argument value container objects (`Optarg::ArgumentValueContainer`) and option value container objects (`Optarg::OptionValueContainer`), all the methods of its ancestor classes (`Reference` and `Object`) are not overridden. + +```crystal +class Model < Optarg::Model + string "--class" +end + +result = Model.parse(%w(--class foo)) +result.class # => Model +result.options[String]["--class"] # => "foo" +``` + +## Want to Do + +* Validation + * Inclusion + * Custom Handler + ## Release Notes +* v0.4.0 + * (Breaking Change) Removed Model#args.named Model#args.nameless. Use Model#named_args, Model#nameless_args instead. + * Argument Value Container + * Option Value Container * v0.3.0 * Stop and Termination * (Breaking Change) "--" (double dash) is no longer a special argument by default. Use the `Model.terminator` method. diff --git a/spec/classes/argument_value_container_spec.cr b/spec/classes/argument_value_container_spec.cr new file mode 100644 index 0000000..3a4721a --- /dev/null +++ b/spec/classes/argument_value_container_spec.cr @@ -0,0 +1,17 @@ +require "../spec_helper" + +module OptargArgumentValueContainerClassFeature + class Model < Optarg::Model + end + + it "#[]" do + list = Model::ArgumentValueContainer.new + list.__values << "arg" + list[0].should eq "arg" + end + + it "#[]?" do + list = Model::ArgumentValueContainer.new + list[0]?.should be_nil + end +end diff --git a/spec/classes/argument_value_list_spec.cr b/spec/classes/argument_value_list_spec.cr deleted file mode 100644 index 74f9041..0000000 --- a/spec/classes/argument_value_list_spec.cr +++ /dev/null @@ -1,17 +0,0 @@ -require "../spec_helper" - -module Optarg::ArgumentValueListFeature - class Model < Optarg::Model - end - - it "#<< and #[]" do - list = Model::ArgumentValueList.new - list << "arg" - list[0].should eq "arg" - end - - it "#[]?" do - list = Model::ArgumentValueList.new - list[0]?.should be_nil - end -end diff --git a/spec/classes/option_value_container_spec.cr b/spec/classes/option_value_container_spec.cr new file mode 100644 index 0000000..2d61cf2 --- /dev/null +++ b/spec/classes/option_value_container_spec.cr @@ -0,0 +1,13 @@ +require "../spec_helper" + +module OptargOptionValueContainerClassFeature + class Model < Optarg::Model + end + + it "#[]" do + list = Model::OptionValueContainer.new + list[String].class.should eq Hash(String, String?) + list[Bool].class.should eq Hash(String, Bool?) + list[Array(String)].class.should eq Hash(String, Array(String)) + end +end diff --git a/spec/features/accessor_spec.cr b/spec/features/accessor_spec.cr index 13a0774..c2ee8a0 100644 --- a/spec/features/accessor_spec.cr +++ b/spec/features/accessor_spec.cr @@ -1,14 +1,12 @@ require "../spec_helper" -module Optarg::AccessorFeature - class Model < ::Optarg::Model +module OptargAccessorFeature + class Model < Optarg::Model string "--foo" end -end -describe "Accessor" do - it "" do - result = Optarg::AccessorFeature::Model.parse(%w(--foo bar)) + it name do + result = Model.parse(%w(--foo bar)) result.foo.should eq "bar" end end diff --git a/spec/features/arguments_spec.cr b/spec/features/arguments_spec.cr index 800563f..cc08b0f 100644 --- a/spec/features/arguments_spec.cr +++ b/spec/features/arguments_spec.cr @@ -1,7 +1,7 @@ require "../spec_helper" module OptargArgumentsFeature - class Model < ::Optarg::Model + class Model < Optarg::Model string "-s" bool "-b" end diff --git a/spec/features/array_spec.cr b/spec/features/array_spec.cr index 4340f1d..84a1f27 100644 --- a/spec/features/array_spec.cr +++ b/spec/features/array_spec.cr @@ -1,11 +1,11 @@ require "../spec_helper" -module Optarg::ArrayFeature - class Model < ::Optarg::Model +module OptargArrayFeature + class Model < Optarg::Model array "-e" end - it "Array" do + it name do result = Model.parse(%w(-e foo -e bar -e baz)) result.e.should eq %w(foo bar baz) end diff --git a/spec/features/boolean_spec.cr b/spec/features/boolean_spec.cr new file mode 100644 index 0000000..4258241 --- /dev/null +++ b/spec/features/boolean_spec.cr @@ -0,0 +1,12 @@ +require "../spec_helper" + +module OptargBooleanFeature + class Model < Optarg::Model + bool "-b" + end + + it name do + result = Model.parse(%w(-b)) + result.b?.should be_true + end +end diff --git a/spec/features/boolean_value_spec.cr b/spec/features/boolean_value_spec.cr deleted file mode 100644 index e91b902..0000000 --- a/spec/features/boolean_value_spec.cr +++ /dev/null @@ -1,14 +0,0 @@ -require "../spec_helper" - -module Optarg::BooleanValueFeature - class Model < ::Optarg::Model - bool "-b" - end -end - -describe "Boolean Value" do - it "" do - result = Optarg::BooleanValueFeature::Model.parse(%w(-b)) - result.b?.should be_true - end -end diff --git a/spec/features/concatenation_spec.cr b/spec/features/concatenation_spec.cr index 8d5cfd7..2ee6c69 100644 --- a/spec/features/concatenation_spec.cr +++ b/spec/features/concatenation_spec.cr @@ -1,15 +1,13 @@ require "../spec_helper" -module Optarg::ConcatenationFeature - class Model < ::Optarg::Model +module OptargConcatenationFeature + class Model < Optarg::Model bool "-a" bool "-b" end -end -describe "Concatenation" do - it "" do - result = Optarg::ConcatenationFeature::Model.parse(%w(-ab)) + it name do + result = Model.parse(%w(-ab)) result.a?.should be_true result.b?.should be_true end diff --git a/spec/features/custom_initializer_spec.cr b/spec/features/custom_initializer_spec.cr index d3eef78..1dd3894 100644 --- a/spec/features/custom_initializer_spec.cr +++ b/spec/features/custom_initializer_spec.cr @@ -1,25 +1,23 @@ require "../spec_helper" -module Optarg::CustomInitializerFeature +module OptargCustomInitializerFeature class The def message "Someday again!" end end - class Model < ::Optarg::Model + class Model < Optarg::Model def initialize(argv, @the : The) super argv end on("--goodbye") { raise @the.message } end -end -describe "Custom Initializer" do - it "" do + it name do argv = %w(--goodbye) - the = Optarg::CustomInitializerFeature::The.new - expect_raises(Exception, "Someday again!") { Optarg::CustomInitializerFeature::Model.new(argv, the).parse } + the = The.new + expect_raises(Exception, "Someday again!") { Model.new(argv, the).parse } end end diff --git a/spec/features/default_value_spec.cr b/spec/features/default_value_spec.cr index e3a78b6..cfd68c0 100644 --- a/spec/features/default_value_spec.cr +++ b/spec/features/default_value_spec.cr @@ -1,14 +1,14 @@ require "../spec_helper" -module Optarg::DefaultValueFeature - class Model < ::Optarg::Model +module OptargDefaultValueFeature + class Model < Optarg::Model string "-s", default: "string" bool "-b", default: false array "-a", default: %w(1 2 3) arg "arg", default: "arg" end - it "Default Value" do + it name do result = Model.parse(%w()) result.s.should eq "string" result.b?.should be_false diff --git a/spec/features/detail/argument_value_container_spec.cr b/spec/features/detail/argument_value_container_spec.cr new file mode 100644 index 0000000..9cefd07 --- /dev/null +++ b/spec/features/detail/argument_value_container_spec.cr @@ -0,0 +1,15 @@ +require "../../spec_helper" + +module OptargArgumentValueContainerFeatureDetail + class Model < Optarg::Model + end + + it name do + result = Model.parse(%w(foo bar baz)) + result.args.size.should eq 3 + result.args[0].should eq "foo" + result.args[1].should eq "bar" + result.args[2].should eq "baz" + result.args.map{|i| "#{i}!"}.should eq %w(foo! bar! baz!) + end +end diff --git a/spec/features/detail/avoiding_overriding_methods_spec.cr b/spec/features/detail/avoiding_overriding_methods_spec.cr new file mode 100644 index 0000000..21f53a6 --- /dev/null +++ b/spec/features/detail/avoiding_overriding_methods_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargAvoidingOverridingMethodsFeatureDetail + class Model < Optarg::Model + string "--class" + end + + it name do + result = Model.parse(%w(--class foo)) + result.class.should eq Model + result.options[String]["--class"].should eq "foo" + end +end diff --git a/spec/features/detail/bool_option_value_accessor_spec.cr b/spec/features/detail/bool_option_value_accessor_spec.cr new file mode 100644 index 0000000..89a74e2 --- /dev/null +++ b/spec/features/detail/bool_option_value_accessor_spec.cr @@ -0,0 +1,17 @@ +require "../../spec_helper" + +module OptargBoolOptionValueAccessorFeatureDetail + class Model < Optarg::Model + bool "-b" + end + + it name do + result = Model.parse(%w(-b)) + result.b?.should be_true + result.options.b?.should be_true + + not_set = Model.parse(%w()) + not_set.b?.should be_false + not_set.options.b?.should be_false + end +end diff --git a/spec/features/detail/named_argument_value_accessor_spec.cr b/spec/features/detail/named_argument_value_accessor_spec.cr new file mode 100644 index 0000000..6124d32 --- /dev/null +++ b/spec/features/detail/named_argument_value_accessor_spec.cr @@ -0,0 +1,16 @@ +require "../../spec_helper" + +module OptargNamedArgumentValueAccessorFeatureDetail + class Model < Optarg::Model + arg "arg1" + arg "arg2" + end + + it name do + result = Model.parse(%w(foo bar)) + result.arg1.should eq "foo" + result.arg2.should eq "bar" + result.args.arg1.should eq "foo" + result.args.arg2.should eq "bar" + end +end diff --git a/spec/features/detail/named_argument_value_hash_spec.cr b/spec/features/detail/named_argument_value_hash_spec.cr new file mode 100644 index 0000000..c6de8aa --- /dev/null +++ b/spec/features/detail/named_argument_value_hash_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargNamedArgumentValueHashFeatureDetail + class Model < Optarg::Model + arg "named" + end + + it name do + result = Model.parse(%w(foo bar baz)) + expected = {"named" => "foo"} + result.named_args.should eq expected + end +end diff --git a/spec/features/detail/nameless_argument_value_hash_spec.cr b/spec/features/detail/nameless_argument_value_hash_spec.cr new file mode 100644 index 0000000..8be14c4 --- /dev/null +++ b/spec/features/detail/nameless_argument_value_hash_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargNamelessArgumentValueHashFeatureDetail + class Model < Optarg::Model + arg "named" + end + + it name do + result = Model.parse(%w(foo bar baz)) + expected = %w(bar baz) + result.nameless_args.should eq expected + end +end diff --git a/spec/features/detail/option_value_container_spec.cr b/spec/features/detail/option_value_container_spec.cr new file mode 100644 index 0000000..3280c67 --- /dev/null +++ b/spec/features/detail/option_value_container_spec.cr @@ -0,0 +1,31 @@ +require "../../spec_helper" + +module OptargOptionValueContainerFeatureDetail + class Model < Optarg::Model + string "-s" + bool "-b" + array "-a" + end + + it name do + result = Model.parse(%w(-s foo -b -a bar -a baz)) + s = {"-s" => "foo"} + b = {"-b" => true} + a = {"-a" => ["bar", "baz"]} + result.options[String].should eq s + result.options[Bool].should eq b + result.options[Array(String)].should eq a + end + + module KeyForMultipleName + class Model < Optarg::Model + bool %w(-f --force) + end + + it name do + result = Model.parse(%w(--force)) + result.options[Bool]["-f"].should be_true + expect_raises(KeyError) { result.options[Bool]["--force"] } + end + end +end diff --git a/spec/features/detail/parsed_argument_value_array_spec.cr b/spec/features/detail/parsed_argument_value_array_spec.cr new file mode 100644 index 0000000..b2cc2d8 --- /dev/null +++ b/spec/features/detail/parsed_argument_value_array_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargParsedArgumentValueArrayFeatureDetail + class Model < Optarg::Model + arg "named" + end + + it name do + result = Model.parse(%w(foo bar baz)) + expected = %w(foo bar baz) + result.parsed_args.should eq expected + end +end diff --git a/spec/features/detail/string_array_option_value_accessor_spec.cr b/spec/features/detail/string_array_option_value_accessor_spec.cr new file mode 100644 index 0000000..2f0c86a --- /dev/null +++ b/spec/features/detail/string_array_option_value_accessor_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargStringArrayOptionValueAccessorFeatureDetail + class Model < Optarg::Model + array "-a" + end + + it name do + result = Model.parse(%w(-a foo -a bar -a baz)) + result.a.should eq %w(foo bar baz) + result.options.a.should eq %w(foo bar baz) + end +end diff --git a/spec/features/detail/string_option_value_accessor_spec.cr b/spec/features/detail/string_option_value_accessor_spec.cr new file mode 100644 index 0000000..18df987 --- /dev/null +++ b/spec/features/detail/string_option_value_accessor_spec.cr @@ -0,0 +1,19 @@ +require "../../spec_helper" + +module OptargStringOptionValueAccessorFeatureDetail + class Model < Optarg::Model + string "-s" + end + + it name do + result = Model.parse(%w(-s value)) + result.s.should eq "value" + result.options.s.should eq "value" + + not_set = Model.parse(%w()) + expect_raises(KeyError) { not_set.s } + not_set.s?.should be nil + expect_raises(KeyError) { not_set.options.s } + not_set.options.s?.should be nil + end +end diff --git a/spec/features/detail/unparsed_argument_value_array_spec.cr b/spec/features/detail/unparsed_argument_value_array_spec.cr new file mode 100644 index 0000000..343e82a --- /dev/null +++ b/spec/features/detail/unparsed_argument_value_array_spec.cr @@ -0,0 +1,13 @@ +require "../../spec_helper" + +module OptargUnparsedArgumentValueArrayFeatureDetail + class Model < Optarg::Model + arg "stopper", stop: true + end + + it name do + result = Model.parse(%w(foo bar baz)) + expected = %w(bar baz) + result.unparsed_args.should eq expected + end +end diff --git a/spec/features/handler_spec.cr b/spec/features/handler_spec.cr index 274e1fa..c3aec77 100644 --- a/spec/features/handler_spec.cr +++ b/spec/features/handler_spec.cr @@ -1,17 +1,15 @@ require "../spec_helper" -module Optarg::HandlerFeature - class Model < ::Optarg::Model +module OptargHandlerFeature + class Model < Optarg::Model on("--goodbye") { goodbye! } def goodbye! raise "Goodbye, world!" end end -end -describe "Handler" do - it "" do - expect_raises(Exception, "Goodbye, world!") { Optarg::HandlerFeature::Model.parse(%w(--goodbye)) } + it name do + expect_raises(Exception, "Goodbye, world!") { Model.parse(%w(--goodbye)) } end end diff --git a/spec/features/inheritance_spec.cr b/spec/features/inheritance_spec.cr index 01ee080..50d1a69 100644 --- a/spec/features/inheritance_spec.cr +++ b/spec/features/inheritance_spec.cr @@ -1,7 +1,7 @@ require "../spec_helper" -module Optarg::InheritanceFeature - class Animal < ::Optarg::Model +module OptargInheritanceFeature + class Animal < Optarg::Model bool "--sleep" end @@ -12,11 +12,9 @@ module Optarg::InheritanceFeature class Dog < Animal bool "--woof" end -end -describe "Inheritance" do - it "" do - Optarg::InheritanceFeature::Cat.parse(%w()).responds_to?(:sleep?).should be_true - Optarg::InheritanceFeature::Dog.parse(%w()).responds_to?(:sleep?).should be_true + it name do + Cat.parse(%w()).responds_to?(:sleep?).should be_true + Dog.parse(%w()).responds_to?(:sleep?).should be_true end end diff --git a/spec/features/minimum_length_of_array_spec.cr b/spec/features/minimum_length_of_array_spec.cr index d56f227..6bb200d 100644 --- a/spec/features/minimum_length_of_array_spec.cr +++ b/spec/features/minimum_length_of_array_spec.cr @@ -1,11 +1,11 @@ require "../spec_helper" -module Optarg::MinimumLengthOfArrayFeature +module OptargMinimumLengthOfArrayFeature class Multiply < Optarg::Model array "-n", min: 2 end - it "Minimum Length of Array" do + it name do expect_raises(Optarg::MinimumLengthError) { Multiply.parse %w(-n 794) } end end diff --git a/spec/features/accessible_arguments_spec.cr b/spec/features/named_arguments_spec.cr similarity index 67% rename from spec/features/accessible_arguments_spec.cr rename to spec/features/named_arguments_spec.cr index b113cb0..a0f023b 100644 --- a/spec/features/accessible_arguments_spec.cr +++ b/spec/features/named_arguments_spec.cr @@ -1,19 +1,19 @@ require "../spec_helper" -module Optarg::AccessibleArgumentsFeature - class Model < ::Optarg::Model +module OptargNamedArgumentsFeature + class Model < Optarg::Model arg "src_dir" arg "build_dir" end - it "Accessible Arguments" do + it name do result = Model.parse(%w(/path/to/src /path/to/build and more)) result.src_dir.should eq "/path/to/src" result.build_dir.should eq "/path/to/build" result.args.should eq ["/path/to/src", "/path/to/build", "and", "more"] result.args.src_dir.should eq "/path/to/src" result.args.build_dir.should eq "/path/to/build" - result.args.named.should eq({"src_dir" => "/path/to/src", "build_dir" => "/path/to/build"}) - result.args.nameless.should eq ["and", "more"] + result.named_args.should eq({"src_dir" => "/path/to/src", "build_dir" => "/path/to/build"}) + result.nameless_args.should eq ["and", "more"] end end diff --git a/spec/features/negation_spec.cr b/spec/features/negation_spec.cr index 04fb706..98c355f 100644 --- a/spec/features/negation_spec.cr +++ b/spec/features/negation_spec.cr @@ -1,14 +1,12 @@ require "../spec_helper" -module Optarg::NegationFeature - class Model < ::Optarg::Model +module OptargNegationFeature + class Model < Optarg::Model bool "-b", default: true, not: "-B" end -end -describe "Negation" do - it "" do - result = Optarg::NegationFeature::Model.parse(%w(-B)) + it name do + result = Model.parse(%w(-B)) result.b?.should be_false end end diff --git a/spec/features/nilable_accessor_spec.cr b/spec/features/nilable_accessor_spec.cr index 7e45115..e53d1fc 100644 --- a/spec/features/nilable_accessor_spec.cr +++ b/spec/features/nilable_accessor_spec.cr @@ -1,14 +1,12 @@ require "../spec_helper" -module Optarg::NilableAccessorFeature - class Model < ::Optarg::Model +module OptargNilableAccessorFeature + class Model < Optarg::Model string "--foo" end -end -describe "Nilable Accessor" do - it "" do - result = Optarg::NilableAccessorFeature::Model.parse(%w()) + it name do + result = Model.parse(%w()) result.foo?.should be_nil expect_raises(KeyError) { result.foo } end diff --git a/spec/features/required_arguments_and_options_spec.cr b/spec/features/required_arguments_and_options_spec.cr index e25422e..9badafa 100644 --- a/spec/features/required_arguments_and_options_spec.cr +++ b/spec/features/required_arguments_and_options_spec.cr @@ -1,19 +1,21 @@ require "../spec_helper" -module Optarg::RequiredArgumentsAndOptionsFeature +module OptargRequiredArgumentsAndOptionsFeature class Compile < Optarg::Model arg "source_file", required: true end - it "Required Arguments" do - expect_raises(Optarg::RequiredArgumentError) { Compile.parse %w() } - end - class Profile < Optarg::Model string "--birthday", required: true end - it "Required Options" do - expect_raises(Optarg::RequiredOptionError) { Profile.parse %w() } + describe name do + it "Arguments" do + expect_raises(Optarg::RequiredArgumentError) { Compile.parse %w() } + end + + it "Options" do + expect_raises(Optarg::RequiredOptionError) { Profile.parse %w() } + end end end diff --git a/spec/features/synonyms_spec.cr b/spec/features/synonyms_spec.cr index cf594ed..70ead99 100644 --- a/spec/features/synonyms_spec.cr +++ b/spec/features/synonyms_spec.cr @@ -1,14 +1,12 @@ require "../spec_helper" -module Optarg::SynonymsFeature - class Model < ::Optarg::Model +module OptargSynonymsFeature + class Model < Optarg::Model string %w(-f --file) end -end -describe "Synonyms" do - it "" do - result = Optarg::SynonymsFeature::Model.parse(%w(-f foo.cr)) + it name do + result = Model.parse(%w(-f foo.cr)) result.f.should eq "foo.cr" result.file.should eq "foo.cr" end diff --git a/spec/internal/argument_display_name_spec.cr b/spec/internal/argument_display_name_spec.cr index 2bba33e..71f8cde 100644 --- a/spec/internal/argument_display_name_spec.cr +++ b/spec/internal/argument_display_name_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargArugmentDisplayNameFeature +module OptargInternalArugmentDisplayNameFeature class Model < Optarg::Model arg "arg1" arg "arg2", required: true diff --git a/spec/internal/argument_has_default_setter_spec.cr b/spec/internal/argument_has_default_setter_spec.cr index 9255e39..31305ee 100644 --- a/spec/internal/argument_has_default_setter_spec.cr +++ b/spec/internal/argument_has_default_setter_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargArugmentHasDefaultSetterFeature +module OptargInternalArugmentHasDefaultSetterFeature class Model < Optarg::Model arg "arg", default: "default" end diff --git a/spec/internal/array_default_spec.cr b/spec/internal/array_default_spec.cr index 7685323..959288e 100644 --- a/spec/internal/array_default_spec.cr +++ b/spec/internal/array_default_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargArrayDefaultFeature +module OptargInternalArrayDefaultFeature class Model < Optarg::Model array "-a", default: %w(default) end diff --git a/spec/internal/array_has_min_method_spec.cr b/spec/internal/array_has_min_method_spec.cr index 0d38227..538cf4c 100644 --- a/spec/internal/array_has_min_method_spec.cr +++ b/spec/internal/array_has_min_method_spec.cr @@ -1,11 +1,11 @@ require "../spec_helper" -module Optarg::ArrayHasMinMethodFeature +module OptargInternalArrayHasMinMethodFeature class Model < Optarg::Model array "-a", min: 1 end - it "array has 'min' method" do + it name do option = Model.__options["-a"] option.responds_to?(:min).should be_true if option.responds_to?(:min) diff --git a/spec/internal/bool_has_not_method_spec.cr b/spec/internal/bool_has_not_method_spec.cr index 44bf57a..47c5d2e 100644 --- a/spec/internal/bool_has_not_method_spec.cr +++ b/spec/internal/bool_has_not_method_spec.cr @@ -1,11 +1,11 @@ require "../spec_helper" -module Optarg::BoolHasNotMethodFeature +module OptargInternalBoolHasNotMethodFeature class Model < Optarg::Model bool "-b", not: "-B" end - it "bool has 'not' method" do + it name do option = Model.__options["-b"] option.responds_to?(:not).should be_true if option.responds_to?(:not) diff --git a/spec/internal/definition_has_group_spec.cr b/spec/internal/definition_has_group_spec.cr index ff20563..c939264 100644 --- a/spec/internal/definition_has_group_spec.cr +++ b/spec/internal/definition_has_group_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargDefinitionHasGroupFeature +module OptargInternalDefinitionHasGroupFeature class Model < Optarg::Model arg "arg", group: :arg array "-a", group: :array diff --git a/spec/internal/no_accessor_spec.cr b/spec/internal/no_accessor_spec.cr index 3f24662..d236aa9 100644 --- a/spec/internal/no_accessor_spec.cr +++ b/spec/internal/no_accessor_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module Optarg::NoAccessorFeature +module OptargInternalNoAccessorFeature class ForArguments < ::Optarg::Model arg "to_s" arg "same" @@ -24,7 +24,7 @@ module Optarg::NoAccessorFeature model_methods.includes?("to_s").should be_false model_methods.includes?("same?").should be_false model_methods.includes?("unparsed_args").should be_false - args_methods = {{ ForArguments::ArgumentValueList.methods.map{|i| i.name.stringify} }} + args_methods = {{ ForArguments::ArgumentValueContainer.methods.map{|i| i.name.stringify} }} args_methods.includes?("to_s").should be_false args_methods.includes?("same?").should be_false args_methods.includes?("unparsed_args").should be_true @@ -36,7 +36,7 @@ module Optarg::NoAccessorFeature model_methods.includes?("to_s").should be_false model_methods.includes?("same?").should be_false model_methods.includes?("unparsed_args").should be_false - model_methods = {{ ForOptions::OptionValueList.methods.map{|i| i.name.stringify} }} + model_methods = {{ ForOptions::OptionValueContainer.methods.map{|i| i.name.stringify} }} model_methods.includes?("to_s").should be_false model_methods.includes?("same?").should be_false model_methods.includes?("unparsed_args").should be_true @@ -46,7 +46,7 @@ module Optarg::NoAccessorFeature result = ForStringSame.parse(%w()) model_methods = {{ ForStringSame.methods.map{|i| i.name.stringify} }} model_methods.includes?("same?").should be_false - model_methods = {{ ForStringSame::OptionValueList.methods.map{|i| i.name.stringify} }} + model_methods = {{ ForStringSame::OptionValueContainer.methods.map{|i| i.name.stringify} }} model_methods.includes?("same?").should be_false end end diff --git a/spec/internal/option_has_required_method_spec.cr b/spec/internal/option_has_required_method_spec.cr index b672076..b91412c 100644 --- a/spec/internal/option_has_required_method_spec.cr +++ b/spec/internal/option_has_required_method_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargOptionHasRequiredMethodFeature +module OptargInternalOptionHasRequiredMethodFeature class Model < Optarg::Model arg "arg" arg "required_arg", required: true diff --git a/spec/internal/raise_unknown_option_if_concatenated_options_not_matched_spec.cr b/spec/internal/raise_unknown_option_if_concatenated_options_not_matched_spec.cr index add198a..fa99eea 100644 --- a/spec/internal/raise_unknown_option_if_concatenated_options_not_matched_spec.cr +++ b/spec/internal/raise_unknown_option_if_concatenated_options_not_matched_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargRaiseUnknownOptionIfConcatenatedOptionsNotMatchedFeature +module OptargInternalRaiseUnknownOptionIfConcatenatedOptionsNotMatchedFeature class Model < Optarg::Model end diff --git a/spec/internal/raise_unknown_option_regardless_of_arg_spec.cr b/spec/internal/raise_unknown_option_regardless_of_arg_spec.cr index 8dd795a..6eef7bf 100644 --- a/spec/internal/raise_unknown_option_regardless_of_arg_spec.cr +++ b/spec/internal/raise_unknown_option_regardless_of_arg_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargRaiseUnknownOptionRegardlessOfArgFeature +module OptargInternalRaiseUnknownOptionRegardlessOfArgFeature class Model < Optarg::Model arg "arg" end diff --git a/spec/internal/raise_unsupported_concatenation_spec.cr b/spec/internal/raise_unsupported_concatenation_spec.cr index d37696e..9aae8d9 100644 --- a/spec/internal/raise_unsupported_concatenation_spec.cr +++ b/spec/internal/raise_unsupported_concatenation_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargRaiseUnsupportedConcatenationFeature +module OptargInternalRaiseUnsupportedConcatenationFeature class Model < Optarg::Model string "-s" array "-a" diff --git a/spec/internal/required_argument_error_preserves_object_spec.cr b/spec/internal/required_argument_error_preserves_object_spec.cr index a591c48..4642c9f 100644 --- a/spec/internal/required_argument_error_preserves_object_spec.cr +++ b/spec/internal/required_argument_error_preserves_object_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargRequiredArgumentErrorPreservesObjectFeature +module OptargInternalRequiredArgumentErrorPreservesObjectFeature class Model < Optarg::Model arg "arg1", required: true end diff --git a/spec/internal/stopper_spec.cr b/spec/internal/stopper_spec.cr index a565926..8b2d4bf 100644 --- a/spec/internal/stopper_spec.cr +++ b/spec/internal/stopper_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargStopperFeature +module OptargInternalStopperFeature class ArgumentModel < Optarg::Model arg "a", stop: true arg "arg" diff --git a/spec/internal/terminator_does_not_affect_another_model_spec.cr b/spec/internal/terminator_does_not_affect_another_model_spec.cr index a422e2b..0ee7cbc 100644 --- a/spec/internal/terminator_does_not_affect_another_model_spec.cr +++ b/spec/internal/terminator_does_not_affect_another_model_spec.cr @@ -1,6 +1,6 @@ require "../spec_helper" -module OptargTerminatorDoesNotAffectAnotherModelFeature +module OptargInternalTerminatorDoesNotAffectAnotherModelFeature class Terminated < Optarg::Model terminator "--" end diff --git a/spec/internal_spec.cr b/spec/internal_spec.cr index 4519f4d..93bbfd8 100644 --- a/spec/internal_spec.cr +++ b/spec/internal_spec.cr @@ -1,6 +1,6 @@ require "./spec_helper" -module Optarg::InternalFeatures +module OptargInternalFeature class ParseModel < ::Optarg::Model string "-s" bool "-b" @@ -17,8 +17,8 @@ module Optarg::InternalFeatures result.s?.should eq "v" result.b?.should be_true result.args.should eq %w(arg parsed) - result.args.named.should eq({"arg" => "arg"}) - result.args.nameless.should eq %w(parsed) + result.named_args.should eq({"arg" => "arg"}) + result.nameless_args.should eq %w(parsed) result.unparsed_args.should eq %w(unparsed) result.__parsed_nodes[0].should eq Optarg::Parser::Node.new(%w(-s v), [ParseModel.__options["-s"]] of Optarg::Definition) result.__parsed_nodes[1].should eq Optarg::Parser::Node.new(%w(-b), [ParseModel.__options["-b"]] of Optarg::Definition) @@ -236,7 +236,7 @@ module Optarg::InternalFeatures end it "Required" do - expect_raises(RequiredArgumentError) { RequiredArgModel.parse %w() } - expect_raises(RequiredOptionError) { RequiredStringModel.parse %w() } + expect_raises(Optarg::RequiredArgumentError) { RequiredArgModel.parse %w() } + expect_raises(Optarg::RequiredOptionError) { RequiredStringModel.parse %w() } end end diff --git a/src/optarg.cr b/src/optarg.cr index a4170b5..1d38ddb 100644 --- a/src/optarg.cr +++ b/src/optarg.cr @@ -1,34 +1,2 @@ require "./optarg/*" require "./optarg/option_mixins/*" - -module Optarg - macro define_option_type(type) - {% - snake = type.id.split("::").map{|i| i.underscore}.join("__").gsub(/^_+/, "") - attribute_name = "#{snake.id}_options" - variable_name = "@#{attribute_name.id}" - %} - - class ::Optarg::OptionValueList - {{variable_name.id}} = ::Hash(::String, ::{{type.id}}).new - getter :{{attribute_name.id}} - end - end - - macro define_array_option_type(type) - {% - snake = type.id.split("::").map{|i| i.underscore}.join("__").gsub(/^_+/, "") - attribute_name = "#{snake.id}_array_options" - variable_name = "@#{attribute_name.id}" - %} - - class ::Optarg::OptionValueList - {{variable_name.id}} = ::Hash(::String, ::Array(::{{type.id}})).new - getter :{{attribute_name.id}} - end - end -end - -Optarg.define_option_type ::String -Optarg.define_option_type ::Bool -Optarg.define_array_option_type ::String diff --git a/src/optarg/argument_value_list.cr b/src/optarg/argument_value_container.cr similarity index 86% rename from src/optarg/argument_value_list.cr rename to src/optarg/argument_value_container.cr index 1463aac..f4e0984 100644 --- a/src/optarg/argument_value_list.cr +++ b/src/optarg/argument_value_container.cr @@ -1,5 +1,5 @@ module Optarg - abstract class ArgumentValueList + abstract class ArgumentValueContainer macro method_missing(call) {% args = call.args.map{|i| i.id}.join(", ") @@ -29,13 +29,5 @@ module Optarg def inspect @__values.inspect end - - def nameless - __nameless - end - - def named - __named - end end end diff --git a/src/optarg/model.cr b/src/optarg/model.cr index aba89d5..961fca1 100644 --- a/src/optarg/model.cr +++ b/src/optarg/model.cr @@ -10,8 +10,8 @@ module Optarg super_option_metadata = "Optarg::Metadata" super_argument_metadata = "Optarg::Metadata" super_handler_metadata = "Optarg::Metadata" - super_option_value_list = "Optarg::OptionValueList" - super_argument_value_list = "Optarg::ArgumentValueList" + super_option_value_container = "Optarg::OptionValueContainer" + super_argument_value_container = "Optarg::ArgumentValueContainer" super_parser = "Optarg::Parser" else is_root = false @@ -21,8 +21,8 @@ module Optarg super_option_metadata = "#{@type.superclass}::Option::Metadata" super_argument_metadata = "#{@type.superclass}::Argument::Metadata" super_handler_metadata = "#{@type.superclass}::Handler::Metadata" - super_option_value_list = "#{@type.superclass}::OptionValueList" - super_argument_value_list = "#{@type.superclass}::ArgumentValueList" + super_option_value_container = "#{@type.superclass}::OptionValueContainer" + super_argument_value_container = "#{@type.superclass}::ArgumentValueContainer" super_parser = "#{@type.superclass}::Parser" end %} @@ -41,10 +41,10 @@ module Optarg end end - class OptionValueList < ::{{super_option_value_list.id}} + class OptionValueContainer < ::{{super_option_value_container.id}} end - class ArgumentValueList < ::{{super_argument_value_list.id}} + class ArgumentValueContainer < ::{{super_argument_value_container.id}} end @@__self_options = {} of ::String => ::Optarg::Option @@ -92,14 +92,14 @@ module Optarg end class Parser < ::{{super_parser.id}} - @parsed_options = ::{{@type}}::OptionValueList.new + @parsed_options = ::{{@type}}::OptionValueContainer.new def parsed_options - @parsed_options.as(::{{@type}}::OptionValueList) + @parsed_options.as(::{{@type}}::OptionValueContainer) end - @parsed_args = ::{{@type}}::ArgumentValueList.new + @parsed_args = ::{{@type}}::ArgumentValueContainer.new def parsed_args - @parsed_args.as(::{{@type}}::ArgumentValueList) + @parsed_args.as(::{{@type}}::ArgumentValueContainer) end def model @@ -141,11 +141,22 @@ module Optarg def __args; __parser.parsed_args; end def args; __args; end + def __named_args; __args.__named; end + def named_args; __named_args; end + + def __nameless_args; __args.__nameless; end + def nameless_args; __nameless_args; end + + def __parsed_args; __args.__values; end + def parsed_args; __parsed_args; end + + def __unparsed_args; __parser.unparsed_args; end + def unparsed_args; __unparsed_args; end + def __unparsed_args; __parser.unparsed_args; end def unparsed_args; __unparsed_args; end def __parsed_nodes; __parser.parsed_nodes; end - def parsed_nodes; __parsed_nodes; end private def __yield yield @@ -164,7 +175,5 @@ module Optarg end end -require "./argument_value_list" -require "./option_value_list" require "./model/macros/*" require "./model/dsl/*" diff --git a/src/optarg/model/dsl/arg.cr b/src/optarg/model/dsl/arg.cr index 9dc5626..27579ea 100644 --- a/src/optarg/model/dsl/arg.cr +++ b/src/optarg/model/dsl/arg.cr @@ -5,7 +5,7 @@ module Optarg method_name = name.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_") class_name = "Argument_" + method_name model_reserved = (::Optarg::Model.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} - args_reserved = (::Optarg::ArgumentValueList.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} + args_reserved = (::Optarg::ArgumentValueContainer.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} %} module Arguments @@ -27,7 +27,7 @@ module Optarg end end - class ArgumentValueList + class ArgumentValueContainer {% unless args_reserved.includes?(method_name.id) %} def {{method_name.id}} __named[{{name}}] diff --git a/src/optarg/model/dsl/array.cr b/src/optarg/model/dsl/array.cr index 09cfaa0..a872130 100644 --- a/src/optarg/model/dsl/array.cr +++ b/src/optarg/model/dsl/array.cr @@ -5,23 +5,23 @@ module Optarg names = [names] unless names.class_name == "ArrayLiteral" method_names = names.map{|i| i.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_")} model_reserved = (::Optarg::Model.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} - options_reserved = (::Optarg::OptionValueList.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} + options_reserved = (::Optarg::OptionValueContainer.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} %} __define_hashed_array_value_option ::String, ::Optarg::OptionMixins::Array(String), {{names}} {% for method_name, index in method_names %} - class OptionValueList + class OptionValueContainer {% unless options_reserved.includes?(method_name.id) %} def {{method_name.id}} - string_array_options[{{names[0]}}] + @__string_arrays[{{names[0]}}] end {% end %} end {% unless model_reserved.includes?(method_name.id) %} def {{method_name.id}} - __options.string_array_options[{{names[0]}}] + __options.__string_arrays[{{names[0]}}] end {% end %} {% end %} diff --git a/src/optarg/model/dsl/bool.cr b/src/optarg/model/dsl/bool.cr index e578f54..17ed019 100644 --- a/src/optarg/model/dsl/bool.cr +++ b/src/optarg/model/dsl/bool.cr @@ -6,23 +6,23 @@ module Optarg method_names = names.map{|i| i.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_")} not = [not] unless not.class_name == "ArrayLiteral" model_reserved = (::Optarg::Model.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} - options_reserved = (::Optarg::OptionValueList.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} + options_reserved = (::Optarg::OptionValueContainer.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} %} __define_hashed_value_option ::Bool, ::Optarg::OptionMixins::Bool, {{names}} {% for method_name, index in method_names %} - class OptionValueList + class OptionValueContainer {% unless options_reserved.includes?("#{method_name.id}?".id) %} def {{method_name.id}}? - !!bool_options[{{names[0]}}]? + !!@__bools[{{names[0]}}]? end {% end %} end {% unless model_reserved.includes?("#{method_name.id}?".id) %} def {{method_name.id}}? - !!__options.bool_options[{{names[0]}}]? + !!__options.__bools[{{names[0]}}]? end {% end %} {% end %} diff --git a/src/optarg/model/dsl/string.cr b/src/optarg/model/dsl/string.cr index 3cb40b2..d88fbb6 100644 --- a/src/optarg/model/dsl/string.cr +++ b/src/optarg/model/dsl/string.cr @@ -5,35 +5,35 @@ module Optarg names = [names] unless names.class_name == "ArrayLiteral" method_names = names.map{|i| i.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_")} model_reserved = (::Optarg::Model.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} - options_reserved = (::Optarg::OptionValueList.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} + options_reserved = (::Optarg::OptionValueContainer.methods + ::Reference.methods + ::Object.methods).map{|i| i.name} %} __define_hashed_value_option ::String, ::Optarg::OptionMixins::String, {{names}} {% for method_name, index in method_names %} - class OptionValueList + class OptionValueContainer {% unless options_reserved.includes?(method_name.id) %} def {{method_name.id}} - string_options[{{names[0]}}] + @__strings[{{names[0]}}] end {% end %} {% unless options_reserved.includes?("#{method_name.id}?".id) %} def {{method_name.id}}? - string_options[{{names[0]}}]? + @__strings[{{names[0]}}]? end {% end %} end {% unless model_reserved.includes?(method_name.id) %} def {{method_name.id}} - __options.string_options[{{names[0]}}] + __options.__strings[{{names[0]}}] end {% end %} {% unless model_reserved.includes?("#{method_name.id}?".id) %} def {{method_name.id}}? - __options.string_options[{{names[0]}}]? + __options.__strings[{{names[0]}}]? end {% end %} {% end %} diff --git a/src/optarg/model/macros/option.cr b/src/optarg/model/macros/option.cr index 69b452e..0957314 100644 --- a/src/optarg/model/macros/option.cr +++ b/src/optarg/model/macros/option.cr @@ -3,7 +3,6 @@ module Optarg macro __define_hashed_value_option(type, mixin, names) {% snake = type.id.split("::").map{|i| i.underscore}.join("__").gsub(/^_+/, "") - attribute_name = "#{snake.id}_options" names = [names] unless names.class_name == "ArrayLiteral" method_names = names.map{|i| i.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_")} class_name = "Option_" + method_names[0] @@ -31,7 +30,7 @@ module Optarg def preset_default_to(data) with_default? do |default| with_data?(data) do |data| - data.__options.{{attribute_name.id}}[key] = default + data.__options.__{{snake.id}}s[key] = default end end end @@ -45,7 +44,6 @@ module Optarg macro __define_hashed_array_value_option(type, mixin, names) {% snake = type.id.split("::").map{|i| i.underscore}.join("__").gsub(/^_+/, "") - attribute_name = "#{snake.id}_array_options" names = [names] unless names.class_name == "ArrayLiteral" method_names = names.map{|i| i.split("=")[0].gsub(/^-*/, "").gsub(/-/, "_")} class_name = "Option_" + method_names[0] @@ -72,14 +70,14 @@ module Optarg def preset_default_to(data) with_data?(data) do |data| - data.__options.{{attribute_name.id}}[key] = ::Array(::{{type.id}}).new + data.__options.__{{snake.id}}_arrays[key] = ::Array(::{{type.id}}).new end end def postset_default_to(data) with_default? do |default| with_data?(data) do |data| - data.__options.{{attribute_name.id}}[key] += default if data.__options.{{attribute_name.id}}[key].empty? + data.__options.__{{snake.id}}_arrays[key] += default if data.__options.__{{snake.id}}_arrays[key].empty? end end end diff --git a/src/optarg/option_mixins/array.cr b/src/optarg/option_mixins/array.cr index b8f18cf..c906cc7 100644 --- a/src/optarg/option_mixins/array.cr +++ b/src/optarg/option_mixins/array.cr @@ -24,12 +24,12 @@ module Optarg::OptionMixins end def parse(args, data) - data.__options.{{snake.id}}_array_options[key] << args[1] + data.__options.__{{snake.id}}_arrays[key] << args[1] end def validate(data) with_data?(data) do |data| - size = data.__options.{{snake.id}}_array_options[key].size + size = data.__options.__{{snake.id}}_arrays[key].size raise ::Optarg::MinimumLengthError.new(key, @min, size) if @min > 0 && size < @min end end diff --git a/src/optarg/option_mixins/bool.cr b/src/optarg/option_mixins/bool.cr index 392dd55..ac918a9 100644 --- a/src/optarg/option_mixins/bool.cr +++ b/src/optarg/option_mixins/bool.cr @@ -27,9 +27,9 @@ module Optarg::OptionMixins def parse(args, data) if matches_to_not?(args[0]) - data.__options.bool_options[key] = false + data.__options.__bools[key] = false else - data.__options.bool_options[key] = true + data.__options.__bools[key] = true end end diff --git a/src/optarg/option_mixins/string.cr b/src/optarg/option_mixins/string.cr index eb1f574..0347f5a 100644 --- a/src/optarg/option_mixins/string.cr +++ b/src/optarg/option_mixins/string.cr @@ -18,12 +18,12 @@ module Optarg::OptionMixins end def parse(args, data) - data.__options.string_options[key] = args[1] + data.__options.__strings[key] = args[1] end def validate(data) with_data?(data) do |data| - raise ::Optarg::RequiredOptionError.new(key) if @required && !data.__options.string_options[key]? + raise ::Optarg::RequiredOptionError.new(key) if @required && !data.__options.__strings[key]? end end diff --git a/src/optarg/option_value_container.cr b/src/optarg/option_value_container.cr new file mode 100644 index 0000000..6c7824b --- /dev/null +++ b/src/optarg/option_value_container.cr @@ -0,0 +1,37 @@ +module Optarg + abstract class OptionValueContainer + getter __strings = {} of ::String => ::String? + getter __bools = {} of ::String => ::Bool? + getter __string_arrays = {} of ::String => ::Array(::String) + + def [](klass : ::String.class) + @__strings + end + + def [](klass : ::Bool.class) + @__bools + end + + def [](klass : ::Array(::String).class) + @__string_arrays + end + + def __to_tuple + { + string: @__strings, + bool: @__bools, + array: { + string: @__string_arrays + } + } + end + + def ==(other) + __to_tuple == other + end + + def inspect + __to_tuple.inspect + end + end +end diff --git a/src/optarg/option_value_list.cr b/src/optarg/option_value_list.cr deleted file mode 100644 index 3316869..0000000 --- a/src/optarg/option_value_list.cr +++ /dev/null @@ -1,4 +0,0 @@ -module Optarg - abstract class OptionValueList - end -end diff --git a/src/optarg/parser.cr b/src/optarg/parser.cr index 9d5bd70..28243be 100644 --- a/src/optarg/parser.cr +++ b/src/optarg/parser.cr @@ -12,8 +12,8 @@ module Optarg getter args : Array(String) @argument_index = 0 @index = 0 - @parsed_args : ArgumentValueList? - @parsed_options : OptionValueList? + @parsed_args : ArgumentValueContainer? + @parsed_options : OptionValueContainer? getter unparsed_args = %w() getter parsed_nodes = [] of Node @@ -125,12 +125,12 @@ module Optarg df = model.__arguments.values[@argument_index] @stopped__p ||= df.stops? parsed_args.__named[df.key] = arg - parsed_args << arg + parsed_args.__values << arg parsed_nodes << Node.new([arg], [df] of Definition) @argument_index += 1 else parsed_args.__nameless << arg - parsed_args << arg + parsed_args.__values << arg parsed_nodes << Node.new([arg], [] of Definition) end @index + 1