hammer_cli 0.19.0 → 2.1.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.
Files changed (213) hide show
  1. checksums.yaml +4 -4
  2. data/bin/hammer-complete +28 -0
  3. data/config/cli_config.template.yml +2 -0
  4. data/config/hammer.completion +5 -0
  5. data/doc/commands_extension.md +12 -0
  6. data/doc/creating_commands.md +100 -0
  7. data/doc/installation.md +47 -4
  8. data/doc/release_notes.md +32 -5
  9. data/lib/hammer_cli.rb +1 -0
  10. data/lib/hammer_cli/abstract.rb +61 -4
  11. data/lib/hammer_cli/apipie/api_connection.rb +5 -1
  12. data/lib/hammer_cli/apipie/command.rb +3 -2
  13. data/lib/hammer_cli/apipie/option_builder.rb +15 -13
  14. data/lib/hammer_cli/apipie/option_definition.rb +9 -7
  15. data/lib/hammer_cli/bash.rb +2 -0
  16. data/lib/hammer_cli/bash/completion.rb +159 -0
  17. data/lib/hammer_cli/bash/prebuild_command.rb +21 -0
  18. data/lib/hammer_cli/command_extensions.rb +21 -1
  19. data/lib/hammer_cli/connection.rb +4 -0
  20. data/lib/hammer_cli/exception_handler.rb +11 -2
  21. data/lib/hammer_cli/full_help.rb +8 -1
  22. data/lib/hammer_cli/help/builder.rb +29 -3
  23. data/lib/hammer_cli/logger_watch.rb +1 -1
  24. data/lib/hammer_cli/main.rb +5 -3
  25. data/lib/hammer_cli/options/normalizers.rb +7 -3
  26. data/lib/hammer_cli/options/option_definition.rb +26 -6
  27. data/lib/hammer_cli/options/option_family.rb +114 -0
  28. data/lib/hammer_cli/options/predefined.rb +1 -1
  29. data/lib/hammer_cli/output.rb +1 -1
  30. data/lib/hammer_cli/output/adapter/abstract.rb +1 -5
  31. data/lib/hammer_cli/output/adapter/base.rb +1 -1
  32. data/lib/hammer_cli/output/adapter/csv.rb +3 -2
  33. data/lib/hammer_cli/output/adapter/json.rb +14 -3
  34. data/lib/hammer_cli/output/adapter/silent.rb +1 -1
  35. data/lib/hammer_cli/output/adapter/table.rb +30 -80
  36. data/lib/hammer_cli/output/adapter/yaml.rb +6 -3
  37. data/lib/hammer_cli/output/definition.rb +11 -56
  38. data/lib/hammer_cli/output/generators.rb +1 -0
  39. data/lib/hammer_cli/output/generators/table.rb +121 -0
  40. data/lib/hammer_cli/output/output.rb +2 -4
  41. data/lib/hammer_cli/settings.rb +2 -1
  42. data/lib/hammer_cli/subcommand.rb +25 -1
  43. data/lib/hammer_cli/testing/command_assertions.rb +2 -2
  44. data/lib/hammer_cli/utils.rb +22 -0
  45. data/lib/hammer_cli/version.rb +1 -1
  46. data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
  47. data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
  48. data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
  49. data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
  50. data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
  51. data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
  52. data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
  53. data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
  54. data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
  55. data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
  56. data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
  57. data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
  58. data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
  59. data/man/hammer.1.gz +0 -0
  60. data/test/unit/abstract_test.rb +23 -2
  61. data/test/unit/apipie/api_connection_test.rb +1 -0
  62. data/test/unit/apipie/option_builder_test.rb +8 -0
  63. data/test/unit/bash_test.rb +138 -0
  64. data/test/unit/command_extensions_test.rb +67 -49
  65. data/test/unit/exception_handler_test.rb +44 -0
  66. data/test/unit/help/builder_test.rb +22 -0
  67. data/test/unit/options/option_family_test.rb +48 -0
  68. data/test/unit/output/adapter/base_test.rb +58 -0
  69. data/test/unit/output/adapter/csv_test.rb +63 -1
  70. data/test/unit/output/adapter/json_test.rb +61 -0
  71. data/test/unit/output/adapter/table_test.rb +70 -1
  72. data/test/unit/output/adapter/yaml_test.rb +59 -0
  73. data/test/unit/output/definition_test.rb +7 -7
  74. data/test/unit/output/output_test.rb +3 -3
  75. metadata +83 -345
  76. data/hammer_cli_complete +0 -13
  77. data/test/reports/TEST-Fields-ContainerField-display-.xml +0 -7
  78. data/test/reports/TEST-Fields-ContainerField-display-blank-is-allowed.xml +0 -15
  79. data/test/reports/TEST-Fields-ContainerField-display-blank-is-not-allowed.xml +0 -15
  80. data/test/reports/TEST-Fields-ContainerField.xml +0 -7
  81. data/test/reports/TEST-Fields-Field-display-.xml +0 -7
  82. data/test/reports/TEST-Fields-Field-display-blank-is-allowed.xml +0 -11
  83. data/test/reports/TEST-Fields-Field-display-blank-is-not-allowed.xml +0 -11
  84. data/test/reports/TEST-Fields-Field-hide-blank-.xml +0 -11
  85. data/test/reports/TEST-Fields-Field-parameters.xml +0 -9
  86. data/test/reports/TEST-Fields-Field.xml +0 -13
  87. data/test/reports/TEST-HammerCLI-AbstractCommand-build-options.xml +0 -15
  88. data/test/reports/TEST-HammerCLI-AbstractCommand-exception-handler.xml +0 -13
  89. data/test/reports/TEST-HammerCLI-AbstractCommand-logging.xml +0 -21
  90. data/test/reports/TEST-HammerCLI-AbstractCommand-option-builder.xml +0 -11
  91. data/test/reports/TEST-HammerCLI-AbstractCommand-options.xml +0 -11
  92. data/test/reports/TEST-HammerCLI-AbstractCommand-output.xml +0 -19
  93. data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-remove-subcommand.xml +0 -11
  94. data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-subcommand-.xml +0 -13
  95. data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior-subcommand.xml +0 -11
  96. data/test/reports/TEST-HammerCLI-AbstractCommand-subcommand-behavior.xml +0 -7
  97. data/test/reports/TEST-HammerCLI-AbstractCommand.xml +0 -11
  98. data/test/reports/TEST-HammerCLI-Apipie-Command-options.xml +0 -11
  99. data/test/reports/TEST-HammerCLI-Apipie-Command-resource-defined.xml +0 -9
  100. data/test/reports/TEST-HammerCLI-Apipie-Command-setting-resources.xml +0 -19
  101. data/test/reports/TEST-HammerCLI-Apipie-Command.xml +0 -9
  102. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-aliasing-resources.xml +0 -13
  103. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-filtering-options.xml +0 -15
  104. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-required-options.xml +0 -11
  105. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-setting-correct-normalizers.xml +0 -9
  106. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-with-hash-params.xml +0 -11
  107. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder-with-one-simple-param.xml +0 -15
  108. data/test/reports/TEST-HammerCLI-Apipie-OptionBuilder.xml +0 -7
  109. data/test/reports/TEST-HammerCLI-Completer-command-completion.xml +0 -29
  110. data/test/reports/TEST-HammerCLI-Completer-option-value-completion.xml +0 -17
  111. data/test/reports/TEST-HammerCLI-Completer-subcommand-completion.xml +0 -19
  112. data/test/reports/TEST-HammerCLI-Completer.xml +0 -7
  113. data/test/reports/TEST-HammerCLI-CompleterLine-line-complete.xml +0 -25
  114. data/test/reports/TEST-HammerCLI-CompleterLine-splitting-words.xml +0 -29
  115. data/test/reports/TEST-HammerCLI-CompleterLine.xml +0 -7
  116. data/test/reports/TEST-HammerCLI-CompleterWord-complete-.xml +0 -23
  117. data/test/reports/TEST-HammerCLI-CompleterWord-quote.xml +0 -15
  118. data/test/reports/TEST-HammerCLI-CompleterWord-quoted-.xml +0 -13
  119. data/test/reports/TEST-HammerCLI-CompleterWord.xml +0 -7
  120. data/test/reports/TEST-HammerCLI-Connection.xml +0 -21
  121. data/test/reports/TEST-HammerCLI-ExceptionHandler.xml +0 -21
  122. data/test/reports/TEST-HammerCLI-I18n.xml +0 -11
  123. data/test/reports/TEST-HammerCLI-MainCommand-loading-context-password.xml +0 -11
  124. data/test/reports/TEST-HammerCLI-MainCommand-loading-context-username.xml +0 -11
  125. data/test/reports/TEST-HammerCLI-MainCommand-loading-context-verbose.xml +0 -9
  126. data/test/reports/TEST-HammerCLI-MainCommand-loading-context.xml +0 -7
  127. data/test/reports/TEST-HammerCLI-MainCommand.xml +0 -7
  128. data/test/reports/TEST-HammerCLI-Modules-find-by-name.xml +0 -13
  129. data/test/reports/TEST-HammerCLI-Modules-load-a-module-module-not-found.xml +0 -13
  130. data/test/reports/TEST-HammerCLI-Modules-load-a-module-module-runtime-exception.xml +0 -13
  131. data/test/reports/TEST-HammerCLI-Modules-load-a-module-success.xml +0 -15
  132. data/test/reports/TEST-HammerCLI-Modules-load-a-module.xml +0 -7
  133. data/test/reports/TEST-HammerCLI-Modules-load-all-modules.xml +0 -9
  134. data/test/reports/TEST-HammerCLI-Modules-names.xml +0 -13
  135. data/test/reports/TEST-HammerCLI-Modules.xml +0 -7
  136. data/test/reports/TEST-HammerCLI-OptionBuilderContainer.0.xml +0 -7
  137. data/test/reports/TEST-HammerCLI-OptionBuilderContainer.xml +0 -11
  138. data/test/reports/TEST-HammerCLI-Options-Normalizers-abstract.xml +0 -9
  139. data/test/reports/TEST-HammerCLI-Options-Normalizers-bool.xml +0 -31
  140. data/test/reports/TEST-HammerCLI-Options-Normalizers-datetime.xml +0 -17
  141. data/test/reports/TEST-HammerCLI-Options-Normalizers-enum.xml +0 -15
  142. data/test/reports/TEST-HammerCLI-Options-Normalizers-enumlist.xml +0 -21
  143. data/test/reports/TEST-HammerCLI-Options-Normalizers-json-input.xml +0 -15
  144. data/test/reports/TEST-HammerCLI-Options-Normalizers-key-value-list.xml +0 -17
  145. data/test/reports/TEST-HammerCLI-Options-Normalizers-list.xml +0 -15
  146. data/test/reports/TEST-HammerCLI-Options-Normalizers.xml +0 -7
  147. data/test/reports/TEST-HammerCLI-Options-OptionDefinition-context.xml +0 -9
  148. data/test/reports/TEST-HammerCLI-Options-OptionDefinition-formatters.xml +0 -11
  149. data/test/reports/TEST-HammerCLI-Options-OptionDefinition.xml +0 -7
  150. data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-error-messages.xml +0 -15
  151. data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-messages.xml +0 -11
  152. data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract-test-data-for-field.xml +0 -15
  153. data/test/reports/TEST-HammerCLI-Output-Adapter-Abstract.xml +0 -17
  154. data/test/reports/TEST-HammerCLI-Output-Adapter-Base-print-collection-show-ids.xml +0 -9
  155. data/test/reports/TEST-HammerCLI-Output-Adapter-Base-print-collection.xml +0 -27
  156. data/test/reports/TEST-HammerCLI-Output-Adapter-Base.xml +0 -7
  157. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-formatters.xml +0 -11
  158. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-fields-with-collections.xml +0 -13
  159. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-fields-with-containers.xml +0 -11
  160. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection-handle-ids.xml +0 -11
  161. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-collection.xml +0 -11
  162. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues-print-message.xml +0 -11
  163. data/test/reports/TEST-HammerCLI-Output-Adapter-CSValues.xml +0 -7
  164. data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-column-width.xml +0 -15
  165. data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-formatters.xml +0 -11
  166. data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-handle-ids.xml +0 -11
  167. data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection-sort-columns.xml +0 -9
  168. data/test/reports/TEST-HammerCLI-Output-Adapter-Table-print-collection.xml +0 -11
  169. data/test/reports/TEST-HammerCLI-Output-Adapter-Table.xml +0 -7
  170. data/test/reports/TEST-HammerCLI-Output-Definition-empty-.xml +0 -11
  171. data/test/reports/TEST-HammerCLI-Output-Definition.xml +0 -11
  172. data/test/reports/TEST-HammerCLI-Output-Dsl-collection.xml +0 -13
  173. data/test/reports/TEST-HammerCLI-Output-Dsl-custom-fields.xml +0 -11
  174. data/test/reports/TEST-HammerCLI-Output-Dsl-fields.xml +0 -15
  175. data/test/reports/TEST-HammerCLI-Output-Dsl-label.xml +0 -13
  176. data/test/reports/TEST-HammerCLI-Output-Dsl-path-definition.xml +0 -13
  177. data/test/reports/TEST-HammerCLI-Output-Dsl.xml +0 -9
  178. data/test/reports/TEST-HammerCLI-Output-FieldFilter.xml +0 -13
  179. data/test/reports/TEST-HammerCLI-Output-Formatters-BooleanFormatter.xml +0 -11
  180. data/test/reports/TEST-HammerCLI-Output-Formatters-ColorFormatter.xml +0 -9
  181. data/test/reports/TEST-HammerCLI-Output-Formatters-DateFormatter.xml +0 -11
  182. data/test/reports/TEST-HammerCLI-Output-Formatters-FieldFormatter.xml +0 -13
  183. data/test/reports/TEST-HammerCLI-Output-Formatters-FormatterContainer.xml +0 -13
  184. data/test/reports/TEST-HammerCLI-Output-Formatters-FormatterLibrary.xml +0 -11
  185. data/test/reports/TEST-HammerCLI-Output-Formatters-KeyValueFormatter.xml +0 -13
  186. data/test/reports/TEST-HammerCLI-Output-Formatters-ListFormatter.xml +0 -13
  187. data/test/reports/TEST-HammerCLI-Output-Formatters-LongTextFormatter.xml +0 -13
  188. data/test/reports/TEST-HammerCLI-Output-Output-adapters.xml +0 -17
  189. data/test/reports/TEST-HammerCLI-Output-Output-data.xml +0 -15
  190. data/test/reports/TEST-HammerCLI-Output-Output-formatters.xml +0 -9
  191. data/test/reports/TEST-HammerCLI-Output-Output-messages.xml +0 -19
  192. data/test/reports/TEST-HammerCLI-Output-Output.xml +0 -7
  193. data/test/reports/TEST-HammerCLI-Output-RecordCollection.xml +0 -13
  194. data/test/reports/TEST-HammerCLI-Settings-load-from-paths.xml +0 -15
  195. data/test/reports/TEST-HammerCLI-Settings.xml +0 -25
  196. data/test/reports/TEST-HammerCLI-ShellHistory-loading-old-history.xml +0 -11
  197. data/test/reports/TEST-HammerCLI-ShellHistory-saving-history.xml +0 -15
  198. data/test/reports/TEST-HammerCLI-ShellHistory.xml +0 -7
  199. data/test/reports/TEST-MiniTest-Spec.xml +0 -7
  200. data/test/reports/TEST-String-camelize.xml +0 -11
  201. data/test/reports/TEST-String-formatting.xml +0 -17
  202. data/test/reports/TEST-String-indent.xml +0 -11
  203. data/test/reports/TEST-String-interactive-.xml +0 -13
  204. data/test/reports/TEST-String.xml +0 -7
  205. data/test/reports/TEST-constraints-HammerCLI-Validator-AllConstraint-exist-.xml +0 -13
  206. data/test/reports/TEST-constraints-HammerCLI-Validator-AllConstraint.xml +0 -7
  207. data/test/reports/TEST-constraints-HammerCLI-Validator-AnyConstraint-exist-.xml +0 -13
  208. data/test/reports/TEST-constraints-HammerCLI-Validator-AnyConstraint.xml +0 -7
  209. data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-exist-.xml +0 -9
  210. data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-rejected.xml +0 -13
  211. data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint-required.xml +0 -13
  212. data/test/reports/TEST-constraints-HammerCLI-Validator-BaseConstraint.xml +0 -7
  213. data/test/reports/TEST-constraints.xml +0 -7
