toys-core 0.3.5 → 0.3.6

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.
@@ -32,5 +32,5 @@ module Toys
32
32
  # Current version of Toys core
33
33
  # @return [String]
34
34
  #
35
- CORE_VERSION = "0.3.5".freeze
35
+ CORE_VERSION = "0.3.6".freeze
36
36
  end
@@ -62,7 +62,7 @@ module Toys
62
62
  # configuration options in the {Toys::Utils::Exec} docs.
63
63
  #
64
64
  def configure_exec(opts = {})
65
- self[Exec].config_defaults(opts)
65
+ self[Exec].configure_defaults(opts)
66
66
  end
67
67
 
68
68
  ##
@@ -35,20 +35,15 @@ module Toys
35
35
  # A module that provides access to highline.
36
36
  #
37
37
  module Highline
38
- ##
39
- # Returns a global highline instance
40
- # @return [::HighLine]
41
- #
42
- def self.highline
43
- @highline ||= ::HighLine.new
44
- end
45
-
46
38
  ##
47
39
  # Returns a global highline instance
48
40
  # @return [::HighLine]
49
41
  #
50
42
  def highline
51
- Highline.highline
43
+ self[Highline] ||= begin
44
+ ::HighLine.use_color = $stdout.tty?
45
+ ::HighLine.new
46
+ end
52
47
  end
53
48
 
54
49
  ##
@@ -89,10 +89,10 @@ module Toys
89
89
  unless verbose_flags.empty?
90
90
  long_desc = "Increase verbosity, causing additional logging levels to display."
91
91
  tool.add_flag(Context::VERBOSITY, verbose_flags,
92
- desc: "Increase verbosity",
93
- long_desc: long_desc,
92
+ report_collisions: false,
94
93
  handler: ->(_val, cur) { cur + 1 },
95
- only_unique: true)
94
+ desc: "Increase verbosity",
95
+ long_desc: long_desc)
96
96
  end
97
97
  end
98
98
 
@@ -102,10 +102,10 @@ module Toys
102
102
  unless quiet_flags.empty?
103
103
  long_desc = "Decrease verbosity, causing fewer logging levels to display."
104
104
  tool.add_flag(Context::VERBOSITY, quiet_flags,
105
- desc: "Decrease verbosity",
106
- long_desc: long_desc,
105
+ report_collisions: false,
107
106
  handler: ->(_val, cur) { cur - 1 },
108
- only_unique: true)
107
+ desc: "Decrease verbosity",
108
+ long_desc: long_desc)
109
109
  end
110
110
  end
111
111
  end
@@ -32,9 +32,12 @@ require "toys/middleware/base"
32
32
  module Toys
33
33
  module Middleware
34
34
  ##
35
- # This middleware sets default description fields for tools that do not
36
- # have them set otherwise. You can set separate descriptions for tools,
37
- # namespaces, and the root.
35
+ # This middleware sets default description fields for tools and command
36
+ # line arguments and flags that do not have them set otherwise.
37
+ #
38
+ # You can modify the static descriptions for tools, namespaces, and the
39
+ # root tool by passing parameters to this middleware. For finer control,
40
+ # you can override methods to modify the description generation logic.
38
41
  #
39
42
  class SetDefaultDescriptions < Base
40
43
  ##
@@ -59,34 +62,25 @@ module Toys
59
62
  # The default long description for the root tool.
60
63
  # @return [String]
61
64
  #
62
- DEFAULT_ROOT_LONG_DESC =
65
+ DEFAULT_ROOT_LONG_DESC = [
63
66
  "This command line tool was built using the toys-core gem. See" \
64
- " https://www.rubydoc.info/gems/toys-core for more info. To replace this message," \
65
- " configure the SetDefaultDescriptions middleware.".freeze
66
-
67
- ##
68
- # The default description for flags.
69
- # @return [String]
70
- #
71
- DEFAULT_FLAG_DESC = "(No flag description available)".freeze
72
-
73
- ##
74
- # The default description for required args.
75
- # @return [String]
76
- #
77
- DEFAULT_REQUIRED_ARG_DESC = "(Required argument - no description available)".freeze
78
-
79
- ##
80
- # The default description for optional args.
81
- # @return [String]
82
- #
83
- DEFAULT_OPTIONAL_ARG_DESC = "(Optional argument - no description available)".freeze
67
+ " https://www.rubydoc.info/gems/toys-core for more info.",
68
+ "To replace this message, configure the SetDefaultDescriptions middleware."
69
+ ].freeze
84
70
 
