command_mapper 0.1.1 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.document +3 -0
- data/.github/workflows/ruby.yml +2 -1
- data/ChangeLog.md +32 -0
- data/Gemfile +2 -0
- data/LICENSE.txt +1 -1
- data/README.md +41 -8
- data/examples/grep.rb +62 -0
- data/lib/command_mapper/arg.rb +5 -0
- data/lib/command_mapper/argument.rb +6 -0
- data/lib/command_mapper/command.rb +209 -56
- data/lib/command_mapper/option.rb +50 -13
- data/lib/command_mapper/option_value.rb +22 -0
- data/lib/command_mapper/types/enum.rb +8 -0
- data/lib/command_mapper/types/hex.rb +16 -2
- data/lib/command_mapper/types/input_dir.rb +2 -0
- data/lib/command_mapper/types/input_file.rb +2 -0
- data/lib/command_mapper/types/input_path.rb +2 -0
- data/lib/command_mapper/types/key_value.rb +10 -0
- data/lib/command_mapper/types/key_value_list.rb +2 -0
- data/lib/command_mapper/types/list.rb +10 -0
- data/lib/command_mapper/types/map.rb +12 -1
- data/lib/command_mapper/types/num.rb +28 -1
- data/lib/command_mapper/types/str.rb +10 -1
- data/lib/command_mapper/types/type.rb +4 -0
- data/lib/command_mapper/version.rb +1 -1
- data/spec/commnad_spec.rb +345 -74
- data/spec/option_spec.rb +252 -1
- data/spec/option_value_spec.rb +28 -0
- data/spec/types/hex_spec.rb +59 -1
- data/spec/types/map_spec.rb +2 -2
- data/spec/types/num_spec.rb +93 -3
- metadata +4 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: abc51ed8c1f7edf0484053eb62854a56b13dce9d5e3ea7b3373799c4b7a1d4fb
         | 
| 4 | 
            +
              data.tar.gz: 0e7945e79e57cb99a4448b4eafef1237e9cc5e06d4523e13efd68b2767106a2f
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: ea9449f43ab086e941cc011dffd778cea4d356a2a9171aef5496e9a4593f62ca3ba68356d455cc510046ee926970c290c065b76bf445ba843a317f60c0fbbd31
         | 
| 7 | 
            +
              data.tar.gz: 5979c264d481d50be2fed8ca17a19cb59b4c522303ff4d5cdf14164195b9b27fd6589ebe5b8e0b06276494f5298c6898fb297a97a606ca10d5fb916dbe1d568d
         | 
    
        data/.document
    ADDED
    
    
    
        data/.github/workflows/ruby.yml
    CHANGED
    
    
    
        data/ChangeLog.md
    CHANGED
    
    | @@ -1,3 +1,35 @@ | |