@@ -1,4 +1,4 @@
1
- require 'awesome_print'
1
+ require 'amazing_print'
2
2
 
3
3
  module HammerCLI
4
4
  module Logger
@@ -47,9 +47,11 @@ module HammerCLI
47
47
  :context_target => :interactive
48
48
  option ["--no-headers"], :flag, _("Hide headers from output")
49
49
  option ["--csv"], :flag, _("Output as CSV (same as --output=csv)")
50
- option ["--output"], "ADAPTER", _("Set output format"),
51
- format: HammerCLI::Options::Normalizers::Enum.new(HammerCLI::Output::Output.adapters.keys.map(&:to_s)),
52
- :context_target => :adapter
50
+ option ['--output'], 'ADAPTER', _('Set output format'),
51
+ format: HammerCLI::Options::Normalizers::Enum.new(
52
+ HammerCLI::Output::Output.adapters.keys.map(&:to_s)
53
+ ),
54
+ context_target: :adapter
53
55
  option ["--output-file"], "OUTPUT_FILE", _("Path to custom output file") do |filename|
54
56
  begin
55
57
  context[:output_file] = File.new(filename, 'w')
@@ -111,10 +111,10 @@ module HammerCLI
111
111
 
112
112
  class ListNested < AbstractNormalizer
113
113
  class Schema < Array
