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.
- checksums.yaml +4 -4
- data/doc/commands_modification.md +82 -0
- data/doc/creating_commands.md +78 -38
- data/doc/developer_docs.md +2 -0
- data/doc/help_modification.md +119 -0
- data/doc/i18n.md +2 -2
- data/doc/installation_rpm.md +3 -3
- data/doc/release_notes.md +9 -1
- data/lib/hammer_cli.rb +0 -1
- data/lib/hammer_cli/abstract.rb +44 -13
- data/lib/hammer_cli/exception_handler.rb +1 -1
- data/lib/hammer_cli/help/definition.rb +55 -0
- data/lib/hammer_cli/help/definition/abstract_item.rb +38 -0
- data/lib/hammer_cli/help/definition/list.rb +53 -0
- data/lib/hammer_cli/help/definition/section.rb +36 -0
- data/lib/hammer_cli/help/definition/text.rb +21 -0
- data/lib/hammer_cli/help/text_builder.rb +26 -49
- data/lib/hammer_cli/i18n.rb +0 -1
- data/lib/hammer_cli/options/option_collector.rb +12 -9
- data/lib/hammer_cli/options/option_processor.rb +17 -0
- data/lib/hammer_cli/options/processor_list.rb +37 -0
- data/lib/hammer_cli/options/sources/base.rb +17 -0
- data/lib/hammer_cli/options/sources/command_line.rb +3 -1
- data/lib/hammer_cli/options/sources/saved_defaults.rb +3 -1
- data/lib/hammer_cli/options/validators/base.rb +20 -0
- data/lib/hammer_cli/options/validators/dsl.rb +160 -0
- data/lib/hammer_cli/options/validators/dsl_block_validator.rb +19 -0
- data/lib/hammer_cli/output/adapter/csv.rb +11 -11
- data/lib/hammer_cli/output/adapter/tree_structure.rb +5 -3
- data/lib/hammer_cli/output/definition.rb +42 -4
- data/lib/hammer_cli/output/dsl.rb +4 -2
- data/lib/hammer_cli/output/fields.rb +9 -2
- data/lib/hammer_cli/testing/messages.rb +6 -6
- data/lib/hammer_cli/utils.rb +15 -0
- data/lib/hammer_cli/version.rb +1 -1
- data/locale/ca/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/de/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/en_GB/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/es/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/fr/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/it/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ja/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ko/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/pt_BR/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/ru/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_CN/LC_MESSAGES/hammer-cli.mo +0 -0
- data/locale/zh_TW/LC_MESSAGES/hammer-cli.mo +0 -0
- data/test/unit/abstract_test.rb +70 -5
- data/test/unit/exception_handler_test.rb +1 -1
- data/test/unit/help/definition/abstract_item_test.rb +33 -0
- data/test/unit/help/definition/list_test.rb +17 -0
- data/test/unit/help/definition/section_test.rb +25 -0
- data/test/unit/help/definition/text_test.rb +11 -0
- data/test/unit/help/definition_test.rb +236 -0
- data/test/unit/help/text_builder_test.rb +170 -1
- data/test/unit/options/option_collector_test.rb +18 -9
- data/test/unit/options/processor_list_test.rb +70 -0
- data/test/unit/{validator_test.rb → options/validators/dsl_test.rb} +57 -93
- data/test/unit/output/adapter/abstract_test.rb +3 -0
- data/test/unit/output/adapter/base_test.rb +5 -0
- data/test/unit/output/adapter/csv_test.rb +3 -0
- data/test/unit/output/adapter/json_test.rb +12 -0
- data/test/unit/output/adapter/table_test.rb +5 -0
- data/test/unit/output/adapter/yaml_test.rb +11 -0
- data/test/unit/output/definition_test.rb +221 -1
- data/test/unit/utils_test.rb +23 -0
- metadata +31 -5
- data/lib/hammer_cli/validator.rb +0 -172
@@ -0,0 +1,55 @@
|
|
1
|
+
require_relative 'definition/abstract_item'
|
2
|
+
require_relative 'definition/text'
|
3
|
+
require_relative 'definition/list'
|
4
|
+
require_relative 'definition/section'
|
5
|
+
|
6
|
+
module HammerCLI
|
7
|
+
module Help
|
8
|
+
class Definition < Array
|
9
|
+
def build_string
|
10
|
+
@out = StringIO.new
|
11
|
+
each do |item|
|
12
|
+
next unless item.is_a? AbstractItem
|
13
|
+
@out.puts unless first_print?
|
14
|
+
@out.puts item.build_string
|
15
|
+
end
|
16
|
+
@out.string
|
17
|
+
end
|
18
|
+
|
19
|
+
def find_item(item_id)
|
20
|
+
self[item_index(item_id)]
|
21
|
+
end
|
22
|
+
|
23
|
+
def at(path)
|
24
|
+
return super(path) if path.is_a? Integer
|
25
|
+
return self if path.empty?
|
26
|
+
expand_path(path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def insert_definition(mode, item_id, definition)
|
30
|
+
HammerCLI.insert_relative(self, mode, item_index(item_id), *definition)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def expand_path(path)
|
36
|
+
path = [path] unless path.is_a? Array
|
37
|
+
item = find_item(path[0])
|
38
|
+
return item if path[1..-1].empty?
|
39
|
+
item.definition.at(path[1..-1])
|
40
|
+
end
|
41
|
+
|
42
|
+
def first_print?
|
43
|
+
@out.size.zero?
|
44
|
+
end
|
45
|
+
|
46
|
+
def item_index(item_id)
|
47
|
+
index = find_index do |item|
|
48
|
+
item.id == item_id
|
49
|
+
end
|
50
|
+
raise ArgumentError, "Help item '#{item_id}' not found" if index.nil?
|
51
|
+
index
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Help
|
3
|
+
class AbstractItem
|
4
|
+
INDENT_STEP = 2
|
5
|
+
|
6
|
+
attr_reader :id
|
7
|
+
attr_accessor :definition
|
8
|
+
|
9
|
+
def initialize(options = {})
|
10
|
+
@id = options[:id]
|
11
|
+
@indentation = options[:indentation]
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_string
|
15
|
+
raise NotImplementedError
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.indent(content, indentation = nil)
|
19
|
+
indentation ||= ' ' * INDENT_STEP
|
20
|
+
content = content.split("\n") unless content.is_a? Array
|
21
|
+
content.map do |line|
|
22
|
+
(indentation + line).rstrip
|
23
|
+
end.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
protected
|
27
|
+
|
28
|
+
def build_definition(content)
|
29
|
+
raise NotImplementedError
|
30
|
+
end
|
31
|
+
|
32
|
+
def indent(content, indentation = nil)
|
33
|
+
indentation ||= @indentation
|
34
|
+
self.class.indent(content, indentation)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Help
|
3
|
+
class List < AbstractItem
|
4
|
+
LIST_INDENT = 20
|
5
|
+
|
6
|
+
def initialize(items, options = {})
|
7
|
+
super(options)
|
8
|
+
@indent_size = options[:indent_size] || indent_size(items)
|
9
|
+
build_definition(items || [])
|
10
|
+
end
|
11
|
+
|
12
|
+
def build_string
|
13
|
+
out = StringIO.new
|
14
|
+
@definition.each do |item|
|
15
|
+
out.puts item.build_string
|
16
|
+
end
|
17
|
+
out.string
|
18
|
+
end
|
19
|
+
|
20
|
+
protected
|
21
|
+
|
22
|
+
def build_definition(items)
|
23
|
+
@definition = Definition.new
|
24
|
+
items.each do |item|
|
25
|
+
@definition << Text.new(format_item(item))
|
26
|
+
end
|
27
|
+
@definition
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def indent_size(items)
|
33
|
+
items = normalize(items)
|
34
|
+
max_len = items.map { |i| i[0].to_s.length }.max
|
35
|
+
(max_len + INDENT_STEP > LIST_INDENT) ? (max_len + INDENT_STEP) : LIST_INDENT
|
36
|
+
end
|
37
|
+
|
38
|
+
def format_item(item)
|
39
|
+
col1, col2 = item
|
40
|
+
col2 = indent(col2.to_s, ' ' * @indent_size).lstrip
|
41
|
+
line = "%-#{@indent_size}s%s" % [col1, col2]
|
42
|
+
line.strip!
|
43
|
+
line
|
44
|
+
end
|
45
|
+
|
46
|
+
def normalize(items)
|
47
|
+
items.map do |i|
|
48
|
+
i.is_a?(Array) ? i : [i]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Help
|
3
|
+
class Section < AbstractItem
|
4
|
+
attr_reader :label
|
5
|
+
|
6
|
+
def initialize(label, definition = nil, options = {})
|
7
|
+
super(options)
|
8
|
+
@label = label
|
9
|
+
@richtext = options[:richtext] || false
|
10
|
+
@id ||= label
|
11
|
+
build_definition(definition)
|
12
|
+
end
|
13
|
+
|
14
|
+
def build_string
|
15
|
+
out = StringIO.new
|
16
|
+
out.puts heading
|
17
|
+
out.puts indent(@definition.build_string)
|
18
|
+
out.string
|
19
|
+
end
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
def build_definition(content)
|
24
|
+
@definition = content || Definition.new
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def heading
|
30
|
+
label = "#{@label}:"
|
31
|
+
label = HighLine.color(label, :bold) if @richtext
|
32
|
+
label
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Help
|
3
|
+
class Text < AbstractItem
|
4
|
+
def initialize(text = nil, options = {})
|
5
|
+
super(options)
|
6
|
+
build_definition(text)
|
7
|
+
end
|
8
|
+
|
9
|
+
def build_string
|
10
|
+
@text
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def build_definition(content)
|
16
|
+
@text = content || ''
|
17
|
+
@definition = Definition.new([self])
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,78 +1,55 @@
|
|
1
|
+
require 'hammer_cli/help/definition'
|
2
|
+
|
1
3
|
module HammerCLI
|
2
4
|
module Help
|
3
5
|
class TextBuilder
|
4
|
-
|
5
|
-
LIST_INDENT = 20
|
6
|
+
attr_accessor :definition
|
6
7
|
|
7
8
|
def initialize(richtext = false)
|
8
|
-
@out = StringIO.new
|
9
9
|
@richtext = richtext
|
10
|
+
@definition = HammerCLI::Help::Definition.new
|
10
11
|
end
|
11
12
|
|
12
13
|
def string
|
13
|
-
@
|
14
|
+
@definition.build_string
|
14
15
|
end
|
15
16
|
|
16
|
-
def text(content)
|
17
|
-
|
18
|
-
puts content
|
17
|
+
def text(content, options = {})
|
18
|
+
@definition << HammerCLI::Help::Text.new(content, options)
|
19
19
|
end
|
20
20
|
|
21
|
-
def list(items)
|
21
|
+
def list(items, options = {})
|
22
22
|
return if items.empty?
|
23
|
-
|
24
|
-
items = normalize_list(items)
|
25
|
-
max_len = items.map { |i| i[0].to_s.length }.max
|
26
|
-
indent_size = (max_len + INDENT_STEP > LIST_INDENT) ? (max_len + INDENT_STEP) : LIST_INDENT
|
27
|
-
|
28
|
-
puts unless first_print?
|
29
|
-
items.each do |col1, col2|
|
30
|
-
# handle multiple lines in the second column
|
31
|
-
col2 = indent(col2.to_s, ' ' * indent_size).lstrip
|
32
|
-
|
33
|
-
line = "%-#{indent_size}s%s" % [col1, col2]
|
34
|
-
line.strip!
|
35
|
-
puts line
|
36
|
-
end
|
23
|
+
@definition << HammerCLI::Help::List.new(items, options)
|
37
24
|
end
|
38
25
|
|
39
|
-
def section(label, &block)
|
40
|
-
puts unless first_print?
|
41
|
-
heading(label)
|
42
|
-
|
26
|
+
def section(label, options = {}, &block)
|
43
27
|
sub_builder = TextBuilder.new(@richtext)
|
44
28
|
yield(sub_builder) if block_given?
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
def indent(content, indentation = nil)
|
49
|
-
indentation ||= " " * INDENT_STEP
|
50
|
-
content = content.split("\n") unless content.is_a? Array
|
51
|
-
content.map do |line|
|
52
|
-
(indentation + line).rstrip
|
53
|
-
end.join("\n")
|
29
|
+
options[:richtext] ||= @richtext
|
30
|
+
@definition << HammerCLI::Help::Section.new(label, sub_builder.definition, options)
|
54
31
|
end
|
55
32
|
|
56
|
-
|
57
|
-
|
58
|
-
def heading(label)
|
59
|
-
label = "#{label}:"
|
60
|
-
label = HighLine.color(label, :bold) if @richtext
|
61
|
-
puts label
|
33
|
+
def find_item(item_id)
|
34
|
+
@definition.find_item(item_id)
|
62
35
|
end
|
63
36
|
|
64
|
-
def
|
65
|
-
@
|
37
|
+
def at(path = [])
|
38
|
+
item = path.empty? ? self : @definition.at(path)
|
39
|
+
sub_builder = TextBuilder.new(@richtext)
|
40
|
+
sub_builder.definition = item.definition
|
41
|
+
yield(sub_builder)
|
42
|
+
item.definition = sub_builder.definition
|
66
43
|
end
|
67
44
|
|
68
|
-
def
|
69
|
-
|
45
|
+
def insert(mode, item_id)
|
46
|
+
sub_builder = TextBuilder.new(@richtext)
|
47
|
+
yield(sub_builder)
|
48
|
+
@definition.insert_definition(mode, item_id, sub_builder.definition)
|
70
49
|
end
|
71
50
|
|
72
|
-
def
|
73
|
-
|
74
|
-
i.is_a?(Array) ? i : [i]
|
75
|
-
end
|
51
|
+
def indent(content, indentation = nil)
|
52
|
+
HammerCLI::Help::AbstractItem.indent(content, indentation)
|
76
53
|
end
|
77
54
|
end
|
78
55
|
end
|
data/lib/hammer_cli/i18n.rb
CHANGED
@@ -1,17 +1,20 @@
|
|
1
1
|
module HammerCLI
|
2
2
|
module Options
|
3
3
|
class OptionCollector
|
4
|
-
attr_accessor :
|
4
|
+
attr_accessor :option_processor
|
5
5
|
|
6
|
-
def initialize(recognised_options,
|
6
|
+
def initialize(recognised_options, option_processor)
|
7
7
|
@recognised_options = recognised_options
|
8
|
-
|
8
|
+
|
9
|
+
if !option_processor.is_a?(HammerCLI::Options::ProcessorList)
|
10
|
+
@option_processor = HammerCLI::Options::ProcessorList.new(option_processor)
|
11
|
+
else
|
12
|
+
@option_processor = option_processor
|
13
|
+
end
|
9
14
|
end
|
10
15
|
|
11
16
|
def all_options_raw
|
12
|
-
@all_options_raw ||= @
|
13
|
-
source.get_options(@recognised_options, all_options)
|
14
|
-
end
|
17
|
+
@all_options_raw ||= @option_processor.process(@recognised_options, {})
|
15
18
|
end
|
16
19
|
|
17
20
|
def all_options
|
@@ -21,13 +24,13 @@ module HammerCLI
|
|
21
24
|
def options
|
22
25
|
@options ||= all_options.reject { |key, value| value.nil? && all_options_raw[key].nil? }
|
23
26
|
end
|
24
|
-
|
27
|
+
|
25
28
|
private
|
26
|
-
|
29
|
+
|
27
30
|
def translate_nils(opts)
|
28
31
|
Hash[ opts.map { |k,v| [k, translate_nil(v)] } ]
|
29
32
|
end
|
30
|
-
|
33
|
+
|
31
34
|
def translate_nil(value)
|
32
35
|
value == HammerCLI::NilValue ? nil : value
|
33
36
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Options
|
3
|
+
class OptionProcessor
|
4
|
+
def initialize(name: nil)
|
5
|
+
@name = name
|
6
|
+
end
|
7
|
+
|
8
|
+
def name
|
9
|
+
@name || self.class.name.split('::')[-1]
|
10
|
+
end
|
11
|
+
|
12
|
+
def process(defined_options, result)
|
13
|
+
result
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Options
|
3
|
+
class ProcessorList < Array
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
def initialize(sources = [], name: nil)
|
7
|
+
@name = name
|
8
|
+
self.push(*sources)
|
9
|
+
end
|
10
|
+
|
11
|
+
def insert_relative(mode, target_name, processor)
|
12
|
+
index = target_name.nil? ? nil : item_index(target_name)
|
13
|
+
HammerCLI.insert_relative(self, mode, index, processor)
|
14
|
+
end
|
15
|
+
|
16
|
+
def find_by_name(name)
|
17
|
+
self[item_index(name)]
|
18
|
+
end
|
19
|
+
|
20
|
+
def process(defined_options, result)
|
21
|
+
self.inject(result) do |all_options, processor|
|
22
|
+
processor.process(defined_options, all_options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def item_index(target_name)
|
29
|
+
idx = find_index do |item|
|
30
|
+
item.respond_to?(:name) && (item.name == target_name)
|
31
|
+
end
|
32
|
+
raise ArgumentError, "Option processor '#{target_name}' not found" if idx.nil?
|
33
|
+
idx
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative '../option_processor'
|
2
|
+
|
3
|
+
module HammerCLI
|
4
|
+
module Options
|
5
|
+
module Sources
|
6
|
+
class Base < HammerCLI::Options::OptionProcessor
|
7
|
+
def process(defined_options, result)
|
8
|
+
get_options(defined_options, result)
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_options(defined_options, result)
|
12
|
+
result
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|