rexe 0.10.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (5) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +5 -0
  3. data/README.md +120 -47
  4. data/exe/rexe +6 -3
  5. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2c0055b60141171c65564e56db902aeb407184a8dae5abc89a1957238b3b35eb
4
- data.tar.gz: 801efa318ca3a7dc8eeaea81e44d0f96331428465789c0cf9899196d6501c934
3
+ metadata.gz: bdd31e24705dfe69cc4f83f5529d1fd528401cb1a675e4203c037c92c4d88eae
4
+ data.tar.gz: '08e378d2729a9af62773deed3f4b653e702b97835e08ceb1b77622eda78d63be'
5
5
  SHA512:
6
- metadata.gz: 1a87be47727dd851c36f93af89034f86ad7e268caa888a44018da344a6b1f9752f5e4e2bbf7460699f84b51bc47b2faf4b66cc6bac4f7b4f3b444856475cffd5
7
- data.tar.gz: 9cdc86c7a7547e84c20286f6185162365453d5a3f0d556e98bc3b28dd6a2338b62999f722222394d4e749269535549cd22c1fa53ec68082fe0943377e8a6afb9
6
+ metadata.gz: bb5f6e5d5a8a19b18fd6ebdd6e5a12bdd6defe25638a91a9602697ba36057bbc905f1c0fb64ba30f830651bb825566eec455d94570f21751458e8c29ad371a0a
7
+ data.tar.gz: 676a94dfa2890c7711b6863dd9840c22cc402d09c940d4eace18832f78e254ff96fb1bf226e0f795c42da8c9f3c17f7630df68d54a7544bf54f8033a71cf2dfb
@@ -1,6 +1,11 @@
1
1
  ## rexe -- Ruby Command Line Executor
2
2
 
3
3
 
4
+ ### v0.10.2
5
+
6
+ * Fix problem in :none input format mode.
7
+
8
+
4
9
  ### v0.10.1
5
10
 
6
11
  * Fix help text for input formats.
data/README.md CHANGED
@@ -3,6 +3,9 @@ title: The `rexe` Command Line Executor and Filter
3
3
  date: 2019-02-15
4
4
  ---
5
5
 
6
+ [Caution: This is a long article! If you lose patience reading it, I suggest skimming the headings
7
+ and the source code, and at minimum, reading the Conclusion.]
8
+
6
9
  I love the power of the command line, but not the awkwardness of shell scripting
7
10
  languages. Sure, there's a lot that can be done with them, but it doesn't take
8
11
  long before I get frustrated with their bluntness and verbosity.
@@ -21,24 +24,31 @@ An excerpt of the output follows the code:
21
24
 
22
25
  ```
23
26
  ➜ ~  export EUR_RATES_JSON=`curl https://api.exchangeratesapi.io/latest`
24
- ➜ ~  echo $EUR_RATES_JSON | ruby -r json -r awesome_print -e 'ap JSON.parse(STDIN.read)'
25
- {
26
- "rates" => {
27
- "MXN" => 21.781,
28
- ...
29
- "DKK" => 7.462
30
- },
31
- "base" => "EUR",
32
- "date" => "2019-02-22"
33
- }
27
+ ➜ ~  echo $EUR_RATES_JSON | ruby -r json -r yaml -e 'puts JSON.parse(STDIN.read).to_yaml'
28
+ ---
29
+ rates:
30
+ MXN: 21.96
31
+ AUD: 1.5964
32
+ HKD: 8.8092
33
+ ...
34
+ base: EUR
35
+ date: '2019-03-08'
34
36
  ```
35
37
 
36
- However, the configuration setup (the `require`s) make the command long and tedious, discouraging this
37
- approach.
38
+ However, the configuration setup (the `require`s) along with the reading, parsing, and formatting
39
+ make the command long and tedious, discouraging this approach.
38
40
 
39
41
  ### Rexe
40
42
 
41
- Enter the `rexe` script. [^1]
43
+ Enter the `rexe` script: [^1]
44
+
45
+ Among other things, `rexe` provides switch-activated input parsing and output formatting so that converting
46
+ from one format to another is trivial.
47
+ This command does the same thing as the previous `ruby` command:
48
+
49
+ ```
50
+ ➜ ~  echo $EUR_RATES_JSON | rexe -mb -ij -oy self
51
+ ```
42
52
 
43
53
  `rexe` is at https://github.com/keithrbennett/rexe and can be installed with
44
54
  `gem install rexe`. `rexe` provides several ways to simplify Ruby on the command
@@ -47,10 +57,12 @@ line, tipping the scale so that it is practical to do it more often.
47
57
  Here is `rexe`'s help text as of the time of this writing:
48
58
 
49
59
  ```