114
- def description
114
+ def description(richtext: true)
115
115
  '"' + reduce([]) do |schema, nested_param|
116
116
  name = nested_param.name
117
- name = HighLine.color(name, :bold) if nested_param.required?
117
+ name = HighLine.color(name, :bold) if nested_param.required? && richtext
118
118
  values = nested_param.validator.scan(/<[^>]+>[\w]+<\/?[^>]+>/)
119
119
  value_pattern = if values.empty?
120
120
  "<#{nested_param.expected_type.downcase}>"
@@ -172,6 +172,9 @@ module HammerCLI
172
172
 
173
173
 
174
174
  class Bool < AbstractNormalizer
175
+ def allowed_values
176
+ ['yes', 'no', 'true', 'false', '1', '0']
177
+ end
175
178
 
176
179
  def description
177
180
  _('One of %s.') % ['true/false', 'yes/no', '1/0'].join(', ')
@@ -189,7 +192,7 @@ module HammerCLI
189
192
  end
190
193
 
191
194
  def complete(value)
192
- ["yes ", "no "]
195
+ allowed_values.map { |v| v + ' ' }
193
196
  end
194
197
  end
195
198
 
@@ -280,6 +283,7 @@ module HammerCLI
280
283
  end
281
284
 
282
285
  class EnumList < AbstractNormalizer
