hammer_cli 0.17.1 → 0.18.0
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/config/cli_config.template.yml +3 -0
- data/doc/commands_modification.md +12 -1
- data/doc/creating_commands.md +35 -3
- data/doc/release_notes.md +6 -1
- data/lib/hammer_cli/abstract.rb +18 -8
- data/lib/hammer_cli/apipie/resource.rb +1 -1
- data/lib/hammer_cli/command_extensions.rb +17 -1
- data/lib/hammer_cli/options/predefined.rb +22 -0
- data/lib/hammer_cli/output/adapter/abstract.rb +24 -12
- data/lib/hammer_cli/output/adapter/base.rb +5 -11
- data/lib/hammer_cli/output/adapter/csv.rb +7 -3
- data/lib/hammer_cli/output/adapter/table.rb +9 -9
- data/lib/hammer_cli/output/adapter/tree_structure.rb +5 -10
- data/lib/hammer_cli/output/definition.rb +84 -0
- data/lib/hammer_cli/output/field_filter.rb +72 -9
- data/lib/hammer_cli/output/fields.rb +23 -3
- data/lib/hammer_cli/output/output.rb +2 -0
- data/lib/hammer_cli/ssloptions.rb +1 -1
- data/lib/hammer_cli/version.rb +1 -1
- data/test/unit/abstract_test.rb +5 -0
- data/test/unit/output/definition_test.rb +20 -0
- data/test/unit/output/field_filter_test.rb +60 -15
- metadata +3 -2
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: eb040c3f40863eea4ec0c05ac2d1ffc597b3ca9499470bda6ecc18ff66bcfad2
         | 
| 4 | 
            +
              data.tar.gz: acb3307c3d9fcda2903ae19f026f1b4767950562c1507cb02afc2e433a4094c0
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 89d7b3eb46518f18b718cef888205a1a62f03a079bd1e8600aae8217b99f882aa18a7fcc3a7787ab727c05a0a8ddc15690bcfc81ab8e19b2a7cb01c1f5034ac8
         | 
| 7 | 
            +
              data.tar.gz: bbbd9bc7fb32e52edfe4451c98c534330d577380074ca3095f00d7666f72e8879fc9efaffd0a141ee86daf006db78cce878e304af21eae50c555a5075da4d0a4
         | 
| @@ -72,3 +72,6 @@ | |
| 72 72 | 
             
              # Local CA cert store path where hammer stores certificates fetched from the server.
         | 
| 73 73 | 
             
              # Certs from the local storage are used only when neither :ssl_ca_file: nor :ssl_ca_path: is cofigured.
         | 
| 74 74 | 
             
              #:local_ca_store_path: '~/.hammer/certs'
         | 
| 75 | 
            +
             | 
| 76 | 
            +
             # Allows setting the SSL version to use when making API calls
         | 
| 77 | 
            +
              #:ssl_version: 'TLSv1_2'
         | 
| @@ -33,10 +33,15 @@ HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition| | |
| 33 33 | 
             
              end
         | 
| 34 34 | 
             
              # Returns output definition of the command or field specified with path.
         | 
| 35 35 | 
             
              # Where:
         | 
| 36 | 
            -
              #   path  | 
| 36 | 
            +
              #   path is an Array of field's :key or/and :id or/and 'label'
         | 
| 37 37 | 
             
              definition.at(path)
         | 
| 38 38 | 
             
              # Returns field from current output definition.
         | 
| 39 39 | 
             
              definition.find_field(:id)
         | 
| 40 | 
            +
              # Finds and adds fields to a set (creates a new one if the set doesn't exist).
         | 
| 41 | 
            +
              # Where:
         | 
| 42 | 
            +
              #   sets is an Array of String with set names
         | 
| 43 | 
            +
              #   fields is an Array of field's :key or/and :id or/and 'label'
         | 
| 44 | 
            +
              definition.update_field_sets(sets, fields)
         | 
| 40 45 | 
             
              # Deletes all fields from current output definition.
         | 
| 41 46 | 
             
              definition.clear
         | 
| 42 47 | 
             
            end
         | 
| @@ -55,6 +60,12 @@ HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition| | |
| 55 60 | 
             
                                                  definition.at(:path)
         | 
| 56 61 | 
             
                                                  .find_field(:id).label = _('New label')
         | 
| 57 62 | 
             
                                                end
         | 
| 63 | 
            +
            # Update fields in a field set
         | 
| 64 | 
            +
            # Adds fields with :field_id and 'My field' to 'SET' set
         | 
| 65 | 
            +
            HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
         | 
| 66 | 
            +
                                                  definition.at(:path)
         | 
| 67 | 
            +
                                                  .update_field_sets('SET', [:field_id, 'My field'])
         | 
| 68 | 
            +
                                                end
         | 
| 58 69 | 
             
            # Expand a field with new definition
         | 
| 59 70 | 
             
            HammerCLIForeman::Host::InfoCommand.extend_output_definition do |definition|
         | 
| 60 71 | 
             
                                                  definition.at([_('some'), :path])
         | 
    
        data/doc/creating_commands.md
    CHANGED
    
    | @@ -164,6 +164,14 @@ In cases when you want to deprecate just one of more possible switches use the e | |
| 164 164 | 
             
                :deprecated => { '--name' => _('Use --alias instead') }
         | 
| 165 165 | 
             
            ```
         | 
| 166 166 |  | 
| 167 | 
            +
            #### Predefined options
         | 
| 168 | 
            +
            Also Hammer offers predefined options now. Those are just options, but with
         | 
| 169 | 
            +
            predefined functionality. To define them in your command use
         | 
| 170 | 
            +
            `use_option :option_name` method.
         | 
| 171 | 
            +
             | 
| 172 | 
            +
            Here is the list of predefined options:
         | 
| 173 | 
            +
              * `:fields` Expects a list with fields to show in output, see [example](creating_commands.md#printing-hash-records).
         | 
| 174 | 
            +
             | 
| 167 175 |  | 
| 168 176 | 
             
            ### Option builders
         | 
| 169 177 | 
             
            Hammer commands offer option builders that can be used for automatic option generation.
         | 
| @@ -523,8 +531,12 @@ Imagine there's an API of some service that returns list of users: | |
| 523 531 | 
             
            ```
         | 
| 524 532 |  | 
| 525 533 | 
             
            We can create an output definition that selects and formats some of the fields:
         | 
| 534 | 
            +
             | 
| 535 | 
            +
            _NOTE_: Every field can be arranged in so-called field sets. All the fields by default go to `'DEFAULT'` and `'ALL'` sets. Fields which are in the `'DEFAULT'` set will be printed by default. To see printed other field sets, use predefined option `--fields NAME`, where `NAME` is a field set name in ALLCAPS.
         | 