| 1 | 
            +
            ### 0.2.1 / 2022-04-22
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            * Properly validate in {CommandMapper::OptionValue#validate} when an option,
         | 
| 4 | 
            +
              who's value is not required, is given `true`.
         | 
| 5 | 
            +
            * Omit `nil` arguments from {CommandMapper::Command#command_argv} if the
         | 
| 6 | 
            +
              argument is not required.
         | 
| 7 | 
            +
            * Improve validation error message for {CommandMapper::Types::Num} when
         | 
| 8 | 
            +
              initialized with a `range:` value.
         | 
| 9 | 
            +
            * Improve validation error message for {CommandMapper::Types::Map} and 
         | 
| 10 | 
            +
              {CommandMapper::Types::Enum}.
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            ### 0.2.0 / 2022-04-18
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            * Added {CommandMapper::Command.spawn} and
         | 
| 15 | 
            +
              {CommandMapper::Command#spawn_command}.
         | 
| 16 | 
            +
            * Added checks to {CommandMapper::Command.option},
         | 
| 17 | 
            +
              {CommandMapper::Command.argument}, and {CommandMapper::Command.subcommand} to
         | 
| 18 | 
            +
              avoid overwriting an existing option/argument/subcommand with the same name.
         | 
| 19 | 
            +
            * Added the `value_in_flag:` keyword argument to
         | 
| 20 | 
            +
              {CommandMapper::Command.option} which indicates an option's value
         | 
| 21 | 
            +
              should be appended to the flag (ex: `-Fvalue`).
         | 
| 22 | 
            +
            * Added the `range:` keyword argument to {CommandMapper::Types::Num#initialize}
         | 
| 23 | 
            +
              for specifying the acceptable range of numbers.
         | 
| 24 | 
            +
            * Allow options with `equals: true` (aka `--opt=...`) or `value_in_flag: true`
         | 
| 25 | 
            +
              (aka `-Fvalue`) to accept values that start with a `-` character.
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            ### 0.1.2 / 2021-11-29
         | 
| 28 | 
            +
             | 
| 29 | 
            +
            * Fixed a bug where {CommandMapper::Command.command_name} was not checking the
         | 
| 30 | 
            +
              superclass for the {CommandMapper::Command.command_name command_name}, if no
         | 
| 31 | 
            +
              `command "..."` was defined in the subclass.
         | 
| 32 | 
            +
             | 
| 1 33 | 
             
            ### 0.1.1 / 2021-11-29
         | 
| 2 34 |  | 
| 3 35 | 
             
            * Fixed a bug where {CommandMapper::Types::Num}, {CommandMapper::Types::Hex},
         | 
    
        data/Gemfile
    CHANGED
    
    
    
        data/LICENSE.txt
    CHANGED
    
    
    
        data/README.md
    CHANGED
    
    | @@ -21,9 +21,9 @@ allow safely and securely executing commands. | |
| 21 21 | 
             
                * [Str][CommandMapper::Types::Str]: string values
         | 
| 22 22 | 
             
                * [Num][CommandMapper::Types::Num]: numeric values
         | 
| 23 23 | 
             
                * [Hex][CommandMapper::Types::Hex]: hexadecimal values
         | 
| 24 | 
            -
                * [Map][CommandMapper::Types::Map]: maps  | 
| 25 | 
            -
                  ` | 
| 26 | 
            -
                   | 
| 24 | 
            +
                * [Map][CommandMapper::Types::Map]: maps Ruby values to other String values.
         | 
| 25 | 
            +
                  * `Map::YesNo`: maps `true`/`false` to `yes`/`no`.
         | 
| 26 | 
            +
                  * `Map::EnabledDisabled`: Maps `true`/`false` to `enabled`/`disabled`.
         | 
| 27 27 | 
             
                * [Enum][CommandMapper::Types::Enum]: maps a finite set of Symbols to a
         | 
| 28 28 | 
             
                  finite set of Strings (aka `--opt={foo|bar|baz}` values).
         | 
| 29 29 | 
             
                * [List][CommandMapper::Types::List]: comma-separated list
         | 
| @@ -43,7 +43,10 @@ allow safely and securely executing commands. | |
| 43 43 | 
             
            * Allows running commands with additional environment variables.
         | 
| 44 44 | 
             
            * Allows overriding the command name or path to the command.
         | 
| 45 45 | 
             
            * Allows running commands via `sudo`.
         | 
| 46 | 
            -
            * Prevents command injection and option injection.
         | 
| 46 | 
            +
            * Prevents [command injection] and [option injection].
         | 
| 47 | 
            +
             | 
| 48 | 
            +
            [command injection]: https://owasp.org/www-community/attacks/Command_Injection
         | 
| 49 | 
            +
            [option injection]: https://staaldraad.github.io/post/2019-11-24-argument-injection/
         | 
| 47 50 |  | 
| 48 51 | 
             
            [CommandMapper::Types::Str]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Str
         | 
| 49 52 | 
             
            [CommandMapper::Types::Num]: https://rubydoc.info/gems/command_mapper/CommandMapper/Types/Num
         | 
| @@ -73,7 +76,7 @@ class Grep < CommandMapper::Command | |
| 73 76 | 
             
                option "--basic-regexp"
         | 
| 74 77 | 
             
                option "--perl-regexp"
         | 
| 75 78 | 
             
                option "--regexp", equals: true, value: true
         | 
| 76 | 
            -
                option "--file", equals: true, value: true
         | 
| 79 | 
            +
                option "--file", name: :patterns_file, equals: true, value: true
         | 
| 77 80 | 
             
                option "--ignore-case"
         | 
| 78 81 | 
             
                option "--no-ignore-case"
         | 
| 79 82 | 
             
                option "--word-regexp"
         | 
| @@ -142,6 +145,18 @@ Defines an option with a required value: | |
| 142 145 | 
             
            option "--output", value: {required: true}
         | 
| 143 146 | 
             
            ```
         | 
| 144 147 |  | 
| 148 | 
            +
            Defines an option that uses an equals sign (ex: `--output=value`):
         | 
| 149 | 
            +
             | 
| 150 | 
            +
            ```ruby
         | 
| 151 | 
            +
            option "--output", equals: true, value: {required: true}
         | 
| 152 | 
            +
            ```
         | 
| 153 | 
            +
             | 
| 154 | 
            +
            Defines an option where the value is embedded into the flag (ex: `-Ivalue`):
         | 
| 155 | 
            +
             | 
| 156 | 
            +
            ```ruby
         | 
| 157 | 
            +
            option "-I", value: {required: true}, value_in_flag: true
         | 
| 158 | 
            +
            ```
         | 
| 159 | 
            +
             | 
| 145 160 | 
             
            Defines an option that can be specified multiple times:
         | 
| 146 161 |  | 
| 147 162 | 
             
            ```ruby
         | 
| @@ -154,6 +169,12 @@ Defines an option that accepts a numeric value: | |
| 154 169 | 
             
            option "--count", value: {type: Num.new}
         | 
| 155 170 | 
             
            ```
         | 
| 156 171 |  | 
| 172 | 
            +
            Define an option that only accepts a range of acceptable values:
         | 
| 173 | 
            +
             | 
| 174 | 
            +
            ```ruby
         | 
| 175 | 
            +
            option "--count", value: {type: Num.new(range: 1..100)}
         | 
| 176 | 
            +
            ```
         | 
| 177 | 
            +
             | 
| 157 178 | 
             
            Defines an option that accepts a comma-separated list:
         | 
| 158 179 |  | 
| 159 180 | 
             
            ```ruby
         | 
| @@ -293,6 +314,18 @@ Grep.run do |grep| | |
| 293 314 | 
             
            end
         | 
| 294 315 | 
             
            ```
         | 
| 295 316 |  | 
| 317 | 
            +
            Overriding the command name:
         | 
| 318 | 
            +
             | 
| 319 | 
            +
            ```ruby
         | 
| 320 | 
            +
            Grep.run(..., command_name: 'grep2')
         | 
| 321 | 
            +
            ```
         | 
| 322 | 
            +
             | 
| 323 | 
            +
            Specifying the direct path to the command:
         | 
| 324 | 
            +
             | 
| 325 | 
            +
            ```ruby
         | 
| 326 | 
            +
            Grep.run(..., command_path: '/path/to/grep')
         | 
| 327 | 
            +
            ```
         | 
| 328 | 
            +
             | 
| 296 329 | 
             
            ### Capturing output
         | 
| 297 330 |  | 
| 298 331 | 
             
            ```ruby
         | 
| @@ -368,18 +401,18 @@ $ gem install command_mapper | |
| 368 401 | 
             
            ### Gemfile
         | 
| 369 402 |  | 
| 370 403 | 
             
            ```ruby
         | 
| 371 | 
            -
            gem 'command_mapper', '~> 0. | 
| 404 | 
            +
            gem 'command_mapper', '~> 0.2'
         | 
| 372 405 | 
             
            ```
         | 
| 373 406 |  | 
| 374 407 | 
             
            ### gemspec
         | 
| 375 408 |  | 
| 376 409 | 
             
            ```ruby
         | 
| 377 | 
            -
            gemspec.add_dependency 'command_mapper', '~> 0. | 
| 410 | 
            +
            gemspec.add_dependency 'command_mapper', '~> 0.2'
         | 
| 378 411 | 
             
            ```
         | 
| 379 412 |  | 
| 380 413 | 
             
            ## License
         | 
| 381 414 |  | 
| 382 | 
            -
            Copyright (c) 2021 Hal Brodigan
         | 
| 415 | 
            +
            Copyright (c) 2021-2022 Hal Brodigan
         | 
| 383 416 |  | 
| 384 417 | 
             
            See {file:LICENSE.txt} for license information.
         | 
| 385 418 |  | 
    
        data/examples/grep.rb
    ADDED
    
    | @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            require 'command_mapper/command'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            #
         | 
| 4 | 
            +
            # Represents the `grep` command
         | 
| 5 | 
            +
            #
         | 
| 6 | 
            +
            class Grep < CommandMapper::Command
         | 
| 7 | 
            +
             | 
| 8 | 
            +
              command "grep" do
         | 
| 9 | 
            +
                option "--extended-regexp"
         | 
| 10 | 
            +
                option "--fixed-strings"
         | 
| 11 | 
            +
                option "--basic-regexp"
         | 
| 12 | 
            +
                option "--perl-regexp"
         | 
| 13 | 
            +
                option "--regexp", equals: true, value: true
         | 
| 14 | 
            +
                option "--file", name: :patterns_file, equals: true, value: true
         | 
| 15 | 
            +
                option "--ignore-case"
         | 
| 16 | 
            +
                option "--no-ignore-case"
         | 
| 17 | 
            +
                option "--word-regexp"
         | 
| 18 | 
            +
                option "--line-regexp"
         | 
| 19 | 
            +
                option "--null-data"
         | 
| 20 | 
            +
                option "--no-messages"
         | 
| 21 | 
            +
                option "--invert-match"
         | 
| 22 | 
            +
                option "--version"
         | 
| 23 | 
            +
                option "--help"
         | 
| 24 | 
            +
                option "--max-count", equals: true, value: {type: Num.new}
         | 
| 25 | 
            +
                option "--byte-offset"
         | 
| 26 | 
            +
                option "--line-number"
         | 
| 27 | 
            +
                option "--line-buffered"
         | 
| 28 | 
            +
                option "--with-filename"
         | 
| 29 | 
            +
                option "--no-filename"
         | 
| 30 | 
            +
                option "--label", equals: true, value: true
         | 
| 31 | 
            +
                option "--only-matching"
         | 
| 32 | 
            +
                option "--quiet"
         | 
| 33 | 
            +
                option "--binary-files", equals: true, value: true
         | 
| 34 | 
            +
                option "--text"
         | 
| 35 | 
            +
                option "-I", name: :binary
         | 
| 36 | 
            +
                option "--directories", equals: true, value: true
         | 
| 37 | 
            +
                option "--devices", equals: true, value: true
         | 
| 38 | 
            +
                option "--recursive"
         | 
| 39 | 
            +
                option "--dereference-recursive"
         | 
| 40 | 
            +
                option "--include", equals: true, value: true
         | 
| 41 | 
            +
                option "--exclude", equals: true, value: true
         | 
| 42 | 
            +
                option "--exclude-from", equals: true, value: true
         | 
| 43 | 
            +
                option "--exclude-dir", equals: true, value: true
         | 
| 44 | 
            +
                option "--files-without-match", value: true
         | 
| 45 | 
            +
                option "--files-with-matches"
         | 
| 46 | 
            +
                option "--count"
         | 
| 47 | 
            +
                option "--initial-tab"
         | 
| 48 | 
            +
                option "--null"
         | 
| 49 | 
            +
                option "--before-context", equals: true, value: {type: Num.new}
         | 
| 50 | 
            +
                option "--after-context", equals: true, value: {type: Num.new}
         | 
| 51 | 
            +
                option "--context", equals: true, value: {type: Num.new}
         | 
| 52 | 
            +
                option "--group-separator", equals: true, value: true
         | 
| 53 | 
            +
                option "--no-group-separator"
         | 
| 54 | 
            +
                option "--color", equals: :optional, value: {required: false}
         | 
| 55 | 
            +
                option "--colour", equals: :optional, value: {required: false}
         | 
| 56 | 
            +
                option "--binary"
         | 
| 57 | 
            +
             | 
| 58 | 
            +
                argument :patterns
         | 
| 59 | 
            +
                argument :file, required: false, repeats: true
         | 
| 60 | 
            +
              end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            end
         | 
    
        data/lib/command_mapper/arg.rb
    CHANGED
    
    | @@ -6,6 +6,7 @@ module CommandMapper | |
| 6 6 | 
             
              # The base class for both {Option options} and {Argument arguments}.
         | 
| 7 7 | 
             
              #
         | 
| 8 8 | 
             
              class Arg
         | 
| 9 | 
            +
             | 
| 9 10 | 
             
                # The argument's arg's type.
         | 
| 10 11 | 
             
                #
         | 
| 11 12 | 
             
                # @return [Types::Type, nil]
         | 
| @@ -23,6 +24,8 @@ module CommandMapper | |
| 23 24 | 
             
                # @raise [ArgumentError]
         | 
| 24 25 | 
             
                #   The `type` keyword argument was given a `nil` value.
         | 
| 25 26 | 
             
                #
         | 
| 27 | 
            +
                # @api private
         | 
| 28 | 
            +
                #
         | 
| 26 29 | 
             
                def initialize(required: true, type: Types::Str.new)
         | 
| 27 30 | 
             
                  @required = required
         | 
| 28 31 |  | 
| @@ -61,6 +64,8 @@ module CommandMapper | |
| 61 64 | 
             
                #   Returns true if the value is valid, or `false` and a validation error
         | 
| 62 65 | 
             
                #   message if the value is not compatible.
         | 
| 63 66 | 
             
                #
         | 
| 67 | 
            +
                # @api semipublic
         | 
| 68 | 
            +
                #
         | 
| 64 69 | 
             
                def validate(value)
         | 
| 65 70 | 
             
                  if value.nil?
         | 
| 66 71 | 
             
                    if required?
         | 
| @@ -30,6 +30,8 @@ module CommandMapper | |
| 30 30 | 
             
                # @raise [ArgumentError]
         | 
| 31 31 | 
             
                #   The given `type:` must not be `false` or `nil`.
         | 
| 32 32 | 
             
                #
         | 
| 33 | 
            +
                # @api private
         | 
| 34 | 
            +
                #
         | 
| 33 35 | 
             
                def initialize(name, required: true, type: Types::Str.new, repeats: false)
         | 
| 34 36 | 
             
                  super(required: required, type: type)
         | 
| 35 37 |  | 
| @@ -56,6 +58,8 @@ module CommandMapper | |
| 56 58 | 
             
                #   Returns true if the value is valid, or `false` and a validation error
         | 
| 57 59 | 
             
                #   message if the value is not compatible.
         | 
| 58 60 | 
             
                #
         | 
| 61 | 
            +
                # @api semipublic
         | 
| 62 | 
            +
                #
         | 
| 59 63 | 
             
                def validate(value)
         | 
| 60 64 | 
             
                  if repeats?
         | 
| 61 65 | 
             
                    values = case value
         | 
| @@ -101,6 +105,8 @@ module CommandMapper | |
| 101 105 | 
             
                # @raise [ArgumentError]
         | 
| 102 106 | 
             
                #   The given value was incompatible with the argument.
         | 
| 103 107 | 
             
                #
         | 
| 108 | 
            +
                # @api semipublic
         | 
| 109 | 
            +
                #
         | 
| 104 110 | 
             
                def argv(argv=[],value)
         | 
| 105 111 | 
             
                  valid, message = validate(value)
         | 
| 106 112 |  |