286
+ attr_reader :allowed_values
283
287
 
284
288
  def initialize(allowed_values)
285
289
  @allowed_values = allowed_values
@@ -22,14 +22,12 @@ module HammerCLI
22
22
 
23
23
  class OptionDefinition < Clamp::Option::Definition
24
24
 
25
- attr_accessor :value_formatter
26
- attr_accessor :context_target
27
- attr_accessor :deprecated_switches
25
+ attr_accessor :value_formatter, :context_target, :deprecated_switches
28
26
 
29
27
  def initialize(switches, type, description, options = {})
30
- self.value_formatter = options[:format] || HammerCLI::Options::Normalizers::Default.new
31
- self.context_target = options[:context_target]
32
- self.deprecated_switches = options[:deprecated]
28
+ @value_formatter = options[:format] || HammerCLI::Options::Normalizers::Default.new
29
+ @context_target = options[:context_target]
30
+ @deprecated_switches = options[:deprecated]
33
31
  super
34
32
  end
35
33
 
@@ -138,6 +136,28 @@ module HammerCLI
138
136
  end
139
137
  end
140
138
 
139
+ def completion_type(formatter = nil)
140
+ return { type: :flag } if @type == :flag
141
+
142
+ formatter ||= value_formatter
143
+ completion_type = case formatter
144
+ when HammerCLI::Options::Normalizers::Bool,
145
+ HammerCLI::Options::Normalizers::Enum
146
+ { type: :enum, values: value_formatter.allowed_values }
147
+ when HammerCLI::Options::Normalizers::EnumList
148
+ { type: :multienum, values: value_formatter.allowed_values }
149
+ when HammerCLI::Options::Normalizers::ListNested
150
+ { type: :schema, schema: value_formatter.schema.description(richtext: false) }
151
+ when HammerCLI::Options::Normalizers::List
152
+ { type: :list }
153
+ when HammerCLI::Options::Normalizers::KeyValueList
154
+ { type: :key_value_list }
155
+ when HammerCLI::Options::Normalizers::File
156
+ { type: :file }
157
+ end
158
+ completion_type || { type: :value }
159
+ end
160
+
141
161
  private