| 526 536 | 
             
            ```ruby
         | 
| 527 537 | 
             
            class Command < HammerCLI::AbstractCommand
         | 
| 538 | 
            +
              # To be able to select fields which should be printed
         | 
| 539 | 
            +
              use_option :fields
         | 
| 528 540 |  | 
| 529 541 | 
             
              output do
         | 
| 530 542 | 
             
                # Simple field with a label. The first parameter is the key in the printed hash.
         | 
| @@ -536,7 +548,7 @@ class Command < HammerCLI::AbstractCommand | |
| 536 548 | 
             
                field :roles, 'System Roles', Fields::List
         | 
| 537 549 |  | 
| 538 550 | 
             
                # Label is used for grouping fields.
         | 
| 539 | 
            -
                label 'Contacts' do
         | 
| 551 | 
            +
                label 'Contacts', sets: ['ADDITIONAL', 'ALL'] do
         | 
| 540 552 | 
             
                  field :email, 'Email'
         | 
| 541 553 | 
             
                  field :phone, 'Phone No.'
         | 
| 542 554 | 
             
                end
         | 
| @@ -565,18 +577,38 @@ Using the base adapter the output will look like: | |
| 565 577 | 
             
            ID:            1
         | 
| 566 578 | 
             
            System Roles:  Admin, Editor
         | 
| 567 579 | 
             
            Name:          Tom Sawyer
         | 
| 580 | 
            +
            Created At:    2012/12/18 15:24:42
         | 
| 581 | 
            +
             | 
| 582 | 
            +
            ID:            2
         | 
| 583 | 
            +
            System Roles:  Admin
         | 
| 584 | 
            +
            Name:          Huckleberry Finn
         | 
| 585 | 
            +
            Created At:    2012/12/18 15:25:00
         | 
| 586 | 
            +
            ```
         | 
| 587 | 
            +
             | 
| 588 | 
            +
            Using the base adapter with `--fields ALL` or `--fields DEFAULT,ADDITIONAL` the output will look like:
         | 
| 589 | 
            +
            ```
         | 
| 590 | 
            +
            ID:            1
         | 
| 591 | 
            +
            System Roles:  Admin, Editor
         | 
| 592 | 
            +
            Name:          Tom Sawyer
         | 
| 593 | 
            +
            Created At:    2012/12/18 15:24:42
         | 
| 568 594 | 
             
            Contacts:
         | 
| 569 595 | 
             
              Email:       tom@email.com
         | 
| 570 596 | 
             
              Phone No.:   123456111
         | 
| 571 | 
            -
            Created At:    2012/12/18 15:24:42
         | 
| 572 597 |  | 
| 573 598 | 
             
            ID:            2
         | 
| 574 599 | 
             
            System Roles:  Admin
         | 
| 575 600 | 
             
            Name:          Huckleberry Finn
         | 
| 601 | 
            +
            Created At:    2012/12/18 15:25:00
         | 
| 576 602 | 
             
            Contacts:
         | 
| 577 603 | 
             
              Email:       huckleberry@email.com
         | 
| 578 604 | 
             
              Phone No.:   123456222
         | 
| 579 | 
            -
             | 
| 605 | 
            +
            ```
         | 
| 606 | 
            +
             | 
| 607 | 
            +
            _NOTE_: `--fields` as well lets you to print desired fields only. E.g. to see the users' emails without any additional information use `--fields contacts/email`:
         | 
| 608 | 
            +
            ```
         | 
| 609 | 
            +
            Email:       tom@email.com
         | 
| 610 | 
            +
             | 
| 611 | 
            +
            Email:       huckleberry@email.com
         | 
| 580 612 | 
             
            ```
         | 
| 581 613 |  | 
| 582 614 | 
             
            You can optionally use the output definition from another command as a base and extend it with
         | 
    
        data/doc/release_notes.md
    CHANGED
    
    | @@ -1,6 +1,11 @@ | |
| 1 1 | 
             
            Release notes
         | 
| 2 2 | 
             
            =============
         | 
| 3 | 
            -
            ### 0. | 
| 3 | 
            +
            ### 0.18.0 (2019-08-01)
         | 
