rexe 0.11.0 → 0.12.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (6) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/README.md +27 -22
  4. data/exe/rexe +61 -37
  5. data/rexe.gemspec +5 -2
  6. metadata +7 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 148f8f91ef5ee20f245d74ee2b16b75550622b7ba80c139a671a26e2e383a482
4
- data.tar.gz: 495447fbd26d0b8205d5c703e6c02577e5b9f85df11ec0892d4717689c17837e
3
+ metadata.gz: 79b7eb979cbeb0ba6d95c150e58bccecef867212b4783808f06381d9e247aa55
4
+ data.tar.gz: e737abbe83eee2bd71d83466a336db48b49ceea1ef88a51615557dcfa623d1d5
5
5
  SHA512:
6
- metadata.gz: fae8f53b62e75773a1245ea5b7e411328146a8bb80538522ec344dd18a86df65523e3226e15421537865a1db7196352f2cd25004303e63b5d0af3fb944e52dcf
7
- data.tar.gz: eacd19481d49bd663ce6d8a9033a73c6eec711031ac766593b60aeca28296c4dacfb38450893ab857bc005663bd29b95883d7a638d45e878d36b7dab7388d5b3
6
+ metadata.gz: 729475e954a39717db0f64b1dbfa2e267c41cf23742fb26de919ba2c80347b25adb1951d4c9ae2a3069068a5ac3baa52c9e8761b235bb72491a1fd0b32f82d94
7
+ data.tar.gz: 53b3ae64d2f92db487299ce46a2808cb82afea02e8b1ed66dbe4d3dfd5d2eddcc31f2697a1f87194f60c9ac7ffa15cfef8d5d11f5bc0e04b666e9e6d4f7d6f79
data/CHANGELOG.md CHANGED
@@ -1,6 +1,13 @@
1
1
  ## rexe -- Ruby Command Line Executor
2
2
 
3
3
 
4
+ ### v0.12.0
5
+
6
+ * Change verbose -v boolean option to log output format -g option.
7
+ * Print error message and exit with nonzero exit code if no source code provided.
8
+ * Add $RC.i alias for $RC.count.
9
+
10
+
4
11
  ### v0.11.0
5
12
 
6
13
  * Make global $RC (Rexe Context) OpenStruct available to user code; added `count` for record count in `-ml` mode.
data/README.md CHANGED
@@ -61,7 +61,7 @@ line, tipping the scale so that it is practical to do it more often.
61
61
  Here is `rexe`'s help text as of the time of this writing:
62
62
 
63
63
  ```
64
- rexe -- Ruby Command Line Executor/Filter -- v0.11.0 -- https://github.com/keithrbennett/rexe
64
+ rexe -- Ruby Command Line Executor/Filter -- v0.12.0 -- https://github.com/keithrbennett/rexe
65
65
 
66
66
  Executes Ruby code on the command line, optionally taking standard input and writing to standard output.
67
67
 
@@ -70,8 +70,9 @@ rexe [options] 'Ruby source code'
70
70
  Options:
71
71
 
72
72
  -c --clear_options Clear all previous command line options specified up to now
73
+ -g --log_format FORMAT Log format, logs to stderr, defaults to none (see -o for format options)
73
74
  -h, --help Print help and exit
74
- -i, --input_format FORMAT Input format (none is default)
75
+ -i, --input_format FORMAT Input format (defaults to none)
75
76
  -ij JSON
76
77
  -im Marshal
77
78
  -in None
@@ -81,9 +82,10 @@ Options:
81
82
  -ml line mode; each line is ingested as a separate string
82
83
  -me enumerator mode
83
84
  -mb big string mode; all lines combined into single multiline string
84
- -mn (default) no input mode; no special handling of input; self is an Object.new
85
- -n, --[no-]noop Do not execute the code (useful with -v); see note (1) below
86
- -o, --output_format FORMAT Output format (puts is default):
85
+ -mn (default) no input mode; no special handling of input; self is an Object.new
86
+ -n, --[no-]noop Do not execute the code (useful with -g); the following are valid:
87
+ -n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -
88
+ -o, --output_format FORMAT Output format (defaults to puts):
87
89
  -oi Inspect
88
90
  -oj JSON
89
91
  -oJ Pretty JSON
@@ -93,16 +95,12 @@ Options:
93
95
  -os to_s
94
96
  -oy YAML
95
97
  -r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated, or ! to clear
96
- -v, --[no-]verbose verbose mode (logs to stderr); see note (1) below
97
98
 
98
- If there is an .rexerc file in your home directory, it will be run as Ruby code
99
+ If there is an .rexerc file in your home directory, it will be run as Ruby code
99
100
  before processing the input.
100
101
 
101
102
  If there is a REXE_OPTIONS environment variable, its content will be prepended to the command line
102
103
  so that you can specify options implicitly (e.g. `export REXE_OPTIONS="-r awesome_print,yaml"`)
103
-
104
- (1) For boolean 'verbose' and 'noop' options, the following are valid:
105
- -v no, -v yes, -v false, -v true, -v n, -v y, -v +, but not -v -
106
104
  ```