142
162
 
143
163
  def format_deprecation_msg(option_desc, deprecation_msg)
@@ -0,0 +1,114 @@
1
+ # frozen_string_literal: true
2
+
3
+ module HammerCLI
4
+ module Options
5
+ class OptionFamily
6
+ attr_reader :children
7
+
8
+ IDS_REGEX = /\s?([Ii][Dd][s]?)\W|([Ii][Dd][s]?\Z)/
9
+
10
+ def initialize(options = {})
11
+ @all = []
12
+ @children = []
13
+ @options = options
14
+ @creator = options[:creator] || Class.new(HammerCLI::Apipie::Command)
15
+ @prefix = options[:prefix]
16
+ @description = options[:description]
17
+ @root = options[:root] || options[:aliased_resource] || options[:referenced_resource]
18
+ end
19
+
20
+ def description
21
+ types = all.map(&:type).map { |s| s.split('_').last.to_s }
22
+ .map(&:capitalize).join('/')
23
+ @description ||= @parent.help[1].gsub(IDS_REGEX) { |w| w.gsub(/\w+/, types) }
24
+ if @options[:deprecation].class <= String
25
+ format_deprecation_msg(@description, _('Deprecated: %{deprecated_msg}') % { deprecated_msg: @options[:deprecation] })
26
+ elsif @options[:deprecation].class <= Hash
27
+ full_msg = @options[:deprecation].map do |flag, msg|
28
+ _('%{flag} is deprecated: %{deprecated_msg}') % { flag: flag, deprecated_msg: msg }
29
+ end.join(', ')
30
+ format_deprecation_msg(@description, full_msg)
31
+ else
32
+ @description
33
+ end
34
+ end
35
+
36
+ def switch
37
+ return if @parent.nil? && @children.empty?
38
+ return @parent.help_lhs.strip if @children.empty?
39
+
40
+ switch_start = main_switch.each_char
41
+ .zip(*all.map(&:switches).flatten.map(&:each_char))
42
+ .select { |a, b| a == b }.transpose.first.join
43
+ suffixes = all.map do |m|
44
+ m.switches.map { |s| s.gsub(switch_start, '') }
45
+ end.flatten.reject(&:empty?).sort { |x, y| x.size <=> y.size }
46
+ "#{switch_start}[#{suffixes.join('|')}]"
47
+ end
48
+
49
+ def head
50
+ @parent
51
+ end
52
+
53
+ def all
54
+ @children + [@parent].compact
55
+ end
56
+
57
+ def parent(switches, type, description, opts = {}, &block)
58
+ raise StandardError, 'Option family can have only one parent' if @parent
59
+
60
+ @parent = new_member(switches, type, description, opts, &block)
61
+ end
62
+
63
+ def child(switches, type, description, opts = {}, &block)
64
+ child = new_member(switches, type, description, opts, &block)
65
+ @children << child
66
+ child
67
+ end
68
+
69
+ def adopt(child)
70
+ child.family = self
71
+ @children << child
72
+ end
73
+
74
+ private
75
+
76
+ def format_deprecation_msg(option_desc, deprecation_msg)
77
+ "#{option_desc} (#{deprecation_msg})"
78
+ end
79
+
80
+ def new_member(switches, type, description, opts = {}, &block)
81
+ opts = opts.merge(@options)
82
+ opts[:family] = self
83
+ if opts[:deprecated]
84
+ handles = [switches].flatten
85
+ opts[:deprecated] = opts[:deprecated].select do |switch, _msg|
86
+ handles.include?(switch)
87
+ end
88
+ end
89
+ @creator.instance_eval do
90
+ option(switches, type, description, opts, &block)
91
+ end
92
+ end
93
+
94
+ def main_switch
95
+ root = @root || @parent.aliased_resource || @parent.referenced_resource || common_root
96
+ "--#{@prefix}#{root}".tr('_', '-')
97
+ end
98
+
99
+ def common_root
100
+ switches = all.map(&:switches).flatten
101
+ shortest = switches.min_by(&:length)
102
+ max_len = shortest.length
103
+ max_len.downto(0) do |curr_len|
104
+ 0.upto(max_len - curr_len) do |start|
105
+ root = shortest[start, curr_len]
106
+ if switches.all? { |switch| switch.include?(root) }
107
+ return root[2..-1].chomp('-')
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
@@ -6,7 +6,7 @@ module HammerCLI
6
6
  module Predefined