85
71
  ##
86
- # The default description for remaining args.
87
- # @return [String]
72
+ # A mapping of names for acceptable types
73
+ # @return [Hash]
88
74
  #
89
- DEFAULT_REMAINING_ARG_DESC = "(Remaining arguments - no description available)".freeze
75
+ ACCEPTABLE_NAMES = {
76
+ nil => "string",
77
+ ::String => "nonempty string",
78
+ ::TrueClass => "boolean",
79
+ ::FalseClass => "boolean",
80
+ ::OptionParser::DecimalInteger => "decimal integer",
81
+ ::OptionParser::OctalInteger => "octal integer",
82
+ ::OptionParser::DecimalNumeric => "decimal numeric"
83
+ }.freeze
90
84
 
91
85
  ##
92
86
  # Create a SetDefaultDescriptions middleware given default descriptions.
@@ -109,100 +103,176 @@ module Toys
109
103
  # @param [String,nil] default_root_long_desc The default long description
110
104
  # for the root tool, or `nil` not to set one. Defaults to
111
105
  # {DEFAULT_ROOT_LONG_DESC}.
112
- # @param [String,nil] default_flag_desc The default short description for
113
- # flags, or `nil` not to set one. Defaults to {DEFAULT_FLAG_DESC}.
114
- # @param [String,nil] default_flag_long_desc The default long description
115
- # for flags, or `nil` not to set one. Defaults to `nil`.
116
- # @param [String,nil] default_required_arg_desc The default short
117
- # description for required args, or `nil` not to set one. Defaults to
118
- # {DEFAULT_REQUIRED_ARG_DESC}.
119
- # @param [String,nil] default_required_arg_long_desc The default long
120
- # description for required args, or `nil` not to set one. Defaults to
121
- # `nil`.
122
- # @param [String,nil] default_optional_arg_desc The default short
123
- # description for optional args, or `nil` not to set one. Defaults to
124
- # {DEFAULT_OPTIONAL_ARG_DESC}.
125
- # @param [String,nil] default_optional_arg_long_desc The default long
126
- # description for optional args, or `nil` not to set one. Defaults to
127
- # `nil`.
128
- # @param [String,nil] default_remaining_arg_desc The default short
129
- # description for remaining args, or `nil` not to set one. Defaults
130
- # to {DEFAULT_REMAINING_ARG_DESC}.
131
- # @param [String,nil] default_remaining_arg_long_desc The default long
132
- # description for remaining args, or `nil` not to set one. Defaults
133
- # to `nil`.
134
106
  #
135
107
  def initialize(default_tool_desc: DEFAULT_TOOL_DESC,
136
108
  default_tool_long_desc: nil,
137
109
  default_namespace_desc: DEFAULT_NAMESPACE_DESC,
138
110
  default_namespace_long_desc: nil,
139
111
  default_root_desc: DEFAULT_ROOT_DESC,
140
- default_root_long_desc: DEFAULT_ROOT_LONG_DESC,
141
- default_flag_desc: DEFAULT_FLAG_DESC,
142
- default_flag_long_desc: nil,
143
- default_required_arg_desc: DEFAULT_REQUIRED_ARG_DESC,
144
- default_required_arg_long_desc: nil,
145
- default_optional_arg_desc: DEFAULT_OPTIONAL_ARG_DESC,
146
- default_optional_arg_long_desc: nil,
147
- default_remaining_arg_desc: DEFAULT_REMAINING_ARG_DESC,
148
- default_remaining_arg_long_desc: nil)
112
+ default_root_long_desc: DEFAULT_ROOT_LONG_DESC)
149
113
  @default_tool_desc = default_tool_desc
150
114
  @default_tool_long_desc = default_tool_long_desc
