hammer_cli 0.19.1 → 2.2.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/bin/hammer-complete +28 -0
- data/config/cli_config.template.yml +2 -0
- data/config/hammer.completion +5 -0
- data/doc/commands_extension.md +12 -0
- data/doc/creating_commands.md +100 -0
- data/doc/installation.md +47 -4
- data/doc/installation_rpm.md +2 -2
- data/doc/release_notes.md +31 -6
- data/lib/hammer_cli.rb +1 -0
- data/lib/hammer_cli/abstract.rb +61 -4
- data/lib/hammer_cli/apipie/api_connection.rb +5 -1
- data/lib/hammer_cli/apipie/command.rb +3 -2
- data/lib/hammer_cli/apipie/option_builder.rb +15 -13
- data/lib/hammer_cli/apipie/option_definition.rb +9 -7
- data/lib/hammer_cli/bash.rb +2 -0
- data/lib/hammer_cli/bash/completion.rb +159 -0
- data/lib/hammer_cli/bash/prebuild_command.rb +21 -0
- data/lib/hammer_cli/command_extensions.rb +21 -1
- data/lib/hammer_cli/connection.rb +4 -0
- data/lib/hammer_cli/exception_handler.rb +11 -2
- data/lib/hammer_cli/full_help.rb +8 -1
- data/lib/hammer_cli/help/builder.rb +29 -3
- data/lib/hammer_cli/logger_watch.rb +1 -1
- data/lib/hammer_cli/main.rb +5 -3
- data/lib/hammer_cli/options/normalizers.rb +7 -3
- data/lib/hammer_cli/options/option_definition.rb +26 -6
- data/lib/hammer_cli/options/option_family.rb +114 -0
- data/lib/hammer_cli/options/predefined.rb +1 -1
- data/lib/hammer_cli/output/adapter/abstract.rb +1 -5
- data/lib/hammer_cli/output/adapter/base.rb +1 -1
- data/lib/hammer_cli/output/adapter/csv.rb +3 -2
- data/lib/hammer_cli/output/adapter/json.rb +14 -3
- data/lib/hammer_cli/output/adapter/silent.rb +1 -1
- data/lib/hammer_cli/output/adapter/table.rb +27 -8
- data/lib/hammer_cli/output/adapter/yaml.rb +6 -3
- data/lib/hammer_cli/output/output.rb +2 -4
- data/lib/hammer_cli/settings.rb +2 -1
- data/lib/hammer_cli/subcommand.rb +25 -1
- data/lib/hammer_cli/testing/command_assertions.rb +2 -2
- data/lib/hammer_cli/utils.rb +22 -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 +23 -2
- data/test/unit/apipie/api_connection_test.rb +1 -0
- data/test/unit/apipie/option_builder_test.rb +8 -0
- data/test/unit/bash_test.rb +138 -0
- data/test/unit/command_extensions_test.rb +67 -49
- data/test/unit/exception_handler_test.rb +44 -0
- data/test/unit/help/builder_test.rb +22 -0
- data/test/unit/options/option_family_test.rb +48 -0
- data/test/unit/output/adapter/base_test.rb +58 -0
- data/test/unit/output/adapter/csv_test.rb +63 -1
- data/test/unit/output/adapter/json_test.rb +61 -0
- data/test/unit/output/adapter/table_test.rb +70 -1
- data/test/unit/output/adapter/yaml_test.rb +59 -0
- data/test/unit/output/output_test.rb +3 -3
- metadata +17 -6
- data/hammer_cli_complete +0 -13
@@ -10,7 +10,11 @@ module HammerCLI::Apipie
|
|
10
10
|
@api = ApipieBindings::API.new(params, HammerCLI::SSLOptions.new.get_options(params[:uri]))
|
11
11
|
if options[:reload_cache]
|
12
12
|
@api.clean_cache
|
13
|
-
|
13
|
+
HammerCLI.clear_cache
|
14
|
+
unless @logger.nil?
|
15
|
+
@logger.debug 'Apipie cache was cleared'
|
16
|
+
@logger.debug 'Completion cache was cleared'
|
17
|
+
end
|
14
18
|
end
|
15
19
|
end
|
16
20
|
|
@@ -65,8 +65,8 @@ module HammerCLI::Apipie
|
|
65
65
|
method_options(options)
|
66
66
|
end
|
67
67
|
|
68
|
-
def print_data(data)
|
69
|
-
print_collection(output_definition, data) unless output_definition.empty?
|
68
|
+
def print_data(data, options = {})
|
69
|
+
print_collection(output_definition, data, options) unless output_definition.empty?
|
70
70
|
print_success_message(data) unless success_message.nil?
|
71
71
|
end
|
72
72
|
|
@@ -86,6 +86,7 @@ module HammerCLI::Apipie
|
|
86
86
|
declared_options << option
|
87
87
|
block ||= option.default_conversion_block
|
88
88
|
define_accessors_for(option, &block)
|
89
|
+
completion_type_for(option, opts)
|
89
90
|
end
|
90
91
|
extend_options_help(option) if option.value_formatter.is_a?(HammerCLI::Options::Normalizers::ListNested)
|
91
92
|
option
|
@@ -41,12 +41,11 @@ module HammerCLI::Apipie
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def create_option(param, resource_name_map)
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
)
|
44
|
+
family = HammerCLI::Options::OptionFamily.new
|
45
|
+
family.parent(option_switch(param, resource_name_map),
|
46
|
+
option_type(param, resource_name_map),
|
47
|
+
option_desc(param),
|
48
|
+
option_opts(param, resource_name_map))
|
50
49
|
end
|
51
50
|
|
52
51
|
def option_switch(param, resource_name_map)
|
@@ -61,7 +60,7 @@ module HammerCLI::Apipie
|
|
61
60
|
param.description || " "
|
62
61
|
end
|
63
62
|
|
64
|
-
def option_opts(param)
|
63
|
+
def option_opts(param, resource_name_map)
|
65
64
|
opts = {}
|
66
65
|
opts[:required] = true if (param.required? and require_options?)
|
67
66
|
if param.expected_type.to_s == 'array'
|
@@ -80,19 +79,22 @@ module HammerCLI::Apipie
|
|
80
79
|
end
|
81
80
|
opts[:attribute_name] = HammerCLI.option_accessor_name(param.name)
|
82
81
|
opts[:referenced_resource] = resource_name(param)
|
82
|
+
opts[:aliased_resource] = aliased_name(resource_name(param), resource_name_map)
|
83
83
|
|
84
84
|
return opts
|
85
85
|
end
|
86
86
|
|
87
|
+
def aliased_name(name, resource_name_map)
|
88
|
+
return if name.nil?
|
89
|
+
|
90
|
+
resource_name_map[name.to_s] || resource_name_map[name.to_sym] || name
|
91
|
+
end
|
92
|
+
|
87
93
|
def aliased(param, resource_name_map)
|
88
94
|
resource_name = resource_name(param)
|
95
|
+
return param.name if resource_name.nil?
|
89
96
|
|
90
|
-
|
91
|
-
return param.name
|
92
|
-
else
|
93
|
-
aliased_name = resource_name_map[resource_name.to_s] || resource_name_map[resource_name.to_sym] || resource_name
|
94
|
-
return param.name.gsub(resource_name, aliased_name.to_s)
|
95
|
-
end
|
97
|
+
param.name.gsub(resource_name, aliased_name(resource_name, resource_name_map).to_s)
|
96
98
|
end
|
97
99
|
|
98
100
|
def resource_name(param)
|
@@ -1,21 +1,23 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), 'options')
|
2
2
|
|
3
3
|
module HammerCLI::Apipie
|
4
|
-
|
5
4
|
class OptionDefinition < HammerCLI::Options::OptionDefinition
|
6
|
-
|
7
|
-
attr_accessor :referenced_resource
|
5
|
+
attr_accessor :referenced_resource, :aliased_resource, :family
|
8
6
|
|
9
7
|
def initialize(switches, type, description, options = {})
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
@referenced_resource = options[:referenced_resource].to_s if options[:referenced_resource]
|
9
|
+
@aliased_resource = options[:aliased_resource].to_s if options[:aliased_resource]
|
10
|
+
@family = options[:family]
|
13
11
|
super
|
14
12
|
# Apipie currently sends descriptions as escaped HTML once this is changed this should be removed.
|
15
13
|
# See #15198 on Redmine.
|
16
14
|
@description = CGI::unescapeHTML(description)
|
17
15
|
end
|
18
16
|
|
19
|
-
|
17
|
+
def child?
|
18
|
+
return unless @family
|
20
19
|
|
20
|
+
@family.children.include?(self)
|
21
|
+
end
|
22
|
+
end
|
21
23
|
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module HammerCLI
|
4
|
+
module Bash
|
5
|
+
class Completion
|
6
|
+
def initialize(dict)
|
7
|
+
@dict = dict
|
8
|
+
end
|
9
|
+
|
10
|
+
def complete(line)
|
11
|
+
@complete_line = line.end_with?(' ')
|
12
|
+
full_path = line.split(' ')
|
13
|
+
complete_path = @complete_line ? full_path : full_path[0..-2]
|
14
|
+
dict, path = traverse_tree(@dict, complete_path)
|
15
|
+
|
16
|
+
return [] unless path.empty? # lost during traversing
|
17
|
+
|
18
|
+
partial = @complete_line ? '' : full_path.last
|
19
|
+
finish_word(dict, partial)
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.load_description(path)
|
23
|
+
JSON.load(File.open(path))
|
24
|
+
rescue Errno::ENOENT
|
25
|
+
{}
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def finish_word(dict, incomplete)
|
31
|
+
finish_option_value(dict, incomplete) ||
|
32
|
+
(finish_option_or_subcommand(dict, incomplete) + finish_param(dict, incomplete))
|
33
|
+
end
|
34
|
+
|
35
|
+
def finish_option_or_subcommand(dict, incomplete)
|
36
|
+
dict.keys.select { |k| k.is_a?(String) && k =~ /^#{incomplete}/ }.map { |k| k + ' ' }
|
37
|
+
end
|
38
|
+
|
39
|
+
def complete_value(value_description, partial, is_param)
|
40
|
+
case value_description['type']
|
41
|
+
when 'value'
|
42
|
+
if !partial.empty?
|
43
|
+
[]
|
44
|
+
elsif is_param
|
45
|
+
['--->', 'Add parameter']
|
46
|
+
else
|
47
|
+
['--->', 'Add option <value>']
|
48
|
+
end
|
49
|
+
when 'directory'
|
50
|
+
directories(partial)
|
51
|
+
when 'file'
|
52
|
+
files(partial, value_description)
|
53
|
+
when 'enum'
|
54
|
+
enum(partial, value_description['values'])
|
55
|
+
when 'multienum'
|
56
|
+
multienum(partial, value_description['values'])
|
57
|
+
when 'schema'
|
58
|
+
schema(value_description['schema'])
|
59
|
+
when 'list'
|
60
|
+
['--->', 'Add comma-separated list of values']
|
61
|
+
when 'key_value_list'
|
62
|
+
['--->', 'Add comma-separated list of key=value']
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def finish_param(dict, incomplete)
|
67
|
+
if dict['params'] && !dict['params'].empty?
|
68
|
+
complete_value(dict['params'].first, incomplete, true)
|
69
|
+
else
|
70
|
+
[]
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def finish_option_value(dict, incomplete)
|
75
|
+
complete_value(dict, incomplete, false) if dict.key?('type')
|
76
|
+
end
|
77
|
+
|
78
|
+
def traverse_tree(dict, path)
|
79
|
+
return [dict, []] if path.nil? || path.empty?
|
80
|
+
result = if dict.key?(path.first)
|
81
|
+
if path.first.start_with?('-')
|
82
|
+
parse_option(dict, path)
|
83
|
+
else
|
84
|
+
parse_subcommand(dict, path)
|
85
|
+
end
|
86
|
+
elsif dict['params']
|
87
|
+
# traverse params one by one
|
88
|
+
parse_params(dict, path)
|
89
|
+
else
|
90
|
+
# not found
|
91
|
+
[{}, path]
|
92
|
+
end
|
93
|
+
result
|
94
|
+
end
|
95
|
+
|
96
|
+
def parse_params(dict, path)
|
97
|
+
traverse_tree({ 'params' => dict['params'][1..-1] }, path[1..-1])
|
98
|
+
end
|
99
|
+
|
100
|
+
def parse_subcommand(dict, path)
|
101
|
+
traverse_tree(dict[path.first], path[1..-1])
|
102
|
+
end
|
103
|
+
|
104
|
+
def parse_option(dict, path)
|
105
|
+
if dict[path.first]['type'] == 'flag' # flag
|
106
|
+
traverse_tree(dict, path[1..-1])
|
107
|
+
elsif path.length >= 2 # option with value
|
108
|
+
traverse_tree(dict, path[2..-1])
|
109
|
+
else # option with value missing
|
110
|
+
[dict[path.first], path[1..-1]]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def directories(partial = '')
|
115
|
+
dirs = []
|
116
|
+
dirs += Dir.glob("#{partial}*").select { |f| File.directory?(f) }
|
117
|
+
dirs = dirs.map { |d| d + '/' } if dirs.length == 1
|
118
|
+
dirs
|
119
|
+
end
|
120
|
+
|
121
|
+
def files(partial = '', opts = {})
|
122
|
+
filter = opts.fetch('filter', '.*')
|
123
|
+
file_names = []
|
124
|
+
file_names += Dir.glob("#{partial}*").select do |f|
|
125
|
+
File.directory?(f) || f =~ /#{filter}/
|
126
|
+
end
|
127
|
+
file_names.map { |f| File.directory?(f) ? f + '/' : f + ' ' }
|
128
|
+
end
|
129
|
+
|
130
|
+
def enum(partial = '', values = [])
|
131
|
+
values.select { |v| v.start_with?(partial) }.map { |v| v + ' ' }
|
132
|
+
end
|
133
|
+
|
134
|
+
def multienum(partial = '', values = [])
|
135
|
+
return values if partial.empty?
|
136
|
+
|
137
|
+
parts = partial.split(',')
|
138
|
+
resolved = []
|
139
|
+
to_complete = parts.each_with_object([]) do |part, res|
|
140
|
+
next resolved << part if values.include?(part)
|
141
|
+
|
142
|
+
res << part
|
143
|
+
end
|
144
|
+
|
145
|
+
hints = to_complete.map do |p|
|
146
|
+
values.select { |v| v.start_with?(p) }
|
147
|
+
end.flatten(1).uniq
|
148
|
+
return values - parts if hints.empty?
|
149
|
+
return [(resolved + hints).join(',')] if hints.size == 1
|
150
|
+
|
151
|
+
hints
|
152
|
+
end
|
153
|
+
|
154
|
+
def schema(template = '')
|
155
|
+
['--->', "Add value by following schema: #{template}"]
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module HammerCLI
|
2
|
+
module Bash
|
3
|
+
class PrebuildCompletionCommand < HammerCLI::AbstractCommand
|
4
|
+
def execute
|
5
|
+
map = HammerCLI::MainCommand.completion_map
|
6
|
+
cache_file = HammerCLI::Settings.get(:completion_cache_file)
|
7
|
+
cache_dir = File.dirname(cache_file)
|
8
|
+
FileUtils.mkdir_p(cache_dir) unless File.directory?(cache_dir)
|
9
|
+
File.write(File.expand_path(cache_file), map.to_json)
|
10
|
+
|
11
|
+
HammerCLI::EX_OK
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
HammerCLI::MainCommand.subcommand(
|
17
|
+
'prebuild-bash-completion',
|
18
|
+
_('Prepare map of options and subcommands for Bash completion'),
|
19
|
+
HammerCLI::Bash::PrebuildCompletionCommand
|
20
|
+
)
|
21
|
+
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 predefined_options use_option
|
18
|
+
option_sources predefined_options use_option option_family
|
19
19
|
].freeze
|
20
20
|
|
21
21
|
def initialize(options = {})
|
@@ -86,6 +86,11 @@ module HammerCLI
|
|
86
86
|
@option_sources_block = block
|
87
87
|
end
|
88
88
|
|
89
|
+
def self.option_family(options = {}, &block)
|
90
|
+
@option_family_opts = options
|
91
|
+
@option_family_block = block
|
92
|
+
end
|
93
|
+
|
89
94
|
# Object
|
90
95
|
|
91
96
|
def extend_options(command_class)
|
@@ -151,6 +156,13 @@ module HammerCLI
|
|
151
156
|
self.class.extend_option_sources(sources, command)
|
152
157
|
end
|
153
158
|
|
159
|
+
def extend_option_family(command_class)
|
160
|
+
allowed = @only & %i[option_family]
|
161
|
+
return if allowed.empty? || (allowed & @except).any?
|
162
|
+
|
163
|
+
self.class.extend_option_family(command_class)
|
164
|
+
end
|
165
|
+
|
154
166
|
def delegatee(command_class)
|
155
167
|
self.class.delegatee = command_class
|
156
168
|
end
|
@@ -234,5 +246,13 @@ module HammerCLI
|
|
234
246
|
@option_sources_block.call(sources, command)
|
235
247
|
logger.debug("Called block for #{@delegatee} option sources:\n\t#{@option_sources_block}")
|
236
248
|
end
|
249
|
+
|
250
|
+
def self.extend_option_family(command_class)
|
251
|
+
return if @option_family_block.nil?
|
252
|
+
|
253
|
+
@option_family_opts[:creator] = command_class
|
254
|
+
command_class.send(:option_family, @option_family_opts, &@option_family_block)
|
255
|
+
logger.debug("Called option family block for #{command_class}:\n\t#{@option_family_block}")
|
256
|
+
end
|
237
257
|
end
|
238
258
|
end
|
@@ -69,7 +69,7 @@ module HammerCLI
|
|
69
69
|
|
70
70
|
def handle_usage_exception(e)
|
71
71
|
print_error (_("Error: %{message}") + "\n\n" +
|
72
|
-
_("See: '%{path} --help'.")) % {:
|
72
|
+
_("See: '%{path} --help'.")) % { message: e.message, path: HammerCLI.expand_invocation_path(e.command.invocation_path) }
|
73
73
|
log_full_error e
|
74
74
|
HammerCLI::EX_USAGE
|
75
75
|
end
|
@@ -138,7 +138,16 @@ module HammerCLI
|
|
138
138
|
end
|
139
139
|
|
140
140
|
def handle_apipie_missing_arguments_error(e)
|
141
|
-
|
141
|
+
params = e.params.map do |p|
|
142
|
+
param = p[/\[.+\]/]
|
143
|
+
param = if param.nil?
|
144
|
+
p.tr('_', '-')
|
145
|
+
else
|
146
|
+
p.scan(/\[[^\[\]]+\]/).first[1...-1].tr('_', '-')
|
147
|
+
end
|
148
|
+
"--#{param}"
|
149
|
+
end
|
150
|
+
message = _("Missing arguments for %s.") % "'#{params.uniq.join("', '")}'"
|
142
151
|
print_error message
|
143
152
|
log_full_error e, message
|
144
153
|
HammerCLI::EX_USAGE
|
data/lib/hammer_cli/full_help.rb
CHANGED
@@ -6,8 +6,11 @@ module HammerCLI
|
|
6
6
|
|
7
7
|
def execute
|
8
8
|
@adapter = option_md? ? MDAdapter.new : TxtAdapter.new
|
9
|
+
HammerCLI.context[:full_help] = true
|
10
|
+
@invocation_paths = {}
|
9
11
|
print_heading
|
10
12
|
print_help
|
13
|
+
HammerCLI.context[:full_help] = false
|
11
14
|
HammerCLI::EX_OK
|
12
15
|
end
|
13
16
|
|
@@ -19,9 +22,13 @@ module HammerCLI
|
|
19
22
|
end
|
20
23
|
|
21
24
|
def print_help(name='hammer', command=HammerCLI::MainCommand, desc='')
|
22
|
-
@
|
25
|
+
@invocation_paths[name] ||= []
|
26
|
+
@adapter.print_command(name, desc, command.new(name, path: @invocation_paths[name]).help)
|
23
27
|
|
24
28
|
command.recognised_subcommands.each do |sub_cmd|
|
29
|
+
path = "#{name} #{sub_cmd.names.first}"
|
30
|
+
@invocation_paths[path] ||= []
|
31
|
+
@invocation_paths[path] += @invocation_paths[name]
|
25
32
|
print_help(@adapter.command_name(name, sub_cmd.names.first), sub_cmd.subcommand_class, sub_cmd.description)
|
26
33
|
end
|
27
34
|
end
|
@@ -14,7 +14,7 @@ module HammerCLI
|
|
14
14
|
def add_usage(invocation_path, usage_descriptions)
|
15
15
|
heading(Clamp.message(:usage_heading))
|
16
16
|
usage_descriptions.each do |usage|
|
17
|
-
puts " #{invocation_path} #{usage}".rstrip
|
17
|
+
puts " #{HammerCLI.expand_invocation_path(invocation_path)} #{usage}".rstrip
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -29,12 +29,19 @@ module HammerCLI
|
|
29
29
|
|
30
30
|
label_width = DEFAULT_LABEL_INDENT
|
31
31
|
items.each do |item|
|
32
|
-
label
|
32
|
+
label = item.help.first
|
33
33
|
label_width = label.size if label.size > label_width
|
34
34
|
end
|
35
35
|
|
36
36
|
items.each do |item|
|
37
|
-
|
37
|
+
if item.respond_to?(:child?) && item.child?
|
38
|
+
next unless HammerCLI.context[:full_help]
|
39
|
+
end
|
40
|
+
label, description = if !HammerCLI.context[:full_help] && item.respond_to?(:family) && item.family
|
41
|
+
[item.family.switch, item.family.description || item.help[1]]
|
42
|
+
else
|
43
|
+
item.help
|
44
|
+
end
|
38
45
|
description.gsub(/^(.)/) { Unicode::capitalize($1) }.each_line do |line|
|
39
46
|
puts " %-#{label_width}s %s" % [label, line]
|
40
47
|
label = ''
|
@@ -54,6 +61,25 @@ module HammerCLI
|
|
54
61
|
label = HighLine.color(label, :bold) if @richtext
|
55
62
|
puts label
|
56
63
|
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def expand_invocation_path(path)
|
68
|
+
bits = path.split(' ')
|
69
|
+
parent_command = HammerCLI::MainCommand
|
70
|
+
new_path = (bits[1..-1] || []).each_with_object([]) do |bit, names|
|
71
|
+
subcommand = parent_command.find_subcommand(bit)
|
72
|
+
next if subcommand.nil?
|
73
|
+
|
74
|
+
names << if subcommand.names.size > 1
|
75
|
+
"<#{subcommand.names.join('|')}>"
|
76
|
+
else
|
77
|
+
subcommand.names.first
|
78
|
+
end
|
79
|
+
parent_command = subcommand.subcommand_class
|
80
|
+
end
|
81
|
+
new_path.unshift(bits.first).join(' ')
|
82
|
+
end
|
57
83
|
end
|
58
84
|
end
|
59
85
|
end
|