toys-core 0.3.6 → 0.3.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -0
  3. data/lib/toys-core.rb +20 -5
  4. data/lib/toys/cli.rb +39 -32
  5. data/lib/toys/core_version.rb +1 -1
  6. data/lib/toys/{tool → definition}/acceptor.rb +21 -15
  7. data/lib/toys/{utils/line_output.rb → definition/alias.rb} +47 -59
  8. data/lib/toys/{tool/arg_definition.rb → definition/arg.rb} +17 -7
  9. data/lib/toys/{tool/flag_definition.rb → definition/flag.rb} +19 -9
  10. data/lib/toys/definition/tool.rb +574 -0
  11. data/lib/toys/dsl/arg.rb +118 -0
  12. data/lib/toys/dsl/flag.rb +132 -0
  13. data/lib/toys/dsl/tool.rb +521 -0
  14. data/lib/toys/errors.rb +2 -2
  15. data/lib/toys/helpers.rb +3 -3
  16. data/lib/toys/helpers/exec.rb +31 -25
  17. data/lib/toys/helpers/fileutils.rb +8 -2
  18. data/lib/toys/helpers/highline.rb +8 -1
  19. data/lib/toys/{alias.rb → helpers/terminal.rb} +44 -53
  20. data/lib/toys/input_file.rb +61 -0
  21. data/lib/toys/loader.rb +87 -77
  22. data/lib/toys/middleware.rb +3 -3
  23. data/lib/toys/middleware/add_verbosity_flags.rb +22 -20
  24. data/lib/toys/middleware/base.rb +53 -5
  25. data/lib/toys/middleware/handle_usage_errors.rb +9 -12
  26. data/lib/toys/middleware/set_default_descriptions.rb +6 -7
  27. data/lib/toys/middleware/show_help.rb +71 -67
  28. data/lib/toys/middleware/show_root_version.rb +9 -9
  29. data/lib/toys/runner.rb +157 -0
  30. data/lib/toys/template.rb +4 -3
  31. data/lib/toys/templates.rb +2 -2
  32. data/lib/toys/templates/clean.rb +2 -2
  33. data/lib/toys/templates/gem_build.rb +5 -5
  34. data/lib/toys/templates/minitest.rb +2 -2
  35. data/lib/toys/templates/rubocop.rb +2 -2
  36. data/lib/toys/templates/yardoc.rb +2 -2
  37. data/lib/toys/tool.rb +168 -625
  38. data/lib/toys/utils/exec.rb +19 -18
  39. data/lib/toys/utils/gems.rb +140 -0
  40. data/lib/toys/utils/help_text.rb +25 -20
  41. data/lib/toys/utils/terminal.rb +412 -0
  42. data/lib/toys/utils/wrappable_string.rb +3 -1
  43. metadata +15 -24
  44. data/lib/toys/config_dsl.rb +0 -699
  45. data/lib/toys/context.rb +0 -290
  46. data/lib/toys/helpers/spinner.rb +0 -142
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1552f14b276734b92f59f9c1d4464679ec1facdc6480e8ecb01b7818d7541712
4
- data.tar.gz: d8da75bf066fa32de202edc57151a37c20b08a29537e7fbb25e9683d705fe625
3
+ metadata.gz: 3f7ff775c645d4bbd1906fab469307dcf06852e83d9fa02aba978fd0db53af21
4
+ data.tar.gz: 408ffcc9b47eff78b05228d811e2a32932a56eebe8e64381a5a96ce1c0e22caf
5
5
  SHA512:
6
- metadata.gz: b3816d90527525a282e55b534a2c250fd7667b7c4a9c4922dbd9a67c9bea72223eb6e16f2d1a0d035213ce86be013bdce2a073c56b8f35c4e223262a494faaaa
7
- data.tar.gz: d73196fce65e1c0cc5904dd93e529bd798cfd10a19a1ac4ac9c138b30c62d516f5e76380502e38306ad91105526fd699dbf41fa20643c2b8bd852dfa1914ce06
6
+ metadata.gz: 4969720705d06c492e7083dbd5d139b71ef3f3e260980acca8ec33771b4ee06b90e8138c341984681ff53a747fcdb256fffcbe412d30d64c9a0b32a82b0975ac
7
+ data.tar.gz: 4db5eed3cc44658511b14d017a3afac43daafc397e3094c1955ae08a95b60886673cfa2196b269a06b9c534f4614300573bf33cc2b43a39981c2bd4500c19cd6
data/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Release History
2
2
 
