hammer_cli 0.15.1 → 0.16.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +4 -4
  2. data/doc/commands_modification.md +82 -0
  3. data/doc/creating_commands.md +78 -38
  4. data/doc/developer_docs.md +2 -0
  5. data/doc/help_modification.md +119 -0
  6. data/doc/i18n.md +2 -2
  7. data/doc/installation_rpm.md +3 -3
  8. data/doc/release_notes.md +9 -1
  9. data/lib/hammer_cli.rb +0 -1
  10. data/lib/hammer_cli/abstract.rb +44 -13
  11. data/lib/hammer_cli/exception_handler.rb +1 -1
  12. data/lib/hammer_cli/help/definition.rb +55 -0
  13. data/lib/hammer_cli/help/definition/abstract_item.rb +38 -0
  14. data/lib/hammer_cli/help/definition/list.rb +53 -0
  15. data/lib/hammer_cli/help/definition/section.rb +36 -0
  16. data/lib/hammer_cli/help/definition/text.rb +21 -0
  17. data/lib/hammer_cli/help/text_builder.rb +26 -49
  18. data/lib/hammer_cli/i18n.rb +0 -1
  19. data/lib/hammer_cli/options/option_collector.rb +12 -9
  20. data/lib/hammer_cli/options/option_processor.rb +17 -0
  21. data/lib/hammer_cli/options/processor_list.rb +37 -0
  22. data/lib/hammer_cli/options/sources/base.rb +17 -0
  23. data/lib/hammer_cli/options/sources/command_line.rb +3 -1
  24. data/lib/hammer_cli/options/sources/saved_defaults.rb +3 -1
  25. data/lib/hammer_cli/options/validators/base.rb +20 -0
  26. data/lib/hammer_cli/options/validators/dsl.rb +160 -0
  27. data/lib/hammer_cli/options/validators/dsl_block_validator.rb +19 -0
  28. data/lib/hammer_cli/output/adapter/csv.rb +11 -11
  29. data/lib/hammer_cli/output/adapter/tree_structure.rb +5 -3
  30. data/lib/hammer_cli/output/definition.rb +42 -4
  31. data/lib/hammer_cli/output/dsl.rb +4 -2
  32. data/lib/hammer_cli/output/fields.rb +9 -2
  33. data/lib/hammer_cli/testing/messages.rb +6 -6
  34. data/lib/hammer_cli/utils.rb +15 -0
  35. data/lib/hammer_cli/version.rb +1 -1
  36. data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
  37. data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
  38. data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
  39. data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
  40. data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
  41. data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
  42. data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
  43. data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
  44. data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
  45. data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
  46. data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
  47. data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
  48. data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
  49. data/test/unit/abstract_test.rb +70 -5
  50. data/test/unit/exception_handler_test.rb +1 -1
  51. data/test/unit/help/definition/abstract_item_test.rb +33 -0
  52. data/test/unit/help/definition/list_test.rb +17 -0
  53. data/test/unit/help/definition/section_test.rb +25 -0
  54. data/test/unit/help/definition/text_test.rb +11 -0
  55. data/test/unit/help/definition_test.rb +236 -0
  56. data/test/unit/help/text_builder_test.rb +170 -1
  57. data/test/unit/options/option_collector_test.rb +18 -9
  58. data/test/unit/options/processor_list_test.rb +70 -0
  59. data/test/unit/{validator_test.rb → options/validators/dsl_test.rb} +57 -93
  60. data/test/unit/output/adapter/abstract_test.rb +3 -0
  61. data/test/unit/output/adapter/base_test.rb +5 -0
  62. data/test/unit/output/adapter/csv_test.rb +3 -0
  63. data/test/unit/output/adapter/json_test.rb +12 -0
  64. data/test/unit/output/adapter/table_test.rb +5 -0
  65. data/test/unit/output/adapter/yaml_test.rb +11 -0
  66. data/test/unit/output/definition_test.rb +221 -1
  67. data/test/unit/utils_test.rb +23 -0
  68. metadata +31 -5
  69. data/lib/hammer_cli/validator.rb +0 -172
@@ -1,7 +1,9 @@
1
+ require_relative './base'
2
+
1
3
  module HammerCLI
2
4
  module Options
3
5
  module Sources
4
- class CommandLine
6
+ class CommandLine < Base
5
7
  def initialize(command)
6
8
  @command = command