107
105
 
108
106
  ### Simplifying the Rexe Invocation
@@ -178,14 +176,16 @@ end
178
176
  Alternatively you could escape the parentheses with backslashes.)
179
177
 
180
178
 
181
- ### Verbose Mode
179
+ ### Logging
182
180
 
183
- Verbose mode will display the version, date/time of execution, source code
184
- to be evaluated, options specified (by all approaches), that the global file has been loaded (if it was found),
181
+ A log entry is optionally output to standard error after completion of the code.
182
+ The entry is a hash containing the version, date/time of execution, source code
183
+ to be evaluated, options (specified by all approaches),
185
184
  and the execution time of your Ruby code:
186
185
 
187
186
  ```
188
- ➜ ~  echo $EUR_RATES_JSON | rexe -v -rjson,awesome_print "ap JSON.parse(STDIN.read)"
187
+ ➜ ~  echo $EUR_RATES_JSON | rexe -gy -rjson,awesome_print "ap JSON.parse(STDIN.read)"
188
+ ...
189
189
  ---
190
190
  :count: 0
191
191
  :rexe_version: 0.11.0
@@ -214,11 +214,9 @@ use it programatically.
214
214
  If you would like to append this informational output to a file, you could do something like this:
215
215
 
216
216
  ```
217
- ➜ ~  rexe ... -v 2>>rexe.log
217
+ ➜ ~  rexe ... -gy 2>>rexe.log
218
218
  ```
219
219
 
220
- If verbose mode is enabled in configuration and you want to disable it, you can
221
- do so by using any of the following: `--[no-]verbose`, `-v n`, or `-v false`.
222
220
 
223
221
  ### Input Modes
224
222
 
@@ -359,13 +357,13 @@ parameterization of the output format.
359
357
 
360
358
  For your convenience, the information displayed in verbose mode is available to your code at runtime
361
359
  by accessing the `$RC` global variable, which contains an OpenStruct. Probably most useful in that object
362
- is the record count (as `$RC.count`). This is only really useful in line mode, because in the others
360
+ is the record count, accessible with both `$RC.count` and `$RC.i`.
361
+ This is only really useful in line mode, because in the others
363
362
  it will always be 0 or 1. Here is an example of how you might use it:
364
363
 
365
364
  ```
366
365
  ➜ ~  ➜ ~  find / | rexe -ml -on \
367
- 'n = $RC.count; if n % 1000 == 0; puts %Q{File entry ##{n} is #{self}}; end'
368
-
366
+ 'if $RC.i % 1000 == 0; puts %Q{File entry ##{$RC.i} is #{self}}; end'
369
367
  ...
370
368
  File entry #106000 is /usr/local/Cellar/go/1.11.5/libexec/src/cmd/vendor/github.com/google/pprof/internal/driver/driver_test.go
371
369
  File entry #107000 is /usr/local/Cellar/go/1.11.5/libexec/src/go/types/testdata/cycles1.src