7
7
  OPTIONS = {
8
8
  fields: [['--fields'], 'FIELDS',
9
- _('Show specified fileds or predefined filed sets only. (See below)'),
9
+ _('Show specified fields or predefined field sets only. (See below)'),
10
10
  format: HammerCLI::Options::Normalizers::List.new,
11
11
  context_target: :fields]
12
12
  }.freeze
@@ -1,9 +1,9 @@
1
1
  require File.join(File.dirname(__FILE__), 'output/output')
2
2
  require File.join(File.dirname(__FILE__), 'output/fields')
3
3
  require File.join(File.dirname(__FILE__), 'output/formatters')
4
+ require File.join(File.dirname(__FILE__), 'output/generators')
4
5
  require File.join(File.dirname(__FILE__), 'output/adapter')
5
6
  require File.join(File.dirname(__FILE__), 'output/definition')
6
7
  require File.join(File.dirname(__FILE__), 'output/dsl')
7
8
  require File.join(File.dirname(__FILE__), 'output/record_collection')
8
9
  require File.join(File.dirname(__FILE__), 'output/field_filter')
9
-
@@ -44,14 +44,10 @@ module HammerCLI::Output::Adapter
44
44
  raise NotImplementedError
45
45
  end
46
46
 
47
- def print_collection(fields, collection)
47
+ def print_collection(fields, collection, options = {})
48
48
  raise NotImplementedError