7
9
  end
@@ -1,7 +1,9 @@
1
+ require_relative './base'
2
+
1
3
  module HammerCLI
2
4
  module Options
3
5
  module Sources
4
- class SavedDefaults
6
+ class SavedDefaults < Base
5
7
  def initialize(defaults, logger)
6
8
  @defaults = defaults
7
9
  @logger = logger
@@ -0,0 +1,20 @@
1
+ require_relative '../option_processor'
2
+
3
+ module HammerCLI
4
+ module Options
5
+ module Validators
6
+ class ValidationError < StandardError
7
+ end
8
+
9
+ class Base < HammerCLI::Options::OptionProcessor
10
+ def process(defined_options, result)
11
+ run(defined_options, result)
12
+ result
13
+ end
14
+
15
+ def run(defined_options, result)
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,160 @@
1
+ module HammerCLI
2
+ module Options
3
+ module Validators
4
+ class DSL
5
+ class BaseConstraint
6
+ attr_reader :rejected_msg, :required_msg
7
+
8
+ def initialize(option_definitions, option_values, to_check)
9
+ @to_check = to_check
10
+ @rejected_msg = ""
11
+ @required_msg = ""
12
+
13
+ @option_values = option_values
14
+ @options = option_definitions.inject({}) do |hash, opt|
15
+ hash.update({opt.attribute_name => opt})
16
+ end
17
+ end
18
+
19
+ def rejected(args={})
20
+ msg = args[:msg] || rejected_msg % option_switches.join(", ")
21
+ raise HammerCLI::Options::Validators::ValidationError.new(msg) if exist?
22
+ end
23
+
24
+ def required(args={})
25
+ msg = args[:msg] || required_msg % option_switches.join(", ")
26
+ raise HammerCLI::Options::Validators::ValidationError.new(msg) unless exist?
27
+ end
28
+
29
+ def exist?
30
+ raise NotImplementedError
31
+ end
32
+
33
+ protected
34
+
35
+ def get_option(name)
36
+ name = name.to_s
37
+ raise _("Unknown option name '%s'.") % name unless @options.has_key? name
38
+ @options[name]
39
+ end
40
+
41
+ def get_option_value(name)
42
+ @option_values[name] || @option_values[name.to_s]
43
+ end
44
+
45
+ def option_passed?(option_name)
46
+ !get_option_value(option_name).nil?
47
+ end
48
+
49
+ def option_switches(opts=nil)
50
+ opts ||= @to_check
51
+ opts.collect do |option_name|
52
+ get_option(option_name).long_switch || get_option(option_name).switches.first
53
+ end
54
+ end
55
+ end
56
+
57
+ class AllConstraint < BaseConstraint
58
+ def initialize(options, option_values, to_check)
59
+ super
60
+ @rejected_msg = _("You can't set all options %s at one time.")
61
+ @required_msg = _("Options %s are required.")
62
+ end
63
+
64
+ def exist?
65
+ @to_check.each do |opt|
66
+ return false unless option_passed?(opt)
67
+ end
68
+ return true
69
+ end
70
+ end
71
+
72
+ class OneOptionConstraint < AllConstraint
73
+ def initialize(options, option_values, to_check)
74
+ super(options, option_values, [to_check])
75
+ @rejected_msg = _("You can't set option %s.")
76
+ @required_msg = _("Option %s is required.")
77
+ end
78
+
79
+ def value
80
+ get_option_value(@to_check[0])
81
+ end
82
+ end
83
+
84
+ class AnyConstraint < BaseConstraint
85
+ def initialize(options, option_values, to_check)
86
+ super
87
+ @rejected_msg = _("You can't set any of options %s.")
88
+ @required_msg = _("At least one of options %s is required.")
89
+ end
90
+
91
+ def exist?
92
+ @to_check.each do |opt|
93
+ return true if option_passed?(opt)
94
+ end
95
+ return @to_check.empty?
96
+ end
97
+ end
98
+
99
+
100
+ class OneOfConstraint < BaseConstraint
101
+ def initialize(options, option_values, to_check)
102
+ raise 'Set at least one expected option' if to_check.empty?
103
+ super
104
+ end
105
+
106
+ def rejected
107
+ raise NotImplementedError, '#rejected is unsupported for OneOfConstraint'
108
+ end
109
+
110
+ def required_msg
111
+ case count_present_options
112
+ when 0
113
+ _("One of options %s is required.")
114
+ when 1
115
+ ''
116
+ else
117
+ _("Only one of options %s can be set.")
118
+ end
119
+ end
120
+
121
+ def exist?
122
+ return count_present_options == 1
123
+ end
124
+
125
+ protected
126
+ def count_present_options
127
+ @to_check.count do |opt|
128
+ option_passed?(opt)
129
+ end
130
+ end
131
+ end
132
+
133
+ def initialize(options, option_values)
134
+ @options = options
135
+ @option_values = option_values
136
+ end
137
+
138
+ def all(*to_check)
139
+ AllConstraint.new(@options, @option_values, to_check.flatten(1))
140
+ end
141
+
142
+ def option(to_check)
143
+ OneOptionConstraint.new(@options, @option_values, to_check)
144
+ end
145
+
146
+ def any(*to_check)
147
+ AnyConstraint.new(@options, @option_values, to_check.flatten(1))
148
+ end
149
+
150
+ def one_of(*to_check)
151
+ OneOfConstraint.new(@options, @option_values, to_check.flatten(1))
152
+ end
153
+
154
+ def run(&block)
155
+ self.instance_eval &block
156
+ end
157
+ end
158
+ end
159
+ end
160
+ end
@@ -0,0 +1,19 @@
1
+ require_relative './base'
2
+ require_relative './dsl'
3
+
4
+ module HammerCLI
5
+ module Options
6
+ module Validators
7
+ class DSLBlockValidator < Base
8
+ def initialize(&block)
9
+ @validation_block = block
10
+ end
11
+
12
+ def run(options, option_values)
13
+ dsl = DSL.new(options, option_values)
14
+ dsl.run(&@validation_block)
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -165,20 +165,20 @@ module HammerCLI::Output::Adapter
165
165
 