3
+ ### 0.3.7 / 2018-05-30
4
+
5
+ * CHANGED: Execution runs in the same scope as the DSL, which lets us use normal methods instead of helper-blocks.
6
+ * CHANGED: Renamed "script" to "run", and allow setting of runnable by defining a "run" method
7
+ * CHANGED: Set up a constant scope for each config file, to make constant lookup make sense.
8
+ * CHANGED: Removed run_toys and dropped EXIT_ON_NONZERO_STATUS key in favor of using cli directly.
9
+ * CHANGED: Renamed definition_path to source_path
10
+ * CHANGED: LineOutput util changed to a simple Terminal util, and folded spinner into it.
11
+ * CHANGED: Removed spinner helper and added terminal helper.
12
+ * CHANGED: Organized DSL and definition classes
13
+ * ADDED: Helper modules scoped to the tool hierarchy
14
+ * ADDED: Utility that installs and activates third-party gems.
15
+
3
16
  ### 0.3.6 / 2018-05-21
4
17
 
5
18
  * CHANGED: Renamed show_version middleware to show_root_version.
data/lib/toys-core.rb CHANGED
@@ -27,8 +27,6 @@
27
27
  # POSSIBILITY OF SUCH DAMAGE.
28
28
  ;
29
29
 
30
- gem "highline", "~> 1.7"
31
-
32
30
  ##
33
31
  # Toys is a Ruby library and command line tool that lets you build your own
34
32
  # command line suite of tools (with commands and subcommands) using a Ruby DSL.
@@ -40,17 +38,34 @@ module Toys
40
38
  # Namespace for common utility classes.
41
39
  #
42
40
  module Utils; end
41
+
42
+ ##
43
+ # Namespace for object definition classes.
44
+ #
45
+ module Definition; end
46
+
47
+ ##
48
+ # Namespace for DSL classes.
49
+ #
50
+ module DSL; end
43
51
  end
44
52
 
45
- require "toys/alias"
46
53
  require "toys/cli"
47
- require "toys/config_dsl"
48
- require "toys/context"
49
54
  require "toys/core_version"
55
+ require "toys/definition/acceptor"
56
+ require "toys/definition/alias"
57
+ require "toys/definition/arg"
58
+ require "toys/definition/flag"
59
+ require "toys/definition/tool"
60
+ require "toys/dsl/arg"
61
+ require "toys/dsl/flag"
62
+ require "toys/dsl/tool"
50
63
  require "toys/errors"
51
64
  require "toys/helpers"
65
+ require "toys/input_file"
52
66
  require "toys/loader"
53
67
  require "toys/middleware"
68
+ require "toys/runner"
54
69
  require "toys/template"
55
70
  require "toys/templates"
56
71
  require "toys/tool"
data/lib/toys/cli.rb CHANGED
@@ -28,9 +28,8 @@
28
28
  ;
29
29
 
30
30
  require "logger"
31
- require "highline"
32
31
 
33
- require "toys/utils/line_output"
32
+ require "toys/utils/terminal"
34
33
 
35
34
  module Toys
36
35
  ##
@@ -99,7 +98,7 @@ module Toys
99
98
  @loader = Loader.new(
100
99
  index_file_name: index_file_name,
101
100
  preload_file_name: preload_file_name,
102
- middleware_stack: middleware_stack
101
+ middleware_stack: @middleware_stack
103
102
  )
104
103
  @error_handler = error_handler || DefaultErrorHandler.new
105
104
  end
@@ -209,10 +208,15 @@ module Toys
209
208
  # @return [Integer] The resulting status code
210
209
  #
211
210
  def run(*args, verbosity: 0)
212
- tool, remaining = ContextualError.capture("Error finding tool definition") do
211
+ tool_definition, remaining = ContextualError.capture("Error finding tool definition") do
213
212
  @loader.lookup(args.flatten)
