Skip to content

Commit c598041

Browse files
authored
Merge pull request #544 from DannyBen/refactor/command-introspection
Refactor `Command::Introspection`
2 parents dae0394 + c228cca commit c598041

File tree

13 files changed

+275
-218
lines changed

13 files changed

+275
-218
lines changed

lib/bashly.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@ module Script
2424
Argument Base CatchAll Command Dependency EnvironmentVariable Flag
2525
Wrapper
2626
]
27+
28+
module Introspection
29+
autoloads 'bashly/script/introspection', %i[
30+
Arguments Commands Dependencies EnvironmentVariables Examples Flags
31+
]
32+
end
2733
end
2834

2935
module Commands

lib/bashly/script/command.rb

Lines changed: 8 additions & 212 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ module Bashly
22
module Script
33
class Command < Base
44
include Completions::Command
5+
include Introspection::Arguments
6+
include Introspection::Commands
7+
include Introspection::Dependencies
8+
include Introspection::EnvironmentVariables
9+
include Introspection::Examples
10+
include Introspection::Flags
511

612
class << self
713
def option_keys
@@ -39,15 +45,6 @@ def alt
3945
options['alias'].is_a?(String) ? [options['alias']] : options['alias']
4046
end
4147

42-
# Returns an array of Arguments
43-
def args
44-
return [] unless options['args']
45-
46-
options['args'].map do |options|
47-
Argument.new options
48-
end
49-
end
50-
5148
# Returns a string suitable to be a headline
5249
def caption_string
5350
help.empty? ? full_name : "#{full_name} - #{summary}"
@@ -58,123 +55,12 @@ def catch_all
5855
@catch_all ||= CatchAll.from_config options['catch_all']
5956
end
6057

61-
# Returns a full list of the Command names and aliases combined
62-
def command_aliases
63-
commands.map(&:aliases).flatten
64-
end
65-
66-
# Returns a data structure for displaying subcommands help
67-
def command_help_data
68-
result = {}
69-
70-
public_commands.each do |command|
71-
result[command.group_string] ||= {}
72-
result[command.group_string][command.name] = { summary: command.summary_string }
73-
next unless command.expose
74-
75-
command.public_commands.each do |subcommand|
76-
result[command.group_string]["#{command.name} #{subcommand.name}"] = {
77-
summary: subcommand.summary_string,
78-
help_only: command.expose != 'always',
79-
}
80-
end
81-
end
82-
83-
result
84-
end
85-
86-
# Returns only the names of the Commands
87-
def command_names
88-
commands.map(&:name)
89-
end
90-
91-
# Returns an array of the Commands
92-
def commands
93-
return [] unless options['commands']
94-
95-
options['commands'].map do |options|
96-
result = Command.new options
97-
result.parents = parents + [name]
98-
result.parent_command = self
99-
result
100-
end
101-
end
102-
103-
# Returns a flat array containing all the commands in this tree.
104-
# This includes children + grandchildren (recursive), and may include self
105-
def deep_commands(include_self: false)
106-
result = []
107-
result << self if include_self
108-
commands.each do |command|
109-
result << command
110-
if command.commands.any?
111-
result += command.deep_commands
112-
end
113-
end
114-
result
115-
end
116-
117-
# If any of this command's subcommands has the default option set to
118-
# true, this default command will be returned, nil otherwise.
119-
def default_command
120-
commands.find(&:default)
121-
end
122-
123-
# Returns an array of all the default Args
124-
def default_args
125-
args.select(&:default)
126-
end
127-
128-
# Returns an array of all the default Environment Variables
129-
def default_environment_variables
130-
environment_variables.select(&:default)
131-
end
132-
133-
# Returns an array of all the default Flags
134-
def default_flags
135-
flags.select(&:default)
136-
end
137-
138-
# Returns an array of Dependency objects
139-
def dependencies
140-
return [] unless options['dependencies']
141-
142-
@dependencies ||= options['dependencies'].map do |key, value|
143-
Dependency.from_config key, value
144-
end
145-
end
146-
147-
# Returns an array of EnvironmentVariable objects
148-
def environment_variables
149-
return [] unless options['environment_variables']
150-
151-
options['environment_variables'].map do |options|
152-
EnvironmentVariable.new options
153-
end
154-
end
155-
156-
# Returns an array of examples
157-
def examples
158-
return nil unless options['examples']
159-
160-
options['examples'].is_a?(Array) ? options['examples'] : [options['examples']]
161-
end
162-
16358
# Returns the filename that is expected to hold the user code for this
16459
# command
16560
def filename
16661
options['filename'] || implicit_filename
16762
end
16863

169-
# Returns an array of Flags
170-
def flags
171-
return [] unless options['flags']
172-
173-
options['flags'].map do |options|
174-
Flag.new options
175-
end
176-
end
177-
17864
# Returns a unique name, suitable to be used in a bash function
17965
def function_name
18066
options['function'] || full_name.to_underscore
@@ -186,12 +72,6 @@ def full_name
18672
parents.any? ? (parents + [name]).join(' ') : name
18773
end
18874