@@ -422,6 +420,13 @@ An excellent reference for how they differ is [here](https://stackoverflow.com/q
422
420
  Feel free to fall back on Ruby's super useful `%q{}` and `%Q{}`, equivalent to single and double quotes, respectively.
423
421
 
424
422
 
423
+ ### No Op Mode
424
+
425
+ The `-n` no-op mode will result in the specified source code _not_ being executed. This can sometimes be handy
426
+ in conjunction with a `-g` (logging) option; if you have a command ready to go but
427
+ you want to see the configuration options before running it for real.
428
+
429
+
425
430
  ### Mimicking Method Arguments
426
431
 
427
432
  You may want to support arguments in your code. One of the previous examples downloaded currency conversion rates. Let's find out the available currency codes:
@@ -562,10 +567,10 @@ Files loaded with the `-l` option are treated the same way.
562
567
  Requiring gems and modules for _all_ invocations of `rexe` will make your commands simpler and more concise, but will be a waste of execution time if they are not needed. You can inspect the execution times to see just how much time is being wasted. For example, we can find out that nokogiri takes about 0.15 seconds to load on my laptop by observing and comparing the execution times with and without the require (output has been abbreviated using the redirection and grep):
563
568
 
564
569
  ```
565
- ➜ ~  rexe -v 2>&1 | grep duration
570
+ ➜ ~  rexe -gy 2>&1 | grep duration
566
571
  :duration_secs: 0.0012
567
572
 
568
- ➜ ~  rexe -v -r nokogiri 2>&1 | grep duration
573
+ ➜ ~  rexe -gy -r nokogiri 2>&1 | grep duration
569
574
  :duration_secs: 0.148671
570
575
  ```
571
576
 
data/exe/rexe CHANGED
@@ -10,9 +10,17 @@ require 'optparse'
10
10
  require 'ostruct'
11
11
  require 'shellwords'
12
12
 
13
- class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :requires, :verbose, :noop)
13
+ class Rexe < Struct.new(
14
+ :input_format,
15
+ :input_mode,
16
+ :loads,
17
+ :output_format,
18
+ :requires,
19
+ :log_format,
20
+ :noop)
14
21
 
15
- VERSION = '0.11.0'
22
+
23
+ VERSION = '0.12.0'
16
24
 
17
25
 
18
26
  def initialize
@@ -82,7 +90,7 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
82
90
  end
83
91
 
84
92
 
85
- def parser_and_format_requires
93
+ def require_format_require(format)
86
94
  @format_requires ||= {
87
95
  json: 'json',
88
96
  pretty_json: 'json',
@@ -90,19 +98,20 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
90
98
  pretty_print: 'pp',
91
99
  yaml: 'yaml'
92
100
  }
101
+ r = @format_requires[format]
102
+ require(r) if r
93
103
  end
94
104
 
95
105
 
96
106
  # Used as an initializer and also when `-!` is specified on the command line.
97
107
  def clear_options
98
- self.input_format = :none
99
- self.input_mode = :no_input
108
+ self.input_format = :none
109
+ self.input_mode = :no_input
100
110
  self.output_format = :puts
101
- self.loads = []
102
- self.requires = []
103
- self.verbose = false
104
- self.noop = false
105
- @output_formatter = nil
111
+ self.loads = []
112
+ self.requires = []
113
+ self.log_format = :none
114
+ self.noop = false
106
115
  end
107
116
 
108
117
 
@@ -118,8 +127,9 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
118
127
  Options:
119
128
 
120
129
  -c --clear_options Clear all previous command line options specified up to now
130
+ -g --log_format FORMAT Log format, logs to stderr, defaults to none (see -o for format options)
121
131
  -h, --help Print help and exit
122
- -i, --input_format FORMAT Input format (none is default)
132
+ -i, --input_format FORMAT Input format (defaults to none)
123
133
  -ij JSON
124
134
  -im Marshal
125
135
  -in None
@@ -130,8 +140,9 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
130
140
  -me enumerator mode
131
141
  -mb big string mode; all lines combined into single multiline string
132
142
  -mn (default) no input mode; no special handling of input; self is an Object.new
133
- -n, --[no-]noop Do not execute the code (useful with -v); see note (1) below
134
- -o, --output_format FORMAT Output format (puts is default):
143
+ -n, --[no-]noop Do not execute the code (useful with -g); the following are valid:
144
+ -n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -
145
+ -o, --output_format FORMAT Output format (defaults to puts):
135
146
  -oi Inspect