151
115
  @default_namespace_desc = default_namespace_desc
152
116
  @default_namespace_long_desc = default_namespace_long_desc
153
117
  @default_root_desc = default_root_desc
154
118
  @default_root_long_desc = default_root_long_desc
155
- @default_flag_desc = default_flag_desc
156
- @default_flag_long_desc = default_flag_long_desc
157
- @default_required_arg_desc = default_required_arg_desc
158
- @default_required_arg_long_desc = default_required_arg_long_desc
159
- @default_optional_arg_desc = default_optional_arg_desc
160
- @default_optional_arg_long_desc = default_optional_arg_long_desc
161
- @default_remaining_arg_desc = default_remaining_arg_desc
162
- @default_remaining_arg_long_desc = default_remaining_arg_long_desc
163
119
  end
164
120
 
165
121
  ##
166
122
  # Add default description text to tools.
167
123
  #
168
- def config(tool, _loader)
169
- if tool.root?
170
- config_descs(tool, @default_root_desc, @default_root_long_desc)
171
- elsif tool.includes_script?
172
- config_descs(tool, @default_tool_desc, @default_tool_long_desc)
173
- else
174
- config_descs(tool, @default_namespace_desc, @default_namespace_long_desc)
175
- end
124
+ def config(tool, loader)
125
+ data = {tool: tool, loader: loader}
176
126
  tool.flag_definitions.each do |flag|
177
- config_descs(flag, @default_flag_desc, @default_flag_long_desc)
127
+ config_desc(flag, generate_flag_desc(flag, data), generate_flag_long_desc(flag, data))
128
+ end
129
+ tool.arg_definitions.each do |arg|
130
+ config_desc(arg, generate_arg_desc(arg, data), generate_arg_long_desc(arg, data))
178
131
  end
179
- config_args(tool)
132
+ config_desc(tool, generate_tool_desc(tool, data), generate_tool_long_desc(tool, data))
180
133
  yield
181
134
  end
182
135
 
183
- private
136
+ protected
184
137
 
185
- def config_args(tool)
186
- tool.required_arg_definitions.each do |arg|
187
- config_descs(arg, @default_required_arg_desc, @default_required_arg_long_desc)
188
- end
189
- tool.optional_arg_definitions.each do |arg|
190
- config_descs(arg, @default_optional_arg_desc, @default_optional_arg_long_desc)
191
- end
192
- if tool.remaining_args_definition
193
- config_descs(tool.remaining_args_definition,
194
- @default_remaining_arg_desc, @default_remaining_arg_long_desc)
138
+ ##
139
+ # This method implements the logic for generating a tool description.
140
+ # By default, it uses the parameters given to the middleware object.
141
+ # Override this method to provide different logic.
142
+ #
143
+ # @param [Toys::Tool] tool The tool to document.
144
+ # @param [Hash] data Additional data that might be useful. Currently,
145
+ # the {Toys::Loader} is passed with key `:loader`. Future versions
146
+ # of Toys may provide additional information.
147
+ # @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
148
+ # default description, or `nil` not to set a default. See
149
+ # {Toys::Tool#desc=} for info on the format.
150
+ #
151
+ def generate_tool_desc(tool, data)
152
+ if tool.root?
153
+ @default_root_desc
154
+ elsif !tool.includes_script? && data[:loader].has_subtools?(tool.full_name)
155
+ @default_namespace_desc
156
+ else
157
+ @default_tool_desc
195
158
  end
196
159
  end
197
160
 
198
- def config_descs(object, default_desc, default_long_desc)
199
- if default_desc && object.desc.empty?
200
- object.desc = default_desc
161
+ ##
162
+ # This method implements logic for generating a tool long description.
163
+ # By default, it uses the parameters given to the middleware object.
164
+ # Override this method to provide different logic.
165
+ #
166
+ # @param [Toys::Tool] tool The tool to document
167
+ # @param [Hash] data Additional data that might be useful. Currently,
168
+ # the {Toys::Loader} is passed with key `:loader`. Future versions
169
+ # of Toys may provide additional information.
170
+ # @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
171
+ # The default long description, or `nil` not to set a default. See
172
+ # {Toys::Tool#long_desc=} for info on the format.
173
+ #
174
+ def generate_tool_long_desc(tool, data)
175
+ if tool.root?
176
+ @default_root_long_desc
177
+ elsif !tool.includes_script? && data[:loader].has_subtools?(tool.full_name)
178
+ @default_namespace_long_desc
179
+ else
180
+ @default_tool_long_desc
201
181
  end
