rexe 0.12.0 → 0.13.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +11 -0
- data/LICENSE.txt +201 -21
- data/README.md +140 -53
- data/exe/rexe +254 -164
- data/rexe.gemspec +2 -0
- metadata +17 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38c1bab41a36c75950db8a2a8aa05f46d324f3c221b66181cc8df302b97aabe7
|
4
|
+
data.tar.gz: 6a3e33b62857804eb18179233aa3de385ee7b44785dbb1fdd27de4a95e9aa0bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52d97220ae00afd76ecb7253f626c135be6f33622130cf43edcabb90bb63f93b8ee3e143734059a6f69a80d57800c29d47adc4c8569c7b08e54676853a6eb36a
|
7
|
+
data.tar.gz: ea666de41864df7f84315e69e4481fd1a1b79bf4c32da29b1e76a4483a4a3276a99e494ecf47850e124170ac43ba00cb5c8e10d81421620d3f2b27bbe5c3af21
|
data/CHANGELOG.md
CHANGED
@@ -1,6 +1,17 @@
|
|
1
1
|
## rexe -- Ruby Command Line Executor
|
2
2
|
|
3
3
|
|
4
|
+
### v0.13.0
|
5
|
+
|
6
|
+
* Much refactoring.
|
7
|
+
* Allow omitting source code in no-op mode.
|
8
|
+
* Add ability to remove load or require files using minus sign preceding name.
|
9
|
+
* Requires needed for parsing and formatting will now be included in log output.
|
10
|
+
* Change license from MIT to Apache version 2.
|
11
|
+
* Add undocumented '--open-project' command line option to launch Github project page in Mac OS and possibly other OS's.
|
12
|
+
* Fix and add tests.
|
13
|
+
|
14
|
+
|
4
15
|
### v0.12.0
|
5
16
|
|
6
17
|
* Change verbose -v boolean option to log output format -g option.
|
data/LICENSE.txt
CHANGED
@@ -1,21 +1,201 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
1
|
+
Apache License
|
2
|
+
Version 2.0, January 2004
|
3
|
+
http://www.apache.org/licenses/
|
4
|
+
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
6
|
+
|
7
|
+
1. Definitions.
|
8
|
+
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
11
|
+
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
13
|
+
the copyright owner that is granting the License.
|
14
|
+
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
16
|
+
other entities that control, are controlled by, or are under common
|
17
|
+
control with that entity. For the purposes of this definition,
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
19
|
+
direction or management of such entity, whether by contract or
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
22
|
+
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
24
|
+
exercising permissions granted by this License.
|
25
|
+
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
27
|
+
including but not limited to software source code, documentation
|
28
|
+
source, and configuration files.
|
29
|
+
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
31
|
+
transformation or translation of a Source form, including but
|
32
|
+
not limited to compiled object code, generated documentation,
|
33
|
+
and conversions to other media types.
|
34
|
+
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
36
|
+
Object form, made available under the License, as indicated by a
|
37
|
+
copyright notice that is included in or attached to the work
|
38
|
+
(an example is provided in the Appendix below).
|
39
|
+
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
46
|
+
the Work and Derivative Works thereof.
|
47
|
+
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
49
|
+
the original version of the Work and any modifications or additions
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
61
|
+
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
64
|
+
subsequently incorporated within the Work.
|
65
|
+
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
72
|
+
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
78
|
+
where such license applies only to those patent claims licensable
|
79
|
+
by such Contributor that are necessarily infringed by their
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
82
|
+
institute patent litigation against any entity (including a
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
85
|
+
or contributory patent infringement, then any patent licenses
|
86
|
+
granted to You under this License for that Work shall terminate
|
87
|
+
as of the date such litigation is filed.
|
88
|
+
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
91
|
+
modifications, and in Source or Object form, provided that You
|
92
|
+
meet the following conditions:
|
93
|
+
|
94
|
+
(a) You must give any other recipients of the Work or
|
95
|
+
Derivative Works a copy of this License; and
|
96
|
+
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
98
|
+
stating that You changed the files; and
|
99
|
+
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
102
|
+
attribution notices from the Source form of the Work,
|
103
|
+
excluding those notices that do not pertain to any part of
|
104
|
+
the Derivative Works; and
|
105
|
+
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
108
|
+
include a readable copy of the attribution notices contained
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
111
|
+
of the following places: within a NOTICE text file distributed
|
112
|
+
as part of the Derivative Works; within the Source form or
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
114
|
+
within a display generated by the Derivative Works, if and
|
115
|
+
wherever such third-party notices normally appear. The contents
|
116
|
+
of the NOTICE file are for informational purposes only and
|
117
|
+
do not modify the License. You may add Your own attribution
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
120
|
+
that such additional attribution notices cannot be construed
|
121
|
+
as modifying the License.
|
122
|
+
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
124
|
+
may provide additional or different license terms and conditions
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
128
|
+
the conditions stated in this License.
|
129
|
+
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
133
|
+
this License, without any additional terms or conditions.
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
135
|
+
the terms of any separate license agreement you may have executed
|
136
|
+
with Licensor regarding such Contributions.
|
137
|
+
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
140
|
+
except as required for reasonable and customary use in describing the
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
142
|
+
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
152
|
+
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
158
|
+
incidental, or consequential damages of any character arising as a
|
159
|
+
result of this License or out of the use or inability to use the
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
162
|
+
other commercial damages or losses), even if such Contributor
|
163
|
+
has been advised of the possibility of such damages.
|
164
|
+
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
168
|
+
or other liability obligations and/or rights consistent with this
|
169
|
+
License. However, in accepting such obligations, You may act only
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
174
|
+
of your accepting any such warranty or additional liability.
|
175
|
+
|
176
|
+
END OF TERMS AND CONDITIONS
|
177
|
+
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
179
|
+
|
180
|
+
To apply the Apache License to your work, attach the following
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
182
|
+
replaced with your own identifying information. (Don't include
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
184
|
+
comment syntax for the file format. We also recommend that a
|
185
|
+
file or class name and description of purpose be included on the
|
186
|
+
same "printed page" as the copyright notice for easier
|
187
|
+
identification within third-party archives.
|
188
|
+
|
189
|
+
Copyright 2019 Bennett Business Solutions, Inc.
|
190
|
+
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
192
|
+
you may not use this file except in compliance with the License.
|
193
|
+
You may obtain a copy of the License at
|
194
|
+
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
196
|
+
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
200
|
+
See the License for the specific language governing permissions and
|
201
|
+
limitations under the License.
|
data/README.md
CHANGED
@@ -42,11 +42,10 @@ make the command long and tedious, discouraging this approach.
|
|
42
42
|
|
43
43
|
### Rexe
|
44
44
|
|
45
|
-
|
46
|
-
|
45
|
+
The `rexe` script [^1] can simplify such commands.
|
47
46
|
Among other things, `rexe` provides switch-activated input parsing and output formatting so that converting
|
48
47
|
from one format to another is trivial.
|
49
|
-
|
48
|
+
The previous `ruby` command can be expressed in `rexe` as:
|
50
49
|
|
51
50
|
```
|
52
51
|
➜ ~ echo $EUR_RATES_JSON | rexe -mb -ij -oy self
|
@@ -61,7 +60,7 @@ line, tipping the scale so that it is practical to do it more often.
|
|
61
60
|
Here is `rexe`'s help text as of the time of this writing:
|
62
61
|
|
63
62
|
```
|
64
|
-
rexe -- Ruby Command Line Executor/Filter -- v0.
|
63
|
+
rexe -- Ruby Command Line Executor/Filter -- v0.13.0 -- https://github.com/keithrbennett/rexe
|
65
64
|
|
66
65
|
Executes Ruby code on the command line, optionally taking standard input and writing to standard output.
|
67
66
|
|
@@ -77,12 +76,13 @@ Options:
|
|
77
76
|
-im Marshal
|
78
77
|
-in None
|
79
78
|
-iy YAML
|
80
|
-
-l, --load RUBY_FILE(S) Ruby file(s) to load, comma separated
|
79
|
+
-l, --load RUBY_FILE(S) Ruby file(s) to load, comma separated;
|
80
|
+
! to clear all, or precede a name with '-' to remove
|
81
81
|
-m, --input_mode MODE Mode with which to handle input (i.e. what `self` will be in your code):
|
82
82
|
-ml line mode; each line is ingested as a separate string
|
83
83
|
-me enumerator mode
|
84
84
|
-mb big string mode; all lines combined into single multiline string
|
85
|
-
-mn (default) no input mode; no special handling of input; self is an Object.new
|
85
|
+
-mn (default) no input mode; no special handling of input; self is an Object.new
|
86
86
|
-n, --[no-]noop Do not execute the code (useful with -g); the following are valid:
|
87
87
|
-n no, -n yes, -n false, -n true, -n n, -n y, -n +, but not -n -
|
88
88
|
-o, --output_format FORMAT Output format (defaults to puts):
|
@@ -94,9 +94,10 @@ Options:
|
|
94
94
|
-op Puts (default)
|
95
95
|
-os to_s
|
96
96
|
-oy YAML
|
97
|
-
-r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated
|
97
|
+
-r, --require REQUIRE(S) Gems and built-in libraries to require, comma separated;
|
98
|
+
! to clear all, or precede a name with '-' to remove
|
98
99
|
|
99
|
-
If there is an .rexerc file in your home directory, it will be run as Ruby code
|
100
|
+
If there is an .rexerc file in your home directory, it will be run as Ruby code
|
100
101
|
before processing the input.
|
101
102
|
|
102
103
|
If there is a REXE_OPTIONS environment variable, its content will be prepended to the command line
|
@@ -105,7 +106,7 @@ so that you can specify options implicitly (e.g. `export REXE_OPTIONS="-r awesom
|
|
105
106
|
|
106
107
|
### Simplifying the Rexe Invocation
|
107
108
|
|
108
|
-
There are two main ways we can
|
109
|
+
There are two main ways we can make the `rexe` command line even more concise:
|
109
110
|
|
110
111
|
* by extracting configuration into the `REXE_OPTIONS` environment variable
|
111
112
|
* by extracting low level and/or shared code into files that are loaded using `-l`,
|
@@ -137,10 +138,12 @@ def valkyries
|
|
137
138
|
end
|
138
139
|
```
|
139
140
|
|
140
|
-
|
141
|
+
To digress a bit, why would you want this? You might want to be able to go to another room until a long job completes, and be notified when it is done. The `valkyries` method will launch a browser window pointed to Richard Wagner's "Ride of the Valkyries" starting at a lively point in the music. (The `open` command is Mac specific and could be replaced with `start` on Windows, a browser command name, etc.) [^2]
|
142
|
+
|
143
|
+
If you like this kind of audio notification, you could download public domain audio files and use a command like player like `afplay` on Mac OS, or `mpg123` or `ogg123` on Linux. This approach is lighter weight, requires no network access, and will not leave an open browser window for you to close.
|
141
144
|
|
142
|
-
Here is an example of how you might use
|
143
|
-
an explicitly loaded file:
|
145
|
+
Here is an example of how you might use the `valkyries` method, assuming the above configuration
|
146
|
+
is loaded from your `~/.rexerc` file or an explicitly loaded file:
|
144
147
|
|
145
148
|
```
|
146
149
|
➜ ~ tar czf /tmp/my-whole-user-space.tar.gz ~ ; rexe valkyries
|
@@ -180,7 +183,7 @@ Alternatively you could escape the parentheses with backslashes.)
|
|
180
183
|
|
181
184
|
A log entry is optionally output to standard error after completion of the code.
|
182
185
|
The entry is a hash containing the version, date/time of execution, source code
|
183
|
-
to be evaluated, options (
|
186
|
+
to be evaluated, options (after parsing both the `REXE_OPTIONS` environment variable and the command line),
|
184
187
|
and the execution time of your Ruby code:
|
185
188
|
|
186
189
|
```
|
@@ -188,8 +191,8 @@ and the execution time of your Ruby code:
|
|
188
191
|
...
|
189
192
|
---
|
190
193
|
:count: 0
|
191
|
-
:rexe_version: 0.
|
192
|
-
:start_time: '2019-03-
|
194
|
+
:rexe_version: 0.12.0
|
195
|
+
:start_time: '2019-03-19T19:39:18+08:00'
|
193
196
|
:source_code: ap JSON.parse(STDIN.read)
|
194
197
|
:options:
|
195
198
|
:input_format: :none
|
@@ -199,10 +202,14 @@ and the execution time of your Ruby code:
|
|
199
202
|
:requires:
|
200
203
|
- json
|
201
204
|
- awesome_print
|
202
|
-
|
205
|
+
- yaml
|
206
|
+
:log_format: :yaml
|
203
207
|
:noop: false
|
204
|
-
:duration_secs: 0.
|
208
|
+
:duration_secs: 0.116171
|
205
209
|
```
|
210
|
+
|
211
|
+
The `yaml` require was not explicitly specified but is automatically added because
|
212
|
+
`rexe` will add any requires needed for automatic parsing and formatting.
|
206
213
|
|
207
214
|
This extra output is sent to standard error (_stderr_) instead of standard output
|
208
215
|
(_stdout_) so that it will not pollute the "real" data when stdout is piped to
|
@@ -232,17 +239,19 @@ and in different ways. Here is the help text relating to input modes:
|
|
232
239
|
```
|
233
240
|
|
234
241
|
The first three are _filter_ modes; they make standard input available
|
235
|
-
to your code as `self
|
236
|
-
the last value evaluated by your code.
|
242
|
+
to your code as `self`.
|
237
243
|
|
238
244
|
The last (and default) is the _executor_ mode. It merely assists you in
|
239
245
|
executing the code you provide without any special implicit handling of standard input.
|
240
246
|
|
247
|
+
All input modes automatically output to standard output the last value evaluated by your code.
|
248
|
+
You can suppress automatic output with the `-on` option.
|
249
|
+
|
241
250
|
|
242
251
|
#### -ml "Line" Filter Mode
|
243
252
|
|
244
253
|
In this mode, your code would be called once per line of input,
|
245
|
-
and in each call, `self` would evaluate to
|
254
|
+
and in each call, `self` would evaluate to each line of text:
|
246
255
|
|
247
256
|
```
|
248
257
|
➜ ~ echo "hello\ngoodbye" | rexe -ms reverse
|
@@ -251,13 +260,13 @@ eybdoog
|
|
251
260
|
```
|
252
261
|
|
253
262
|
`reverse` is implicitly called on each line of standard input. `self`
|
254
|
-
is the input line in each call (we could also have used `self.reverse` but the `self
|
263
|
+
is the input line in each call (we could also have used `self.reverse` but the `self.` would have been redundant.).
|
255
264
|
|
256
|
-
Be aware that although you can control the _content_ of output records,
|
265
|
+
Be aware that, in this mode, although you can control the _content_ of output records,
|
257
266
|
there is no way to selectively _exclude_ records from being output. Even if the result of the code
|
258
267
|
is nil or the empty string, a newline will be output. If this is an issue, you could do one of the following:
|
259
268
|
|
260
|
-
* use Enumerator mode and call `select`, `filter`, `reject`, etc.
|
269
|
+
* use `-me` Enumerator mode and call `select`, `filter`, `reject`, etc.
|
261
270
|
* use the `-on` _no output_ mode and call `puts` explicitly for the output you _do_ want
|
262
271
|
|
263
272
|
|
@@ -284,7 +293,7 @@ Since `self` is an enumerable, we can call `first` and then `each_with_index`.
|
|
284
293
|
|
285
294
|
#### -mb "Big String" Filter Mode
|
286
295
|
|
287
|
-
In this mode, all standard input is combined into a single
|
296
|
+
In this mode, all standard input is combined into a single (possibly
|
288
297
|
large) string, with newline characters joining the lines in the string.
|
289
298
|
|
290
299
|
A good example of when you would use this is when you parse JSON or YAML text;
|
@@ -306,8 +315,8 @@ if you defined methods, constants, instance variables, etc., in your code.
|
|
306
315
|
If you may have more input than would fit in memory, you can do the following:
|
307
316
|
|
308
317
|
* use `-ml` (line) mode so you are fed only 1 line at a time
|
309
|
-
* use an Enumerator, either by specifying the `-me` (enumerator) mode option,
|
310
|
-
or using `-mn` (no input) mode in conjunction with something like `STDIN.each_line`. Then:
|
318
|
+
* use an Enumerator, either by a) specifying the `-me` (enumerator) mode option,
|
319
|
+
or b) using `-mn` (no input) mode in conjunction with something like `STDIN.each_line`. Then:
|
311
320
|
* Make sure not to call any methods (e.g. `map`, `select`)
|
312
321
|
that will produce an array of all the input because that will pull all the records into memory, or:
|
313
322
|
* use [lazy enumerators](https://www.honeybadger.io/blog/using-lazy-enumerators-to-work-with-large-files-in-ruby/)
|
@@ -332,7 +341,7 @@ since there is no preprocessing of standard input in that mode.
|
|
332
341
|
|
333
342
|
### Output Formats
|
334
343
|
|
335
|
-
Several output formats are provided for your convenience
|
344
|
+
Several output formats are provided for your convenience:
|
336
345
|
|
337
346
|
* `-oa` - Awesome Print - calls `.ai` on the object to get the string that `ap` would print
|
338
347
|
* `-oi` - Inspect - calls `inspect` on the object
|
@@ -349,7 +358,7 @@ You may wonder why these formats are provided, given that their functionality
|
|
349
358
|
could be included in the custom code instead. Here's why:
|
350
359
|
|
351
360
|
* The savings in command line length goes a long way to making these commands more readable and feasible.
|
352
|
-
* It's much simpler to
|
361
|
+
* It's much simpler to switch formats, as there is no need to change the code itself. This also enables
|
353
362
|
parameterization of the output format.
|
354
363
|
|
355
364
|
|
@@ -359,7 +368,7 @@ For your convenience, the information displayed in verbose mode is available to
|
|
359
368
|
by accessing the `$RC` global variable, which contains an OpenStruct. Probably most useful in that object
|
360
369
|
is the record count, accessible with both `$RC.count` and `$RC.i`.
|
361
370
|
This is only really useful in line mode, because in the others
|
362
|
-
it will always be 0 or 1. Here is an example of how you might use it:
|
371
|
+
it will always be 0 or 1. Here is an example of how you might use it as a kind of progress indicator:
|
363
372
|
|
364
373
|
```
|
365
374
|
➜ ~ ➜ ~ find / | rexe -ml -on \
|
@@ -371,6 +380,11 @@ File entry #108000 is /usr/local/Cellar/go/1.11.5/libexec/src/runtime/os_linux_n
|
|
371
380
|
...
|
372
381
|
```
|
373
382
|
|
383
|
+
Note that a single quote was used for the Ruby code here;
|
384
|
+
if a double quote were used, the `$RC` would have been interpreted
|
385
|
+
and removed by the shell.
|
386
|
+
|
387
|
+
|
374
388
|
### Implementing Domain Specific Languages (DSL's)
|
375
389
|
|
376
390
|
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 I wrote code to work with Ansible and put it in `~/projects/rexe-ansible.rb`, I could define an alias in my startup script:
|
@@ -393,7 +407,7 @@ trivially easily. Just to illustrate, here's how you would open a REPL on the Fi
|
|
393
407
|
`self` would evaluate to the `File` class, so you could call class methods implicitly using only their names:
|
394
408
|
|
395
409
|
```
|
396
|
-
➜
|
410
|
+
➜ ~ rexe -r pry File.pry
|
397
411
|
|
398
412
|
[6] pry(File)> size '/etc/passwd'
|
399
413
|
6804
|
@@ -403,7 +417,11 @@ true
|
|
403
417
|
true
|
404
418
|
```
|
405
419
|
|
406
|
-
This could be really handy if you call `pry` on a custom object that has methods especially suited to your task
|
420
|
+
This could be really handy if you call `pry` on a custom object that has methods especially suited to your task:
|
421
|
+
|
422
|
+
```
|
423
|
+
➜ ~ rexe -r wifi-wand,pry WifiWand::MacOsModel.new.pry
|
424
|
+
```
|
407
425
|
|
408
426
|
Ruby is supremely well suited for DSL's since it does not require parentheses for method calls,
|
409
427
|
so calls to your custom methods _look_ like built in language commands and keywords.
|
@@ -417,7 +435,11 @@ necessary to quote the Ruby code. You can use single or double quotes to have th
|
|
417
435
|
as a single argument.
|
418
436
|
An excellent reference for how they differ is [here](https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash).
|
419
437
|
|
420
|
-
|
438
|
+
Personally, I find single quotes more useful since special characters like `$` in my Ruby code will
|
439
|
+
not be disturbed.
|
440
|
+
|
441
|
+
When specifying the Ruby code, feel free to fall back on Ruby's super useful `%q{}` and `%Q{}`,
|
442
|
+
equivalent to single and double quotes, respectively.
|
421
443
|
|
422
444
|
|
423
445
|
### No Op Mode
|
@@ -429,15 +451,19 @@ you want to see the configuration options before running it for real.
|
|
429
451
|
|
430
452
|
### Mimicking Method Arguments
|
431
453
|
|
432
|
-
You may want to support arguments in your
|
454
|
+
You may want to support arguments in your `rexe` commands.
|
455
|
+
You could do this by piping in the arguments as `rexe`'s stdin.
|
456
|
+
|
457
|
+
One of the previous examples downloaded currency conversion rates.
|
458
|
+
To prepare for an example of how to do this, let's find out the available currency codes:
|
433
459
|
|
434
460
|
```
|
435
|
-
➜ / echo $EUR_RATES_JSON | rexe -
|
436
|
-
"JSON.parse(self)['rates'].keys.sort.join(' ')"
|
461
|
+
➜ / echo $EUR_RATES_JSON | rexe -ij -mb "self['rates'].keys.sort.join(' ')"
|
437
462
|
AUD BGN BRL CAD CHF CNY CZK DKK GBP HKD HRK HUF IDR ILS INR ISK JPY KRW MXN MYR NOK NZD PHP PLN RON RUB SEK SGD THB TRY USD ZAR
|
438
463
|
```
|
439
|
-
|
440
|
-
|
464
|
+
|
465
|
+
The codes output are the legal arguments that could be sent to `rexe`'s stdin as an argument.
|
466
|
+
Let's find out the Euro exchange rate for _PHP_, Philippine Pesos:
|
441
467
|
|
442
468
|
```
|
443
469
|
➜ ~ echo PHP | rexe -ml -rjson \
|
@@ -449,6 +475,12 @@ AUD BGN BRL CAD CHF CNY CZK DKK GBP HKD HRK HUF IDR ILS INR ISK JPY KRW MXN MYR
|
|
449
475
|
|
450
476
|
In this code, `self` is the currency code `PHP` (Philippine Peso). We have accessed the JSON text to parse from the environment variable we previously populated.
|
451
477
|
|
478
|
+
Because we "used up" stdin for the argument, we could not make use of automatic parsing
|
479
|
+
of the currency exchange data (using the `-ij` option),
|
480
|
+
which would have greatly simplified the command. One possible solution to this would be
|
481
|
+
to pipe in the JSON or YAML representation of a hash
|
482
|
+
with entries for both the argument and the currency exchange data...but this might
|
483
|
+
make the command line too complex to be practical.
|
452
484
|
|
453
485
|
### Using the Clipboard for Text Processing
|
454
486
|
|
@@ -486,11 +518,9 @@ when you change the content of the clipboard.
|
|
486
518
|
### Multiline Ruby Commands
|
487
519
|
|
488
520
|
Although `rexe` is cleanest with short one liners, you may want to use it to include nontrivial Ruby code
|
489
|
-
in your shell script as well. If you do this, you may need to
|
521
|
+
in your shell script as well. If you do this, you may need to add trailing backslashes to the lines of Ruby code.
|
490
522
|
|
491
|
-
|
492
|
-
* use %q{} and %Q{} in your Ruby code instead of single and double quotes,
|
493
|
-
since the quotes have special meaning to the shell
|
523
|
+
In addition, don't forget you can use `%q{}` and `%Q{}` in your Ruby code instead of single and double quotes.
|
494
524
|
|
495
525
|
|
496
526
|
### The Use of Semicolons
|
@@ -536,9 +566,20 @@ puts to_a"
|
|
536
566
|
|
537
567
|
There may be times when you have specified a load or require on the command line
|
538
568
|
or in the `REXE_OPTIONS` environment variable,
|
539
|
-
but you want to override it for a single invocation.
|
540
|
-
|
541
|
-
with the `-r!` and `-l!` command line options, respectively.
|
569
|
+
but you want to override it for a single invocation. Here are your options:
|
570
|
+
|
571
|
+
1) Unspecify _all_ the requires or loads with the `-r!` and `-l!` command line options, respectively.
|
572
|
+
|
573
|
+
2) Unspecify individual requires or loads by preceding the name with `-`, e.g. `-r -rails`.
|
574
|
+
Array subtraction is used, so:
|
575
|
+
|
576
|
+
```
|
577
|
+
➜ ~ rexe -n -r rails,rails,rails,-rails -ga
|
578
|
+
```
|
579
|
+
|
580
|
+
...would show that the final `-rails` cancelled all the previous `rails` specifications.
|
581
|
+
|
582
|
+
|
542
583
|
|
543
584
|
|
544
585
|
### Clearing _All_ Options
|
@@ -567,27 +608,49 @@ Files loaded with the `-l` option are treated the same way.
|
|
567
608
|
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):
|
568
609
|
|
569
610
|
```
|
570
|
-
➜ ~
|
611
|
+
➜ ~ rexe -gy 2>&1 "''" | grep duration
|
571
612
|
:duration_secs: 0.0012
|
572
613
|
|
573
|
-
➜ ~ rexe -gy -r nokogiri 2>&1 | grep duration
|
614
|
+
➜ ~ rexe -gy -r nokogiri "''" 2>&1 | grep duration
|
574
615
|
:duration_secs: 0.148671
|
575
616
|
```
|
576
617
|
|
618
|
+
(For the above to work, the `nokogiri` gem needs to be installed.)
|
619
|
+
|
620
|
+
|
621
|
+
### Operating System Support
|
622
|
+
|
623
|
+
`rexe` has been tested successfully on Mac OS, Linux, and Windows Subsystem for Linux (WSL).
|
624
|
+
It is intended as a tool for the Unix shell, and, as such, no attempt is made to support
|
625
|
+
Windows non-Unix shells.
|
577
626
|
|
578
627
|
|
579
628
|
### More Examples
|
580
629
|
|
581
630
|
Here are some more examples to illustrate the use of `rexe`.
|
582
631
|
|
632
|
+
----
|
633
|
+
Output the contents of `ENV` using AwesomePrint:
|
634
|
+
|
635
|
+
```
|
636
|
+
➜ ~ rexe -oa ENV
|
637
|
+
{
|
638
|
+
...
|
639
|
+
"LANG" => "en_US.UTF-8",
|
640
|
+
"PWD" => "/Users/kbennett/work/rexe",
|
641
|
+
"SHELL" => "/bin/zsh",
|
642
|
+
...
|
643
|
+
}
|
644
|
+
```
|
645
|
+
|
583
646
|
----
|
584
647
|
|
585
648
|
Show disk space used/free on a Mac's main hard drive's main partition:
|
586
649
|
|
587
650
|
```
|
588
651
|
➜ ~ df -h | grep disk1s1 | rexe -ml \
|
589
|
-
"x = split; puts %Q{#{x[4]} Used: #{x[2]}, Avail #{x[3]}}"
|
590
|
-
91% Used: 412Gi, Avail 44Gi
|
652
|
+
"x = split; puts %Q{#{x[4]} Used: #{x[2]}, Avail: #{x[3]}}"
|
653
|
+
91% Used: 412Gi, Avail: 44Gi
|
591
654
|
```
|
592
655
|
|
593
656
|
(Note that `split` is equivalent to `self.split`, and because the `-ml` option is used, `self` is the line of text.
|
@@ -729,7 +792,7 @@ Then when I issue a command that succeeds, the Hallelujah Chorus is played:
|
|
729
792
|
|
730
793
|
----
|
731
794
|
|
732
|
-
Another formatting example...I wanted to reformat this help text
|
795
|
+
Another formatting example...I wanted to reformat this help text...
|
733
796
|
|
734
797
|
```
|
735
798
|
'i' => Inspect
|
@@ -741,6 +804,7 @@ Another formatting example...I wanted to reformat this help text:
|
|
741
804
|
'y' => YAML
|
742
805
|
```
|
743
806
|
|
807
|
+
...into something more suitable for my help text.
|
744
808
|
Admittedly, the time it took to do this with rexe probably exceeded the time to do it manually,
|
745
809
|
but it was an interesting exercise and made it easy to try different formats. Here it is:
|
746
810
|
|
@@ -759,14 +823,15 @@ but it was an interesting exercise and made it easy to try different formats. He
|
|
759
823
|
|
760
824
|
### Conclusion
|
761
825
|
|
762
|
-
`rexe` is not revolutionary technology, it's just plumbing that removes
|
826
|
+
`rexe` is not revolutionary technology, it's just plumbing that removes parsing,
|
827
|
+
formatting, and low level
|
763
828
|
configuration from your command line so that you can focus on the high level
|
764
829
|
task at hand.
|
765
830
|
|
766
|
-
When we
|
831
|
+
When we consider a new piece of software, we usually think "what would this be
|
767
832
|
helpful with now?". However, for me, the power of `rexe` is not so much what I can do
|
768
833
|
with it in a single use case now, but rather what will I be able to do with it over time
|
769
|
-
as I
|
834
|
+
as I accumulate more experience and expertise.
|
770
835
|
|
771
836
|
I suggest starting to use `rexe` even for modest improvements in workflow, even
|
772
837
|
if it doesn't seem compelling. There's a good chance that as you use it over
|
@@ -779,10 +844,32 @@ will be proportional to the extent to which you use environment variables
|
|
779
844
|
and loaded files for configuration and shared code.
|
780
845
|
Be responsible and disciplined in making this configuration and code as clean and organized as possible.
|
781
846
|
|
847
|
+
----
|
848
|
+
|
782
849
|
#### Footnotes
|
783
850
|
|
784
851
|
[^1]: `rexe` is an embellishment of the minimal but excellent `rb` script at
|
785
852
|
https://github.com/thisredone/rb. I started using `rb` and thought of lots of
|
786
853
|
other features I would like to have, so I started working on `rexe`.
|
787
854
|
|
788
|
-
[^2]:
|
855
|
+
[^2]: Making this truly OS-portable is a lot more complex than it looks on the surface.
|
856
|
+
On Linux, `xdg-open` may not be installed by default. Also, Windows Subsystem for Linux (WSL)
|
857
|
+
out of the box is not able to launch graphical applications.
|
858
|
+
|
859
|
+
Here is a _start_ at a method that opens a resource portably across operating systems:
|
860
|
+
|
861
|
+
```ruby
|
862
|
+
def open_resource(resource_identifier)
|
863
|
+
command = case (`uname`.chomp)
|
864
|
+
when 'Darwin'
|
865
|
+
'open'
|
866
|
+
when 'Linux'
|
867
|
+
'xdg-open'
|
868
|
+
else
|
869
|
+
'start'
|
870
|
+
end
|
871
|
+
|
872
|
+
`#{command} #{resource_identifier}`
|
873
|
+
end
|
874
|
+
```
|
875
|
+
|