136
147
  -oj JSON
137
148
  -oJ Pretty JSON
@@ -141,7 +152,6 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
141
152
  -os to_s
142
153
  -oy YAML
143
154
  -r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated, or ! to clear
144
- -v, --[no-]verbose verbose mode (logs to stderr); see note (1) below
145
155
 
146
156
  If there is an .rexerc file in your home directory, it will be run as Ruby code
147
157
  before processing the input.
@@ -149,9 +159,6 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
149
159
  If there is a REXE_OPTIONS environment variable, its content will be prepended to the command line
150
160
  so that you can specify options implicitly (e.g. `export REXE_OPTIONS="-r awesome_print,yaml"`)
151
161
 
152
- (1) For boolean 'verbose' and 'noop' options, the following are valid:
153
- -v no, -v yes, -v false, -v true, -v n, -v y, -v +, but not -v -
154
-
155
162
  HEREDOC
156
163
  end
157
164
 
@@ -169,6 +176,14 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
169
176
 
170
177
  OptionParser.new do |parser|
171
178
 
179
+ parser.on('-g', '--log_format FORMAT', 'Log format, logs to stderr, defaults to none (see -o for format options)') do |v|
180
+ self.log_format = output_formats[v]
181
+ if self.log_format.nil?
182
+ puts help_text
183
+ raise "Output mode was '#{v}' but must be one of #{output_formats.keys}."
184
+ end
185
+ end
186
+
172
187
  parser.on("-h", "--help", "Show help") do |_help_requested|
173
188
  puts help_text
174
189
  exit
@@ -227,23 +242,19 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
227
242
  end
228
243
  end
229
244
 
230
- # See https://stackoverflow.com/questions/54576873/ruby-optionparser-short-code-for-boolean-option
231
- # for an excellent explanation of this optparse incantation.
232
- # According to the answer, valid options are:
233
- # -v no, -v yes, -v false, -v true, -v n, -v y, -v +, but not -v -.
234
- parser.on('-v', '--[no-]verbose [FLAG]', TrueClass, 'Verbose mode (logs to stderr)') do |v|
235
- self.verbose = (v.nil? ? true : v)
236
- end
237
-
238
245
  parser.on('-c', '--clear_options', "Clear all previous command line options") do |v|
239
246
  clear_options
240
247
  end
241
248
 
242
- parser.on('-n', '--[no-]noop [FLAG]', TrueClass, "Do not execute the code (useful with -v)") do |v|
249
+ # See https://stackoverflow.com/questions/54576873/ruby-optionparser-short-code-for-boolean-option
250
+ # for an excellent explanation of this optparse incantation.
251
+ # According to the answer, valid options are:
252
+ # -n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -.
253
+ parser.on('-n', '--[no-]noop [FLAG]', TrueClass, "Do not execute the code (useful with -g)") do |v|
243
254
  self.noop = (v.nil? ? true : v)
244
255
  end
245
256
 
246
- parser.on('', '--version', 'Print version') do
257
+ parser.on('-v', '--version', 'Print version') do
247
258
  puts VERSION
248
259
  exit
249
260
  end
@@ -280,7 +291,12 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
280
291
 
281
292
  prepend_environment_options
282
293
  parse_command_line
294
+
283
295
  user_source_code = ARGV.join(' ')
296
+ if user_source_code.empty?
297
+ STDERR.puts "No source code provided. Use -h to display help."
298
+ exit(-1)
299
+ end
284
300
 
285
301
  requires.each { |r| require(r) }
286
302
  load_global_config_if_exists
@@ -289,9 +305,9 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
289
305
  callable = eval("Proc.new { #{user_source_code} }")
290
306
 
291
307
  actions = {
292
- line: -> { STDIN.each { |l| execute(l.chomp, callable); $RC[:count] += 1 } },
293
- enumerator: -> { execute(STDIN.each_line, callable); $RC[:count] += 1 },
294
- one_big_string: -> { big_string = STDIN.read; execute(big_string, callable); $RC[:count] += 1 },
308
+ line: -> { STDIN.each { |l| execute(l.chomp, callable); $RC.count += 1 } },
309
+ enumerator: -> { execute(STDIN.each_line, callable); $RC.count += 1 },
310
+ one_big_string: -> { big_string = STDIN.read; execute(big_string, callable); $RC.count += 1 },
295
311
  no_input: -> { execute(Object.new, callable) }
296
312
  }