202
- if default_long_desc && object.long_desc.empty?
203
- object.long_desc = default_long_desc
182
+ end
183
+
184
+ ##
185
+ # This method implements the logic for generating a flag description.
186
+ # Override this method to provide different logic.
187
+ #
188
+ # @param [Toys::Tool::FlagDefinition] flag The flag to document
189
+ # @param [Hash] data Additional data that might be useful. Currently,
190
+ # the {Toys::Tool} is passed with key `:tool`. Future versions of
191
+ # Toys may provide additional information.
192
+ # @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
193
+ # default description, or `nil` not to set a default. See
194
+ # {Toys::Tool#desc=} for info on the format.
195
+ #
196
+ def generate_flag_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
197
+ name = flag.key.to_s.tr("_", "-").gsub(/[^\w-]/, "").downcase.inspect
198
+ acceptable = flag.flag_type == :value ? acceptable_name(flag.accept) : "boolean flag"
199
+ default_clause = flag.default ? " (default is #{flag.default.inspect})" : ""
200
+ "Sets the #{name} option as type #{acceptable}#{default_clause}."
201
+ end
202
+
203
+ ##
204
+ # This method implements logic for generating a flag long description.
205
+ # Override this method to provide different logic.
206
+ #
207
+ # @param [Toys::Tool::FlagDefinition] flag The flag to document
208
+ # @param [Hash] data Additional data that might be useful. Currently,
209
+ # the {Toys::Tool} is passed with key `:tool`. Future versions of
210
+ # Toys may provide additional information.
211
+ # @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
212
+ # The default long description, or `nil` not to set a default. See
213
+ # {Toys::Tool#long_desc=} for info on the format.
214
+ #
215
+ def generate_flag_long_desc(flag, data) # rubocop:disable Lint/UnusedMethodArgument
216
+ nil
217
+ end
218
+
219
+ ##
220
+ # This method implements the logic for generating an arg description.
221
+ # Override this method to provide different logic.
222
+ #
223
+ # @param [Toys::Tool::ArgDefinition] arg The arg to document
224
+ # @param [Hash] data Additional data that might be useful. Currently,
225
+ # the {Toys::Tool} is passed with key `:tool`. Future versions of
226
+ # Toys may provide additional information.
227
+ # @return [String,Array<String>,Toys::Utils::WrappableString,nil] The
228
+ # default description, or `nil` not to set a default. See
229
+ # {Toys::Tool#desc=} for info on the format.
230
+ #
231
+ def generate_arg_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
232
+ acceptable = acceptable_name(arg.accept)
233
+ default_clause = arg.default ? " (default is #{arg.default.inspect})" : ""
234
+ case arg.type
235
+ when :required
236
+ "Required #{acceptable} argument."
237
+ when :optional
238
+ "Optional #{acceptable} argument#{default_clause}."
239
+ else
240
+ "Remaining arguments are type #{acceptable}#{default_clause}."
204
241
  end
205
242
  end
