rexe 1.3.0 → 1.5.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/README.md +85 -79
- data/exe/rexe +30 -10
- data/rexe.gemspec +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: '036597bf795aea3d05206bec898b2688dc1b75cf51c2dec772574a86734f56ef'
|
4
|
+
data.tar.gz: 6d404ef04a3fdcf8913e654da1cb71e18191f3796e70f0da2dc249f467f88f5a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6002bbc565faf3861ec08752b22160453b2b35dbab126e4e7d53b9e4e7b68da49545fb615f48eb4a8bddc087943cf33572e36521b38d1e0fe12a17812e0ea4a8
|
7
|
+
data.tar.gz: 63cfec0e25406005aa3c030376755333842f294530ee96fc7d9344460f9b7efbd4c7380eeffed689905bf2331c836b8935e297278237cb8721ba19e0a19c81e9
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,31 @@
|
|
1
1
|
## rexe -- Ruby Command Line Executor/Filter
|
2
2
|
|
3
|
+
### 1.5.1
|
4
|
+
|
5
|
+
* Change string concatenations using << to creation of new strings with += to accommodate default-frozen strings.
|
6
|
+
|
7
|
+
|
8
|
+
### 1.5.0
|
9
|
+
|
10
|
+
* Switch from AwesomePrint to AmazingPrint, and change all references in text, help, etc.
|
11
|
+
|
12
|
+
|
13
|
+
### 1.4.1
|
14
|
+
|
15
|
+
* As of later versions of Ruby, `stringio` is a gem and must be required. Fixed.
|
16
|
+
|
17
|
+
|
18
|
+
### 1.4.0
|
19
|
+
|
20
|
+
* Handle Bundler deprecation of `with_clean_env` method.
|
21
|
+
* Mark entire file frozen_string_literal: true.
|
22
|
+
|
23
|
+
|
24
|
+
### 1.3.1
|
25
|
+
|
26
|
+
* Add Awesome Print and Pretty Print output formats to help.
|
27
|
+
|
28
|
+
|
3
29
|
### 1.3.0
|
4
30
|
|
5
31
|
* Document --project-url option.
|
data/README.md
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
__Rexe__ is a Ruby script and gem that multiplies Ruby's usefulness and conciseness on the command line by:
|
4
4
|
|
5
|
-
* automating parsing and formatting using JSON, YAML, Ruby marshalling,
|
5
|
+
* automating parsing and formatting using JSON, YAML, Ruby marshalling, Amazing Print, and others
|
6
6
|
* simplifying the use of Ruby as a shell filter, optionally predigesting input as lines, an enumerator, or one big string
|
7
7
|
* extracting the plumbing from the command line; requires and other options can be set in an environment variable
|
8
8
|
* enabling the loading of Ruby helper files to keep your code DRY and your command line code high level
|
@@ -24,8 +24,8 @@ Sometimes a good solution is to combine Ruby and shell scripting on the same com
|
|
24
24
|
Let's start by seeing what the Ruby interpreter already provides. Here we use `ruby` on the command line, using an intermediate environment variable to simplify the logic and save the data for use by future commands. An excerpt of the output follows the code:
|
25
25
|
|
26
26
|
```bash
|
27
|
-
|
28
|
-
|
27
|
+
$ export EUR_RATES_JSON=`curl https://api.exchangeratesapi.io/latest`
|
28
|
+
$ echo $EUR_RATES_JSON | ruby -r json -r yaml -e 'puts JSON.parse(STDIN.read).to_yaml'
|
29
29
|
```
|
30
30
|
```yaml
|
31
31
|
---
|
@@ -45,13 +45,13 @@ Unfortunately, the configuration setup (the `require`s) along with the reading,
|
|
45
45
|
Rexe [see footnote ^1 regarding its origin] can simplify such commands. Among other things, rexe provides switch-activated input parsing and output formatting so that converting from one format to another is trivial. The previous `ruby` command can be expressed in `rexe` as:
|
46
46
|
|
47
47
|
```bash
|
48
|
-
|
48
|
+
$ echo $EUR_RATES_JSON | rexe -mb -ij -oy self
|
49
49
|
```
|
50
50
|
|
51
51
|
Or, even more concisely (`self` is the default Ruby source code for rexe commands):
|
52
52
|
|
53
53
|
```bash
|
54
|
-
|
54
|
+
$ echo $EUR_RATES_JSON | rexe -mb -ij -oy
|
55
55
|
```
|
56
56
|
|
57
57
|
The command options may seem cryptic, but they're logical so it shouldn't take long to learn them:
|
@@ -63,7 +63,7 @@ The command options may seem cryptic, but they're logical so it shouldn't take l
|
|
63
63
|
If input comes from a JSON or YAML file, rexe determines the input format from the file's extension, and it's even simpler:
|
64
64
|
|
65
65
|
```bash
|
66
|
-
|
66
|
+
$ rexe -f eur_rates.json -oy
|
67
67
|
```
|
68
68
|
|
69
69
|
Rexe is at https://github.com/keithrbennett/rexe and can be installed with `gem install rexe`. Rexe provides several ways to simplify Ruby on the command line, tipping the scale so that it is practical to do it more often.
|
@@ -73,7 +73,7 @@ Rexe is at https://github.com/keithrbennett/rexe and can be installed with `gem
|
|
73
73
|
Here is rexe's help text as of the time of this writing:
|
74
74
|
|
75
75
|
```
|
76
|
-
rexe -- Ruby Command Line Executor/Filter -- v1.
|
76
|
+
rexe -- Ruby Command Line Executor/Filter -- v1.5.0 -- https://github.com/keithrbennett/rexe
|
77
77
|
|
78
78
|
Executes Ruby code on the command line,
|
79
79
|
optionally automating management of standard input and standard output,
|
@@ -107,12 +107,14 @@ Options:
|
|
107
107
|
-n, --[no-]noop Do not execute the code (useful with -g);
|
108
108
|
For true: yes, true, y, +; for false: no, false, n
|
109
109
|
-o, --output_format FORMAT Output format, defaults to -on (no output):
|
110
|
+
-oa Amazing Print
|
110
111
|
-oi Inspect
|
111
112
|
-oj JSON
|
112
113
|
-oJ Pretty JSON
|
113
114
|
-om Marshal
|
114
115
|
-on No Output (default)
|
115
116
|
-op Puts
|
117
|
+
-oP Pretty Print
|
116
118
|
-os to_s
|
117
119
|
-oy YAML
|
118
120
|
If 2 letters are provided, 1st is for tty devices, 2nd for block
|
@@ -133,7 +135,7 @@ before processing the input.
|
|
133
135
|
|
134
136
|
If there is a REXE_OPTIONS environment variable, its content will be prepended
|
135
137
|
to the command line so that you can specify options implicitly
|
136
|
-
(e.g. `export REXE_OPTIONS="-r
|
138
|
+
(e.g. `export REXE_OPTIONS="-r amazing_print,yaml"`)
|
137
139
|
```
|
138
140
|
|
139
141
|
### Simplifying the Rexe Invocation
|
@@ -152,15 +154,15 @@ The `REXE_OPTIONS` environment variable can contain command line options that wo
|
|
152
154
|
Instead of this:
|
153
155
|
|
154
156
|
```bash
|
155
|
-
|
157
|
+
$ rexe -r wifi-wand -oa WifiWand::MacOsModel.new.wifi_info
|
156
158
|
```
|
157
159
|
|
158
160
|
you can do this:
|
159
161
|
|
160
162
|
```bash
|
161
|
-
|
162
|
-
|
163
|
-
|
163
|
+
$ export REXE_OPTIONS="-r wifi-wand -oa"
|
164
|
+
$ rexe WifiWand::MacOsModel.new.wifi_info
|
165
|
+
$ # [more rexe commands with the same options]
|
164
166
|
```
|
165
167
|
|
166
168
|
Putting configuration options in `REXE_OPTIONS` effectively creates custom defaults, and is useful when you use the same options in most or all of your commands. Any options specified on the rexe command line will override the environment variable options.
|
@@ -187,7 +189,7 @@ To digress a bit, why would you want this? You might want to be able to go to an
|
|
187
189
|
Here is an example of how you might use the `valkyries` method, assuming the above configuration is loaded from your `~/.rexerc` file or an explicitly loaded file:
|
188
190
|
|
189
191
|
```bash
|
190
|
-
|
192
|
+
$ tar czf /tmp/my-whole-user-space.tar.gz ~ ; rexe valkyries
|
191
193
|
```
|
192
194
|
|
193
195
|
(Note that `;` is used rather than `&&` because we want to hear the music whether or not the command succeeds.)
|
@@ -211,7 +213,7 @@ end
|
|
211
213
|
...which you could then call like this:
|
212
214
|
|
213
215
|
```bash
|
214
|
-
|
216
|
+
$ tar czf /tmp/my-whole-user-space.tar.gz ~ ; rexe 'play(:hallelujah)'
|
215
217
|
```
|
216
218
|
|
217
219
|
(You need to quote the `play` call because otherwise the shell will process and remove the parentheses. Alternatively you could escape the parentheses with backslashes.)
|
@@ -224,27 +226,29 @@ One of the examples at the end of this articles shows how you could have differe
|
|
224
226
|
A log entry is optionally output to standard error after completion of the code. This entry is a hash representation (to be precise, `to_h`) of the `$RC` OpenStruct described in the $RC section below. It contains the version, date/time of execution, source code to be evaluated, options (after parsing both the `REXE_OPTIONS` environment variable and the command line), and the execution time of your Ruby code:
|
225
227
|
|
226
228
|
```bash
|
227
|
-
|
229
|
+
$ echo $EUR_RATES_JSON | rexe -gy -ij -mb -oa -n self
|
228
230
|
```
|
229
231
|
```yaml
|
230
232
|
---
|
231
233
|
:count: 0
|
232
|
-
:rexe_version: 1.
|
233
|
-
:start_time: '2019-
|
234
|
+
:rexe_version: 1.3.1
|
235
|
+
:start_time: '2019-09-11T13:28:46+07:00'
|
234
236
|
:source_code: self
|
235
237
|
:options:
|
236
238
|
:input_filespec:
|
237
239
|
:input_format: :json
|
238
240
|
:input_mode: :one_big_string
|
239
241
|
:loads: []
|
240
|
-
:output_format: :
|
242
|
+
:output_format: :amazing_print
|
243
|
+
:output_format_tty: :amazing_print
|
244
|
+
:output_format_block: :amazing_print
|
241
245
|
:requires:
|
242
|
-
-
|
246
|
+
- amazing_print
|
243
247
|
- json
|
244
248
|
- yaml
|
245
249
|
:log_format: :yaml
|
246
250
|
:noop: true
|
247
|
-
:duration_secs: 0.
|
251
|
+
:duration_secs: 0.095705
|
248
252
|
```
|
249
253
|
|
250
254
|
We specified `-gy` for YAML format; there are other formats as well (see the help output or this document) and the default is `-gn`, which means don't output the log entry at all.
|
@@ -256,7 +260,7 @@ This extra output is sent to standard error (_stderr_) instead of standard outpu
|
|
256
260
|
If you would like to append this informational output to a file(e.g. `rexe.log`), you could do something like this:
|
257
261
|
|
258
262
|
```bash
|
259
|
-
|
263
|
+
$ rexe ... -gy 2>>rexe.log
|
260
264
|
```
|
261
265
|
|
262
266
|
|
@@ -284,7 +288,7 @@ The last (and default) is the _executor_ mode. It merely assists you in executin
|
|
284
288
|
In this mode, your code would be called once per line of input, and in each call, `self` would evaluate to each line of text:
|
285
289
|
|
286
290
|
```bash
|
287
|
-
|
291
|
+
$ echo "hello\ngoodbye" | rexe -ml puts reverse
|
288
292
|
olleh
|
289
293
|
eybdoog
|
290
294
|
```
|
@@ -306,7 +310,7 @@ Dealing with input as an enumerator enables you to use the wealth of `Enumerable
|
|
306
310
|
Here is an example of using `-me` to add line numbers to the first 3 files in the directory listing:
|
307
311
|
|
308
312
|
```bash
|
309
|
-
|
313
|
+
$ ls / | rexe -me "first(3).each_with_index { |ln,i| puts '%5d %s' % [i, ln] }"
|
310
314
|
|
311
315
|
0 AndroidStudioProjects
|
312
316
|
1 Applications
|
@@ -359,7 +363,7 @@ The input format option is ignored if the input _mode_ is `-mn` ("no input" exec
|
|
359
363
|
|
360
364
|
Several output formats are provided for your convenience:
|
361
365
|
|
362
|
-
* `-oa` -
|
366
|
+
* `-oa` - Amazing Print - calls `.ai` on the object to get the string that `ap` would print
|
363
367
|
* `-oi` - Inspect - calls `inspect` on the object
|
364
368
|
* `-oj` - JSON - calls `to_json` on the object
|
365
369
|
* `-oJ` - Pretty JSON calls `JSON.pretty_generate` with the object
|
@@ -386,12 +390,12 @@ You may wonder why these formats are provided, given that their functionality co
|
|
386
390
|
Rexe also simplifies getting input from a file rather than standard input. The `-f` option takes a filespec and does with its content exactly what it would have done with standard input. This shortens:
|
387
391
|
|
388
392
|
```bash
|
389
|
-
|
393
|
+
$ cat filename.ext | rexe ...
|
390
394
|
```
|
391
395
|
...to...
|
392
396
|
|
393
397
|
```bash
|
394
|
-
|
398
|
+
$ rexe -f filename.ext ...
|
395
399
|
```
|
396
400
|
|
397
401
|
This becomes even more useful if you are using files whose extensions are `.yml`, `.yaml`, or `.json` (case insensitively). In this case the input format and mode will be set automatically for you to:
|
@@ -402,14 +406,14 @@ This becomes even more useful if you are using files whose extensions are `.yml`
|
|
402
406
|
So the example we gave above:
|
403
407
|
|
404
408
|
```bash
|
405
|
-
|
406
|
-
|
409
|
+
$ export EUR_RATES_JSON=`curl https://api.exchangeratesapi.io/latest`
|
410
|
+
$ echo $EUR_RATES_JSON | rexe -mb -ij -oy self
|
407
411
|
```
|
408
412
|
...could be changed to:
|
409
413
|
|
410
414
|
```bash
|
411
|
-
|
412
|
-
|
415
|
+
$ curl https://api.exchangeratesapi.io/latest > eur_rates.json
|
416
|
+
$ rexe -f eur_rates.json -oy self
|
413
417
|
```
|
414
418
|
|
415
419
|
Another possible win for using `-f` is that since it is a command line option, it could be specified in `REXE_OPTIONS`. This could be useful if you are doing many operations on the same file.
|
@@ -417,7 +421,7 @@ Another possible win for using `-f` is that since it is a command line option, i
|
|
417
421
|
If you need to override the input mode and format automatically configured for file input, you can simply specify the desired options on the command line _after_ the `-f`:
|
418
422
|
|
419
423
|
```bash
|
420
|
-
|
424
|
+
$ rexe -f eur_rates.json -mb -in 'puts self.class, self[0..20]'
|
421
425
|
String
|
422
426
|
{"base":"EUR","rates"
|
423
427
|
```
|
@@ -448,21 +452,23 @@ This feature is probably only useful in the filter modes, since in the executor
|
|
448
452
|
For your convenience, the information displayed in verbose mode is available to your code at runtime by accessing the `$RC` global variable, which contains an OpenStruct. Let's print out its contents using YAML:
|
449
453
|
|
450
454
|
```bash
|
451
|
-
|
455
|
+
$ rexe -oy '$RC'
|
452
456
|
```
|
453
457
|
```yaml
|
454
458
|
--- !ruby/object:OpenStruct
|
455
459
|
table:
|
456
460
|
:count: 0
|
457
|
-
:rexe_version: 1.
|
458
|
-
:start_time: '2019-
|
461
|
+
:rexe_version: 1.3.1
|
462
|
+
:start_time: '2019-09-11T13:25:53+07:00'
|
459
463
|
:source_code: "$RC"
|
460
464
|
:options:
|
461
|
-
:input_filespec:
|
465
|
+
:input_filespec:
|
462
466
|
:input_format: :none
|
463
467
|
:input_mode: :none
|
464
468
|
:loads: []
|
465
469
|
:output_format: :yaml
|
470
|
+
:output_format_tty: :yaml
|
471
|
+
:output_format_block: :yaml
|
466
472
|
:requires:
|
467
473
|
- yaml
|
468
474
|
:log_format: :none
|
@@ -473,7 +479,7 @@ modifiable: true
|
|
473
479
|
Probably most useful in that object at runtime is the record count, accessible with both `$RC.count` and `$RC.i`. This is only really useful in line mode, because in the others it will always be 0 or 1. Here is an example of how you might use it as a kind of progress indicator:
|
474
480
|
|
475
481
|
```bash
|
476
|
-
|
482
|
+
$ find / | rexe -ml -on \
|
477
483
|
'if $RC.i % 1000 == 0; puts %Q{File entry ##{$RC.i} is #{self}}; end'
|
478
484
|
```
|
479
485
|
```
|
@@ -492,22 +498,22 @@ Note that a single quote was used for the Ruby code here; if a double quote were
|
|
492
498
|
Defining methods in your loaded files enables you to effectively define a [DSL](https://en.wikipedia.org/wiki/Domain-specific_language) for your command line use. You could use different load files for different projects, domains, or contexts, and define aliases or one line scripts to give them meaningful names. For example, if you had Ansible helper code in `~/projects/ansible-tools/rexe-ansible.rb`, you could define an alias in your startup script:
|
493
499
|
|
494
500
|
```bash
|
495
|
-
|
501
|
+
$ alias rxans="rexe -l ~/projects/ansible-tools/rexe-ansible.rb $*"
|
496
502
|
```
|
497
503
|
...and then you would have an Ansible DSL available for me to use by calling `rxans`.
|
498
504
|
|
499
505
|
In addition, since you can also call `pry` on the context of any object, you can provide a DSL in a [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop) (shell) trivially easily. Just to illustrate, here's how you would open a REPL on the File class:
|
500
506
|
|
501
507
|
```bash
|
502
|
-
|
508
|
+
$ ruby -r pry -e File.pry
|
503
509
|
# or
|
504
|
-
|
510
|
+
$ rexe -r pry File.pry
|
505
511
|
```
|
506
512
|
|
507
513
|
`self` would evaluate to the `File` class, so you could call class methods using only their names:
|
508
514
|
|
509
515
|
```bash
|
510
|
-
|
516
|
+
$ rexe -r pry File.pry
|
511
517
|
```
|
512
518
|
```
|
513
519
|
[6] pry(File)> size '/etc/passwd'
|
@@ -521,7 +527,7 @@ true
|
|
521
527
|
This could be really handy if you call `pry` on a custom object that has methods especially suited to your task:
|
522
528
|
|
523
529
|
```bash
|
524
|
-
|
530
|
+
$ rexe -r wifi-wand,pry WifiWand::MacOsModel.new.pry
|
525
531
|
```
|
526
532
|
```
|
527
533
|
[1] pry(#<WifiWand::MacOsModel>)> random_mac_address
|
@@ -542,25 +548,25 @@ Personally, I find single quotes more useful since I usually don't want special
|
|
542
548
|
Sometimes it doesn't matter:
|
543
549
|
|
544
550
|
```bash
|
545
|
-
|
551
|
+
$ rexe 'puts "hello"'
|
546
552
|
hello
|
547
|
-
|
553
|
+
$ rexe "puts 'hello'"
|
548
554
|
hello
|
549
555
|
```
|
550
556
|
|
551
557
|
We can also use `%q` or `%Q`, and sometimes this eliminates the needs for the outer quotes altogether:
|
552
558
|
|
553
559
|
```bash
|
554
|
-
|
560
|
+
$ rexe puts %q{hello}
|
555
561
|
hello
|
556
|
-
|
562
|
+
$ rexe puts %Q{hello}
|
557
563
|
hello
|
558
564
|
```
|
559
565
|
|
560
566
|
Sometimes the quotes to use on the outside (quoting your command in the shell) need to be chosen based on which quotes are needed on the inside. For example, in the following command, we need double quotes in Ruby in order for interpolation to work, so we use single quotes on the outside:
|
561
567
|
|
562
568
|
```bash
|
563
|
-
|
569
|
+
$ rexe puts '"The time is now #{Time.now}"'
|
564
570
|
```
|
565
571
|
```
|
566
572
|
The time is now 2019-03-29 16:41:26 +0800
|
@@ -569,7 +575,7 @@ The time is now 2019-03-29 16:41:26 +0800
|
|
569
575
|
In this case we also need to use single quotes on the outside, because we need literal double quotes in a `%Q{}` expression:
|
570
576
|
|
571
577
|
```bash
|
572
|
-
|
578
|
+
$ rexe 'puts %Q{The operating system name is "#{`uname`.chomp}".}'
|
573
579
|
```
|
574
580
|
```
|
575
581
|
The operating system name is "Darwin".
|
@@ -578,7 +584,7 @@ The operating system name is "Darwin".
|
|
578
584
|
We can eliminate the need for any quotes in the Ruby code using `%Q{}`:
|
579
585
|
|
580
586
|
```bash
|
581
|
-
|
587
|
+
$ rexe puts '%Q{The time is now #{Time.now}}'
|
582
588
|
```
|
583
589
|
```
|
584
590
|
The time is now 2019-03-29 17:06:13 +0800
|
@@ -609,7 +615,7 @@ AUD BGN BRL CAD CHF CNY CZK DKK GBP HKD HRK HUF IDR ILS INR ISK JPY KRW MXN MYR
|
|
609
615
|
The codes output are the legal arguments that could be sent to rexe's stdin as an argument in the command below. Let's find out the Euro exchange rate for _PHP_, Philippine Pesos:
|
610
616
|
|
611
617
|
```bash
|
612
|
-
|
618
|
+
$ echo PHP | rexe -ml -op -rjson \
|
613
619
|
"rate = JSON.parse(ENV['EUR_RATES_JSON'])['rates'][self];\
|
614
620
|
%Q{1 EUR = #{rate} #{self}}"
|
615
621
|
|
@@ -641,13 +647,13 @@ AUD BGN BRL PHP TRY USD ZAR
|
|
641
647
|
We could manually select that text and use system menu commands or keys to copy it to the clipboard, or we could do this:
|
642
648
|
|
643
649
|
```bash
|
644
|
-
|
650
|
+
$ echo AUD BGN BRL PHP TRY USD ZAR | pbcopy
|
645
651
|
```
|
646
652
|
|
647
653
|
After copying this line to the clipboard, we could run this:
|
648
654
|
|
649
655
|
```bash
|
650
|
-
|
656
|
+
$ pbpaste | rexe -ml -op \
|
651
657
|
"split.map(&:downcase).map { |s| %Q{ #{s}: '',} }.join(%Q{\n})"
|
652
658
|
aud: '',
|
653
659
|
bgn: '',
|
@@ -666,7 +672,7 @@ Although rexe is cleanest with short one liners, you may want to use it to inclu
|
|
666
672
|
What might not be so obvious is that you will often need to use semicolons as statement separators. For example, here is an example without a semicolon:
|
667
673
|
|
668
674
|
```bash
|
669
|
-
|
675
|
+
$ cowsay hello | rexe -me "print %Q{\u001b[33m} \
|
670
676
|
puts to_a"
|
671
677
|
```
|
672
678
|
```
|
@@ -678,13 +684,13 @@ rexe: (eval):1: syntax error, unexpected tIDENTIFIER, expecting '}'
|
|
678
684
|
The shell combines all backslash terminated lines into a single line of text, so when the Ruby interpreter sees your code, it's all in a single line:
|
679
685
|
|
680
686
|
```bash
|
681
|
-
|
687
|
+
$ cowsay hello | rexe -me "print %Q{\u001b[33m} puts to_a"
|
682
688
|
```
|
683
689
|
|
684
690
|
Adding the semicolon fixes the problem:
|
685
691
|
|
686
692
|
```bash
|
687
|
-
|
693
|
+
$ cowsay hello | rexe -me "print %Q{\u001b[33m}; \
|
688
694
|
puts to_a"
|
689
695
|
```
|
690
696
|
```
|
@@ -708,7 +714,7 @@ There may be times when you have specified a load or require on the command line
|
|
708
714
|
2) Unspecify individual requires or loads by preceding the name with `-`, e.g. `-r -rails`. Array subtraction is used, and array subtraction removes _all_ occurrences of each element of the subtracted (subtrahend) array, so:
|
709
715
|
|
710
716
|
```bash
|
711
|
-
|
717
|
+
$ rexe -n -r rails,rails,rails,-rails -gP
|
712
718
|
...
|
713
719
|
:requires=>["pp"],
|
714
720
|
...
|
@@ -719,7 +725,7 @@ There may be times when you have specified a load or require on the command line
|
|
719
725
|
We could have also extracted the requires list programmatically using `$RC` (described above) by doing this:
|
720
726
|
|
721
727
|
```bash
|
722
|
-
|
728
|
+
$ rexe -oP -r rails,rails,rails,-rails '$RC[:options][:requires]'
|
723
729
|
["pp"]
|
724
730
|
```
|
725
731
|
|
@@ -734,9 +740,9 @@ You can also clear _all_ options specified up to a certain point in time with th
|
|
734
740
|
For consistency with the `ruby` interpreter, rexe supports requires with the `-r` option, but also allows grouping them together using commas:
|
735
741
|
|
736
742
|
```bash
|
737
|
-
|
738
|
-
|
739
|
-
|
743
|
+
vvvvvvvvvvvvvvvvvv
|
744
|
+
$ echo $EUR_RATES_JSON | rexe -r json,amazing_print 'ap JSON.parse(STDIN.read)'
|
745
|
+
^^^^^^^^^^^^^^^^^^
|
740
746
|
```
|
741
747
|
|
742
748
|
Files loaded with the `-l` option are treated the same way.
|
@@ -747,9 +753,9 @@ Files loaded with the `-l` option are treated the same way.
|
|
747
753
|
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 consumed. For example, we can find out that rails takes about 0.63 seconds to load on one system by observing and comparing the execution times with and without the require (output has been abbreviated using `grep`):
|
748
754
|
|
749
755
|
```bash
|
750
|
-
|
756
|
+
$ rexe -gy -r rails 2>&1 | grep duration
|
751
757
|
:duration_secs: 0.660138
|
752
|
-
|
758
|
+
$ rexe -gy 2>&1 | grep duration
|
753
759
|
:duration_secs: 0.027781
|
754
760
|
```
|
755
761
|
(For the above to work, the `rails` gem and its dependencies need to be installed.)
|
@@ -771,29 +777,29 @@ Here are some more examples to illustrate the use of rexe.
|
|
771
777
|
To output the result to stdout, you can either call `puts` or specify the `-op` option:
|
772
778
|
|
773
779
|
```bash
|
774
|
-
|
780
|
+
$ rexe puts 1 / 3.0
|
775
781
|
0.3333333333333333
|
776
782
|
```
|
777
783
|
|
778
784
|
or:
|
779
785
|
|
780
786
|
```bash
|
781
|
-
|
787
|
+
$ rexe -op 1 / 3.0
|
782
788
|
0.3333333333333333
|
783
789
|
```
|
784
790
|
|
785
791
|
Since `*` is interpreted by the shell, if we do multiplication, we need to quote the expression:
|
786
792
|
|
787
793
|
```bash
|
788
|
-
|
794
|
+
$ rexe -op '2 * 7'
|
789
795
|
14
|
790
796
|
```
|
791
797
|
|
792
798
|
Of course, if you put the `-op` in the `REXE_OPTIONS` environment variable, you don't need to be explicit about the output:
|
793
799
|
|
794
800
|
```bash
|
795
|
-
|
796
|
-
|
801
|
+
$ export REXE_OPTIONS=-op
|
802
|
+
$ rexe '2 * 7'
|
797
803
|
14
|
798
804
|
```
|
799
805
|
|
@@ -802,10 +808,10 @@ Of course, if you put the `-op` in the `REXE_OPTIONS` environment variable, you
|
|
802
808
|
|
803
809
|
#### Outputting ENV
|
804
810
|
|
805
|
-
Output the contents of `ENV` using
|
811
|
+
Output the contents of `ENV` using AmazingPrint [see footnote ^4 regarding ENV.to_s]:
|
806
812
|
|
807
813
|
```bash
|
808
|
-
|
814
|
+
$ rexe -oa ENV
|
809
815
|
```
|
810
816
|
```
|
811
817
|
{
|
@@ -824,7 +830,7 @@ Output the contents of `ENV` using AwesomePrint [see footnote ^4 regarding ENV.t
|
|
824
830
|
Show disk space used/free on a Mac's main hard drive's main partition:
|
825
831
|
|
826
832
|
```bash
|
827
|
-
|
833
|
+
$ df -h | grep disk1s1 | rexe -ml \
|
828
834
|
"x = split; puts %Q{#{x[4]} Used: #{x[2]}, Avail: #{x[3]}}"
|
829
835
|
91% Used: 412Gi, Avail: 44Gi
|
830
836
|
```
|
@@ -838,7 +844,7 @@ Show disk space used/free on a Mac's main hard drive's main partition:
|
|
838
844
|
Show the 3 longest file names of the current directory, with their lengths, in descending order:
|
839
845
|
|
840
846
|
```bash
|
841
|
-
|
847
|
+
$ ls | rexe -ml -op "%Q{[%4d] %s} % [length, self]" | sort -r | head -3
|
842
848
|
[ 50] Agoda_Booking_ID_9999999 49_–_RECEIPT_enclosed.pdf
|
843
849
|
[ 40] 679a5c034994544aab4635ecbd50ab73-big.jpg
|
844
850
|
[ 28] 2018-abc-2019-01-16-2340.zip
|
@@ -853,11 +859,11 @@ When you right align numbers using printf formatting, sorting the lines alphabet
|
|
853
859
|
This uses an [ANSI escape code](https://en.wikipedia.org/wiki/ANSI_escape_code) to output text to the terminal in yellow:
|
854
860
|
|
855
861
|
```bash
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
862
|
+
$ cowsay hello | rexe -me "print %Q{\u001b[33m}; puts to_a"
|
863
|
+
$ # or
|
864
|
+
$ cowsay hello | rexe -mb "print %Q{\u001b[33m}; puts self"
|
865
|
+
$ # or
|
866
|
+
$ cowsay hello | rexe "print %Q{\u001b[33m}; puts STDIN.read"
|
861
867
|
```
|
862
868
|
```
|
863
869
|
_______
|
@@ -906,13 +912,13 @@ end
|
|
906
912
|
Then when we issue a command that succeeds, the Hallelujah Chorus is played [see footnote ^2]:
|
907
913
|
|
908
914
|
```bash
|
909
|
-
|
915
|
+
$ uname; echo $? | rexe play_result_by_exit_code
|
910
916
|
```
|
911
917
|
|
912
918
|
...but when the command fails, in this case, with an executable which is not found, it plays Rick Astley's "Never Gonna Give You Up":
|
913
919
|
|
914
920
|
```bash
|
915
|
-
|
921
|
+
$ uuuuu; echo $? | rexe play_result_by_exit_code
|
916
922
|
```
|
917
923
|
|
918
924
|
----
|
@@ -934,7 +940,7 @@ Another formatting example...I wanted to reformat this source code...
|
|
934
940
|
...into something more suitable for my help text. Admittedly, the time it took to do this with rexe probably exceeded the time to do it manually, but it was an interesting exercise and made it easy to try different formats. Here it is, after copying the original text to the clipboard:
|
935
941
|
|
936
942
|
```bash
|
937
|
-
|
943
|
+
$ pbpaste | rexe -ml -op "sub(%q{'}, '-o').sub(%q{' =>}, %q{ })"
|
938
944
|
-oi Inspect
|
939
945
|
-oj JSON
|
940
946
|
-oJ Pretty JSON
|
@@ -991,7 +997,7 @@ lib/rock_books/documents/journal_entry.rb:
|
|
991
997
|
So this is what worked well for me:
|
992
998
|
|
993
999
|
```bash
|
994
|
-
|
1000
|
+
$ grep Struct **/*.rb | grep -v OpenStruct | rexe -ml -op \
|
995
1001
|
"a = \
|
996
1002
|
gsub('lib/rock_books/', '') \
|
997
1003
|
.gsub('< Struct.new', '') \
|
data/exe/rexe
CHANGED
@@ -4,6 +4,9 @@
|
|
4
4
|
#
|
5
5
|
# Inspired by https://github.com/thisredone/rb
|
6
6
|
|
7
|
+
# frozen_string_literal: true
|
8
|
+
|
9
|
+
|
7
10
|
require 'bundler'
|
8
11
|
require 'date'
|
9
12
|
require 'optparse'
|
@@ -12,9 +15,9 @@ require 'shellwords'
|
|
12
15
|
|
13
16
|
class Rexe
|
14
17
|
|
15
|
-
VERSION = '1.
|
18
|
+
VERSION = '1.5.1'
|
16
19
|
|
17
|
-
PROJECT_URL = 'https://github.com/keithrbennett/rexe'
|
20
|
+
PROJECT_URL = 'https://github.com/keithrbennett/rexe'
|
18
21
|
|
19
22
|
|
20
23
|
module Helpers
|
@@ -25,7 +28,7 @@ class Rexe
|
|
25
28
|
yield
|
26
29
|
rescue Exception => e
|
27
30
|
unless e.class == SystemExit
|
28
|
-
$stderr.puts(
|
31
|
+
$stderr.puts("rexe: #{e}")
|
29
32
|
$stderr.puts("Use the -h option to get help.")
|
30
33
|
exit(-1)
|
31
34
|
end
|
@@ -104,7 +107,7 @@ class Rexe
|
|
104
107
|
|
105
108
|
def output_formats
|
106
109
|
@output_formats ||= {
|
107
|
-
'a' => :
|
110
|
+
'a' => :amazing_print,
|
108
111
|
'i' => :inspect,
|
109
112
|
'j' => :json,
|
110
113
|
'J' => :pretty_json,
|
@@ -120,14 +123,14 @@ class Rexe
|
|
120
123
|
|
121
124
|
def formatters
|
122
125
|
@formatters ||= {
|
123
|
-
|
126
|
+
amazing_print: ->(obj) { obj.ai + "\n" },
|
124
127
|
inspect: ->(obj) { obj.inspect + "\n" },
|
125
128
|
json: ->(obj) { obj.to_json },
|
126
129
|
marshal: ->(obj) { Marshal.dump(obj) },
|
127
130
|
none: ->(_obj) { nil },
|
128
131
|
pretty_json: ->(obj) { JSON.pretty_generate(obj) },
|
129
132
|
pretty_print: ->(obj) { obj.pretty_inspect },
|
130
|
-
puts: ->(obj) { sio = StringIO.new; sio.puts(obj); sio.string },
|
133
|
+
puts: ->(obj) { require 'stringio'; sio = StringIO.new; sio.puts(obj); sio.string },
|
131
134
|
to_s: ->(obj) { obj.to_s + "\n" },
|
132
135
|
yaml: ->(obj) { obj.to_yaml },
|
133
136
|
}
|
@@ -138,7 +141,7 @@ class Rexe
|
|
138
141
|
@format_requires ||= {
|
139
142
|
json: 'json',
|
140
143
|
pretty_json: 'json',
|
141
|
-
|
144
|
+
amazing_print: 'amazing_print',
|
142
145
|
pretty_print: 'pp',
|
143
146
|
yaml: 'yaml'
|
144
147
|
}
|
@@ -214,12 +217,14 @@ class Rexe
|
|
214
217
|
-n, --[no-]noop Do not execute the code (useful with -g);
|
215
218
|
For true: yes, true, y, +; for false: no, false, n
|
216
219
|
-o, --output_format FORMAT Output format, defaults to -on (no output):
|
220
|
+
-oa Amazing Print
|
217
221
|
-oi Inspect
|
218
222
|
-oj JSON
|
219
223
|
-oJ Pretty JSON
|
220
224
|
-om Marshal
|
221
225
|
-on No Output (default)
|
222
226
|
-op Puts
|
227
|
+
-oP Pretty Print
|
223
228
|
-os to_s
|
224
229
|
-oy YAML
|
225
230
|
If 2 letters are provided, 1st is for tty devices, 2nd for block
|
@@ -240,7 +245,7 @@ class Rexe
|
|
240
245
|
|
241
246
|
If there is a REXE_OPTIONS environment variable, its content will be prepended
|
242
247
|
to the command line so that you can specify options implicitly
|
243
|
-
(e.g. `export REXE_OPTIONS="-r
|
248
|
+
(e.g. `export REXE_OPTIONS="-r amazing_print,yaml"`)
|
244
249
|
|
245
250
|
HEREDOC
|
246
251
|
|
@@ -511,7 +516,7 @@ class Rexe
|
|
511
516
|
raise error # re-raise the error, can't fix it
|
512
517
|
else
|
513
518
|
load_dir = File.dirname(gem_path)
|
514
|
-
$LOAD_PATH
|
519
|
+
$LOAD_PATH += load_dir
|
515
520
|
require the_require
|
516
521
|
end
|
517
522
|
end
|
@@ -546,4 +551,19 @@ class Rexe
|
|
546
551
|
end
|
547
552
|
end
|
548
553
|
|
549
|
-
|
554
|
+
|
555
|
+
def bundler_run(&block)
|
556
|
+
# This used to be an unconditional call to with_clean_env but that method is now deprecated:
|
557
|
+
# [DEPRECATED] `Bundler.with_clean_env` has been deprecated in favor of `Bundler.with_unbundled_env`.
|
558
|
+
# If you instead want the environment before bundler was originally loaded,
|
559
|
+
# use `Bundler.with_original_env`
|
560
|
+
|
561
|
+
if Bundler.respond_to?(:with_unbundled_env)
|
562
|
+
Bundler.with_unbundled_env { block.call }
|
563
|
+
else
|
564
|
+
Bundler.with_clean_env { block.call }
|
565
|
+
end
|
566
|
+
end
|
567
|
+
|
568
|
+
|
569
|
+
bundler_run { Rexe::Main.new.call }
|
data/rexe.gemspec
CHANGED
@@ -38,7 +38,7 @@ Gem::Specification.new do |spec|
|
|
38
38
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
39
39
|
spec.require_paths = ["lib"]
|
40
40
|
|
41
|
-
spec.add_dependency "
|
41
|
+
spec.add_dependency "amazing_print"
|
42
42
|
|
43
43
|
spec.add_development_dependency "bundler", "~> 2.0"
|
44
44
|
spec.add_development_dependency "os"
|
metadata
CHANGED
@@ -1,17 +1,17 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rexe
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Keith Bennett
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-11-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: amazing_print
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
@@ -125,7 +125,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: '0'
|
127
127
|
requirements: []
|
128
|
-
rubygems_version: 3.
|
128
|
+
rubygems_version: 3.1.2
|
129
129
|
signing_key:
|
130
130
|
specification_version: 4
|
131
131
|
summary: Ruby Command Line Executor
|