50
- rexe -- Ruby Command Line Executor/Filter -- v0.10.1 -- https://github.com/keithrbennett/rexe
60
+ rexe -- Ruby Command Line Executor/Filter -- v0.10.2 -- https://github.com/keithrbennett/rexe
51
61
 
52
62
  Executes Ruby code on the command line, optionally taking standard input and writing to standard output.
53
63
 
64
+ rexe [options] 'Ruby source code'
65
+
54
66
  Options:
55
67
 
56
68
  -c --clear_options Clear all previous command line options specified up to now
@@ -65,7 +77,7 @@ Options:
65
77
  -ml line mode; each line is ingested as a separate string
66
78
  -me enumerator mode
67
79
  -mb big string mode; all lines combined into single multiline string
68
- -mn (default) no input mode; no special handling of input; self is not input
80
+ -mn (default) no input mode; no special handling of input; self is an Object.new
69
81
  -n, --[no-]noop Do not execute the code (useful with -v); see note (1) below
70
82
  -o, --output_format FORMAT Output format (puts is default):
71
83
  -oi Inspect
@@ -76,7 +88,7 @@ Options:
76
88
  -op Puts (default)
77
89
  -os to_s
78
90
  -oy YAML
79
- -r, --require REQUIRES Gems and built-in libraries to require, comma separated, or ! to clear
91
+ -r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated, or ! to clear
80
92
  -v, --[no-]verbose verbose mode (logs to stderr); see note (1) below
81
93
 
82
94
  If there is an .rexerc file in your home directory, it will be run as Ruby code