243
+
244
+ ##
245
+ # This method implements logic for generating an arg long description.
246
+ # Override this method to provide different logic.
247
+ #
248
+ # @param [Toys::Tool::ArgDefinition] arg The arg to document
249
+ # @param [Hash] data Additional data that might be useful. Currently,
250
+ # the {Toys::Tool} is passed with key `:tool`. Future versions of
251
+ # Toys may provide additional information.
252
+ # @return [Array<Toys::Utils::WrappableString,String,Array<String>>,nil]
253
+ # The default long description, or `nil` not to set a default. See
254
+ # {Toys::Tool#long_desc=} for info on the format.
255
+ #
256
+ def generate_arg_long_desc(arg, data) # rubocop:disable Lint/UnusedMethodArgument
257
+ nil
258
+ end
259
+
260
+ ##
261
+ # Return a reasonable name for an acceptor
262
+ #
263
+ # @param [Object] accept An acceptor to name
264
+ # @return [String]
265
+ #
266
+ def acceptable_name(accept)
267
+ ACCEPTABLE_NAMES[accept] || accept.to_s.downcase
268
+ end
269
+
270
+ private
271
+
272
+ def config_desc(object, desc, long_desc)
273
+ object.desc = desc if desc && object.desc.empty?
274
+ object.long_desc = long_desc if long_desc && object.long_desc.empty?
275
+ end
206
276
  end
207
277
  end
208
278
  end
@@ -110,6 +110,8 @@ module Toys
110
110
  # help or usage, and doesn't otherwise use positional arguments,
111
111
  # then a tool name can be passed as arguments to display help for
112
112
  # that tool.
113
+ # @param [Boolean] show_source_path Show the source path section. Default
114
+ # is `false`.
113
115
  # @param [Boolean] use_less If the `less` tool is available, and the
114
116
  # output stream is a tty, then use `less` to display help text.
115
117
  # @param [IO] stream Output stream to write to. Default is stdout.
@@ -124,6 +126,7 @@ module Toys
124
126
  default_recursive: false,
125
127
  fallback_execution: false,
126
128
  allow_root_args: false,
129
+ show_source_path: false,
127
130
  use_less: false,
128
131
  stream: $stdout,
129
132
  styled_output: nil)
@@ -134,6 +137,7 @@ module Toys
134
137
  @default_recursive = default_recursive ? true : false
135
138
  @fallback_execution = fallback_execution
136
139
  @allow_root_args = allow_root_args
140
+ @show_source_path = show_source_path
137
141
  @stream = stream
138
142
  @styled_output = styled_output
139
143
  @use_less = use_less
@@ -171,6 +175,7 @@ module Toys
171
175
  help_text = get_help_text(context)
172
176
  str = help_text.help_string(recursive: context[:_recursive_subtools],
173
177
  search: context[:_search_subtools],
178
+ show_source_path: @show_source_path,
174
179
  wrap_width: output_cols)
175
180
  output_help(str)
176
181
  else
@@ -229,7 +234,7 @@ module Toys
229
234
  DEFAULT_HELP_FLAGS)
230
235
  unless help_flags.empty?
231
236
  tool.add_flag(:_show_help, help_flags,
232
- desc: "Display help for this tool", only_unique: true)
237
+ report_collisions: false, desc: "Display help for this tool")
233
238
  end
234
239
  help_flags
235
240
  end
@@ -239,7 +244,8 @@ module Toys
239
244
  DEFAULT_USAGE_FLAGS)
240
245
  unless usage_flags.empty?
241
246
  tool.add_flag(:_show_usage, usage_flags,
242
- desc: "Display a brief usage string for this tool", only_unique: true)
247
+ report_collisions: false,
248
+ desc: "Display a brief usage string for this tool")
243
249
  end
244
250
  usage_flags
245
251
  end
@@ -249,9 +255,9 @@ module Toys
249
255
  DEFAULT_RECURSIVE_FLAGS)
250
256
  unless recursive_flags.empty?
251
257
  tool.add_flag(:_recursive_subtools, recursive_flags,
258
+ report_collisions: false,
252
259
  default: @default_recursive,
253
- desc: "Show all subtools recursively (default is #{@default_recursive})",
254
- only_unique: true)
260
+ desc: "Show all subtools recursively (default is #{@default_recursive})")
255
261
  end
256
262
  end
257
263
 
@@ -260,8 +266,8 @@ module Toys
260
266
  DEFAULT_SEARCH_FLAGS)
261
267
  unless search_flags.empty?
262
268
  tool.add_flag(:_search_subtools, search_flags,
263
- desc: "Search subtools for the given regular expression",
264
- only_unique: true)
269
+ report_collisions: false,
270
+ desc: "Search subtools for the given regular expression")
265
271
  end
266
272
  end
267
273
  end