rbcli 0.1.10 → 0.2.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 +31 -0
- data/CODE_OF_CONDUCT.md +1 -1
- data/Gemfile.lock +12 -12
- data/LICENSE.txt +674 -21
- data/README.md +80 -443
- data/bin/console +19 -0
- data/bin/setup +20 -0
- data/docs/404.html +639 -0
- data/docs/advanced/automatic_updates/index.html +791 -0
- data/docs/advanced/command_types/index.html +946 -0
- data/docs/advanced/distributed_state_locking/index.html +777 -0
- data/docs/advanced/hooks/index.html +836 -0
- data/docs/advanced/state_storage/index.html +957 -0
- data/docs/advanced/user_config_files/index.html +818 -0
- data/docs/assets/fonts/font-awesome.css +4 -0
- data/docs/assets/fonts/material-icons.css +13 -0
- data/docs/assets/fonts/specimen/FontAwesome.ttf +0 -0
- data/docs/assets/fonts/specimen/FontAwesome.woff +0 -0
- data/docs/assets/fonts/specimen/FontAwesome.woff2 +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.ttf +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.woff +0 -0
- data/docs/assets/fonts/specimen/MaterialIcons-Regular.woff2 +0 -0
- data/docs/assets/images/favicon.png +0 -0
- data/docs/assets/images/icons/bitbucket.1b09e088.svg +20 -0
- data/docs/assets/images/icons/github.f0b8504a.svg +18 -0
- data/docs/assets/images/icons/gitlab.6dd19c00.svg +38 -0
- data/docs/assets/javascripts/application.a59e2a89.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.da.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.de.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.du.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.es.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.fi.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.fr.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.hu.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.it.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.jp.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.multi.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.no.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.pt.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.ro.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.ru.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.stemmer.support.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.sv.js +1 -0
- data/docs/assets/javascripts/lunr/lunr.tr.js +1 -0
- data/docs/assets/javascripts/lunr/tinyseg.js +1 -0
- data/docs/assets/javascripts/modernizr.1aa3b519.js +1 -0
- data/docs/assets/stylesheets/application-palette.6079476c.css +2 -0
- data/docs/assets/stylesheets/application.ba0fd1a6.css +2 -0
- data/docs/development/code_of_conduct/index.html +883 -0
- data/docs/development/contributing/index.html +744 -0
- data/docs/development/license/index.html +715 -0
- data/docs/imported/changelog/index.html +853 -0
- data/docs/imported/quick_reference/index.html +1057 -0
- data/docs/index.html +732 -0
- data/docs/search/search_index.json +569 -0
- data/docs/sitemap.xml +93 -0
- data/docs/tutorial/10-getting_started/index.html +806 -0
- data/docs/tutorial/20-project_layout/index.html +972 -0
- data/docs/tutorial/30-your_first_command/index.html +906 -0
- data/docs/tutorial/40-options_parameters_and_arguments/index.html +1049 -0
- data/docs/tutorial/50-publishing/index.html +838 -0
- data/docs/whoami/index.html +709 -0
- data/docs-src/docs/advanced/automatic_updates.md +42 -0
- data/docs-src/docs/advanced/command_types.md +144 -0
- data/docs-src/docs/advanced/distributed_state_locking.md +33 -0
- data/docs-src/docs/advanced/hooks.md +65 -0
- data/docs-src/docs/advanced/logging.md +35 -0
- data/docs-src/docs/advanced/state_storage.md +117 -0
- data/docs-src/docs/advanced/user_config_files.md +47 -0
- data/docs-src/docs/development/code_of_conduct.md +74 -0
- data/docs-src/docs/development/contributing.md +49 -0
- data/docs-src/docs/development/license.md +10 -0
- data/docs-src/docs/imported/changelog.md +31 -0
- data/docs-src/docs/imported/quick_reference.md +150 -0
- data/docs-src/docs/index.md +38 -0
- data/docs-src/docs/tutorial/10-getting_started.md +41 -0
- data/docs-src/docs/tutorial/20-project_layout.md +115 -0
- data/docs-src/docs/tutorial/30-your_first_command.md +126 -0
- data/docs-src/docs/tutorial/40-options_parameters_and_arguments.md +251 -0
- data/docs-src/docs/tutorial/50-publishing.md +47 -0
- data/docs-src/docs/whoami.md +28 -0
- data/docs-src/makesite.sh +14 -0
- data/docs-src/mkdocs.yml +76 -0
- data/docs-src/runsite.sh +3 -0
- data/exe/rbcli +76 -5
- data/lib/rbcli/autoupdate/autoupdate.rb +24 -4
- data/lib/rbcli/autoupdate/gem_updater.rb +23 -2
- data/lib/rbcli/autoupdate/github_updater.rb +22 -1
- data/lib/rbcli/configuration/config.rb +22 -1
- data/lib/rbcli/configuration/configurate.rb +24 -2
- data/lib/rbcli/engine/command.rb +26 -6
- data/lib/rbcli/engine/load_project.rb +29 -3
- data/lib/rbcli/engine/parser.rb +25 -4
- data/lib/rbcli/logging/logging.rb +21 -0
- data/lib/rbcli/scriptwrapping/scriptwrapper.rb +30 -11
- data/lib/rbcli/stateful_systems/configuratestorage.rb +20 -0
- data/lib/rbcli/stateful_systems/state_storage.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/localstate.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/remote_state_connectors/dynamodb.rb +20 -0
- data/lib/rbcli/stateful_systems/storagetypes/remotestate_dynamodb.rb +20 -0
- data/lib/rbcli/util/hash_deep_symbolize.rb +43 -22
- data/lib/rbcli/util/string_colorize.rb +20 -0
- data/lib/rbcli/version.rb +21 -1
- data/lib/rbcli-tool/generators.rb +20 -0
- data/lib/rbcli-tool/mdless_fix.rb +20 -0
- data/lib/rbcli-tool/project.rb +27 -2
- data/lib/rbcli-tool/util.rb +20 -0
- data/lib/rbcli-tool.rb +20 -0
- data/lib/rbcli.rb +20 -0
- data/lib-sh/lib-rbcli.sh +19 -0
- data/rbcli.gemspec +22 -3
- data/skeletons/project/CODE_OF_CONDUCT.md +1 -1
- data/skeletons/project/README.md +17 -2
- data/skeletons/project/application/commands/command.erb +10 -8
- data/skeletons/project/application/commands/script.erb +3 -1
- data/skeletons/project/application/commands/scripts/script.sh +2 -2
- data/skeletons/project/application/options.rb +12 -3
- data/skeletons/project/config/autoupdate.rb +5 -2
- data/skeletons/project/config/storage.rb +7 -6
- data/skeletons/project/config/userspace.rb +6 -1
- data/skeletons/project/exe/executable +1 -1
- data/skeletons/project/lib/.keep +0 -0
- data/skeletons/project/untitled.gemspec +4 -4
- data/skeletons/project/{default_user_configs → userconf}/user_defaults.yml +0 -0
- metadata +85 -9
- data/examples/defaults.yml +0 -4
- data/examples/myscript.sh +0 -23
- data/examples/mytool +0 -95
@@ -0,0 +1,251 @@
|
|
1
|
+
# Options, Paramters, and Arguments
|
2
|
+
|
3
|
+
If you're already an experienced coder, you can jump to the last section of this document, the [Simplified Reference (TLDR)](#simplified-reference-tldr)
|
4
|
+
|
5
|
+
## Command Line Structure
|
6
|
+
|
7
|
+
In the previous section, you saw two parts of the RBCli command line structure - the executable followed by the command. However, RBCli is capable of more complex interaction. The structure is as follows:
|
8
|
+
|
9
|
+
```
|
10
|
+
toolname [options] command [parameters] argument1 argument2...
|
11
|
+
```
|
12
|
+
|
13
|
+
* __Options__ are command line parameters such as `-f`, or `--force`. These are available globally to every command. You can create your own, though several are already built-in and reserved for RBCli:
|
14
|
+
* `--config-file=<filename>` allows specifying a config file location manually.
|
15
|
+
* `--generate-config` generates a config file for the user by writing out the defaults to a YAML file. This option will only appear if a config file has been set. The location is configurable, with more on that in the documentation on [User Config Files][user_config_documentation]).
|
16
|
+
* `-v / --version` shows the version.
|
17
|
+
* `-h / --help` shows the help.
|
18
|
+
* __Command__ represents the subcommands that you will create, such as `list`, `test`, or `apply`.
|
19
|
+
* __Parameters__ are the same as options, but only apply to the specific subcommand being executed. In this case only the `-h / --help` parameter is provided automatically.
|
20
|
+
* __Arguments__ are strings that don't begin with a '-', and are passed to the command's code as an array. These can be used as subcommands or additional parameters for your command.
|
21
|
+
|
22
|
+
So a valid command could look something like these:
|
23
|
+
|
24
|
+
```shell
|
25
|
+
mytool -n load --filename=foo.txt
|
26
|
+
mytool parse foo.txt
|
27
|
+
mytool show -l
|
28
|
+
```
|
29
|
+
|
30
|
+
Note that all options and parameters will have both a short and long version of the parameter available for use.
|
31
|
+
|
32
|
+
So let's take a look at how we define them.
|
33
|
+
|
34
|
+
|
35
|
+
## Options
|
36
|
+
|
37
|
+
You can find the options declarations under `application/options.rb`. You'll see the example in the code:
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
option :name, 'Give me your name', short: 'n', type: :string, default: 'Jack', required: false, permitted: ['Jack', 'Jill']
|
41
|
+
```
|
42
|
+
|
43
|
+
This won't do for our tool, so let's change it. Remember that these options will be applicable to all of our commands, so lets make it something appropriate:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
option :color, 'Enable color output', short: 'c', type: :boolean, default: false
|
47
|
+
```
|
48
|
+
|
49
|
+
So now, let's take advantage of this flag in our `list` command. Let's change our block to:
|
50
|
+
|
51
|
+
```ruby
|
52
|
+
action do |params, args, global_opts, config|
|
53
|
+
Dir.glob "./*" do |filename|
|
54
|
+
outname = filename.split('/')[1]
|
55
|
+
outname += '/' if File.directory? filename
|
56
|
+
|
57
|
+
# We change the color based on the kind of file shown
|
58
|
+
if global_opts[:color]
|
59
|
+
if File.directory? filename
|
60
|
+
outname = outname.light_blue
|
61
|
+
elsif File.executable? filename
|
62
|
+
outname = outname.light_green
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
puts outname
|
67
|
+
end
|
68
|
+
end
|
69
|
+
```
|
70
|
+
|
71
|
+
Notice how we referenced the value by using `global_opts[:color]`. It's that simple. To see it in action, run:
|
72
|
+
|
73
|
+
```bash
|
74
|
+
mytool -c list
|
75
|
+
```
|
76
|
+
|
77
|
+
## Parameters
|
78
|
+
|
79
|
+
Parameters work the same way as options, but they are localized to only the selected command. They are declared - as you probably guessed by now - in the command's class. So let's add the following lines to our list command within the class declaration:
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
parameter :sort, 'Sort output alphabetically', type: :boolean, default: false
|
83
|
+
parameter :all, 'Show hidden files', type: :boolean, default: false
|
84
|
+
parameter :directoriesfirst, 'Show directories on top', type: :boolean, default: false
|
85
|
+
```
|
86
|
+
|
87
|
+
And let's modify our action block to utilize them:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
action do |params, args, global_opts, config|
|
91
|
+
filelist = []
|
92
|
+
|
93
|
+
# We include dotfiles if specified
|
94
|
+
include_dotfiles = (params[:all]) ? File::FNM_DOTMATCH : 0
|
95
|
+
|
96
|
+
# We store a list of the files in an array, including dotfiles if specified
|
97
|
+
Dir.glob "./*", include_dotfiles do |filename|
|
98
|
+
outname = filename.split('/')[1]
|
99
|
+
outname += '/' if File.directory? filename
|
100
|
+
filelist.append outname
|
101
|
+
end
|
102
|
+
|
103
|
+
# Sort alphabetically if specified
|
104
|
+
filelist.sort! if params[:sort]
|
105
|
+
|
106
|
+
# Put directories first if specified
|
107
|
+
if params[:directoriesfirst]
|
108
|
+
files = []; dirs = []
|
109
|
+
filelist.each do |filename|
|
110
|
+
if File.directory? filename
|
111
|
+
dirs.append(filename)
|
112
|
+
else
|
113
|
+
files.append(filename)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
filelist = dirs + files
|
117
|
+
end
|
118
|
+
|
119
|
+
# Apply color. We do this at the end now because color codes can alter the sorting.
|
120
|
+
filelist.map! do |filename|
|
121
|
+
if File.directory? filename
|
122
|
+
filename.light_blue
|
123
|
+
elsif File.executable? filename
|
124
|
+
filename.light_green
|
125
|
+
else
|
126
|
+
filename
|
127
|
+
end
|
128
|
+
end if global_opts[:color]
|
129
|
+
|
130
|
+
puts filelist
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
134
|
+
You should be able to run it now:
|
135
|
+
|
136
|
+
```bash
|
137
|
+
mytool -c list -asd
|
138
|
+
```
|
139
|
+
|
140
|
+
Note how the parameters come after the `list` command in the syntax above. As you create more commands, each will have its own unique set of parameters, while the options remain _before_ the command and are available to all of them.
|
141
|
+
|
142
|
+
## Arguments
|
143
|
+
|
144
|
+
Lastly on the command line, there are arguments. Arguments are simply strings without the `-` character in front, and automatically get passed into an array in your applicaiton. Let's take a look at how we can use them.
|
145
|
+
|
146
|
+
Unlike options and parameters, arguments require no setup. So let's assume that we want any arguments passed to the `list` command to be filenames that you want to display, and that you can pass multiple ones. Since arguments aren't listed automatically by the help function, this is a good example of what to put in your usage text. Let's take a look at what our class looks like now:
|
147
|
+
|
148
|
+
```ruby
|
149
|
+
class List < Rbcli::Command
|
150
|
+
description %q{List files in current directory}
|
151
|
+
usage <<-EOF
|
152
|
+
To list only specific files, you can enter filenames as arguments
|
153
|
+
|
154
|
+
mytool list filename1 filename2...
|
155
|
+
EOF
|
156
|
+
parameter :sort, 'Sort output alphabetically', type: :boolean, default: false
|
157
|
+
parameter :all, 'Show hidden files', type: :boolean, default: false
|
158
|
+
parameter :directoriesfirst, 'Show directories on top', type: :boolean, default: false
|
159
|
+
|
160
|
+
action do |params, args, global_opts, config|
|
161
|
+
filelist = []
|
162
|
+
|
163
|
+
# We include dotfiles if specified
|
164
|
+
include_dotfiles = (params[:all]) ? File::FNM_DOTMATCH : 0
|
165
|
+
|
166
|
+
# We store a list of the files in an array, including dotfiles if specified
|
167
|
+
Dir.glob "./*", include_dotfiles do |filename|
|
168
|
+
outname = filename.split('/')[1]
|
169
|
+
next unless args.include? outname if args.length > 0
|
170
|
+
outname += '/' if File.directory? filename
|
171
|
+
filelist.append outname
|
172
|
+
end
|
173
|
+
|
174
|
+
# Sort alphabetically if specified
|
175
|
+
filelist.sort! if params[:sort]
|
176
|
+
|
177
|
+
# Put directories first if specified
|
178
|
+
if params[:directoriesfirst]
|
179
|
+
files = []; dirs = []
|
180
|
+
filelist.each do |filename|
|
181
|
+
if File.directory? filename
|
182
|
+
dirs.append(filename)
|
183
|
+
else
|
184
|
+
files.append(filename)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
filelist = dirs + files
|
188
|
+
end
|
189
|
+
|
190
|
+
# Apply color. We do this at the end because color codes can alter the sorting
|
191
|
+
filelist.map! do |filename|
|
192
|
+
if File.directory? filename
|
193
|
+
filename.light_blue
|
194
|
+
elsif File.executable? filename
|
195
|
+
filename.light_green
|
196
|
+
else
|
197
|
+
filename
|
198
|
+
end
|
199
|
+
end if global_opts[:color]
|
200
|
+
|
201
|
+
puts filelist
|
202
|
+
end
|
203
|
+
end
|
204
|
+
```
|
205
|
+
|
206
|
+
|
207
|
+
|
208
|
+
## Simplified Reference (TLDR)
|
209
|
+
|
210
|
+
RBCli enforces a CLI structure of:
|
211
|
+
|
212
|
+
```
|
213
|
+
toolname [options] command [parameters] argument1 argument2...
|
214
|
+
```
|
215
|
+
|
216
|
+
__Options__ are declared in `application/options.rb` file.
|
217
|
+
|
218
|
+
__Parameters__ are declared in the respective command's class declaration.
|
219
|
+
|
220
|
+
__Arguments__ don't need to be declared, and are passed in as an array to your commands. It is helpful to describe the argument purpose in the `usage` text declaration so that the user can see what to do in the help.
|
221
|
+
|
222
|
+
__Options__ and __parameters__ both use the same format:
|
223
|
+
|
224
|
+
```ruby
|
225
|
+
option :<name>, "<description_string>", short: '<character>', type: <variable_type>, default: <default_value>, permitted: [<array_of_permitted_values]
|
226
|
+
|
227
|
+
parameter :<name>, "<description_string>", short: '<character>', type: <variable_type>, default: <default_value>, permitted: [<array_of_permitted_values]
|
228
|
+
```
|
229
|
+
|
230
|
+
* `name`
|
231
|
+
* (Required) The long name of the option, as a symbol. This will be represented as `--name` on the command line
|
232
|
+
* `description_string`
|
233
|
+
* (Required) A short description of the command that will appear in the help text for the user
|
234
|
+
* `type`
|
235
|
+
* (Required) The following types are supported: `:string`, `:boolean` or `:flag`, `:integer`, and `:float`
|
236
|
+
* `default`
|
237
|
+
* (Optional) A default value for the option if one isn't entered (default: nil)
|
238
|
+
* `short`
|
239
|
+
* (Optional) A letter that acts as a shortcut for the option. This will allow users to apply the command as `-n`
|
240
|
+
* To not have a short value, set this to :none (default: the first letter of the long name)
|
241
|
+
* `required`
|
242
|
+
* (Optional) Specify whether the option is required from the user (default: false)
|
243
|
+
* `permitted`
|
244
|
+
* (Optional) An array of whitelisted values for the option (default: nil)
|
245
|
+
|
246
|
+
## Next Steps
|
247
|
+
|
248
|
+
Next, we're going to take a quick look at how to publish and distribute your application, both publicly and within your organization.
|
249
|
+
|
250
|
+
[user_config_documentation]: ../advanced/user_config_files.md
|
251
|
+
[regex_explanation]: https://medium.com/factory-mind/regex-tutorial-a-simple-cheatsheet-by-examples-649dc1c3f285
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# Publishing Your Application
|
2
|
+
|
3
|
+
RBCli creates projects designed to be easily distributed via either source control or as a gem. We'll go over both methods.
|
4
|
+
|
5
|
+
## Common Tasks
|
6
|
+
|
7
|
+
Regardless of where you are publishing, certain tasks need to be accomplished. Namely, preparing the gemspec and the README.
|
8
|
+
|
9
|
+
In both files the items that need changing are pretty obvious -- you'll need to fill out your name, email, etc, and replace the placeholder text in the README with something useful to your users.
|
10
|
+
|
11
|
+
Then, for every release, you'll need to update the version number in `config/version.rb`. This number is automatically used by the `gemspec` when versioning the gem in the system, and by RBCli when displaying help to the user and checking for automatic updates if you enable that feature (see [Automatic Updates][automatic_update_documentation] for more information).
|
12
|
+
|
13
|
+
## Source Control Distribution
|
14
|
+
|
15
|
+
With Source Control distribution your users will be cloning the source code directly from your repository, and building and installing the gem locally. Thankfully, the process is pretty simple:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
git clone <your_repo_here>
|
19
|
+
gem build mytool.gemspec
|
20
|
+
gem install mytool-*.gem
|
21
|
+
```
|
22
|
+
|
23
|
+
Note that he README's placeholder text has these commands already listed for your users, which you can leave as instructions.
|
24
|
+
|
25
|
+
When using this method, we highly recommend using a git flow where you only merge to master when you are ready to release, this way your users don't inadvertently download a buggy commit.
|
26
|
+
|
27
|
+
## Rubygems.org Distribution
|
28
|
+
|
29
|
+
If you're distributing as a gem via Rubygems.org, you'll need to follow a specific release process.
|
30
|
+
|
31
|
+
1. Update the version number in `config/version.rb`
|
32
|
+
2. Commit the change locally
|
33
|
+
3. Run `bundle exec rake release`
|
34
|
+
|
35
|
+
This will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
36
|
+
|
37
|
+
## Recommended Platforms
|
38
|
+
|
39
|
+
As far as RBCli is concerned, all Git hosts and gem platforms work equally well, and as long as the code reaches your users in one piece it's all the same. That said, if you'd like to take advantage of automatic update notifications for your users, please see the documentation for [Automatic Updates][automatic_update_documentation] for a list of supported platforms for that feature.
|
40
|
+
|
41
|
+
## Next Steps
|
42
|
+
|
43
|
+
Congratulations! You've completed the tutorial on RBCli and should be able to make all sorts of CLI applications and tools with what you learned. That said, there are still many features in RBCli that we didn't explore, which you can find in the __Advanced__ section of this site. If you aren't sure where to start, we recommend looking at [User Config Files][user_config_files_documentation] and going from there.
|
44
|
+
|
45
|
+
|
46
|
+
[automatic_update_documentation]: ../advanced/automatic_updates.md
|
47
|
+
[user_config_files_documentation]: ../advanced/user_config_files.md
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# My Letter To You
|
2
|
+
|
3
|
+
My Fellow Coder,
|
4
|
+
|
5
|
+
I'm glad to see you are interested in RBCli. I'd like to introduce myself. My name is Andrew, and I've been a technologist since 1992 when my father bought our first family computer -- a 486DX2 which ran at 66Mhz (33Mhz if you turned off the 'turbo' button) and came with MS DOS 5.0, [QBasic](https://en.wikipedia.org/wiki/QBasic), and a game already coded in it called [Nibbles](https://classicreload.com/qbasic-nibbles.html) (if you care to see the code, die 5 times and don't play again). I didn't like that the game forced my name to be "Sammy", and thought, "hey, if I can see the code, can't I change it?". So I did what any annoyed child would do and learned to code so I could do just that. I'd tell you what I changed it to, but I was so proud of myself for this simple feat that I changed it every 30 seconds and couldn't settle on just one name. Then I performed my first ever hack, and figured out how to go through walls without dying. All of a sudden the world seemed limitless.
|
6
|
+
|
7
|
+
I was only a child at the time, but on that day I learned that every "rule" in computing was an artifical construct and could be changed to suit your needs. Thus began my career in tech and my obsession to change the world with it. This is why RBCli was born.
|
8
|
+
|
9
|
+
RBCli started as a collection of code that I would copy-paste between projects, until one day when I wondered if I could just find a framework that suited me. I couldn't - in case you hadn't guessed - so I decided to build my own and give it to the world. I would not have accomplished even half of what I have without the open source community, and this is to be the first of hopefully many contributions back.
|
10
|
+
|
11
|
+
The features in RBCli have been chosen from over 25 years of experience writing applications, building features that 3rd parties left out, managing large scale infrastructure, designing embedded systems, integrating enterprise systems, automating CI/CD, scripting my own computers, and so much more. I hope that you can find as much use out of it as I have.
|
12
|
+
|
13
|
+
If you'd like to get in touch with me at any time, feel free to email me at [andrew@blacknex.us](mailto:andrew@blacknex.us).
|
14
|
+
|
15
|
+
All the best,
|
16
|
+
|
17
|
+
Andrew
|
18
|
+
|
19
|
+
|
20
|
+
P.S.: If you really liked RBCli and want to support it, any amount you can help out with goes a long way.
|
21
|
+
|
22
|
+
<form action="https://www.paypal.com/cgi-bin/webscr" method="post" target="_top">
|
23
|
+
<input type="hidden" name="cmd" value="_s-xclick">
|
24
|
+
<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----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-----END PKCS7-----
|
25
|
+
">
|
26
|
+
<input type="image" src="https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif" border="0" name="submit" alt="PayPal - The safer, easier way to pay online!">
|
27
|
+
<img alt="" border="0" src="https://www.paypalobjects.com/en_US/i/scr/pixel.gif" width="1" height="1">
|
28
|
+
</form>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
|
3
|
+
if ! pip list | grep mkdocs &> /dev/null; then
|
4
|
+
echo "Python package mkdocs not found. Installing..."
|
5
|
+
pip install mkdocs mkdocs-material
|
6
|
+
fi
|
7
|
+
|
8
|
+
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
|
9
|
+
|
10
|
+
mkdir -p "${DIR}/docs/imported" || true
|
11
|
+
cp "${DIR}/../CHANGELOG.md" "${DIR}/docs/imported/changelog.md"
|
12
|
+
sed -n '/Quick Reference/,$p' "${DIR}/../README.md" > "${DIR}/docs/imported/quick_reference.md"
|
13
|
+
|
14
|
+
mkdocs build --clean
|
data/docs-src/mkdocs.yml
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# https://www.mkdocs.org/user-guide/configuration
|
2
|
+
|
3
|
+
site_name: RBCli Documentation
|
4
|
+
site_description: Description
|
5
|
+
site_author: Andrew Khoury
|
6
|
+
copyright: Copyright © 2018 Andrew Khoury
|
7
|
+
|
8
|
+
pages:
|
9
|
+
- Home: index.md
|
10
|
+
- Quick Reference: imported/quick_reference.md
|
11
|
+
- Tutorial:
|
12
|
+
- Getting Started: tutorial/10-getting_started.md
|
13
|
+
- The Project Layout: tutorial/20-project_layout.md
|
14
|
+
- Your First Command: tutorial/30-your_first_command.md
|
15
|
+
- Options, Parameters, and Arguments: tutorial/40-options_parameters_and_arguments.md
|
16
|
+
- Publishing and Distribution: tutorial/50-publishing.md
|
17
|
+
- Advanced Features:
|
18
|
+
- Command Types: advanced/command_types.md
|
19
|
+
- User Config Files: advanced/user_config_files.md
|
20
|
+
- Hooks: advanced/hooks.md
|
21
|
+
- Automatic Updates: advanced/automatic_updates.md
|
22
|
+
- State Storage: advanced/state_storage.md
|
23
|
+
- Distributed State Locking: advanced/distributed_state_locking.md
|
24
|
+
- Development:
|
25
|
+
- Contribution Guide: development/contributing.md
|
26
|
+
- License Info: development/license.md
|
27
|
+
- Code of Conduct: development/code_of_conduct.md
|
28
|
+
- Changelog: imported/changelog.md
|
29
|
+
- $ whoami: whoami.md
|
30
|
+
|
31
|
+
# The repo link on the top-right of the page
|
32
|
+
#repo_name: GitHub
|
33
|
+
repo_url: https://github.com/akhoury6/rbcli/
|
34
|
+
edit_uri: ''
|
35
|
+
|
36
|
+
# For use with mkdocs build
|
37
|
+
#docs_dir: ./docs-src/docs/
|
38
|
+
site_dir: ../docs/
|
39
|
+
|
40
|
+
# For use with gh-deploy
|
41
|
+
#remote_branch: master
|
42
|
+
#remote_name: origin
|
43
|
+
|
44
|
+
#theme: windmill
|
45
|
+
|
46
|
+
theme:
|
47
|
+
name: material
|
48
|
+
logo:
|
49
|
+
icon: devices # from https://material.io/tools/icons/?style=baseline
|
50
|
+
feature:
|
51
|
+
tabs: true
|
52
|
+
# logo: 'images/logo.svg'
|
53
|
+
# palette:
|
54
|
+
# primary: 'indigo'
|
55
|
+
# accent: 'indigo'
|
56
|
+
# language: 'en'
|
57
|
+
# direction: 'ltr'
|
58
|
+
# favicon: 'assets/images/favicon.ico'
|
59
|
+
|
60
|
+
|
61
|
+
#theme: readthedocs
|
62
|
+
#theme:
|
63
|
+
# name: mkdocs
|
64
|
+
# custom_dir: my_theme_customizations/
|
65
|
+
# static_templates:
|
66
|
+
# - sitemap.html
|
67
|
+
# include_sidebar: false
|
68
|
+
#extra_css:
|
69
|
+
# - css/extra.css
|
70
|
+
# - css/second_extra.css
|
71
|
+
#extra_javascript:
|
72
|
+
#extra_templates:
|
73
|
+
#extra:
|
74
|
+
# rbcli_version: 0.1.0
|
75
|
+
|
76
|
+
# For formatting options see https://www.mkdocs.org/user-guide/configuration/#formatting-options
|
data/docs-src/runsite.sh
ADDED
data/exe/rbcli
CHANGED
@@ -1,4 +1,23 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
##################################################################################
|
3
|
+
# RBCli -- A framework for developing command line applications in Ruby #
|
4
|
+
# Copyright (C) 2018 Andrew Khoury #
|
5
|
+
# #
|
6
|
+
# This program is free software: you can redistribute it and/or modify #
|
7
|
+
# it under the terms of the GNU General Public License as published by #
|
8
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
9
|
+
# (at your option) any later version. #
|
10
|
+
# #
|
11
|
+
# This program is distributed in the hope that it will be useful, #
|
12
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
13
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
14
|
+
# GNU General Public License for more details. #
|
15
|
+
# #
|
16
|
+
# You should have received a copy of the GNU General Public License #
|
17
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
18
|
+
# #
|
19
|
+
# For questions regarding licensing, please contact andrew@blacknex.us #
|
20
|
+
##################################################################################
|
2
21
|
|
3
22
|
require "#{File.dirname(__FILE__)}/../lib/rbcli.rb"
|
4
23
|
|
@@ -6,6 +25,7 @@ Rbcli::Configurate.me do
|
|
6
25
|
scriptname __FILE__.split('/')[-1]
|
7
26
|
version Rbcli::VERSION
|
8
27
|
description 'RBCli initialization tool'
|
28
|
+
autoupdate gem: 'rbcli', force_update: false, message: "Please run `gem update rbcli` to upgrade to the latest version."
|
9
29
|
end
|
10
30
|
|
11
31
|
require "#{File.dirname(__FILE__)}/../lib/rbcli-tool.rb"
|
@@ -23,6 +43,26 @@ class Docs < Rbcli::Command
|
|
23
43
|
end
|
24
44
|
end
|
25
45
|
|
46
|
+
class License < Rbcli::Command
|
47
|
+
description 'Shows Copyright and License Info'
|
48
|
+
usage nil
|
49
|
+
|
50
|
+
parameter :full, 'Display Full License Text', default: false
|
51
|
+
|
52
|
+
action do |params|
|
53
|
+
puts File.read("#{File.dirname(__FILE__)}/../LICENSE.txt") if params[:full]
|
54
|
+
puts <<-EOF
|
55
|
+
RBCli Copyright (C) 2018 Andrew Khoury
|
56
|
+
This program comes with ABSOLUTELY NO WARRANTY.
|
57
|
+
This is free software, and you are welcome to redistribute it
|
58
|
+
under certain conditions.
|
59
|
+
If you wish to release this library as part of commercial software,
|
60
|
+
please contact andrew@blacknex.us.
|
61
|
+
Type `rbcli license --full' to show the license text.
|
62
|
+
EOF
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
26
66
|
class Init < Rbcli::Command
|
27
67
|
description 'Initialize a skeleton RBCli project.'
|
28
68
|
usage <<-EOF
|
@@ -107,13 +147,12 @@ EOF
|
|
107
147
|
end
|
108
148
|
end
|
109
149
|
|
110
|
-
class
|
150
|
+
class Script < Rbcli::Command
|
111
151
|
description 'Generate an Rbcli Command with Bash Script under the current project'
|
112
152
|
usage <<-EOF
|
113
153
|
This will generate a new command under the current RBCli project, and a skeleton bash script to code it.
|
114
154
|
|
115
|
-
Use this option if you prefer to use bash (or another shell) to script your command
|
116
|
-
a third party application.
|
155
|
+
Use this option if you prefer to use bash (or another shell) to script your command.
|
117
156
|
|
118
157
|
Please run this command from within the project's directory structure.
|
119
158
|
EOF
|
@@ -121,7 +160,6 @@ EOF
|
|
121
160
|
parameter :name, 'Name of command to generate', type: :string, required: true
|
122
161
|
parameter :description, 'A short description of the command', type: :string, default: 'TODO: Description goes here'
|
123
162
|
parameter :usagetext, 'Usage help text for the command', type: :string, default: 'TODO: Usage text goes here'
|
124
|
-
parameter :skip_script, 'Skip creating a bash script and set executable path manually', type: :boolean, default: false
|
125
163
|
|
126
164
|
action do |params, args, global_opts, config|
|
127
165
|
# First we check that we are working within a project folder
|
@@ -133,7 +171,40 @@ EOF
|
|
133
171
|
name: params[:name],
|
134
172
|
description: params[:description],
|
135
173
|
usage_text: params[:usagetext],
|
136
|
-
no_script:
|
174
|
+
no_script: false,
|
175
|
+
rbcli_version: Rbcli::VERSION
|
176
|
+
}
|
177
|
+
|
178
|
+
generator = RBCliTool::Generator.new(:extern, project_root, template_vars)
|
179
|
+
generator.run
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
class Extern < Rbcli::Command
|
184
|
+
description 'Generate an Rbcli Command that can wrap an external application'
|
185
|
+
usage <<-EOF
|
186
|
+
This will generate a new command under the current RBCli project
|
187
|
+
|
188
|
+
Use this option if you need to integrate with a third party application.
|
189
|
+
|
190
|
+
Please run this command from within the project's directory structure.
|
191
|
+
EOF
|
192
|
+
|
193
|
+
parameter :name, 'Name of command to generate', type: :string, required: true
|
194
|
+
parameter :description, 'A short description of the command', type: :string, default: 'TODO: Description goes here'
|
195
|
+
parameter :usagetext, 'Usage help text for the command', type: :string, default: 'TODO: Usage text goes here'
|
196
|
+
|
197
|
+
action do |params, args, global_opts, config|
|
198
|
+
# First we check that we are working within a project folder
|
199
|
+
project_root = RBCliTool::Project.find_root(Dir.pwd)
|
200
|
+
RBCliTool.exit_with_error("Can't find the project root in the current path. Please `cd` to your project's directory before running this command, and ensure that the `.rbcli` file is present in its root path.") unless project_root
|
201
|
+
|
202
|
+
# Prepare template vars
|
203
|
+
template_vars = {
|
204
|
+
name: params[:name],
|
205
|
+
description: params[:description],
|
206
|
+
usage_text: params[:usagetext],
|
207
|
+
no_script: true,
|
137
208
|
rbcli_version: Rbcli::VERSION
|
138
209
|
}
|
139
210
|
|
@@ -1,13 +1,33 @@
|
|
1
|
+
##################################################################################
|
2
|
+
# RBCli -- A framework for developing command line applications in Ruby #
|
3
|
+
# Copyright (C) 2018 Andrew Khoury #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
17
|
+
# #
|
18
|
+
# For questions regarding licensing, please contact andrew@blacknex.us #
|
19
|
+
##################################################################################
|
20
|
+
|
1
21
|
module Rbcli::Configurate
|
2
|
-
def self.autoupdate gem: nil, github_repo: nil, access_token: nil, enterprise_hostname: nil, force_update: false
|
22
|
+
def self.autoupdate gem: nil, github_repo: nil, access_token: nil, enterprise_hostname: nil, force_update: false, message: nil
|
3
23
|
raise StandardError.new "Autoupdater can not have both a gem and git target defined. Please pick one." if gem and github_repo
|
4
24
|
raise StandardError.new "Only one autoupdater can be defined." if @data[:autoupdater]
|
5
25
|
if gem
|
6
26
|
#Rbcli::Autoupdate::GemUpdater.save_defaults
|
7
|
-
@data[:autoupdater] = Rbcli::Autoupdate::GemUpdater.new gem, force_update
|
27
|
+
@data[:autoupdater] = Rbcli::Autoupdate::GemUpdater.new gem, force_update, message
|
8
28
|
else
|
9
29
|
Rbcli::Autoupdate::GithubUpdater.save_defaults
|
10
|
-
@data[:autoupdater] = Rbcli::Autoupdate::GithubUpdater.new github_repo, access_token, enterprise_hostname, force_update
|
30
|
+
@data[:autoupdater] = Rbcli::Autoupdate::GithubUpdater.new github_repo, access_token, enterprise_hostname, force_update, message
|
11
31
|
end
|
12
32
|
@data[:autoupdater].show_message if @data[:autoupdater].update_available?
|
13
33
|
end
|
@@ -32,7 +52,7 @@ module Rbcli::Autoupdate
|
|
32
52
|
|
33
53
|
def show_message
|
34
54
|
puts "WARNING: An update is available to #{Rbcli::Configurate::configuration[:scriptname]}. You are currently running version #{Rbcli.configuration[:version]}; the latest is #{@latest_version || get_latest_version}."
|
35
|
-
puts update_message
|
55
|
+
puts @message || update_message
|
36
56
|
puts "\n"
|
37
57
|
if @force_update
|
38
58
|
puts "This application requires that you update to the latest version to continue using it. It will now exit."
|
@@ -1,3 +1,23 @@
|
|
1
|
+
##################################################################################
|
2
|
+
# RBCli -- A framework for developing command line applications in Ruby #
|
3
|
+
# Copyright (C) 2018 Andrew Khoury #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <https://www.gnu.org/licenses/>. #
|
17
|
+
# #
|
18
|
+
# For questions regarding licensing, please contact andrew@blacknex.us #
|
19
|
+
##################################################################################
|
20
|
+
|
1
21
|
require 'net/http'
|
2
22
|
require 'json'
|
3
23
|
|
@@ -5,10 +25,11 @@ module Rbcli::Autoupdate
|
|
5
25
|
class GemUpdater
|
6
26
|
include Common
|
7
27
|
|
8
|
-
def initialize gemname, force_update
|
28
|
+
def initialize gemname, force_update, message
|
9
29
|
@gemname = gemname
|
10
30
|
@uri = URI.parse "https://rubygems.org/api/v1/versions/#{gemname}/latest.json"
|
11
31
|
@force_update = force_update
|
32
|
+
@message = message
|
12
33
|
end
|
13
34
|
|
14
35
|
def get_latest_version
|
@@ -21,7 +42,7 @@ module Rbcli::Autoupdate
|
|
21
42
|
end
|
22
43
|
|
23
44
|
def update_message
|
24
|
-
"Please
|
45
|
+
"Please run `gem update #{@gemname}` to upgrade to the latest version. You can see it at: https://rubygems.org/gems/#{@gemname}/versions/#{@latest_version}"
|
25
46
|
end
|
26
47
|
|
27
48
|
# def self.save_defaults
|