cli_helper 0.0.4 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +222 -11
- data/cli_helper.gemspec +17 -14
- data/example/cli_stub.rb +64 -11
- data/lib/cli_helper.rb +251 -277
- data/tests/README.txt +18 -0
- data/tests/cli_helper_test.rb +217 -0
- data/tests/config/sample.ini +6 -0
- data/tests/config/sample.ini.erb +9 -0
- data/tests/config/sample.rb +15 -0
- data/tests/config/sample.rb.erb +20 -0
- data/tests/config/sample.txt +12 -0
- data/tests/config/sample.txt.erb +16 -0
- data/tests/config/sample.xyzzy +1 -0
- data/tests/config/sample.yml +16 -0
- data/tests/config/sample.yml.erb +17 -0
- metadata +61 -23
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bf433b3f85f6369eda6ca70e7270c62ea73de64
|
4
|
+
data.tar.gz: 9c080c925aa6f8e106d2cd7055e8015cd9391bc4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b4c1bf70ad6f53fd6c1a6578be150a8621c9588452cad240c233500a00aea0613fa7f4b428caf5c029fb806c5b9ba537f0c78e60aa58af727e1f83116915b65b
|
7
|
+
data.tar.gz: 86d255f5568ff8ce8ea8d1ce024f7ddf7eabb5d22f1e05cd7dfd8322de57edb241795c96ace9b20458c856ebfd8a08d6f7f4eadbece59b6b341df6a01904265f
|
data/README.md
CHANGED
@@ -1,22 +1,233 @@
|
|
1
|
-
# cli_helper
|
1
|
+
# cli_helper
|
2
|
+
|
3
|
+
If you write lots of command-line utility programs, or
|
4
|
+
even if you don't the cli_helper gem can be a helper
|
5
|
+
to you. It integrates several common gems to give
|
6
|
+
a comprehensive configuration management experience.
|
7
|
+
|
8
|
+
Here are the gems used and what they do:
|
9
|
+
|
10
|
+
* configatron
|
11
|
+
* makes config info available
|
12
|
+
* http://github.com/markbates/configatron
|
13
|
+
|
14
|
+
* nenv
|
15
|
+
* parses ENV for friendly use
|
16
|
+
* http://github.com/e2/nenv
|
17
|
+
|
18
|
+
* parseconfig
|
19
|
+
* parses INI files
|
20
|
+
* http://github.com/datafolklabs/ruby-parseconfig
|
21
|
+
|
22
|
+
* slop
|
23
|
+
* parses ARGV
|
24
|
+
* http://github.com/leejarvis/slop
|
25
|
+
|
26
|
+
|
27
|
+
## Convention
|
28
|
+
|
29
|
+
The convention w/r/t what value amoung concurrent sources
|
30
|
+
is the correct one to use is hierarchic
|
31
|
+
where the layer above trumps all the layers below. This is the order:
|
32
|
+
|
33
|
+
* command-line parameter
|
34
|
+
* config file value
|
35
|
+
* system environment variable
|
36
|
+
* default
|
37
|
+
|
38
|
+
This ordering says that regardless what you have set in
|
39
|
+
a config file or ENV or as a default, the value of the
|
40
|
+
command line parameter will be used.
|
41
|
+
|
42
|
+
I like to use ERB within my config files. Consider 'default.yml.erb'
|
43
|
+
below:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
---
|
47
|
+
host: <%= Nenv.host || 'localhost' %>
|
48
|
+
```
|
49
|
+
|
50
|
+
Processing this file will give me either the default value for host
|
51
|
+
of 'localhost' or if defined the value of the system environment
|
52
|
+
variable HOST. I like Nenv over ENV.
|
53
|
+
|
54
|
+
Now suppose I use cli_helper within a program and execute the
|
55
|
+
program like this:
|
56
|
+
|
57
|
+
```ruby
|
58
|
+
program.rb --host devhost --config default.yml.erb,prod.ini
|
59
|
+
```
|
60
|
+
|
61
|
+
Because I have specifically called out the value of host on the
|
62
|
+
command line, that value will trump anything that comes from the
|
63
|
+
config file.
|
64
|
+
|
65
|
+
Did you notice that I had two files specified with the --config option?
|
66
|
+
|
67
|
+
The config files are processed in the order that they are given on the command
|
68
|
+
line. Whatever values were obtained from the first file will be over-written
|
69
|
+
by the second and any subsequent config files. Regardless of their
|
70
|
+
values for host, the command-line value trumps them all.
|
71
|
+
|
72
|
+
|
73
|
+
## Config files
|
74
|
+
|
75
|
+
cli_helper supports multiple types of configuration files:
|
76
|
+
|
77
|
+
```text
|
78
|
+
*.rb
|
79
|
+
*.yml
|
80
|
+
*.yml.erb
|
81
|
+
*.ini
|
82
|
+
*.txt (in the INI format)
|
83
|
+
*.ini.erb -- not currently supported
|
84
|
+
*.txt.erb -- not currenly supported
|
85
|
+
```
|
86
|
+
|
87
|
+
All values obtained from config files and command line parameters are
|
88
|
+
held in the configatron structure.
|
89
|
+
|
90
|
+
|
91
|
+
## Common Command-line Options
|
92
|
+
|
93
|
+
cli_helper predefines common command-line options. These
|
94
|
+
can to disabled by the program if necessary. The common options
|
95
|
+
are:
|
96
|
+
|
97
|
+
```text
|
98
|
+
-h, --help
|
99
|
+
-d, --debug
|
100
|
+
-v, --verbose
|
101
|
+
--version
|
102
|
+
--config (optional)
|
103
|
+
```
|
104
|
+
|
105
|
+
To enable the support for config files do this before
|
106
|
+
calling the #cli_helger() method:
|
107
|
+
|
108
|
+
```ruby
|
109
|
+
configatron.support_config_files = true
|
110
|
+
```
|
2
111
|
|
3
|
-
|
4
|
-
|
5
|
-
quick and dirty command-line based utilities. Mostly they are one-offs
|
6
|
-
but sometimes they hang around.
|
112
|
+
To disable any of the other common options do this before
|
113
|
+
involking cli_helper:
|
7
114
|
|
8
|
-
|
9
|
-
|
10
|
-
|
115
|
+
```ruby
|
116
|
+
configatron.disable_help = true
|
117
|
+
configatron.disable_debug = true
|
118
|
+
configatron.disable_verbose = true
|
119
|
+
cpnfogatrpm/dosab;e_version = true
|
120
|
+
```
|
121
|
+
|
122
|
+
## Other options
|
123
|
+
|
124
|
+
The default behavior is to raise an exception if an unspecified option is
|
125
|
+
used on the command line. For example if your program just uses the common
|
126
|
+
options and someone invokes the program with --xyzzy then an exception will be
|
127
|
+
raised saying that the option is unknown.
|
128
|
+
|
129
|
+
To prevent this exception you can set the suppress_errors parameter. With
|
130
|
+
this parameter set to true an unknown option will just be added to the unprocessed
|
131
|
+
arguments array.
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
configatron.suppress_errors = true
|
135
|
+
```
|
136
|
+
|
137
|
+
The unprocessed options can be access via the arguments array:
|
138
|
+
|
139
|
+
```ruby
|
140
|
+
configatron.arguments
|
141
|
+
```
|
142
|
+
|
143
|
+
The arguments array is also where you will find anything else from the
|
144
|
+
command line that was not processed by the cli_helper. For example:
|
145
|
+
|
146
|
+
```ruby
|
147
|
+
my_program.rb -v *.txt
|
148
|
+
```
|
149
|
+
|
150
|
+
The file names matching the '*.txt' glob will be put into the configatron.arguments
|
151
|
+
array.
|
152
|
+
|
153
|
+
|
154
|
+
## Boolean options auto-generate methods
|
155
|
+
|
156
|
+
Any boolean command-line option specified, even the predefined common ones,
|
157
|
+
have two methods defined: query(?) and banger(!). For the help options
|
158
|
+
the methods look like this:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
def help?
|
162
|
+
configatron.help
|
163
|
+
end
|
164
|
+
|
165
|
+
def help!
|
166
|
+
configatron.help = true
|
167
|
+
end
|
168
|
+
```
|
169
|
+
|
170
|
+
## Names of command-line options
|
171
|
+
|
172
|
+
If you specify a command-line option of xyzzy, then an
|
173
|
+
entry in the configatron structure will be created having the
|
174
|
+
name 'xyzzy'. If you do not use a long-form for the option
|
175
|
+
the short option name will be used. For example '-x' will
|
176
|
+
be accessed as configatron.x
|
177
|
+
|
178
|
+
|
179
|
+
## Support methods
|
180
|
+
|
181
|
+
There are several support methods that I have included in cli_helper
|
182
|
+
that you may want to use. The first three deal with
|
183
|
+
errors and warnings and what to do with them.
|
184
|
+
|
185
|
+
* warning(a_string)
|
186
|
+
* error(a_string)
|
187
|
+
* abort_if_errors
|
188
|
+
|
189
|
+
cli_helper defines two arrays within configatron: errors and warnings. The
|
190
|
+
warning() and error() methods insert their strings into these arrays. The
|
191
|
+
abort_if_errors method first looks at the warnings array and presents all of
|
192
|
+
those strings to the user via STDOUT. It then asks the user if they want
|
193
|
+
to abort the program. The default answer is no.
|
194
|
+
|
195
|
+
After presenting the warnings to the user, the abort_if_error method presents
|
196
|
+
all of the errors to the user. Then it exits the program.
|
197
|
+
|
198
|
+
These next support methods are self explanatory:
|
199
|
+
|
200
|
+
* usage() #=> a_string
|
201
|
+
* show_usage() #=> usage string sent to STDOUT
|
202
|
+
* me() #=> The full path to the file that "require 'cli_helper"" was involked
|
203
|
+
* my_name() #=> the basename of me
|
204
|
+
|
205
|
+
But this one needs some explaining:
|
206
|
+
|
207
|
+
* get_pathnames_from(an_array, extnames=['.json', '.txt', '.docx'])
|
208
|
+
|
209
|
+
The method get_pathnames_from() returns an array of pathnames matching a specific
|
210
|
+
set of file types. The default types are txt, json and docx because that tends to
|
211
|
+
be the majority of the files in which I am interested. Might add wcml to the default list
|
212
|
+
later. Regardless you propabily ought to provide your own array of file extensions. And
|
213
|
+
don't forget the dot!
|
214
|
+
|
215
|
+
If an entry in the array is a directory then its children will be search including any sub-directories recursively.
|
216
|
+
|
217
|
+
Here is how I typically use it :)
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
get_pathnames_from(configatron.arguments, '.php').each do |f|
|
221
|
+
f.delete_without_regret!
|
222
|
+
end
|
223
|
+
```
|
11
224
|
|
12
225
|
|
13
226
|
## Usage
|
14
227
|
|
15
|
-
|
16
|
-
for themselves.
|
228
|
+
Take a look at http://github.com/MadBomber/cli_helper/blob/master/example/cli_stub.rb
|
17
229
|
|
18
230
|
|
19
231
|
## License
|
20
232
|
|
21
233
|
You want it? Its yours.
|
22
|
-
# cli_helper
|
data/cli_helper.gemspec
CHANGED
@@ -4,18 +4,20 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "cli_helper"
|
7
|
-
spec.version = '0.0
|
7
|
+
spec.version = '0.1.0'
|
8
8
|
spec.authors = ["Dewayne VanHoozer"]
|
9
9
|
spec.email = ["dvanhoozer@gmail.com"]
|
10
10
|
|
11
|
-
spec.summary = %q{An
|
12
|
-
spec.description = %q{
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
11
|
+
spec.summary = %q{An encapsulation of an integration of slop, nenv, parseconfig and configatron.}
|
12
|
+
spec.description = %q{
|
13
|
+
An encapsulation of a convention I have been using
|
14
|
+
with the slop, nenv, parseconfig and configatron gems for quick and dirty
|
15
|
+
development of
|
16
|
+
command-line based utility programs. Slop parses ARGV; Nenv parses ENV;
|
17
|
+
ParseConfig parses INI; Configatron keeps it all together. YAML and ERB
|
18
|
+
preprocessing is also available. Ruby configuration files are also supported.
|
19
|
+
and you can specify multiple config files of mixed types at once.
|
20
|
+
}
|
19
21
|
spec.homepage = "http://github.com/MadBomber/cli_helper"
|
20
22
|
spec.license = "You want it? It's yours."
|
21
23
|
|
@@ -26,14 +28,15 @@ Gem::Specification.new do |spec|
|
|
26
28
|
spec.metadata['allowed_push_host'] = 'https://rubygems.org'
|
27
29
|
end
|
28
30
|
|
29
|
-
spec.add_dependency '
|
31
|
+
spec.add_dependency 'configatron'
|
30
32
|
spec.add_dependency 'nenv'
|
31
|
-
spec.add_dependency '
|
32
|
-
spec.add_dependency '
|
33
|
-
|
33
|
+
spec.add_dependency 'parseconfig'
|
34
|
+
spec.add_dependency 'slop', "~> 4.0"
|
34
35
|
|
35
36
|
spec.add_development_dependency "bundler", "~> 1.9"
|
36
37
|
spec.add_development_dependency "rake", "~> 10.0"
|
37
|
-
spec.add_development_dependency '
|
38
|
+
spec.add_development_dependency 'kick_the_tires'
|
39
|
+
spec.add_development_dependency 'awesome_print'
|
40
|
+
spec.add_development_dependency 'debug_me'
|
38
41
|
|
39
42
|
end
|
data/example/cli_stub.rb
CHANGED
@@ -7,19 +7,55 @@
|
|
7
7
|
## By: Dewayne VanHoozer (dvanhoozer@gmail.com)
|
8
8
|
#
|
9
9
|
|
10
|
-
require '
|
11
|
-
|
12
|
-
$options[:version] = '0.0.1' # the version of this utility program
|
10
|
+
require 'awesome_print'
|
13
11
|
|
14
|
-
|
12
|
+
require 'cli_helper'
|
13
|
+
include CliHelper
|
14
|
+
|
15
|
+
configatron.version = '0.0.1' # the version of this utility program
|
16
|
+
configatron.support_config_files = true # default is false
|
17
|
+
configatron.disable_help = false # default is false set true to remove the option
|
18
|
+
configatron.disable_verbose = false # ditto
|
19
|
+
configatron.disable_debug = false # ditto
|
20
|
+
configatron.disable_version = false # ditto
|
21
|
+
configatron.suppress_errors = false # set to true to eat exceptions; unknown options added to arguments
|
22
|
+
|
23
|
+
# HELP is extra stuff shown with usage. It is optional. You
|
24
|
+
# can put anything you want into it. Since it is optional, it
|
25
|
+
# can be completely left out of your program. This HELP text
|
26
|
+
# will appear at the end of the usage message after the help
|
27
|
+
# text for each option (command-line parameter).
|
15
28
|
HELP = <<EOHELP
|
16
29
|
Important:
|
17
30
|
|
18
31
|
Put important stuff here.
|
19
32
|
|
33
|
+
Config files also support ERB preprocessing. use
|
34
|
+
cile names like: *.uml.erb *.ini.erb *.txt.erb
|
35
|
+
|
36
|
+
Do not use *.rb.erb that's just silly.
|
37
|
+
|
20
38
|
EOHELP
|
21
39
|
|
22
|
-
# The description (aka banner) text is optional. The block is required.
|
40
|
+
# The description (aka banner) text is optional. The block is not required.it
|
41
|
+
# only the default options and config files are desired. The block allows for
|
42
|
+
# the definition of program-specific options.
|
43
|
+
#
|
44
|
+
# Default options for help, debug, verbose, and version are automatically inserted
|
45
|
+
# by cli_helper. If configatron.support_config_files is TRUE then a '--config' parameter
|
46
|
+
# will also be presented. '--config' takes a comma-separated list of file paths. Each
|
47
|
+
# config file is processed within cli_helper and results combined within the configatron
|
48
|
+
# structure.
|
49
|
+
#
|
50
|
+
# -h, --help will automatically show a usage message on STDOUT and exit the program
|
51
|
+
# --version will print the program's version string to STDOUT and exit
|
52
|
+
# =v, --verbose will set the verbose boolean to true.
|
53
|
+
# -d, --debug will set the debug boolean to true.
|
54
|
+
# All boolean options have '?' and '!' methods generated, For example debug? and
|
55
|
+
# verbose? are automatically generated. Any program-specific booleans specified will
|
56
|
+
# also get methods defined for them. The debug! methods sets the debug boollean to true.
|
57
|
+
# Same for verbose! etc.
|
58
|
+
|
23
59
|
cli_helper("An example use of cli_helper") do |o|
|
24
60
|
|
25
61
|
# For a complete list of stuff see Slop on github.com
|
@@ -33,11 +69,13 @@ cli_helper("An example use of cli_helper") do |o|
|
|
33
69
|
|
34
70
|
o.array '-a', '--array', 'example array parameter', default: [:bob, :carol, :ted, :alice]
|
35
71
|
o.path '-p', '--path', 'example Pathname parameter', default: Pathname.new('default/path/to/file.txt')
|
36
|
-
o.paths '--paths', 'example Pathnames parameter', delimiter: ',', default: ['default/path/to/file.txt',
|
72
|
+
o.paths '--paths', 'example Pathnames parameter', delimiter: ',', default: ['default/path/to/file.txt',
|
73
|
+
'file2.txt'].map{|f| Pathname.new f}
|
37
74
|
|
38
75
|
# FIXME: Issue with Slop; default is not passed to the block. When no parameter is
|
39
76
|
# given, an exception is raised. Using the suppress_errors: true option silents
|
40
77
|
# the exception BUT still the default value is not passed to the block.
|
78
|
+
# This issue has been raised with the Slop author and a fix is in the works.
|
41
79
|
o.string '-n', '--name', 'print Hello <name>', default: 'World!', suppress_errors: true do |a_string|
|
42
80
|
a_string = 'world' if a_string.empty?
|
43
81
|
puts "Hello #{a_string}"
|
@@ -46,7 +84,7 @@ cli_helper("An example use of cli_helper") do |o|
|
|
46
84
|
end
|
47
85
|
|
48
86
|
# ARGV is not touched. However all command line parameters that are not consummed
|
49
|
-
# are available in
|
87
|
+
# are available in configatron.arguments
|
50
88
|
|
51
89
|
# Display the usage info
|
52
90
|
if ARGV.empty?
|
@@ -57,14 +95,29 @@ end
|
|
57
95
|
|
58
96
|
# Error check your stuff; use error('some message') and warning('some message')
|
59
97
|
|
60
|
-
unless
|
61
|
-
warning "These items were not processed #{
|
98
|
+
unless configatron.arguments.empty?
|
99
|
+
warning "These items were not processed #{configatron.arguments}"
|
62
100
|
end
|
63
101
|
|
64
|
-
if
|
102
|
+
if configatron.arguments.include?('error')
|
65
103
|
error "You wanted an error, so you got one."
|
66
104
|
end
|
67
105
|
|
106
|
+
if configatron.arguments.include?('warning')
|
107
|
+
warning "You wanted a warning, so you got one."
|
108
|
+
end
|
109
|
+
|
110
|
+
=begin
|
111
|
+
|
112
|
+
rescue
|
113
|
+
configatron.errors and configatron.warnings are of type Array.
|
114
|
+
All warnings will be presented to the user. The user will
|
115
|
+
be asked wither the program should be aborted.
|
116
|
+
=end
|
117
|
+
|
118
|
+
# present all warnings and all errors to the user
|
119
|
+
# if there are errors, the program will exit after
|
120
|
+
# displaying the error messages.
|
68
121
|
abort_if_errors
|
69
122
|
|
70
123
|
|
@@ -81,7 +134,7 @@ at_exit do
|
|
81
134
|
puts
|
82
135
|
end
|
83
136
|
|
84
|
-
ap
|
137
|
+
ap configatron.to_h if verbose? || debug?
|
85
138
|
|
86
139
|
stub = <<EOS
|
87
140
|
|