214
213
  end
215
- tool.execute(self, remaining, verbosity: verbosity)
214
+ ContextualError.capture_path(
215
+ "Error during tool execution!", tool_definition.source_path,
216
+ tool_name: tool_definition.full_name, tool_args: remaining
217
+ ) do
218
+ Runner.new(self, tool_definition).run(remaining, verbosity: verbosity)
219
+ end
216
220
  rescue ContextualError => e
217
221
  @error_handler.call(e)
218
222
  end
@@ -247,16 +251,20 @@ module Toys
247
251
  ##
248
252
  # Create an error handler.
249
253
  #
250
- # @param [IO,Logger,nil] sink Where to write errors. Default is `$stderr`.
254
+ # @param [IO] output Where to write errors. Default is `$stderr`.
251
255
  #
252
- def initialize(sink = $stderr)
253
- @line_output = Utils::LineOutput.new(sink, log_level: ::Logger::FATAL)
256
+ def initialize(output = $stderr)
257
+ @terminal = Utils::Terminal.new(output: output)
254
258
  end
255
259
 
256
- ## @private
260
+ ##
261
+ # The error handler routine. Prints out the error message and backtrace.
262
+ #
263
+ # @param [Exception] error The error that occurred.
264
+ #
257
265
  def call(error)
258
- @line_output.puts(cause_string(error.cause))
259
- @line_output.puts(context_string(error), :bold)
266
+ @terminal.puts(cause_string(error.cause))
267
+ @terminal.puts(context_string(error), :bold)
260
268
  -1
261
269
  end
262
270
 
@@ -315,13 +323,14 @@ module Toys
315
323
  end
316
324
 
317
325
  ##
318
- # Returns a default logger that logs to `STDERR`.
326
+ # Returns a default logger that logs to `$stderr`.
319
327
  #
320
328
  # @param [IO] stream Stream to write to. Defaults to `$stderr`.
321
329
  # @return [Logger]
322
330
  #
323
331
  def default_logger(stream = $stderr)
324
332
  logger = ::Logger.new(stream)
333
+ terminal = Utils::Terminal.new(output: stream)
325
334
  logger.formatter = proc do |severity, time, _progname, msg|
326
335
  msg_str =
327
336
  case msg
@@ -332,7 +341,7 @@ module Toys
332
341
  else
333
342
  msg.inspect
334
343
  end
335
- format_log(stream.tty?, time, severity, msg_str)
344
+ format_log(terminal, time, severity, msg_str)
336
345
  end
337
346
  logger.level = ::Logger::WARN
338
347
  logger
@@ -340,27 +349,25 @@ module Toys
340
349
 
341
350
  private
342
351
 
343
- def format_log(is_tty, time, severity, msg)
352
+ def format_log(terminal, time, severity, msg)
344
353
  timestr = time.strftime("%Y-%m-%d %H:%M:%S")
345
354
  header = format("[%s %5s]", timestr, severity)
346
- if is_tty
347
- header =
348
- case severity
349
- when "FATAL"
350
- ::HighLine.color(header, :bright_magenta, :bold, :underline)
351
- when "ERROR"
352
- ::HighLine.color(header, :bright_red, :bold)
353
- when "WARN"
354
- ::HighLine.color(header, :bright_yellow)
355
- when "INFO"
356
- ::HighLine.color(header, :bright_cyan)
357
- when "DEBUG"
358
- ::HighLine.color(header, :white)
359
- else
360
- header
361
- end
362
- end
363
- "#{header} #{msg}\n"
355
+ styled_header =
356
+ case severity
357
+ when "FATAL"
358
+ terminal.apply_styles(header, :bright_magenta, :bold, :underline)
359
+ when "ERROR"
360
+ terminal.apply_styles(header, :bright_red, :bold)
361
+ when "WARN"
362
+ terminal.apply_styles(header, :bright_yellow)
363
+ when "INFO"
364
+ terminal.apply_styles(header, :bright_cyan)
365
+ when "DEBUG"
366
+ terminal.apply_styles(header, :white)
367
+ else
368
+ header
369
+ end
370
+ "#{styled_header} #{msg}\n"
364
371
  end
365
372
  end
366
373
  end
