gli 1.6.0 → 2.0.0.rc3
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.
- data/.gitignore +11 -0
- data/.rvmrc +1 -0
- data/.travis.yml +10 -0
- data/Gemfile +8 -0
- data/LICENSE.txt +201 -0
- data/ObjectModel.graffle +1191 -0
- data/README.rdoc +60 -10
- data/Rakefile +145 -0
- data/bin/gli +12 -30
- data/bin/report_on_rake_results +10 -0
- data/bin/test_all_rubies.sh +6 -0
- data/features/gli_executable.feature +84 -0
- data/features/gli_init.feature +219 -0
- data/features/step_definitions/gli_executable_steps.rb +12 -0
- data/features/step_definitions/gli_init_steps.rb +11 -0
- data/features/step_definitions/todo_steps.rb +69 -0
- data/features/support/env.rb +49 -0
- data/features/todo.feature +182 -0
- data/gli.cheat +95 -0
- data/gli.gemspec +34 -0
- data/lib/gli.rb +11 -571
- data/lib/gli/app.rb +184 -0
- data/lib/gli/app_support.rb +226 -0
- data/lib/gli/command.rb +107 -95
- data/lib/gli/command_line_option.rb +34 -0
- data/lib/gli/command_line_token.rb +13 -9
- data/lib/gli/command_support.rb +200 -0
- data/lib/gli/commands/compound_command.rb +42 -0
- data/lib/gli/commands/help.rb +63 -0
- data/lib/gli/commands/help_modules/command_help_format.rb +134 -0
- data/lib/gli/commands/help_modules/global_help_format.rb +61 -0
- data/lib/gli/commands/help_modules/list_formatter.rb +22 -0
- data/lib/gli/commands/help_modules/options_formatter.rb +50 -0
- data/lib/gli/commands/help_modules/text_wrapper.rb +53 -0
- data/lib/gli/commands/initconfig.rb +67 -0
- data/lib/{support → gli/commands}/scaffold.rb +150 -34
- data/lib/gli/dsl.rb +194 -0
- data/lib/gli/exceptions.rb +13 -4
- data/lib/gli/flag.rb +30 -41
- data/lib/gli/gli_option_parser.rb +98 -0
- data/lib/gli/option_parser_factory.rb +44 -0
- data/lib/gli/options.rb +2 -1
- data/lib/gli/switch.rb +19 -51
- data/lib/gli/terminal.rb +30 -20
- data/lib/gli/version.rb +5 -0
- data/test/apps/README.md +2 -0
- data/test/apps/todo/Gemfile +2 -0
- data/test/apps/todo/README.rdoc +6 -0
- data/test/apps/todo/Rakefile +23 -0
- data/test/apps/todo/bin/todo +52 -0
- data/test/apps/todo/lib/todo/commands/create.rb +22 -0
- data/test/apps/todo/lib/todo/commands/list.rb +53 -0
- data/test/apps/todo/lib/todo/commands/ls.rb +47 -0
- data/test/apps/todo/lib/todo/version.rb +3 -0
- data/test/apps/todo/test/tc_nothing.rb +14 -0
- data/test/apps/todo/todo.gemspec +23 -0
- data/test/apps/todo/todo.rdoc +5 -0
- data/test/config.yaml +10 -0
- data/test/fake_std_out.rb +30 -0
- data/test/gli.reek +122 -0
- data/test/init_simplecov.rb +8 -0
- data/test/option_test_helper.rb +13 -0
- data/test/roodi.yaml +18 -0
- data/test/tc_command.rb +260 -0
- data/test/tc_compount_command.rb +22 -0
- data/test/tc_flag.rb +56 -0
- data/test/tc_gli.rb +611 -0
- data/test/tc_help.rb +223 -0
- data/test/tc_options.rb +31 -0
- data/test/tc_subcommands.rb +162 -0
- data/test/tc_switch.rb +57 -0
- data/test/tc_terminal.rb +97 -0
- data/test/test_helper.rb +13 -0
- metadata +318 -49
- data/lib/gli_version.rb +0 -3
- data/lib/support/help.rb +0 -179
- data/lib/support/initconfig.rb +0 -34
- data/lib/support/rdoc.rb +0 -119
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'gli/command_line_token.rb'
|
2
|
+
|
3
|
+
module GLI
|
4
|
+
# An option, not a command or argument, on the command line
|
5
|
+
class CommandLineOption < CommandLineToken #:nodoc:
|
6
|
+
|
7
|
+
attr_accessor :default_value
|
8
|
+
# Command to which this option "belongs", nil if it's a global option
|
9
|
+
attr_accessor :associated_command
|
10
|
+
|
11
|
+
# Creates a new option
|
12
|
+
#
|
13
|
+
# names - Array of symbols or strings representing the names of this switch
|
14
|
+
# options - hash of options:
|
15
|
+
# :desc - the short description
|
16
|
+
# :long_desc - the long description
|
17
|
+
# :default_value - the default value of this option
|
18
|
+
def initialize(names,options = {})
|
19
|
+
super(names,options[:desc],options[:long_desc])
|
20
|
+
@default_value = options[:default_value]
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.name_as_string(name,negatable=true)
|
24
|
+
string = name.to_s
|
25
|
+
if string.length == 1
|
26
|
+
"-#{string}"
|
27
|
+
elsif negatable
|
28
|
+
"--[no-]#{string}"
|
29
|
+
else
|
30
|
+
"--#{string}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -2,12 +2,12 @@ module GLI
|
|
2
2
|
# Abstract base class for a logical element of a command line, mostly so that subclasses can have similar
|
3
3
|
# initialization and interface
|
4
4
|
class CommandLineToken
|
5
|
-
attr_reader :name #:
|
6
|
-
attr_reader :aliases #:
|
7
|
-
attr_reader :description #:
|
8
|
-
attr_reader :long_description #:
|
5
|
+
attr_reader :name #:nodoc:
|
6
|
+
attr_reader :aliases #:nodoc:
|
7
|
+
attr_reader :description #:nodoc:
|
8
|
+
attr_reader :long_description #:nodoc:
|
9
9
|
|
10
|
-
def initialize(names,description,long_description=nil) #:
|
10
|
+
def initialize(names,description,long_description=nil) #:nodoc:
|
11
11
|
@description = description
|
12
12
|
@long_description = long_description
|
13
13
|
@name,@aliases,@names = parse_names(names)
|
@@ -17,7 +17,7 @@ module GLI
|
|
17
17
|
all_forms
|
18
18
|
end
|
19
19
|
|
20
|
-
# Sort based on name
|
20
|
+
# Sort based on primary name
|
21
21
|
def <=>(other)
|
22
22
|
self.name.to_s <=> other.name.to_s
|
23
23
|
end
|
@@ -37,7 +37,7 @@ module GLI
|
|
37
37
|
def parse_names(names)
|
38
38
|
# Allow strings; convert to symbols
|
39
39
|
names = [names].flatten.map { |name| name.to_sym }
|
40
|
-
names_hash =
|
40
|
+
names_hash = {}
|
41
41
|
names.each do |name|
|
42
42
|
raise ArgumentError.new("#{name} has spaces; they are not allowed") if name.to_s =~ /\s/
|
43
43
|
names_hash[self.class.name_as_string(name)] = true
|
@@ -47,10 +47,14 @@ module GLI
|
|
47
47
|
[name,aliases,names_hash]
|
48
48
|
end
|
49
49
|
|
50
|
+
def negatable?
|
51
|
+
false;
|
52
|
+
end
|
53
|
+
|
50
54
|
def all_forms_a
|
51
|
-
forms = [self.class.name_as_string(name)]
|
55
|
+
forms = [self.class.name_as_string(name,negatable?)]
|
52
56
|
if aliases
|
53
|
-
forms |= aliases.
|
57
|
+
forms |= aliases.map { |one_alias| self.class.name_as_string(one_alias,negatable?) }.sort { |one,two| one.length <=> two.length }
|
54
58
|
end
|
55
59
|
forms
|
56
60
|
end
|
@@ -0,0 +1,200 @@
|
|
1
|
+
module GLI
|
2
|
+
# Things unrelated to the true public interface of Command that are needed for bookkeeping
|
3
|
+
# and help support. Generally, you shouldn't be calling these methods; they are technically public
|
4
|
+
# but are essentially part of GLI's internal implementation and subject to change
|
5
|
+
module CommandSupport
|
6
|
+
# The parent of this command, either the GLI app, or another command
|
7
|
+
attr_accessor :parent
|
8
|
+
|
9
|
+
def context_description
|
10
|
+
"in the command #{name}"
|
11
|
+
end
|
12
|
+
|
13
|
+
# Return true to avoid including this command in your help strings
|
14
|
+
def nodoc
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return the arguments description
|
19
|
+
def arguments_description
|
20
|
+
@arguments_description
|
21
|
+
end
|
22
|
+
|
23
|
+
# If true, this command doesn't want the pre block run before it executes
|
24
|
+
def skips_pre
|
25
|
+
@skips_pre
|
26
|
+
end
|
27
|
+
|
28
|
+
# If true, this command doesn't want the post block run before it executes
|
29
|
+
def skips_post
|
30
|
+
@skips_post
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return the Array of the command's names
|
34
|
+
def names
|
35
|
+
all_forms
|
36
|
+
end
|
37
|
+
|
38
|
+
def flag(*names)
|
39
|
+
new_flag = if parent.kind_of? Command
|
40
|
+
parent.flag(*names)
|
41
|
+
else
|
42
|
+
super(*names)
|
43
|
+
end
|
44
|
+
new_flag.associated_command = self
|
45
|
+
new_flag
|
46
|
+
end
|
47
|
+
|
48
|
+
def switch(*names)
|
49
|
+
new_switch = if parent.kind_of? Command
|
50
|
+
parent.switch(*names)
|
51
|
+
else
|
52
|
+
super(*names)
|
53
|
+
end
|
54
|
+
new_switch.associated_command = self
|
55
|
+
new_switch
|
56
|
+
end
|
57
|
+
|
58
|
+
def desc(d)
|
59
|
+
if parent.kind_of? Command
|
60
|
+
parent.desc(d)
|
61
|
+
else
|
62
|
+
super(d)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def long_desc(d)
|
67
|
+
if parent.kind_of? Command
|
68
|
+
parent.long_desc(d)
|
69
|
+
else
|
70
|
+
super(d)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def arg_name(d)
|
75
|
+
if parent.kind_of? Command
|
76
|
+
parent.arg_name(d)
|
77
|
+
else
|
78
|
+
super(d)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def default_value(d)
|
83
|
+
if parent.kind_of? Command
|
84
|
+
parent.default_value(d)
|
85
|
+
else
|
86
|
+
super(d)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Get the usage string
|
91
|
+
# CR: This should probably not be here
|
92
|
+
def usage
|
93
|
+
usage = name.to_s
|
94
|
+
usage += ' [command options]' if !flags.empty? || !switches.empty?
|
95
|
+
usage += ' ' + @arguments_description if @arguments_description
|
96
|
+
usage
|
97
|
+
end
|
98
|
+
|
99
|
+
# Return the flags as a Hash
|
100
|
+
def flags
|
101
|
+
@flags ||= {}
|
102
|
+
end
|
103
|
+
# Return the switches as a Hash
|
104
|
+
def switches
|
105
|
+
@switches ||= {}
|
106
|
+
end
|
107
|
+
|
108
|
+
def commands # :nodoc:
|
109
|
+
@commands ||= {}
|
110
|
+
end
|
111
|
+
|
112
|
+
def default_description
|
113
|
+
@default_desc
|
114
|
+
end
|
115
|
+
|
116
|
+
# Executes the command
|
117
|
+
def execute(global_options,options,arguments)
|
118
|
+
subcommand,arguments = find_subcommand(arguments)
|
119
|
+
if subcommand
|
120
|
+
subcommand.execute(global_options,options,arguments)
|
121
|
+
else
|
122
|
+
get_action(arguments).call(global_options,options,arguments)
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def topmost_ancestor
|
127
|
+
some_command = self
|
128
|
+
top = some_command
|
129
|
+
while some_command.kind_of? self.class
|
130
|
+
top = some_command
|
131
|
+
some_command = some_command.parent
|
132
|
+
end
|
133
|
+
top
|
134
|
+
end
|
135
|
+
|
136
|
+
def has_action?
|
137
|
+
!!@action
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_default_command
|
141
|
+
@default_command
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def get_action(arguments)
|
147
|
+
if @action
|
148
|
+
@action
|
149
|
+
else
|
150
|
+
generate_error_action(arguments)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
def generate_error_action(arguments)
|
155
|
+
lambda { |global_options,options,arguments|
|
156
|
+
if am_subcommand?
|
157
|
+
if arguments.size > 0
|
158
|
+
raise UnknownCommand,"Unknown command '#{arguments[0]}'"
|
159
|
+
else
|
160
|
+
raise BadCommandLine,"Command '#{name}' requires a subcommand"
|
161
|
+
end
|
162
|
+
elsif have_subcommands?
|
163
|
+
raise BadCommandLine,"Command '#{name}' requires a subcommand"
|
164
|
+
else
|
165
|
+
raise "Command '#{name}' has no action block"
|
166
|
+
end
|
167
|
+
}
|
168
|
+
end
|
169
|
+
|
170
|
+
def am_subcommand?
|
171
|
+
parent.kind_of?(Command)
|
172
|
+
end
|
173
|
+
|
174
|
+
def have_subcommands?
|
175
|
+
!self.commands.empty?
|
176
|
+
end
|
177
|
+
|
178
|
+
def find_subcommand(arguments)
|
179
|
+
subcommand = find_explicit_subcommand(arguments)
|
180
|
+
if subcommand
|
181
|
+
[subcommand,arguments[1..-1]]
|
182
|
+
else
|
183
|
+
if !@default_command.nil?
|
184
|
+
[find_explicit_subcommand([@default_command.to_s]),arguments]
|
185
|
+
else
|
186
|
+
[false,arguments]
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
def find_explicit_subcommand(arguments)
|
192
|
+
arguments = Array(arguments)
|
193
|
+
return false if arguments.empty?
|
194
|
+
subcommand_name = arguments.first
|
195
|
+
self.commands.values.find { |command|
|
196
|
+
[command.name,Array(command.aliases)].flatten.map(&:to_s).any? { |name| name == subcommand_name }
|
197
|
+
}
|
198
|
+
end
|
199
|
+
end
|
200
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module GLI
|
2
|
+
module Commands
|
3
|
+
# A command that calls other commands in order
|
4
|
+
class CompoundCommand < Command
|
5
|
+
# base:: object that respondes to +commands+
|
6
|
+
# configuration:: Array of arrays: index 0 is the array of names of this command and index 1
|
7
|
+
# is the names of the compound commands.
|
8
|
+
def initialize(base,configuration,options={})
|
9
|
+
name = configuration.keys.first
|
10
|
+
super(options.merge(:names => [name]))
|
11
|
+
|
12
|
+
command_names = configuration[name]
|
13
|
+
|
14
|
+
check_for_unknown_commands!(base,command_names)
|
15
|
+
|
16
|
+
@commands = command_names.map { |name| self.class.find_command(base,name) }
|
17
|
+
end
|
18
|
+
|
19
|
+
def execute(global_options,options,arguments) #:nodoc:
|
20
|
+
@commands.each do |command|
|
21
|
+
command.execute(global_options,options,arguments)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def check_for_unknown_commands!(base,command_names)
|
28
|
+
known_commands = base.commands.keys.map(&:to_s)
|
29
|
+
unknown_commands = command_names.map(&:to_s) - known_commands
|
30
|
+
|
31
|
+
unless unknown_commands.empty?
|
32
|
+
raise "Unknown commands #{unknown_commands.join(',')}"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.find_command(base,name)
|
37
|
+
base.commands.values.find { |command| command.name == name }
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'gli/command'
|
3
|
+
require 'gli/terminal'
|
4
|
+
require 'gli/commands/help_modules/list_formatter'
|
5
|
+
require 'gli/commands/help_modules/text_wrapper'
|
6
|
+
require 'gli/commands/help_modules/options_formatter'
|
7
|
+
require 'gli/commands/help_modules/global_help_format'
|
8
|
+
require 'gli/commands/help_modules/command_help_format'
|
9
|
+
|
10
|
+
module GLI
|
11
|
+
module Commands
|
12
|
+
# The help command used for the two-level interactive help system
|
13
|
+
class Help < Command
|
14
|
+
def initialize(app,output=$stdout,error=$stderr)
|
15
|
+
super(:names => :help,
|
16
|
+
:description => 'Shows a list of commands or help for one command',
|
17
|
+
:arguments_name => 'command',
|
18
|
+
:long_desc => 'Gets help for the application or its commands. Can also list the commands in a way helpful to creating a bash-style completion function',
|
19
|
+
:skips_pre => true,
|
20
|
+
:skips_post => true)
|
21
|
+
@app = app
|
22
|
+
action do |global_options,options,arguments|
|
23
|
+
show_help(global_options,options,arguments,output,error)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def show_help(global_options,options,arguments,out,error)
|
30
|
+
if arguments.empty?
|
31
|
+
out.puts HelpModules::GlobalHelpFormat.new(@app).format
|
32
|
+
else
|
33
|
+
name = arguments.shift
|
34
|
+
command = find_command(name,@app)
|
35
|
+
return if unknown_command(command,name,error)
|
36
|
+
while !arguments.empty?
|
37
|
+
name = arguments.shift
|
38
|
+
command = find_command(name,command)
|
39
|
+
return if unknown_command(command,name,error)
|
40
|
+
end
|
41
|
+
out.puts HelpModules::CommandHelpFormat.new(command,@app,File.basename($0).to_s).format
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def unknown_command(command,name,error)
|
46
|
+
if command.nil?
|
47
|
+
error.puts "error: Unknown command '#{name}'. Use 'gli help' for a list of commands."
|
48
|
+
true
|
49
|
+
else
|
50
|
+
false
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def find_command(command_name,base)
|
55
|
+
base.commands.values.select { |command|
|
56
|
+
if [command.name,Array(command.aliases)].flatten.map(&:to_s).any? { |_| _ == command_name }
|
57
|
+
command
|
58
|
+
end
|
59
|
+
}.first
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,134 @@
|
|
1
|
+
require 'erb'
|
2
|
+
|
3
|
+
module GLI
|
4
|
+
module Commands
|
5
|
+
module HelpModules
|
6
|
+
class CommandHelpFormat
|
7
|
+
def initialize(command,app,basic_invocation)
|
8
|
+
@basic_invocation = basic_invocation
|
9
|
+
@app = app
|
10
|
+
@command = command
|
11
|
+
end
|
12
|
+
|
13
|
+
def format
|
14
|
+
command_wrapper = TextWrapper.new(Terminal.instance.size[0],4 + @command.name.to_s.size + 3)
|
15
|
+
wrapper = TextWrapper.new(Terminal.instance.size[0],4)
|
16
|
+
flags_and_switches = Hash[@command.topmost_ancestor.flags.merge(@command.topmost_ancestor.switches).select { |_,option| option.associated_command == @command }]
|
17
|
+
options_description = OptionsFormatter.new(flags_and_switches).format
|
18
|
+
commands_description = format_subcommands(@command)
|
19
|
+
|
20
|
+
synopses = []
|
21
|
+
one_line_usage = basic_usage(flags_and_switches)
|
22
|
+
one_line_usage << @command.arguments_description
|
23
|
+
if @command.commands.empty?
|
24
|
+
synopses << one_line_usage
|
25
|
+
else
|
26
|
+
synopses = sorted_synopses(flags_and_switches)
|
27
|
+
if @command.has_action?
|
28
|
+
synopses.unshift(one_line_usage)
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
COMMAND_HELP.result(binding)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
COMMAND_HELP = ERB.new(%q(NAME
|
38
|
+
<%= @command.name %> - <%= command_wrapper.wrap(@command.description) %>
|
39
|
+
|
40
|
+
SYNOPSIS
|
41
|
+
<% synopses.each do |s| %>
|
42
|
+
<%= s %>
|
43
|
+
<% end %>
|
44
|
+
<% unless @command.long_description.nil? %>
|
45
|
+
|
46
|
+
DESCRIPTION
|
47
|
+
<%= wrapper.wrap(@command.long_description) %>
|
48
|
+
<% end %>
|
49
|
+
<% if options_description.strip.length != 0 %>
|
50
|
+
|
51
|
+
COMMAND OPTIONS
|
52
|
+
<%= options_description %>
|
53
|
+
<% end %>
|
54
|
+
<% unless @command.commands.empty? %>
|
55
|
+
|
56
|
+
COMMANDS
|
57
|
+
<%= commands_description %>
|
58
|
+
<% end %>),nil,'<>')
|
59
|
+
|
60
|
+
def command_with_subcommand_usage(sub,flags_and_switches,is_default_command)
|
61
|
+
usage = basic_usage(flags_and_switches)
|
62
|
+
sub_options = @command.flags.merge(@command.switches).select { |_,o| o.associated_command == sub }
|
63
|
+
usage << sub_options.map { |option_name,option|
|
64
|
+
all_names = [option.name,Array(option.aliases)].flatten
|
65
|
+
all_names.map { |_|
|
66
|
+
CommandLineOption.name_as_string(_,false) + (option.kind_of?(Flag) ? " #{option.argument_name }" : '')
|
67
|
+
}.join('|')
|
68
|
+
}.map { |_| "[#{_}]" }.sort.join(' ')
|
69
|
+
usage << ' '
|
70
|
+
if is_default_command
|
71
|
+
usage << "[#{sub.name}]"
|
72
|
+
else
|
73
|
+
usage << sub.name.to_s
|
74
|
+
end
|
75
|
+
usage
|
76
|
+
end
|
77
|
+
|
78
|
+
def basic_usage(flags_and_switches)
|
79
|
+
usage = @basic_invocation.dup
|
80
|
+
usage << " [global options] #{path_to_command} "
|
81
|
+
usage << "[command options] " unless global_flags_and_switches.empty?
|
82
|
+
usage
|
83
|
+
end
|
84
|
+
|
85
|
+
def path_to_command
|
86
|
+
path = []
|
87
|
+
c = @command
|
88
|
+
while c.kind_of? Command
|
89
|
+
path.unshift(c.name)
|
90
|
+
c = c.parent
|
91
|
+
end
|
92
|
+
path.join(' ')
|
93
|
+
end
|
94
|
+
|
95
|
+
def global_flags_and_switches
|
96
|
+
@app.flags.merge(@app.switches)
|
97
|
+
end
|
98
|
+
|
99
|
+
def format_subcommands(command)
|
100
|
+
commands_array = command.commands.values.sort.map { |cmd|
|
101
|
+
if command.get_default_command == cmd.name
|
102
|
+
[cmd.names,cmd.description + " (default)"]
|
103
|
+
else
|
104
|
+
[cmd.names,cmd.description]
|
105
|
+
end
|
106
|
+
}
|
107
|
+
if command.has_action?
|
108
|
+
commands_array.unshift(["<default>",command.default_description])
|
109
|
+
end
|
110
|
+
formatter = ListFormatter.new(commands_array)
|
111
|
+
StringIO.new.tap { |io| formatter.output(io) }.string
|
112
|
+
end
|
113
|
+
|
114
|
+
def sorted_synopses(flags_and_switches)
|
115
|
+
synopses_command = {}
|
116
|
+
@command.commands.each do |name,sub|
|
117
|
+
default = @command.get_default_command == name
|
118
|
+
synopsis = command_with_subcommand_usage(sub,flags_and_switches,default)
|
119
|
+
synopses_command[synopsis] = sub
|
120
|
+
end
|
121
|
+
synopses = synopses_command.keys.sort { |one,two|
|
122
|
+
if synopses_command[one].name == @command.get_default_command
|
123
|
+
-1
|
124
|
+
elsif synopses_command[two].name == @command.get_default_command
|
125
|
+
1
|
126
|
+
else
|
127
|
+
synopses_command[one] <=> synopses_command[two]
|
128
|
+
end
|
129
|
+
}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|