189-
# Returns true if this command's flags should be considered as gloal
190-
# flags, and cascade to subcommands
191-
def global_flags?
192-
flags.any? and commands.any?
193-
end
194-
19575
# Returns the string for the group caption
19676
def group_string
19777
if group
@@ -201,23 +81,6 @@ def group_string
20181
end
20282
end
20383

204-
# Returns subcommands by group
205-
def grouped_commands
206-
result = {}
207-
208-
public_commands.each do |command|
209-
result[command.group_string] ||= []
210-
result[command.group_string] << command
211-
next unless command.expose
212-
213-
command.public_commands.each do |subcommand|
214-
result[command.group_string] << subcommand
215-
end
216-
end
217-
218-
result
219-
end
220-
22184
# Returns true if this command, or any subcommand (deep) as any arg or
22285
# flag with arg that is defined as unique
22386
def has_unique_args_or_flags?
@@ -246,60 +109,11 @@ def parents
246109
@parents ||= []
247110
end
248111

249-
# Returns only commands that are not private
250-
def public_commands
251-
commands.reject(&:private)
252-
end
253-
254-
# Returns a full list of the public Command names and aliases combined
255-
def public_command_aliases
256-
public_commands.map(&:aliases).flatten
257-
end
258-
259-
# Returns only environment variables that are not private
260-
def public_environment_variables
261-
environment_variables.reject(&:private)
262-
end
263-
264-
# Returns only flags that are not private
265-
def public_flags
266-
flags.reject(&:private)
267-
end
268-
269-
# Returns true if one of the args is repeatable
270-
def repeatable_arg_exist?
271-
args.any?(&:repeatable)
272-
end
273-
274-
# Returns an array of all the required Arguments
275-
def required_args
276-
args.select(&:required)
277-
end
278-
279-
# Returns an array of all the required EnvironmentVariables
280-
def required_environment_variables
281-
environment_variables.select(&:required)
282-
end
283-
284-
# Returns an array of all the required Flags
285-
def required_flags
286-
flags.select(&:required)
287-
end
288-
289-
def needy_flags
290-
flags.select(&:needs)
291-
end
292-
293112
# Returns true if this is the root command (no parents)
294113
def root_command?
295114
parents.empty?
296115
end
297116

298-
# Returns true if one of the flags matches the provided short code
299-
def short_flag_exist?(flag)
300-
flags.any? { |f| f.short == flag }
301-
end
302-
303117
# Returns the summary string
304118
def summary_string
305119
if default
@@ -326,11 +140,8 @@ def usage_string
326140
result.compact.join ' '
327141
end
328142

329-
# Returns an array of args usage_string for the command's usage_string
330-
def usage_string_args
331-
args.map(&:usage_string)
332-
end
333-
143+
# Returns a base usage string that considers whether this command is the
144+
# default, and if it has any parents. Used internally by `usage_string`.
334145
def base_usage_pattern
335146
usage_pattern = default ? "[#{name}]" : name
336147
parents.any? ? (parents + [usage_pattern]).join(' ') : usage_pattern
@@ -348,21 +159,6 @@ def validatables
348159
@validatables ||= args.select(&:validate) + flags.select(&:validate)
349160
end
350161

351-
# Returns an array of all the args with a whitelist
352-
def whitelisted_args
353-
args.select(&:allowed)
354-
end
355-
356-
# Returns an array of all the environment_variables with a whitelist arg
357-
def whitelisted_environment_variables
358-
environment_variables.select(&:allowed)
359-
end
360-
361-
# Returns an array of all the flags with a whitelist arg
362-
def whitelisted_flags
363-
flags.select(&:allowed)
364-
end
365-
366162
private
367163

368164
# Returns either a flat filename (docker_status_command.sh) or a nested
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
module Bashly
2+
module Script
3+
module Introspection
4+
module Arguments
5+
# Returns an array of Arguments
6+
def args
7+
return [] unless options['args']
8+
9+
options['args'].map do |options|
10+
Argument.new options
11+
end
12+
end
13+
14+
# Returns an array of all the default Args
15+
def default_args
16+
args.select(&:default)
17+
end
18+
19+
# Returns true if one of the args is repeatable
20+
def repeatable_arg_exist?
21+
args.any?(&:repeatable)
22+
end
23+
24+
# Returns an array of all the required Arguments
25+
def required_args
26+
args.select(&:required)
27+
end
28+
29+
# Returns an array of args usage_string for the command's usage_string
30+
def usage_string_args
31+
args.map(&:usage_string)
32+
end
33+
34+
# Returns an array of all the args with a whitelist
35+
def whitelisted_args
36+
args.select(&:allowed)
37+
end
38+
end
39+
end
40+
end
41+
end

0 commit comments

Comments
 (0)