166
166
  def print_message(msg, msg_params={})
167
167
  csv_string = generate do |csv|
168
- id = msg_params["id"] || msg_params[:id]
169
- name = msg_params["name"] || msg_params[:name]
170
-
171
168
  labels = [_("Message")]
172
169
  data = [msg.format(msg_params)]
173
170
 
174
- if id
175
- labels << _("Id")
176
- data << id
177
- end
178
-
179
- if name
180
- labels << _("Name")
181
- data << name
171
+ unless msg_params.nil?
172
+ id = msg_params["id"] || msg_params[:id]
173
+ name = msg_params["name"] || msg_params[:name]
174
+ if id
175
+ labels << _("Id")
176
+ data << id
177
+ end
178
+ if name
179
+ labels << _("Name")
180
+ data << name
181
+ end
182
182
  end
183
183
 
184
184
  csv << labels
@@ -19,12 +19,14 @@ module HammerCLI::Output::Adapter
19
19
  end
20
20
 
21
21
  def prepare_message(msg, msg_params = {})
22
- id = msg_params['id'] || msg_params[:id]
23
- name = msg_params['name'] || msg_params[:name]
24
-
25
22
  data = {
26
23
  capitalize(:message) => msg.format(msg_params)
27
24
  }
25
+ return data if msg_params.nil?
26
+
27
+ id = msg_params['id'] || msg_params[:id]
28
+ name = msg_params['name'] || msg_params[:name]
29
+
28
30
  data[capitalize(:id)] = id unless id.nil?
29
31
  data[capitalize(:name)] = name unless name.nil?
30
32
  data
@@ -1,21 +1,59 @@
1
1
  module HammerCLI::Output
2
-
3
2
  class Definition
4
-
5
3
  attr_accessor :fields
6
4
 
7
5
  def initialize
8
6
  @fields = []
9
7
  end
10
8
 
11
- def append(fields)
9
+ def append(fields = nil, &block)
10
+ fields = [fields].compact unless fields.is_a?(Array)
12
11
  @fields += fields
12
+ return @fields unless block_given?
13
+ dsl = Dsl.new
14
+ dsl.build(&block)
15
+ @fields += dsl.fields
16
+ end
17
+
18
+ def find_field(field_id)
19
+ @fields[field_index(field_id)]
20
+ end
21
+
22
+ def insert(mode, field_id, fields = nil, &block)
23
+ definition = self.class.new
24
+ definition.append(fields, &block)
25
+ HammerCLI.insert_relative(@fields, mode, field_index(field_id), *definition.fields)
26
+ end
27
+
28
+ def at(path = [])
29
+ path = [path] unless path.is_a? Array
30
+ return self if path.empty?
31
+
32
+ field = find_field(path[0])
33
+
34
+ unless field.respond_to?(:output_definition)
35
+ raise ArgumentError, "Field #{path[0]} doesn't have nested output definition"
36
+ end
37
+
38
+ field.output_definition.at(path[1..-1])
39
+ end
40
+
41
+ def clear
42
+ @fields = []
13
43
  end