| 4 | 
            +
            * Unsure minimal label length ([PR #310](https://github.com/theforeman/hammer-cli/pull/310)) ([#26960](http://projects.theforeman.org/issues/26960))
         | 
| 5 | 
            +
            * The --fields option has set help ([PR #308](https://github.com/theforeman/hammer-cli/pull/308)) ([#26960](http://projects.theforeman.org/issues/26960))
         | 
| 6 | 
            +
            * Filter fields properly ([#26961](http://projects.theforeman.org/issues/26961))
         | 
| 7 | 
            +
            * Possibility to limit fields that are displayed ([PR #276](https://github.com/theforeman/hammer-cli/pull/276)) ([#19135](http://projects.theforeman.org/issues/19135))
         | 
| 8 | 
            +
            * Allow setting the SSL version to use for API calls
         | 
| 4 9 | 
             
            * Make sure list opts return a list ([#26703](http://projects.theforeman.org/issues/26703))
         | 
| 5 10 |  | 
| 6 11 | 
             
            ### 0.17.0 (2019-04-24)
         | 
    
        data/lib/hammer_cli/abstract.rb
    CHANGED
    
    | @@ -9,13 +9,13 @@ require 'hammer_cli/options/validators/dsl_block_validator' | |
| 9 9 | 
             
            require 'hammer_cli/clamp'
         | 
| 10 10 | 
             
            require 'hammer_cli/subcommand'
         | 
| 11 11 | 
             
            require 'hammer_cli/options/matcher'
         | 
| 12 | 
            +
            require 'hammer_cli/options/predefined'
         | 
| 12 13 | 
             
            require 'hammer_cli/help/builder'
         | 
| 13 14 | 
             
            require 'hammer_cli/help/text_builder'
         | 
| 14 15 | 
             
            require 'hammer_cli/command_extensions'
         | 
| 15 16 | 
             
            require 'logging'
         | 
| 16 17 |  | 
| 17 18 | 
             
            module HammerCLI
         | 
| 18 | 
            -
             | 
| 19 19 | 
             
              class AbstractCommand < Clamp::Command
         | 
| 20 20 | 
             
                include HammerCLI::Subcommand
         | 
| 21 21 |  | 
| @@ -57,6 +57,12 @@ module HammerCLI | |
| 57 57 | 
             
                      end
         | 
| 58 58 | 
             
                    end
         | 
| 59 59 | 
             
                  end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                  def add_sets_help(help)
         | 
| 62 | 
            +
                    sets_details = HammerCLI::Help::Section.new(_('Predefined field sets'), nil, id: :s_sets_details, richtext: true)
         | 
| 63 | 
            +
                    sets_details.definition << HammerCLI::Help::Text.new(output_definition.sets_table)
         | 
| 64 | 
            +
                    help.definition.unshift(sets_details)
         | 
| 65 | 
            +
                  end
         | 
| 60 66 | 
             
                end
         | 
| 61 67 |  | 
| 62 68 | 
             
                def adapter
         | 
| @@ -118,9 +124,10 @@ module HammerCLI | |
| 118 124 |  | 
| 119 125 | 
             
                def self.help(invocation_path, builder = HammerCLI::Help::Builder.new)
         | 
| 120 126 | 
             
                  super(invocation_path, builder)
         | 
| 121 | 
            -
             | 
| 127 | 
            +
                  help_extension = HammerCLI::Help::TextBuilder.new(builder.richtext)
         | 
| 128 | 
            +
                  fields_switch = HammerCLI::Options::Predefined::OPTIONS[:fields].first[0]
         | 
| 129 | 
            +
                  add_sets_help(help_extension) if find_option(fields_switch)
         | 
| 122 130 | 
             
                  unless help_extension_blocks.empty?
         | 
| 123 | 
            -
                    help_extension = HammerCLI::Help::TextBuilder.new(builder.richtext)
         | 
| 124 131 | 
             
                    help_extension_blocks.each do |extension_block|
         | 
| 125 132 | 
             
                      begin
         | 
| 126 133 | 
             
                        extension_block.call(help_extension)
         | 
| @@ -129,8 +136,8 @@ module HammerCLI | |
| 129 136 | 
             
                        handler.handle_exception(e)
         | 
| 130 137 | 
             
                      end
         | 
| 131 138 | 
             
                    end
         | 
| 132 | 
            -
                    builder.add_text(help_extension.string)
         | 
| 133 139 | 
             
                  end
         | 
| 140 | 
            +
                  builder.add_text(help_extension.string)
         | 
| 134 141 | 
             
                  builder.string
         | 
| 135 142 | 
             
                end
         | 
| 136 143 |  | 
| @@ -161,13 +168,11 @@ module HammerCLI | |
| 161 168 | 
             
                  self.class.output_definition
         | 
| 162 169 | 
             
                end
         | 
| 163 170 |  | 
| 164 | 
            -
             | 
| 165 171 | 
             
                def self.output_definition
         | 
| 166 172 | 
             
                  @output_definition = @output_definition || inherited_output_definition || HammerCLI::Output::Definition.new
         | 
| 167 173 | 
             
                  @output_definition
         | 
| 168 174 | 
             
                end
         | 
| 169 175 |  | 
| 170 | 
            -
             | 
| 171 176 | 
             
                def interactive?
         | 
| 172 177 | 
             
                  HammerCLI.interactive?
         | 
| 173 178 | 
             
                end
         | 
| @@ -197,6 +202,7 @@ module HammerCLI | |
| 197 202 | 
             
                      raise ArgumentError, _('Command extensions should be inherited from %s.') % HammerCLI::CommandExtensions
         | 
| 198 203 | 
             
                    end
         | 
| 199 204 | 
             
                    extension.delegatee(self)
         | 
| 205 | 
            +
                    extension.extend_predefined_options(self)
         | 
| 200 206 | 
             
                    extension.extend_options(self)
         | 
| 201 207 | 
             
                    extension.extend_output(self)
         | 
| 202 208 | 
             
                    extension.extend_help(self)
         | 
| @@ -205,6 +211,12 @@ module HammerCLI | |
| 205 211 | 
             
                  end
         | 
| 206 212 | 
             
                end
         | 
| 207 213 |  | 
| 214 | 
            +
                def self.use_option(*names)
         | 
| 215 | 
            +
                  names.each do |name|
         | 
| 216 | 
            +
                    HammerCLI::Options::Predefined.use(name, self)
         | 
| 217 | 
            +
                  end
         | 
| 218 | 
            +
                end
         | 
| 219 | 
            +
             | 
| 208 220 | 
             
                protected
         | 
| 209 221 |  | 
| 210 222 | 
             
                def self.find_options(switch_filter, other_filters={})
         | 
| @@ -316,7 +328,6 @@ module HammerCLI | |
| 316 328 | 
             
                  @option_collector ||= HammerCLI::Options::OptionCollector.new(self.class.recognised_options, add_validators(option_sources))
         | 
| 317 329 | 
             
                end
         | 
| 318 330 |  | 
| 319 | 
            -
             | 
| 320 331 | 
             
                def option_sources
         | 
| 321 332 | 
             
                  sources = HammerCLI::Options::ProcessorList.new(name: 'DefaultInputs')
         | 
| 322 333 | 
             
                  sources << HammerCLI::Options::Sources::CommandLine.new(self)
         | 
| @@ -348,6 +359,5 @@ module HammerCLI | |
| 348 359 | 
             
                  end
         | 
| 349 360 | 
             
                  od
         | 
| 350 361 | 
             
                end
         | 
| 351 | 
            -
             | 
| 352 362 | 
             
              end
         | 
| 353 363 | 
             
            end
         | 
| @@ -15,7 +15,7 @@ module HammerCLI | |
| 15 15 | 
             
                ALLOWED_EXTENSIONS = %i[
         | 
| 16 16 | 
             
                  option command_options before_print data output help request
         | 
| 17 17 | 
             
                  request_headers headers request_options options request_params params
         | 
| 18 | 
            -
                  option_sources
         | 
| 18 | 
            +
                  option_sources predefined_options use_option
         | 
| 19 19 | 
             
                ].freeze
         | 
| 20 20 |  | 
| 21 21 | 
             
                def initialize(options = {})
         | 
| @@ -54,6 +54,10 @@ module HammerCLI | |
| 54 54 | 
             
                                opts: opts, block: block }
         | 
| 55 55 | 
             
                end
         | 
| 56 56 |  | 
| 57 | 
            +
                def self.use_option(*names)
         | 
| 58 | 
            +
                  @predefined_option_names = names
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 57 61 | 
             
                def self.before_print(&block)
         | 
| 58 62 | 
             
                  @before_print_block = block
         | 
| 59 63 | 
             
                end
         | 
| @@ -91,6 +95,13 @@ module HammerCLI | |
| 91 95 | 
             
                  self.class.extend_options(command_class)
         | 
| 92 96 | 
             
                end
         | 
| 93 97 |  | 
| 98 | 
            +
                def extend_predefined_options(command_class)
         | 
| 99 | 
            +
                  allowed = @only & %i[predefined_options use_option]
         | 
| 100 | 
            +
                  return if allowed.empty? || (allowed & @except).any?
         | 
| 101 | 
            +
             | 
| 102 | 
            +
                  self.class.extend_predefined_options(command_class)
         | 
| 103 | 
            +
                end
         | 
| 104 | 
            +
             | 
| 94 105 | 
             
                def extend_before_print(data)
         | 
| 95 106 | 
             
                  allowed = @only & %i[before_print data]
         | 
| 96 107 | 
             
                  return if allowed.empty? || (allowed & @except).any?
         | 
| @@ -170,6 +181,11 @@ module HammerCLI | |
| 170 181 | 
             
                  end
         | 
| 171 182 | 
             
                end
         | 
| 172 183 |  | 
| 184 | 
            +
                def self.extend_predefined_options(command_class)
         | 
| 185 | 
            +
                  command_class.send(:use_option, *@predefined_option_names)
         | 
| 186 | 
            +
                  logger.debug("Added predefined options for #{command_class}: #{@predefined_option_names}")
         | 
| 187 | 
            +
                end
         | 
| 188 | 
            +
             | 
| 173 189 | 
             
                def self.extend_before_print(data)
         | 
| 174 190 | 
             
                  return if @before_print_block.nil?
         | 
| 175 191 |  | 
| @@ -0,0 +1,22 @@ | |
| 1 | 
            +
            # frozen_string_literal: true
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module HammerCLI
         | 
| 4 | 
            +
              module Options
         | 
| 5 | 
            +
                # Contains predefined by HammerCLI options for commands
         | 
| 6 | 
            +
                module Predefined
         | 
| 7 | 
            +
                  OPTIONS = {
         | 
| 8 | 
            +
                    fields: [['--fields'], 'FIELDS',
         | 
| 9 | 
            +
                             _('Show specified fileds or predefined filed sets only. (See below)'),
         | 
| 10 | 
            +
                             format: HammerCLI::Options::Normalizers::List.new,
         | 
| 11 | 
            +
                             context_target: :fields]
         | 
| 12 | 
            +
                  }.freeze
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                  def self.use(option_name, command_class)
         | 
| 15 | 
            +
                    unless OPTIONS.key?(option_name)
         | 
| 16 | 
            +
                      raise ArgumentError, _('There is no such predefined option %s.') % option_name
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                    command_class.send(:option, *OPTIONS[option_name])
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| @@ -6,11 +6,12 @@ module HammerCLI::Output::Adapter | |
| 6 6 | 
             
                  []
         | 
| 7 7 | 
             
                end
         | 
| 8 8 |  | 
| 9 | 
            -
                def initialize(context={}, formatters={})
         | 
| 9 | 
            +
                def initialize(context={}, formatters={}, filters = {})
         | 
| 10 10 | 
             
                  context[:verbosity] ||= HammerCLI::V_VERBOSE
         | 
| 11 11 | 
             
                  @context = context
         | 
| 12 12 | 
             
                  @formatters = HammerCLI::Output::Formatters::FormatterLibrary.new(filter_formatters(formatters))
         | 
| 13 13 | 
             
                  @paginate_by_default = true
         | 
| 14 | 
            +
                  @filters = filters
         | 
| 14 15 | 
             
                end
         | 
| 15 16 |  | 
| 16 17 | 
             
                def paginate_by_default?
         | 
| @@ -41,10 +42,14 @@ module HammerCLI::Output::Adapter | |
| 41 42 | 
             
                  raise NotImplementedError
         | 
| 42 43 | 
             
                end
         | 
| 43 44 |  | 
| 45 | 
            +
                def reset_context
         | 
| 46 | 
            +
                  @context.delete(:fields)
         | 
| 47 | 
            +
                end
         | 
| 48 | 
            +
             | 
| 44 49 | 
             
                protected
         | 
| 45 50 |  | 
| 46 | 
            -
                def  | 
| 47 | 
            -
                  HammerCLI::Output::FieldFilter.new
         | 
| 51 | 
            +
                def filter_fields(fields)
         | 
| 52 | 
            +
                  HammerCLI::Output::FieldFilter.new(fields, field_filters)
         | 
| 48 53 | 
             
                end
         | 
| 49 54 |  | 
| 50 55 | 
             
                def self.data_for_field(field, record)
         | 
| @@ -71,17 +76,25 @@ module HammerCLI::Output::Adapter | |
| 71 76 | 
             
                  $stdout
         | 
| 72 77 | 
             
                end
         | 
| 73 78 |  | 
| 74 | 
            -
                def  | 
| 75 | 
            -
                   | 
| 76 | 
            -
                     | 
| 77 | 
            -
                     | 
| 78 | 
            -
             | 
| 79 | 
            -
                     | 
| 80 | 
            -
                      field.display?(field_data)
         | 
| 81 | 
            -
                    end
         | 
| 79 | 
            +
                def field_filters
         | 
| 80 | 
            +
                  {
         | 
| 81 | 
            +
                    classes_filter: classes_filter,
         | 
| 82 | 
            +
                    sets_filter: sets_filter
         | 
| 83 | 
            +
                  }.merge(@filters) do |_, old_filter, new_filter|
         | 
| 84 | 
            +
                    old_filter + new_filter
         | 
| 82 85 | 
             
                  end
         | 
| 83 86 | 
             
                end
         | 
| 84 87 |  | 
| 88 | 
            +
                def classes_filter
         | 
| 89 | 
            +
                  return [] if @context[:show_ids]
         | 
| 90 | 
            +
             | 
| 91 | 
            +
                  [Fields::Id]
         | 
| 92 | 
            +
                end
         | 
| 93 | 
            +
             | 
| 94 | 
            +
                def sets_filter
         | 
| 95 | 
            +
                  @context[:fields] || ['DEFAULT']
         | 
| 96 | 
            +
                end
         | 
| 97 | 
            +
             | 
| 85 98 | 
             
                private
         | 
| 86 99 |  | 
| 87 100 | 
             
                def filter_formatters(formatters_map)
         | 
| @@ -94,6 +107,5 @@ module HammerCLI::Output::Adapter | |
| 94 107 | 
             
                    map
         | 
| 95 108 | 
             
                  end
         | 
| 96 109 | 
             
                end
         | 
| 97 | 
            -
             | 
| 98 110 | 
             
              end
         | 
| 99 111 | 
             
            end
         | 
| @@ -21,18 +21,12 @@ module HammerCLI::Output::Adapter | |
| 21 21 |  | 
| 22 22 | 
             
                protected
         | 
| 23 23 |  | 
| 24 | 
            -
                def field_filter
         | 
| 25 | 
            -
                  filtered = []
         | 
| 26 | 
            -
                  filtered << Fields::Id unless @context[:show_ids]
         | 
| 27 | 
            -
                  HammerCLI::Output::FieldFilter.new(filtered)
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 24 | 
             
                def render_fields(fields, data)
         | 
| 31 | 
            -
                  output =  | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 25 | 
            +
                  output = ''
         | 
| 26 | 
            +
                  fields = filter_fields(fields).filter_by_classes
         | 
| 27 | 
            +
                                                .filter_by_sets
         | 
| 28 | 
            +
                                                .filter_by_data(data)
         | 
| 29 | 
            +
                                                .filtered_fields
         | 
| 36 30 | 
             
                  label_width = label_width(fields)
         | 
| 37 31 |  | 
| 38 32 | 
             
                  fields.collect do |field|
         | 
| @@ -126,7 +126,7 @@ module HammerCLI::Output::Adapter | |
| 126 126 | 
             
                  end
         | 
| 127 127 | 
             
                end
         | 
| 128 128 |  | 
| 129 | 
            -
                def initialize(context={}, formatters={})
         | 
| 129 | 
            +
                def initialize(context = {}, formatters = {}, filters = {})
         | 
| 130 130 | 
             
                  super
         | 
| 131 131 | 
             
                  @paginate_by_default = false
         | 
| 132 132 | 
             
                end
         | 
| @@ -148,7 +148,11 @@ module HammerCLI::Output::Adapter | |
| 148 148 | 
             
                end
         | 
| 149 149 |  | 
| 150 150 | 
             
                def print_collection(fields, collection)
         | 
| 151 | 
            -
                  fields =  | 
| 151 | 
            +
                  fields = filter_fields(fields).filter_by_classes
         | 
| 152 | 
            +
                                                .filter_by_sets
         | 
| 153 | 
            +
                                                .filter_by_data(collection.first,
         | 
| 154 | 
            +
                                                                compact_only: true)
         | 
| 155 | 
            +
                                                .filtered_fields
         | 
| 152 156 | 
             
                  rows = row_data(fields, collection)
         | 
| 153 157 | 
             
                  # get headers using columns heuristic
         | 
| 154 158 | 
             
                  headers = rows.map{ |r| Cell.headers(r, @context) }.max_by{ |headers| headers.size }
         | 
| @@ -198,7 +202,7 @@ module HammerCLI::Output::Adapter | |
| 198 202 | 
             
                end
         | 
| 199 203 |  | 
| 200 204 | 
             
                def default_headers(fields)
         | 
| 201 | 
            -
                  fields. | 
| 205 | 
            +
                  fields.map(&:label)
         | 
| 202 206 | 
             
                end
         | 
| 203 207 |  | 
| 204 208 | 
             
              end
         | 
| @@ -21,9 +21,11 @@ module HammerCLI::Output::Adapter | |
| 21 21 | 
             
                end
         | 
| 22 22 |  | 
| 23 23 | 
             
                def print_collection(all_fields, collection)
         | 
| 24 | 
            -
                  fields =  | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 24 | 
            +
                  fields = filter_fields(all_fields).filter_by_classes
         | 
| 25 | 
            +
                                                    .filter_by_sets
         | 
| 26 | 
            +
                                                    .filter_by_data(collection.first,
         | 
| 27 | 
            +
                                                                    compact_only: true)
         | 
| 28 | 
            +
                                                    .filtered_fields
         | 
| 27 29 | 
             
                  formatted_collection = format_values(fields, collection)
         | 
| 28 30 | 
             
                  # calculate hash of column widths (label -> width)
         | 
| 29 31 | 
             
                  widths = calculate_widths(fields, formatted_collection)
         | 
| @@ -63,6 +65,10 @@ module HammerCLI::Output::Adapter | |
| 63 65 |  | 
| 64 66 | 
             
                protected
         | 
| 65 67 |  | 
| 68 | 
            +
                def classes_filter
         | 
| 69 | 
            +
                  super << Fields::ContainerField
         | 
| 70 | 
            +
                end
         | 
| 71 | 
            +
             | 
| 66 72 | 
             
                def normalize_column(width, value)
         | 
| 67 73 | 
             
                  value = value.to_s
         | 
| 68 74 | 
             
                  padding = width - HammerCLI::Output::Utils.real_length(value)
         | 
| @@ -103,12 +109,6 @@ module HammerCLI::Output::Adapter | |
| 103 109 | 
             
                  width
         | 
| 104 110 | 
             
                end
         | 
| 105 111 |  | 
| 106 | 
            -
                def field_filter
         | 
| 107 | 
            -
                  filtered = [Fields::ContainerField]
         | 
| 108 | 
            -
                  filtered << Fields::Id unless @context[:show_ids]
         | 
| 109 | 
            -
                  HammerCLI::Output::FieldFilter.new(filtered)
         | 
| 110 | 
            -
                end
         | 
| 111 | 
            -
             | 
| 112 112 | 
             
                private
         | 
| 113 113 |  | 
| 114 114 | 
             
                def max_width_for(field)
         | 
| @@ -1,7 +1,6 @@ | |
| 1 1 | 
             
            module HammerCLI::Output::Adapter
         | 
| 2 2 | 
             
              class TreeStructure < Abstract
         | 
| 3 | 
            -
             | 
| 4 | 
            -
                def initialize(context={}, formatters={})
         | 
| 3 | 
            +
                def initialize(context = {}, formatters = {}, filters = {})
         | 
| 5 4 | 
             
                  super
         | 
| 6 5 | 
             
                  @paginate_by_default = false
         | 
| 7 6 | 
             
                end
         | 
| @@ -34,15 +33,11 @@ module HammerCLI::Output::Adapter | |
| 34 33 |  | 
| 35 34 | 
             
                protected
         | 
| 36 35 |  | 
| 37 | 
            -
                def field_filter
         | 
| 38 | 
            -
                  filtered = []
         | 
| 39 | 
            -
                  filtered << Fields::Id unless @context[:show_ids]
         | 
| 40 | 
            -
                  HammerCLI::Output::FieldFilter.new(filtered)
         | 
| 41 | 
            -
                end
         | 
| 42 | 
            -
             | 
| 43 36 | 
             
                def render_fields(fields, data)
         | 
| 44 | 
            -
                  fields =  | 
| 45 | 
            -
             | 
| 37 | 
            +
                  fields = filter_fields(fields).filter_by_classes
         | 
| 38 | 
            +
                                                .filter_by_sets
         | 
| 39 | 
            +
                                                .filter_by_data(data)
         | 
| 40 | 
            +
                                                .filtered_fields
         | 
| 46 41 | 
             
                  fields.reduce({}) do |hash, field|
         | 
| 47 42 | 
             
                    field_data = data_for_field(field, data)
         | 
| 48 43 | 
             
                    next unless field.display?(field_data)
         | 
| @@ -19,6 +19,14 @@ module HammerCLI::Output | |
| 19 19 | 
             
                  @fields[field_index(field_id)]
         | 
| 20 20 | 
             
                end
         | 
| 21 21 |  | 
| 22 | 
            +
                def update_field_sets(set_names, field_ids)
         | 
| 23 | 
            +
                  set_names = [set_names] unless set_names.is_a?(Array)
         | 
| 24 | 
            +
                  field_ids = [field_ids] unless field_ids.is_a?(Array)
         | 
| 25 | 
            +
                  field_ids.each do |field_id|
         | 
| 26 | 
            +
                    find_field(field_id).sets = find_field(field_id).sets.concat(set_names).uniq
         | 
| 27 | 
            +
                  end
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
             | 
| 22 30 | 
             
                def insert(mode, field_id, fields = nil, &block)
         | 
| 23 31 | 
             
                  definition = self.class.new
         | 
| 24 32 | 
             
                  definition.append(fields, &block)
         | 
| @@ -46,8 +54,84 @@ module HammerCLI::Output | |
| 46 54 | 
             
                  @fields.empty?
         | 
| 47 55 | 
             
                end
         | 
| 48 56 |  | 
| 57 | 
            +
                def field_sets
         | 
| 58 | 
            +
                  nested_fields_sets(@fields).uniq.sort
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
             | 
| 61 | 
            +
                def sets_table
         | 
| 62 | 
            +
                  fields_col_size = max_label_length || _('Fields').size
         | 
| 63 | 
            +
                  fields_col = normalize_column(fields_col_size, _('Fields'), centralize: true)
         | 
| 64 | 
            +
                  fields_col += ' ' unless (fields_col_size - fields_col.size).zero?
         | 
| 65 | 
            +
                  header_bits = [fields_col]
         | 
| 66 | 
            +
                  hline_bits = ['-' * fields_col_size]
         | 
| 67 | 
            +
                  field_sets.map do |set|
         | 
| 68 | 
            +
                    header_bits << normalize_column(set.size, set)
         | 
| 69 | 
            +
                    hline_bits << '-' * set.size
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                  rows_bits = fields_row(@fields, field_sets, fields_col_size)
         | 
| 72 | 
            +
                  line = "+-#{hline_bits.join('-+-')}-+\n"
         | 
| 73 | 
            +
                  table = line
         | 
| 74 | 
            +
                  table += "| #{header_bits.join(' | ')} |\n"
         | 
| 75 | 
            +
                  table += line
         | 
| 76 | 
            +
                  table += "#{rows_bits.join("\n")}\n"
         | 
| 77 | 
            +
                  table += line
         | 
| 78 | 
            +
                  table
         | 
| 79 | 
            +
                end
         | 
| 80 | 
            +
             | 
| 49 81 | 
             
                private
         | 
| 50 82 |  | 
| 83 | 
            +
                def max_label_length
         | 
| 84 | 
            +
                  field_labels(@fields, full_labels: true).map(&:size).max
         | 
| 85 | 
            +
                end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                def normalize_column(width, col, centralize: false)
         | 
| 88 | 
            +
                  padding = width - HammerCLI::Output::Utils.real_length(col)
         | 
| 89 | 
            +
                  if padding >= 0
         | 
| 90 | 
            +
                    if centralize
         | 
| 91 | 
            +
                      padding /= 2
         | 
| 92 | 
            +
                      col.prepend(' ' * padding)
         | 
| 93 | 
            +
                    end
         | 
| 94 | 
            +
                    col += (' ' * padding)
         | 
| 95 | 
            +
                  else
         | 
| 96 | 
            +
                    col, real_len = HammerCLI::Output::Utils.real_truncate(col, width - 3)
         | 
| 97 | 
            +
                    col += '...'
         | 
| 98 | 
            +
                    col += ' ' if real_len < (width - 3)
         | 
| 99 | 
            +
                  end
         | 
| 100 | 
            +
                  col
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
             | 
| 103 | 
            +
                def fields_row(fields, sets, fields_col_size)
         | 
| 104 | 
            +
                  fields.each_with_object([]) do |field, rows|
         | 
| 105 | 
            +
                    next rows << fields_row(field.fields, sets, fields_col_size) if field.respond_to?(:fields)
         | 
| 106 | 
            +
             | 
| 107 | 
            +
                    row = [normalize_column(fields_col_size, field.full_label)]
         | 
| 108 | 
            +
                    sets.each do |set|
         | 
| 109 | 
            +
                      mark = field.sets.include?(set) ? 'x' : ' '
         | 
| 110 | 
            +
                      column = normalize_column(set.size, mark, centralize: true)
         | 
| 111 | 
            +
                      column += ' ' unless (set.size - column.size).zero?
         | 
| 112 | 
            +
                      row << column
         | 
| 113 | 
            +
                    end
         | 
| 114 | 
            +
                    rows << "| #{row.join(' | ')} |"
         | 
| 115 | 
            +
                  end
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
             | 
| 118 | 
            +
                def field_labels(fields, full_labels: false)
         | 
| 119 | 
            +
                  fields.each_with_object([]) do |field, labels|
         | 
| 120 | 
            +
                    label = full_labels ? field.full_label : field.label
         | 
| 121 | 
            +
                    next labels << label unless field.respond_to?(:fields)
         | 
| 122 | 
            +
             | 
| 123 | 
            +
                    labels.concat(field_labels(field.fields, full_labels: full_labels))
         | 
| 124 | 
            +
                  end
         | 
| 125 | 
            +
                end
         | 
| 126 | 
            +
             | 
| 127 | 
            +
                def nested_fields_sets(fields)
         | 
| 128 | 
            +
                  fields.map do |field|
         | 
| 129 | 
            +
                    next field.sets unless field.respond_to?(:fields)
         | 
| 130 | 
            +
             | 
| 131 | 
            +
                    nested_fields_sets(field.fields)
         | 
| 132 | 
            +
                  end.flatten
         | 
| 133 | 
            +
                end
         | 
| 134 | 
            +
             | 
| 51 135 | 
             
                def field_index(field_id)
         | 
| 52 136 | 
             
                  index = @fields.find_index do |f|
         | 
| 53 137 | 
             
                    f.match_id?(field_id)
         | 
| @@ -1,21 +1,84 @@ | |
| 1 1 | 
             
            module HammerCLI::Output
         | 
| 2 | 
            -
             | 
| 3 2 | 
             
              class FieldFilter
         | 
| 3 | 
            +
                attr_reader :fields, :filtered_fields
         | 
| 4 | 
            +
                attr_accessor :classes_filter, :sets_filter
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def initialize(fields = [], filters = {})
         | 
| 7 | 
            +
                  self.fields = fields
         | 
| 8 | 
            +
                  @classes_filter = filters[:classes_filter] || []
         | 
| 9 | 
            +
                  @sets_filter = filters[:sets_filter] || []
         | 
| 10 | 
            +
                end
         | 
| 4 11 |  | 
| 5 | 
            -
                def  | 
| 6 | 
            -
                  @ | 
| 12 | 
            +
                def fields=(fields)
         | 
| 13 | 
            +
                  @fields = fields || []
         | 
| 14 | 
            +
                  @filtered_fields = @fields.dup
         | 
| 7 15 | 
             
                end
         | 
| 8 16 |  | 
| 9 | 
            -
                def  | 
| 10 | 
            -
                   | 
| 11 | 
            -
                   | 
| 12 | 
            -
                     | 
| 17 | 
            +
                def filter_by_classes(classes = nil)
         | 
| 18 | 
            +
                  classes ||= @classes_filter
         | 
| 19 | 
            +
                  classes.each do |cls|
         | 
| 20 | 
            +
                    @filtered_fields.reject! do |f|
         | 
| 13 21 | 
             
                      f.is_a? cls
         | 
| 14 22 | 
             
                    end
         | 
| 15 23 | 
             
                  end
         | 
| 16 | 
            -
                   | 
| 24 | 
            +
                  self
         | 
| 17 25 | 
             
                end
         | 
| 18 26 |  | 
| 19 | 
            -
             | 
| 27 | 
            +
                def filter_by_sets(sets = nil)
         | 
| 28 | 
            +
                  sets ||= @sets_filter
         | 
| 29 | 
            +
                  return self if sets.empty?
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                  set_names, labels = resolve_set_names(sets)
         | 
| 32 | 
            +
                  deep_filter(@filtered_fields, set_names, labels)
         | 
| 33 | 
            +
                  self
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
             | 
| 36 | 
            +
                def filter_by_data(data, compact_only: false)
         | 
| 37 | 
            +
                  @filtered_fields = displayable_fields(@filtered_fields,
         | 
| 38 | 
            +
                                                        data,
         | 
| 39 | 
            +
                                                        compact_only: compact_only)
         | 
| 40 | 
            +
                  self
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                private
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                def deep_filter(fields, set_names, labels)
         | 
| 46 | 
            +
                  fields.select! do |f|
         | 
| 47 | 
            +
                    allowed = include_by_label?(labels, f.full_label.downcase)
         | 
| 48 | 
            +
                    allowed ||= (f.sets & set_names).any?
         | 
| 49 | 
            +
                    deep_filter(f.fields, set_names, labels) if f.respond_to?(:fields)
         | 
| 50 | 
            +
                    allowed
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 20 53 |  | 
| 54 | 
            +
                def displayable_fields(fields, record, compact_only: false)
         | 
| 55 | 
            +
                  fields.select do |field|
         | 
| 56 | 
            +
                    field_data = HammerCLI::Output::Adapter::Abstract.data_for_field(
         | 
| 57 | 
            +
                      field, record
         | 
| 58 | 
            +
                    )
         | 
| 59 | 
            +
                    if compact_only && !field_data.is_a?(HammerCLI::Output::DataMissing)
         | 
| 60 | 
            +
                      true
         | 
| 61 | 
            +
                    else
         | 
| 62 | 
            +
                      field.display?(field_data)
         | 
| 63 | 
            +
                    end
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
             | 
| 67 | 
            +
                def include_by_label?(labels, label)
         | 
| 68 | 
            +
                  labels.any? do |l|
         | 
| 69 | 
            +
                    l.start_with?("#{label}/") || label.match(%r{^#{l.gsub(/\*/, '.*')}(|\/.*)$})
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def resolve_set_names(sets)
         | 
| 74 | 
            +
                  set_names = []
         | 
| 75 | 
            +
                  labels = []
         | 
| 76 | 
            +
                  sets.each do |name|
         | 
| 77 | 
            +
                    next set_names << name if name.upcase == name
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                    labels << name.downcase
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                  [set_names, labels]
         | 
| 82 | 
            +
                end
         | 
| 83 | 
            +
              end
         | 
| 21 84 | 
             
            end
         | 
| @@ -1,16 +1,17 @@ | |
| 1 1 | 
             
            require 'hammer_cli/output/dsl'
         | 
| 2 2 |  | 
| 3 3 | 
             
            module Fields
         | 
| 4 | 
            -
             | 
| 5 4 | 
             
              class Field
         | 
| 6 5 | 
             
                attr_reader :path
         | 
| 7 | 
            -
                 | 
| 6 | 
            +
                attr_writer :sets
         | 
| 7 | 
            +
                attr_accessor :label, :parent
         | 
| 8 8 |  | 
| 9 9 | 
             
                def initialize(options={})
         | 
| 10 10 | 
             
                  @hide_blank = options[:hide_blank].nil? ? false : options[:hide_blank]
         | 
| 11 11 | 
             
                  @hide_missing = options[:hide_missing].nil? ? true : options[:hide_missing]
         | 
| 12 12 | 
             
                  @path = options[:path] || []
         | 
| 13 13 | 
             
                  @label = options[:label]
         | 
| 14 | 
            +
                  @sets = options[:sets]
         | 
| 14 15 | 
             
                  @options = options
         | 
| 15 16 | 
             
                end
         | 
| 16 17 |  | 
| @@ -30,6 +31,15 @@ module Fields | |
| 30 31 | 
             
                  @hide_missing
         | 
| 31 32 | 
             
                end
         | 
| 32 33 |  | 
| 34 | 
            +
                def full_label
         | 
| 35 | 
            +
                  return @label.to_s if @parent.nil?
         | 
| 36 | 
            +
                  "#{@parent.full_label}/#{@label}"
         | 
| 37 | 
            +
                end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
                def sets
         | 
| 40 | 
            +
                  @sets || inherited_sets || default_sets
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 33 43 | 
             
                def display?(value)
         | 
| 34 44 | 
             
                  if value.is_a?(HammerCLI::Output::DataMissing)
         | 
| 35 45 | 
             
                    !hide_missing?
         | 
| @@ -44,6 +54,16 @@ module Fields | |
| 44 54 | 
             
                  @options
         | 
| 45 55 | 
             
                end
         | 
| 46 56 |  | 
| 57 | 
            +
                protected
         | 
| 58 | 
            +
             | 
| 59 | 
            +
                def inherited_sets
         | 
| 60 | 
            +
                  return nil if @parent.nil?
         | 
| 61 | 
            +
                  @parent.sets
         | 
| 62 | 
            +
                end
         | 
| 63 | 
            +
             | 
| 64 | 
            +
                def default_sets
         | 
| 65 | 
            +
                  %w[DEFAULT ALL]
         | 
| 66 | 
            +
                end
         | 
| 47 67 | 
             
              end
         | 
| 48 68 |  | 
| 49 69 |  | 
| @@ -53,7 +73,7 @@ module Fields | |
| 53 73 | 
             
                  super(options)
         | 
| 54 74 | 
             
                  dsl = HammerCLI::Output::Dsl.new
         | 
| 55 75 | 
             
                  dsl.build &block if block_given?
         | 
| 56 | 
            -
             | 
| 76 | 
            +
                  dsl.fields.each { |f| f.parent = self }
         | 
| 57 77 | 
             
                  self.output_definition.append dsl.fields
         | 
| 58 78 | 
             
                end
         | 
| 59 79 |  | 
| @@ -25,6 +25,7 @@ module HammerCLI::Output | |
| 25 25 |  | 
| 26 26 | 
             
                def print_record(definition, record)
         | 
| 27 27 | 
             
                  adapter.print_record(definition.fields, record) if appropriate_verbosity?(:record)
         | 
| 28 | 
            +
                  adapter.reset_context
         | 
| 28 29 | 
             
                end
         | 
| 29 30 |  | 
| 30 31 | 
             
                def print_collection(definition, collection)
         | 
| @@ -32,6 +33,7 @@ module HammerCLI::Output | |
| 32 33 | 
             
                    collection = HammerCLI::Output::RecordCollection.new([collection].flatten(1))
         | 
| 33 34 | 
             
                  end
         | 
| 34 35 | 
             
                  adapter.print_collection(definition.fields, collection) if appropriate_verbosity?(:collection)
         | 
| 36 | 
            +
                  adapter.reset_context
         | 
| 35 37 | 
             
                end
         | 
| 36 38 |  | 
| 37 39 | 
             
                def adapter
         | 
| @@ -14,7 +14,7 @@ module HammerCLI | |
| 14 14 |  | 
| 15 15 | 
             
                def get_options(uri = nil)
         | 
| 16 16 | 
             
                  ssl_options = {}
         | 
| 17 | 
            -
                  for sslopt in [:ssl_ca_file, :ssl_ca_path, :verify_ssl] do
         | 
| 17 | 
            +
                  for sslopt in [:ssl_ca_file, :ssl_ca_path, :verify_ssl, :ssl_version] do
         | 
| 18 18 | 
             
                    ssloptval = read_ssl_option(sslopt)
         | 
| 19 19 | 
             
                    ssl_options[sslopt] = ssloptval unless ssloptval.nil?
         | 
| 20 20 | 
             
                  end
         | 
    
        data/lib/hammer_cli/version.rb
    CHANGED
    
    
    
        data/test/unit/abstract_test.rb
    CHANGED
    
    | @@ -270,6 +270,7 @@ describe HammerCLI::AbstractCommand do | |
| 270 270 | 
             
                  option "--test", "TEST", "Test option"
         | 
| 271 271 | 
             
                  option "--test-format", "TEST_FORMAT", "Test option with a formatter",
         | 
| 272 272 | 
             
                    :format => HammerCLI::Options::Normalizers::List.new
         | 
| 273 | 
            +
                  use_option :fields
         | 
| 273 274 | 
             
                end
         | 
| 274 275 |  | 
| 275 276 | 
             
                it "should create instances of hammer options" do
         | 
| @@ -282,6 +283,10 @@ describe HammerCLI::AbstractCommand do | |
| 282 283 | 
             
                  opt.value_formatter.kind_of?(HammerCLI::Options::Normalizers::List).must_equal true
         | 
| 283 284 | 
             
                end
         | 
| 284 285 |  | 
| 286 | 
            +
                it 'should allow using of predefined options' do
         | 
| 287 | 
            +
                  opt = TestOptionCmd.find_option('--fields')
         | 
| 288 | 
            +
                  opt.is_a?(HammerCLI::Options::OptionDefinition).must_equal true
         | 
| 289 | 
            +
                end
         | 
| 285 290 | 
             
              end
         | 
| 286 291 |  | 
| 287 292 | 
             
              describe "#options" do
         | 
| @@ -257,4 +257,24 @@ describe HammerCLI::Output::Definition do | |
| 257 257 | 
             
                  definition.at(path).must_equal label_field.output_definition
         | 
| 258 258 | 
             
                end
         | 
| 259 259 | 
             
              end
         | 
| 260 | 
            +
             | 
| 261 | 
            +
              describe 'sets_table' do
         | 
| 262 | 
            +
                it 'prints a table with fields and sets ' do
         | 
| 263 | 
            +
                  cont_field = Fields::ContainerField.new(id: :id1, label: 'cf', sets: ['SET']) do
         | 
| 264 | 
            +
                    field :a, 'abc', Fields::Field
         | 
| 265 | 
            +
                    field :b, 'bca', Fields::Field
         | 
| 266 | 
            +
                  end
         | 
| 267 | 
            +
                  definition.fields += [new_field, cont_field]
         | 
| 268 | 
            +
             | 
| 269 | 
            +
                  sets_table = "+----------+-----+---------+-----+
         | 
| 270 | 
            +
            |  Fields  | ALL | DEFAULT | SET |
         | 
| 271 | 
            +
            +----------+-----+---------+-----+
         | 
| 272 | 
            +
            | newfield |  x  |    x    |     |
         | 
| 273 | 
            +
            | cf/abc   |     |         |  x  |
         | 
| 274 | 
            +
            | cf/bca   |     |         |  x  |
         | 
| 275 | 
            +
            +----------+-----+---------+-----+\n"
         | 
| 276 | 
            +
             | 
| 277 | 
            +
                  definition.sets_table.must_equal sets_table
         | 
| 278 | 
            +
                end
         | 
| 279 | 
            +
              end
         | 
| 260 280 | 
             
            end
         | 
| @@ -1,27 +1,72 @@ | |
| 1 1 | 
             
            require File.join(File.dirname(__FILE__), '../test_helper')
         | 
| 2 2 |  | 
| 3 3 | 
             
            describe HammerCLI::Output::FieldFilter do
         | 
| 4 | 
            -
             | 
| 5 | 
            -
             | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 4 | 
            +
              let(:fields) do
         | 
| 5 | 
            +
                [
         | 
| 6 | 
            +
                  Fields::Field.new(:label => 'field', :hide_blank => true),
         | 
| 7 | 
            +
                  Fields::Collection.new(:label => 'collection'),
         | 
| 8 | 
            +
                  Fields::Id.new(:label => 'id', :sets => ['THIN'])
         | 
| 9 | 
            +
                ]
         | 
| 10 | 
            +
              end
         | 
| 11 | 
            +
              let(:container_fields) do
         | 
| 12 | 
            +
                fields + [
         | 
| 13 | 
            +
                  Fields::ContainerField.new(:label => 'container') do
         | 
| 14 | 
            +
                    field :first, 'first'
         | 
| 15 | 
            +
                    field :second, 'second', Fields::ContainerField do
         | 
| 16 | 
            +
                      field :nested, 'nested'
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                ]
         | 
| 20 | 
            +
              end
         | 
| 10 21 | 
             
              let(:field_labels) { fields.map(&:label).sort }
         | 
| 11 22 |  | 
| 12 | 
            -
              it  | 
| 13 | 
            -
                f = HammerCLI::Output::FieldFilter.new
         | 
| 14 | 
            -
                f. | 
| 23 | 
            +
              it 'lets all fields go by default' do
         | 
| 24 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields)
         | 
| 25 | 
            +
                f.filtered_fields.map(&:label).sort.must_equal ['field', 'collection', 'id'].sort
         | 
| 26 | 
            +
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              it 'filters fields by class' do
         | 
| 29 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields, classes_filter: [Fields::Id])
         | 
| 30 | 
            +
                f.filter_by_classes.filtered_fields.map(&:label).sort.must_equal ['field', 'collection'].sort
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
              it 'filters fields by superclass' do
         | 
| 34 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields, classes_filter: [Fields::ContainerField])
         | 
| 35 | 
            +
                f.filter_by_classes.filtered_fields.map(&:label).sort.must_equal ['field', 'id'].sort
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
              it 'filters fields by sets' do
         | 
| 39 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields, sets_filter: ['THIN'])
         | 
| 40 | 
            +
                f.filter_by_sets.filtered_fields.map(&:label).must_equal ['id']
         | 
| 41 | 
            +
              end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              it 'filters fields by sets with labels' do
         | 
| 44 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields, sets_filter: ['THIN', 'field'])
         | 
| 45 | 
            +
                f.filter_by_sets.filtered_fields.map(&:label).sort.must_equal ['field', 'id'].sort
         | 
| 46 | 
            +
              end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
              it 'filters by full labels' do
         | 
| 49 | 
            +
                f = HammerCLI::Output::FieldFilter.new(container_fields, sets_filter: ['container/first'])
         | 
| 50 | 
            +
                f.filter_by_sets.filtered_fields.first.fields.map(&:label).must_equal ['first']
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              it 'filters by superclass labels' do
         | 
| 54 | 
            +
                f = HammerCLI::Output::FieldFilter.new(container_fields, sets_filter: ['container'])
         | 
| 55 | 
            +
                f.filter_by_sets.filtered_fields.first.fields.map(&:label).must_equal ['first', 'second']
         | 
| 15 56 | 
             
              end
         | 
| 16 57 |  | 
| 17 | 
            -
              it  | 
| 18 | 
            -
                f = HammerCLI::Output::FieldFilter.new([ | 
| 19 | 
            -
                f. | 
| 58 | 
            +
              it 'filters by labels with wildcards' do
         | 
| 59 | 
            +
                f = HammerCLI::Output::FieldFilter.new(container_fields, sets_filter: ['container/f*'])
         | 
| 60 | 
            +
                f.filter_by_sets.filtered_fields.first.fields.map(&:label).must_equal ['first']
         | 
| 20 61 | 
             
              end
         | 
| 21 62 |  | 
| 22 | 
            -
              it  | 
| 23 | 
            -
                f = HammerCLI::Output::FieldFilter.new([Fields:: | 
| 24 | 
            -
                f. | 
| 63 | 
            +
              it 'allows chained filtering' do
         | 
| 64 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields, sets_filter: ['THIN'], classes_filter: [Fields::Id])
         | 
| 65 | 
            +
                f.filter_by_classes.filter_by_sets.filtered_fields.map(&:label).must_equal []
         | 
| 25 66 | 
             
              end
         | 
| 26 67 |  | 
| 68 | 
            +
              it 'filters fields by data' do
         | 
| 69 | 
            +
                f = HammerCLI::Output::FieldFilter.new(fields)
         | 
| 70 | 
            +
                f.filter_by_data(nil).filtered_fields.map(&:label).sort.must_equal ['id', 'collection'].sort
         | 
| 71 | 
            +
              end
         | 
| 27 72 | 
             
            end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: hammer_cli
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.18.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Martin Bačovský
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2019- | 
| 12 | 
            +
            date: 2019-08-01 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: clamp
         | 
| @@ -242,6 +242,7 @@ files: | |
| 242 242 | 
             
            - lib/hammer_cli/options/option_collector.rb
         | 
| 243 243 | 
             
            - lib/hammer_cli/options/option_definition.rb
         | 
| 244 244 | 
             
            - lib/hammer_cli/options/option_processor.rb
         | 
| 245 | 
            +
            - lib/hammer_cli/options/predefined.rb
         | 
| 245 246 | 
             
            - lib/hammer_cli/options/processor_list.rb
         | 
| 246 247 | 
             
            - lib/hammer_cli/options/sources/base.rb
         | 
| 247 248 | 
             
            - lib/hammer_cli/options/sources/command_line.rb
         |