@@ -89,16 +101,6 @@ so that you can specify options implicitly (e.g. `export REXE_OPTIONS="-r awesom
89
101
  -v no, -v yes, -v false, -v true, -v n, -v y, -v +, but not -v -
90
102
  ```
91
103
 
92
- For consistency with the `ruby` interpreter we called previously, `rexe` supports requires with the `-r` option, but as one tiny improvement it also allows grouping them together using commas:
93
-
94
- ```
95
- vvvvvvvvvvvvvvvvvvvvv
96
- ➜ ~  echo $EUR_RATES_JSON | rexe -r json,awesome_print 'ap JSON.parse(STDIN.read)'
97
- ^^^^^^^^^^^^^^^^^^^^^
98
- ```
99
-
100
- This command produces the same results as the previous `ruby` one.
101
-
102
104
  ### Simplifying the Rexe Invocation with Configuration
103
105
 
104
106
  `rexe` provides two approaches to configuration:
@@ -271,9 +273,12 @@ eybdoog
271
273
  `reverse` is implicitly called on each line of standard input. `self`
272
274
  is the input line in each call (we could also have used `self.reverse` but the `self` would have been redundant.).
273
275
 
274
- Be aware that there is no way to selectively exclude records from being output. Even if the result of the code
275
- is nil or the empty string, a newline will be output. If this is an issue, you might be better off using Enumerator
276
- mode and calling `select`, `filter`, `reject`, etc.
276
+ Be aware that although you can control the _content_ of output records,
277
+ there is no way to selectively _exclude_ records from being output. Even if the result of the code
278
+ is nil or the empty string, a newline will be output. If this is an issue, you could do one of the following:
279
+
280
+ * use Enumerator mode and call `select`, `filter`, `reject`, etc.
281
+ * use the `-on` _no output_ mode and call `puts` explicitly for the output you _do_ want
277
282
 
278
283
 
279
284
  #### -me "Enumerator" Filter Mode
@@ -299,23 +304,21 @@ Since `self` is an enumerable, we can call `first` and then `each_with_index`.
299
304
 
300
305
  #### -mb "Big String" Filter Mode
301
306
 
302
- In this mode, all standard input is combined into a single, (possibly)
303
- large string, with newline characters joining the lines in the string.
307
+ In this mode, all standard input is combined into a single, (possibly
308
+ large) string, with newline characters joining the lines in the string.
304
309
 
305
- A good example of when you would use this is when you parse JSON or YAML text; you need to pass the entire (probably) multiline string to the parse method.
310
+ A good example of when you would use this is when you parse JSON or YAML text;
311
+ you need to pass the entire (probably) multiline string to the parse method.
312
+ This is the mode that was used in the first `rexe` example in this article.
306
313
 
307
- An earlier example would be more simply specified using this mode, since `STDIN.read` could be replaced with `self`:
308
-
309
- ```
310
- ➜ ~  echo $EUR_RATES_JSON | rexe -mb -r awesome_print,json 'ap JSON.parse(self)'
311
- ```
312
314
 
313
315
  #### -mn "No Input" Executor Mode -- The Default
314
316
 
315
- Examples up until this point have all used the default
316
- `-mn` mode. This is the simplest use case, where `self`
317
- does not evaluate to anything useful, and if you cared about standard
318
- input, you would have to code it yourself (e.g. as we did earlier with `STDIN.read`).
317
+ In this mode, no special handling of standard input is done at all;
318
+ if you want standard input you need to code it yourself (e.g. with `STDIN.read`).
319
+
320
+ `self` evaluates to a new instance of `Object`, which would be used
321
+ if you defined methods, constants, instance variables, etc., in your code.
319
322
 
320
323
 
321
324
  #### Filter Input Mode Memory Considerations
@@ -325,9 +328,9 @@ If you may have more input than would fit in memory, you can do the following:
325
328
  * use `-ml` (line) mode so you are fed only 1 line at a time
326
329
  * use an Enumerator, either by specifying the `-me` (enumerator) mode option,
327
330
  or using `-mn` (no input) mode in conjunction with something like `STDIN.each_line`. Then:
328
- ** Make sure not to call any methods (e.g. `map`, `select`)
331
+ * Make sure not to call any methods (e.g. `map`, `select`)
329
332
  that will produce an array of all the input because that will pull all the records into memory, or:
330
- ** use lazy enumerators
333
+ * use [lazy enumerators](https://www.honeybadger.io/blog/using-lazy-enumerators-to-work-with-large-files-in-ruby/)
331
334
 
332
335
 
333
336
 
@@ -396,7 +399,8 @@ so calls to your custom methods _look_ like built in language commands and keywo
396
399
 
397
400
  One complication of using utilities like `rexe` where Ruby code is specified on the shell command line is that
398
401
  you need to be careful about the shell's special treatment of certain characters. For this reason, it is often
399
- necessary to quote the Ruby code. You can use single or double quotes.
402
+ necessary to quote the Ruby code. You can use single or double quotes to have the shell treat your source code
403
+ as a single argument.
400
404
  An excellent reference for how they differ is [here](https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash).
401
405
 
402
406
  Feel free to fall back on Ruby's super useful `%q{}` and `%Q{}`, equivalent to single and double quotes, respectively.
@@ -454,6 +458,70 @@ If I add `| pbcopy` to the rexe command, then that output text would be copied i
454
458
  displayed in the terminal, and I could then paste it in my editor.
455
459
 
456
460
 
461
+ ### Multiline Ruby Commands
462
+
463
+ Although `rexe` is cleanest with short one liners, you may want to use it to include nontrivial Ruby code
464
+ in your shell script as well. If you do this, you may need to:
465
+
466
+ * add trailing backslashes to lines of Ruby code
467
+ * use %q{} and %Q{} in your Ruby code instead of single and double quotes,
468
+ since the quotes have special meaning to the shell
469
+
470
+
471
+ ### The Use of Semicolons
472
+
473
+ You will probably find yourself using semicolons much more often than usual when you use `rexe`.
474
+ Obviously you would need them to separate statements on the same line:
475
+
476
+ ```
477
+ ➜ ~  cowsay hello | rexe -me "print %Q{\u001b[33m}; puts to_a"
478
+ ```
479
+
480
+ What might not be so obvious is that you _also_ need them if each statement is on its own line.
481
+ For example, here is an example without a semicolon:
482
+
483
+ ```
484
+ ➜ ~  cowsay hello | rexe -me "print %Q{\u001b[33m} \
485
+ puts to_a"
486
+
487
+ /Users/kbennett/.rvm/gems/ruby-2.6.0/gems/rexe-0.10.1/exe/rexe:256:in `eval':
488
+ (eval):1: syntax error, unexpected tIDENTIFIER, expecting '}' (SyntaxError)
489
+ ...new { print %Q{\u001b[33m} puts to_a }
490
+ ... ^~~~
491
+ ```
492
+
493
+ The shell combines all backslash terminated lines into a single line of text, so when the Ruby
494
+ interpreter sees your code, it's all in a single line. Adding the semicolon fixes the problem:
495
+
496
+ ```
497
+ ➜ ~  cowsay hello | rexe -me "print %Q{\u001b[33m}; \
498
+ puts to_a"
499
+
500
+ eval_context_object: #<Enumerator:0x00007f92b1972840>
501
+ _______
502
+ < hello >
503
+ -------
504
+ \ ^__^
505
+ \ (oo)\_______
506
+ (__)\ )\/\
507
+ ||----w |
508
+ || ||
509
+ ```
510
+
511
+
512
+ ### Comma Separated Requires and Loads
513
+
514
+ For consistency with the `ruby` interpreter, `rexe` supports requires with the `-r` option, but
515
+ also allows grouping them together using commas:
516
+
517
+ ```
518
+ vvvvvvvvvvvvvvvvvvvvv
519
+ ➜ ~  echo $EUR_RATES_JSON | rexe -r json,awesome_print 'ap JSON.parse(STDIN.read)'
520
+ ^^^^^^^^^^^^^^^^^^^^^
521
+ ```
522
+
523
+ Files loaded with the `-l` option are treated the same way.
524
+
457
525
  ### More Examples
458
526
 
459
527
  Here are some more examples to illustrate the use of `rexe`.
@@ -642,15 +710,20 @@ configuration from your command line so that you can focus on the high level
642
710
  task at hand.
643
711
 
644
712
  When we think of a new piece of software, we usually think "what would this be
645
- helpful with now?". However, the power of `rexe` is not so much what can be done
646
- with it in a single use case now, but rather what will it do for me as I get
647
- used to the concept and my supporting code and its uses evolve.
713
+ helpful with now?". However, for me, the power of `rexe` is not so much what I can do
714
+ with it in a single use case now, but rather what will I be able to do with it over time
715
+ as I get used to the concept and my supporting code and its uses evolve.
648
716
 
649
717
  I suggest starting to use `rexe` even for modest improvements in workflow, even
650
718
  if it doesn't seem compelling. There's a good chance that as you use it over
651
719
  time, new ideas will come to you and the workflow improvements will increase
652
720
  exponentially.
653
721
 
722
+ A word of caution though --
723
+ the complexity and difficulty of sharing your `rexe` scripts across systems
724
+ will be proportional to the extent to which you use environment variables
725
+ and loaded files for configuration and shared code.
726
+ Be responsible and disciplined in making this configuration as organized as possible.
654
727
 
655
728
  #### Footnotes
656
729
 
data/exe/rexe CHANGED
@@ -10,7 +10,7 @@ require 'shellwords'
10
10
 
11
11
  class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :requires, :verbose, :noop)
12
12
 
13
- VERSION = '0.10.1'
13
+ VERSION = '0.10.2'
14
14
 
15
15
  def initialize
16
16
  clear_options
@@ -19,6 +19,7 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
19
19
 
20
20
  # Used as an initializer and also when `-!` is specified on the command line.
21
21
  def clear_options
22
+ self.input_format = :none
22
23
  self.input_mode = :no_input
23
24
  self.output_format = :puts
24
25
  self.loads = []
@@ -36,6 +37,8 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
36
37
 
37
38
  Executes Ruby code on the command line, optionally taking standard input and writing to standard output.
38
39
 
40
+ rexe [options] 'Ruby source code'
41
+
39
42
  Options:
40
43
 
41
44
  -c --clear_options Clear all previous command line options specified up to now
@@ -50,7 +53,7 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
50
53
  -ml line mode; each line is ingested as a separate string
51
54
  -me enumerator mode
52
55
  -mb big string mode; all lines combined into single multiline string
53
- -mn (default) no input mode; no special handling of input; self is not input
56
+ -mn (default) no input mode; no special handling of input; self is an Object.new
54
57
  -n, --[no-]noop Do not execute the code (useful with -v); see note (1) below
55
58
  -o, --output_format FORMAT Output format (puts is default):
56
59
  -oi Inspect
@@ -61,7 +64,7 @@ class Rexe < Struct.new(:input_format, :input_mode, :loads, :output_format, :req
61
64
  -op Puts (default)
62
65
  -os to_s
63
66
  -oy YAML
64
- -r, --require REQUIRES Gems and built-in libraries to require, comma separated, or ! to clear
67
+ -r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated, or ! to clear
65
68
  -v, --[no-]verbose verbose mode (logs to stderr); see note (1) below
66
69
 
67
70
  If there is an .rexerc file in your home directory, it will be run as Ruby code
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rexe
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.1
4
+ version: 0.10.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Keith Bennett