49
49
  end
50
50
 
51
- def reset_context
52
- @context.delete(:fields)
53
- end
54
-
55
51
  protected
56
52
 
57
53
  def filter_fields(fields)
@@ -14,7 +14,7 @@ module HammerCLI::Output::Adapter
14
14
  print_collection(fields, [record].flatten(1))
15
15
  end
16
16
 
17
- def print_collection(fields, collection)
17
+ def print_collection(fields, collection, options = {})
18
18
  collection.each do |data|
19
19
  output_stream.puts render_fields(fields, data)
20
20
  output_stream.puts
@@ -149,7 +149,8 @@ module HammerCLI::Output::Adapter
149
149
  print_collection(fields, [record].flatten(1))
150
150
  end
151
151
 
152
- def print_collection(fields, collection)
152
+ def print_collection(fields, collection, options = {})
153
+ current_chunk = options[:current_chunk] || :single
153
154
  fields = filter_fields(fields).filter_by_classes
154
155
  .filter_by_sets
155
156
  .filter_by_data(collection.first,
@@ -161,7 +162,7 @@ module HammerCLI::Output::Adapter
161
162
  # or use headers from output definition
162
163
  headers ||= default_headers(fields)
163
164
  csv_string = generate do |csv|
164
- csv << headers if headers && !@context[:no_headers]
165
+ csv << headers if headers && !@context[:no_headers] && %i[first single].include?(current_chunk)
165
166
  rows.each do |row|
166
167
  csv << Cell.values(headers, row)
167
168
  end
@@ -6,9 +6,20 @@ module HammerCLI::Output::Adapter
6
6
  output_stream.puts JSON.pretty_generate(result.first)
7
7
  end
8
8
 
9
- def print_collection(fields, collection)
10
- result = prepare_collection(fields, collection)
11
- output_stream.puts JSON.pretty_generate(result)
9
+ def print_collection(fields, collection, options = {})
10
+ current_chunk = options[:current_chunk] || :single
11
+ prepared = prepare_collection(fields, collection)
12
+ result = JSON.pretty_generate(prepared)
13
+ if current_chunk != :single
14
+ result = if current_chunk == :first
15
+ result[0...-2] + ','
16
+ elsif current_chunk == :last
17
+ result[2..-1]
18
+ else
19
+ result[2...-2] + ','
20
+ end
21
+ end
22
+ output_stream.puts result
12
23
  end
13
24
 
14
25
  def print_message(msg, msg_params={})
@@ -12,7 +12,7 @@ module HammerCLI::Output::Adapter
12
12
  def print_record(fields, record)
13
13
  end
14
14
 
15
- def print_collection(fields, collection)
15
+ def print_collection(fields, collection, options = {})
16
16
  end
17
17
 
18
18
  end
@@ -1,16 +1,11 @@
1
1
  require File.join(File.dirname(__FILE__), 'wrapper_formatter')
2
- require 'hammer_cli/output/utils'
3
2
 
4
3
  module HammerCLI::Output::Adapter
5
-
6
4
  class Table < Abstract
7
-
8
- MAX_COLUMN_WIDTH = 80
9
- MIN_COLUMN_WIDTH = 5
10
-
11
- HLINE = '-'
12
- LINE_SEPARATOR = '-|-'
13
- COLUMN_SEPARATOR = ' | '
5
+ def initialize(context = {}, formatters = {}, filters = {})
6
+ super
7
+ @printed = 0
8
+ end
14
9
 
15
10
  def features
16
11
  return %i[rich_text serialized inline] if tags.empty?
@@ -22,46 +17,42 @@ module HammerCLI::Output::Adapter
22
17
  print_collection(fields, [record].flatten(1))
23
18
  end
24
19
 
25
- def print_collection(all_fields, collection)
20
+ def print_collection(all_fields, collection, options = {})
21
+ current_chunk = options[:current_chunk] || :single
26
22
  fields = filter_fields(all_fields).filter_by_classes
27
23
  .filter_by_sets
28
24
  .filter_by_data(collection.first,
29
25
  compact_only: true)
30
26
  .filtered_fields
31
27
  formatted_collection = format_values(fields, collection)
32
- # calculate hash of column widths (label -> width)
33
- widths = calculate_widths(fields, formatted_collection)
34
-
35
- header_bits = []
36
- hline_bits = []
37
- fields.map do |f|
38
- header_bits << normalize_column(widths[f.label], f.label.upcase)
39
- hline_bits << HLINE * widths[f.label]
40
- end
41
28
 
42
- line = hline_bits.join(LINE_SEPARATOR)
43
- unless @context[:no_headers]
44
- output_stream.puts line
45
- output_stream.puts header_bits.join(COLUMN_SEPARATOR)
46
- output_stream.puts line
29
+ columns = fields.each_with_object({}) do |field, result|
30
+ result[field.label] = field.parameters
47
31
  end
48
32
 
49
- formatted_collection.collect do |row|
50
- row_bits = fields.map do |f|
51
- normalize_column(widths[f.label], row[f.label] || "")
52
- end
53
- output_stream.puts row_bits.join(COLUMN_SEPARATOR)
54
- end
33
+ table_gen = HammerCLI::Output::Generators::Table.new(
34
+ columns, formatted_collection, no_headers: @context[:no_headers]
35
+ )
55
36
 
56
- # print closing line only when the table isn't empty
57
- # and there is no --no-headers option
58
- output_stream.puts line unless formatted_collection.empty? || @context[:no_headers]
37
+ meta = collection.respond_to?(:meta) ? collection.meta : nil
59
38
 
60
- if collection.respond_to?(:meta) && collection.meta.pagination_set? &&
61
- @context[:verbosity] >= collection.meta.pagination_verbosity &&
62
- collection.count < collection.meta.subtotal
63
- pages = (collection.meta.subtotal.to_f / collection.meta.per_page).ceil
64
- puts _("Page %{page} of %{total} (use --page and --per-page for navigation).") % {:page => collection.meta.page, :total => pages}
39
+ output_stream.print(table_gen.header) if %i[first single].include?(current_chunk)
40
+
41
+ output_stream.print(table_gen.body)
42
+
43
+ @printed += collection.count
44
+
45
+ # print closing line only after the last chunk
46
+ output_stream.print(table_gen.footer) if %i[last single].include?(current_chunk)
47
+
48
+ return unless meta && meta.pagination_set?
49
+
50
+ leftovers = %i[last single].include?(current_chunk) && @printed < meta.subtotal
51
+ if @context[:verbosity] >= meta.pagination_verbosity &&
52
+ collection.count < meta.subtotal &&
53
+ leftovers
54
+ pages = (meta.subtotal.to_f / meta.per_page).ceil
55
+ puts _("Page %{page} of %{total} (use --page and --per-page for navigation).") % {:page => meta.page, :total => pages}
65
56
  end
66
57
  end
67
58
 
@@ -71,55 +62,14 @@ module HammerCLI::Output::Adapter
71
62
  super << Fields::ContainerField
72
63
  end
73
64
 
74
- def normalize_column(width, value)
75
- value = value.to_s
76
- padding = width - HammerCLI::Output::Utils.real_length(value)
77
- if padding >= 0
78
- value += (" " * padding)
79
- else
80
- value, real_length = HammerCLI::Output::Utils.real_truncate(value, width-3)
81
- value += '...'
82
- value += ' ' if real_length < (width - 3)
83
- end
84
- value
85
- end
86
-
87
65
  def format_values(fields, collection)
88
66
  collection.collect do |d|
89
67
  fields.inject({}) do |row, f|
90
68
  formatter = WrapperFormatter.new(@formatters.formatter_for_type(f.class), f.parameters)
91
- row.update(f.label => formatter.format(data_for_field(f, d) || "").to_s)
69
+ row.update(f.label => formatter.format(data_for_field(f, d)).to_s)
92
70
  end
93
71
  end
94
72
  end
95
-
96
- def calculate_widths(fields, collection)
97
- Hash[fields.map { |f| [f.label, calculate_column_width(f, collection)] }]
98
- end
99
-
100
- def calculate_column_width(field, collection)
101
- if field.parameters[:width]
102
- return [field.parameters[:width], MIN_COLUMN_WIDTH].max
103
- end
104
-
105
- width = HammerCLI::Output::Utils.real_length(field.label.to_s)
106
- max_width = max_width_for(field)
107
- collection.each do |item|
108
- width = [HammerCLI::Output::Utils.real_length(item[field.label]), width].max
109
- return max_width if width >= max_width
110
- end
111
- width
112
- end
113
-
114
- private
115
-
116
- def max_width_for(field)
117
- if field.parameters[:max_width]
118
- [field.parameters[:max_width], MAX_COLUMN_WIDTH].min
119
- else
120
- MAX_COLUMN_WIDTH
121
- end
122
- end
123
73
  end
124
74
 
125
75
  HammerCLI::Output::Output.register_adapter(:table, Table)