@@ -32,5 +32,5 @@ module Toys
32
32
  # Current version of Toys core
33
33
  # @return [String]
34
34
  #
35
- CORE_VERSION = "0.3.6".freeze
35
+ CORE_VERSION = "0.3.7".freeze
36
36
  end
@@ -28,7 +28,7 @@
28
28
  ;
29
29
 
30
30
  module Toys
31
- class Tool
31
+ module Definition
32
32
  ##
33
33
  # An Acceptor validates and converts arguments. It is designed to be
34
34
  # compatible with the OptionParser accept mechanism.
@@ -47,16 +47,19 @@ module Toys
47
47
  ##
48
48
  # Create a base acceptor.
49
49
  #
50
- # The basic acceptor does not do any validation (i.e. it accepts all
51
- # arguments). You may subclass this object and implement the {#match}
50
+ # The base acceptor does not do any validation (i.e. it accepts all
51
+ # arguments). You may subclass this object and override the {#match}
52
52
  # method to change this behavior.
53
53
  #
54
- # The converter should take one or more arguments, the first of which is
55
- # the entire argument string, and the others of which may be returned
56
- # from validation. The converter should return the final converted value
57
- # of the argument. If you do not provide a converter, this acceptor will
58
- # set the final value to the input argument string by default.
59
- # You may provide a converter either as a proc or a block.
54
+ # The base acceptor lets you provide a converter as a proc. The proc
55
+ # should take one or more arguments, the first of which is the entire
56
+ # argument string, and the others of which are any additional values
57
+ # returned from validation. The converter should return the final
58
+ # converted value of the argument.
59
+ #
60
+ # The converter may be provided either as a proc in the `converter`
61
+ # parameter, or as a block. If neither is provided, the base acceptor
62
+ # performs no conversion and uses the argument string.
60
63
  #
61
64
  # @param [String] name A visible name for the acceptor, shown in help.
62
65
  # @param [Proc] converter A converter function. May also be given as a
@@ -105,7 +108,8 @@ module Toys
105
108
  end
106
109
 
107
110
  ##
108
- # Convert the given input.
111
+ # Convert the given input. Uses the converter provided to this object's
112
+ # constructor. Subclasses may also override this method.
109
113
  #
110
114
  # @param [String] str Original argument string
111
115
  # @param [Object...] extra Zero or more additional arguments comprising
@@ -123,10 +127,11 @@ module Toys
123
127
  #
124
128
  class PatternAcceptor < Acceptor
125
129
  ##
126
- # Create an acceptor.
130
+ # Create a pattern acceptor.
127
131
  #
128
132
  # You must provide a regular expression as a validator. You may also
129
- # provide a converter.
133
+ # provide a converter proc. See {Toys::Definition::Acceptor} for details
134
+ # on the converter.
130
135
  #
131
136
  # @param [String] name A visible name for the acceptor, shown in help.
132
137
  # @param [Regexp] regex Regular expression defining value values.
@@ -140,7 +145,7 @@ module Toys
140
145
  end
141
146
 
142
147
  ##
143
- # Overrides match to match from the given regex.
148
+ # Overrides {Toys::Definition::Acceptor#match} to use the given regex.
144
149
  #
145
150
  def match(str)
146
151
  @regex.match(str)
@@ -173,14 +178,15 @@ module Toys
173
178
  end
174
179
 
175
180
  ##
176
- # Overrides match to find the value.
181
+ # Overrides {Toys::Definition::Acceptor#match} to find the value.
177
182
  #
178
183
  def match(str)
179
184
  @values.find { |s, _e| s == str }
180
185
  end
181
186
 
182
187
  ##
183
- # Overrides convert to return the original element.
188
+ # Overrides {Toys::Definition::Acceptor#convert} to return the original
189
+ # element.
184
190
  #
185
191
  def convert(_str, elem)
186
192
  elem
@@ -27,95 +27,83 @@
27
27
  # POSSIBILITY OF SUCH DAMAGE.
28
28
  ;
29
29
 
30
- require "highline"
31
-
32
30
  module Toys
33
- module Utils
31
+ module Definition
34
32
  ##