14
44
 
15
45
  def empty?
16
46
  @fields.empty?
17
47
  end
18
48
 
19
- end
49
+ private
20
50
 
51
+ def field_index(field_id)
52
+ index = @fields.find_index do |f|
53
+ f.match_id?(field_id)
54
+ end
55
+ raise ArgumentError, "Field #{field_id} not found" if index.nil?
56
+ index
57
+ end
58
+ end
21
59
  end
@@ -19,8 +19,10 @@ module HammerCLI::Output
19
19
 
20
20
  def field(key, label, type=nil, options={}, &block)
21
21
  options[:path] = current_path.clone
22
- options[:path] << key if !key.nil?
23
-
22
+ unless key.nil?
23
+ options[:path] << key
24
+ options[:key] = key
25
+ end
24
26
  options[:label] = label
25
27
  type ||= Fields::Field
26
28
  custom_field type, options, &block
@@ -3,9 +3,8 @@ require 'hammer_cli/output/dsl'
3
3
  module Fields
4
4
 
5
5
  class Field
6
-
7
- attr_reader :label
8
6
  attr_reader :path
7
+ attr_accessor :label
9
8
 
10
9
  def initialize(options={})
11
10
  @hide_blank = options[:hide_blank].nil? ? false : options[:hide_blank]
@@ -15,6 +14,14 @@ module Fields
15
14
  @options = options
16
15
  end
17
16
 
17
+ def id
18
+ @options[:id] || @options[:key] || @label
19
+ end
20
+
21
+ def match_id?(field_id)
22
+ @options[:id] == field_id || @options[:key] == field_id || @label == _(field_id)
23
+ end
24
+
18
25
  def hide_blank?
19
26
  @hide_blank
20
27
  end
@@ -33,19 +33,19 @@ module HammerCLI
33
33
  refute opt.description.end_with?('.'), "Description for option #{opt.long_switch} in #{cmd} ends with '.'"
34
34
  end
35
35
 
36
- def check_command_messages(cmd)
36
+ def check_command_messages(cmd, except: [])
37
37
  cmd.recognised_options.each do |opt|
38
38
  check_option_description(cmd, opt)
39
39
  end
40
- refute_msg_period(cmd, :desc)
41
- assert_msg_period(cmd, :success_message)
42
- refute_msg_period(cmd, :failure_message)
40
+ refute_msg_period(cmd, :desc) unless except.include?(:desc)
41
+ assert_msg_period(cmd, :success_message) unless except.include?(:success_message)
42
+ refute_msg_period(cmd, :failure_message) unless except.include?(:failure_message)
43
43
  end
44
44
 
45
- def check_all_command_messages(main_cmd, parent=HammerCLI::AbstractCommand)
45
+ def check_all_command_messages(main_cmd, parent=HammerCLI::AbstractCommand, except: {})
46
46
  all_subcommands(main_cmd, parent).each do |cmd|
47
47
  it "test messages of #{cmd}" do
48
- check_command_messages(cmd)
48
+ check_command_messages(cmd, except: (except[cmd.to_s] || []))
49
49
  end
50
50
  end
51
51
  end
@@ -96,4 +96,19 @@ module HammerCLI
96
96
  end
97
97
  result
98
98
  end
99
+
100
+ def self.insert_relative(array, mode, idx, *new_items)
101
+ case mode
102
+ when :prepend
103
+ idx = 0
104
+ when :append
105
+ idx = -1
106
+ when :after
107
+ idx += 1
108
+ when :replace
109
+ array.delete_at(idx)
110
+ end
111
+
112
+ array.insert(idx, *new_items)
113
+ end
99
114
  end
@@ -1,5 +1,5 @@
1
1
  module HammerCLI
2
2
  def self.version
3
- @version ||= Gem::Version.new '0.15.1'
3
+ @version ||= Gem::Version.new '0.16.0'
4
4
  end
5
5
  end