297
313
 
@@ -306,12 +322,13 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
306
322
  $RC.source_code = user_source_code
307
323
  $RC.options = self.to_h
308
324
 
325
+ def $RC.i; count end # `i` aliases `count` so you can more concisely get the count in your user code
326
+
309
327
  actions[input_mode].() unless self.noop
310
328
 
311
- if verbose
329
+ if log_format != :none
312
330
  $RC.duration_secs = Time.now - start_time.to_time
313
- require 'yaml'
314
- STDERR.puts($RC.to_h.to_yaml)
331
+ STDERR.puts(log_formatter.($RC.to_h))
315
332
  end
316
333
  end
317
334
  end
@@ -319,8 +336,7 @@ end
319
336
 
320
337
  def input_parser
321
338
  if @input_parser.nil?
322
- require_spec = parser_and_format_requires[input_format]
323
- require require_spec if require_spec
339
+ require_format_require(input_format)
324
340
  @input_parser = input_parsers[input_format]
325
341
  end
326
342
  @input_parser
@@ -329,14 +345,22 @@ end
329
345
 
330
346
  def output_formatter
331
347
  if @output_formatter.nil?
332
- require_spec = parser_and_format_requires[output_format]
333
- require require_spec if require_spec
348
+ require_format_require(output_format)
334
349
  @output_formatter = formatters[output_format]
335
350
  end
336
351
  @output_formatter
337
352
  end
338
353
 
339
354
 
355
+ def log_formatter
356
+ if @log_formatter.nil?
357
+ require_format_require(log_format)
358
+ @log_formatter = formatters[log_format]
359
+ end
360
+ @log_formatter
361
+ end
362
+
363
+
340
364
  # This is needed because the gemspec file loads this file to access Rexe::VERSION
341
365
  # and must not have it run at that time:
342
366
  called_as_script = (File.basename($0) == File.basename(__FILE__))
data/rexe.gemspec CHANGED
@@ -51,10 +51,13 @@ Gem::Specification.new do |spec|
51
51
  WARNING!
52
52
 
53
53
  The default rexe input mode was changed from -ms to -mn in version 0.6.0
54
- and
55
- the -ms (separate string mode) mode name was changed
54
+
55
+ The -ms (separate string mode) mode name was changed
56
56
  to -ml (line mode) in version 0.9.0.
57
57
 
58
+ The verbose mode boolean switch (-v) was changed to the
59
+ log format option (-g) in version 0.12.0.
60
+
58
61
  !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
59
62
 
60
63
  HEREDOC
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rexe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.11.0
4
+ version: 0.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith Bennett
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-11 00:00:00.000000000 Z
11
+ date: 2019-03-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -94,19 +94,11 @@ metadata:
94
94
  homepage_uri: https://github.com/keithrbennett/rexe
95
95
  source_code_uri: https://github.com/keithrbennett/rexe
96
96
  changelog_uri: https://github.com/keithrbennett/rexe/blob/master/README.md
97
- post_install_message: |2+
98
-
99
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
100
-
101
- WARNING!
102
-
103
- The default rexe input mode was changed from -ms to -mn in version 0.6.0
104
- and
105
- the -ms (separate string mode) mode name was changed
106
- to -ml (line mode) in version 0.9.0.
107
-
108
- !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
109
-
97
+ post_install_message: "\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\nWARNING!\n\nThe
98
+ default rexe input mode was changed from -ms to -mn in version 0.6.0\n\nThe -ms
99
+ (separate string mode) mode name was changed\nto -ml (line mode) in version 0.9.0.\n\nThe
100
+ verbose mode boolean switch (-v) was changed to the\nlog format option (-g) in version
101
+ 0.12.0. \n\n!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n\n"
110
102
  rdoc_options: []
111
103
  require_paths:
112
104
  - lib