35
- # Something that outputs lines to the console or log.
33
+ # An alias is a name that refers to another name.
36
34
  #
37
- class LineOutput
35
+ class Alias
38
36
  ##
39
- # Create a line output.
37
+ # Create a new alias.
40
38
  #
41
- # @param [IO,Logger,nil] sink Where to write lines.
39
+ # @param [Array<String>] full_name The name of the alias.
40
+ # @param [String,Array<String>] target The name of the target. May either
41
+ # be a local reference (a single string) or a global reference (an
42
+ # array of strings)
42
43
  #
43
- def initialize(sink, log_level: ::Logger::INFO, styled: nil)
44
- @sink = sink
45
- @log_level = sink.is_a?(::Logger) ? log_level : nil
46
- @styled =
47
- if styled.nil?
48
- sink.respond_to?(:tty?) && sink.tty?
44
+ def initialize(loader, full_name, target, priority)
45
+ @target_name =
46
+ if target.is_a?(::String)
47
+ full_name[0..-2] + [target]
49
48
  else
50
- styled ? true : false
49
+ target.dup
51
50
  end
52
- @buffer = ""
51
+ @target_name.freeze
52
+ @full_name = full_name.dup.freeze
53
+ @priority = priority
54
+ @tool_class = DSL::Tool.new_class(@full_name, priority, loader)
53
55
  end
54
56
 
55
57
  ##
56
- # Where to write lines
57
- # @return [IO,Logger,nil]
58
+ # Return the tool class.
59
+ # @return [Class]
58
60
  #
59
- attr_reader :sink
61
+ attr_reader :tool_class
60
62
 
61
63
  ##
62
- # Whether output is styled
63
- # @return [Boolean]
64
+ # Return the name of the tool as an array of strings.
65
+ # This array may not be modified.
66
+ # @return [Array<String>]
64
67
  #
65
- attr_accessor :styled
68
+ attr_reader :full_name
66
69
 
67
70
  ##
68
- # If the sink is a Logger, the level to log, otherwise `nil`.
69
- # @return [Integer,nil]
71
+ # Return the priority of this alias.
72
+ # @return [Integer]
70
73
  #
71
- attr_reader :log_level
74
+ attr_reader :priority
72
75
 
73
76
  ##
74
- # Write a line.
75
- #
76
- # @param [String] str The line to write
77
- # @param [Symbol...] styles Styles to apply to the entire line.
77
+ # Return the name of the target as an array of strings.
78
+ # This array may not be modified.
79
+ # @return [Array<String>]
78
80
  #
79
- def puts(str = "", *styles)
80
- str = @buffer + apply_styles(str, styles)
81
- @buffer = ""
82
- case sink
83
- when ::Logger
84
- sink.log(log_level, str)
85
- when ::IO
86
- sink.puts(str)
87
- sink.flush
88
- end
89
- self
90
- end
81
+ attr_reader :target_name
91
82
 
92
83
  ##
93
- # Write a newline and flush the current line.
84
+ # Returns the local name of this tool.
85
+ # @return [String]
94
86
  #
95
- def newline
96
- puts
87
+ def simple_name
88
+ full_name.last
97
89
  end
98
90
 
99
91
  ##
100
- # Buffer a partial line but do not write it out yet because the line
101
- # may not yet be complete.
102
- #
103
- # @param [String] str The line to write
104
- # @param [Symbol...] styles Styles to apply to the partial line.
92
+ # Returns a displayable name of this tool, generally the full name
93
+ # delimited by spaces.
94
+ # @return [String]
105
95
  #
106
- def write(str = "", *styles)
107
- @buffer << apply_styles(str, styles)
108
- self
96
+ def display_name
97
+ full_name.join(" ")
109
98
  end
110
99
 
111
- private
112
-
113
- def apply_styles(str, styles)
114
- if styled
115
- styles.empty? ? str : ::HighLine.color(str, *styles)
116
- else
117
- ::HighLine.uncolor(str)
118
- end
100
+ ##
101
+ # Returns a displayable name of the target, generally the full name
102
+ # delimited by spaces.
103
+ # @return [String]
104
+ #
105
+ def display_target
106
+ target_name.join(" ")
119
107
  end
120
108
  end
121
109
  end