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,150 @@
|
|
1
|
+
# Quick Reference
|
2
|
+
|
3
|
+
## Installation
|
4
|
+
|
5
|
+
RBCli is available on rubygems.org. You can add it to your application's `Gemfile` or `gemspec`, or install it manually by running:
|
6
|
+
|
7
|
+
```bash
|
8
|
+
gem install rbcli
|
9
|
+
```
|
10
|
+
|
11
|
+
Then, `cd` to the folder you'd like to create your project under and run:
|
12
|
+
|
13
|
+
```bash
|
14
|
+
rbcli init -n mytool -d "A simple CLI tool"
|
15
|
+
```
|
16
|
+
|
17
|
+
Or, for a single-file tool without any folder/gem tructure, run `rbcli init -t mini -n <projectname>` or `rbcli init -t micro -n <projectname>`.
|
18
|
+
|
19
|
+
|
20
|
+
## Creating a command
|
21
|
+
|
22
|
+
There are three types of commands: standard, scripted, and external.
|
23
|
+
|
24
|
+
* __Standard__ commands let you code the command directly in Ruby
|
25
|
+
* __Scripted__ commands provide you with a bash script, where all of the parsed information (params, options, args, and config) is shared
|
26
|
+
* __External__ commands let you wrap 3rd party applications directly
|
27
|
+
|
28
|
+
### Standard Commands
|
29
|
+
|
30
|
+
To create a new command called `foo`, run:
|
31
|
+
|
32
|
+
```bash
|
33
|
+
rbcli command -n foo
|
34
|
+
```
|
35
|
+
|
36
|
+
You will now find the command code in `application/commands/list.rb`. Edit the `action` block to write your coode.
|
37
|
+
|
38
|
+
### Scripted Commands
|
39
|
+
|
40
|
+
To create a new scripted command called `bar`, run:
|
41
|
+
|
42
|
+
```bash
|
43
|
+
rbcli script -n bar
|
44
|
+
```
|
45
|
+
|
46
|
+
You will then find two new files:
|
47
|
+
|
48
|
+
* The command declaration under `application/commands/bar.rb`
|
49
|
+
* The script code under `application/commands/scripts/bar.sh`
|
50
|
+
|
51
|
+
Edit the script to write your code.
|
52
|
+
|
53
|
+
### External Commands
|
54
|
+
|
55
|
+
To create a new external command called `baz`, run:
|
56
|
+
|
57
|
+
```bash
|
58
|
+
rbcli extern -n baz
|
59
|
+
```
|
60
|
+
|
61
|
+
You will then find the command code in `application/commands/baz.rb`.
|
62
|
+
|
63
|
+
Use one of the two provided modes -- direct path mode or variable path mode -- to provide the path to the external program.
|
64
|
+
|
65
|
+
|
66
|
+
## Hooks
|
67
|
+
|
68
|
+
RBCli has several hooks that run at different points in the exectution chain. They can be created via the `rbcli` command line tool:
|
69
|
+
|
70
|
+
```bash
|
71
|
+
rbcli hook --default # Runs when no command is provided
|
72
|
+
rbcli hook --pre # Runs before any command
|
73
|
+
rbcli hook --post # Runs after any command
|
74
|
+
rbcli hook --firstrun # Runs the first time a user runs your application. Requires userspace config.
|
75
|
+
rbcli hook -dpof # Create all hooks at once
|
76
|
+
```
|
77
|
+
|
78
|
+
## Storage
|
79
|
+
|
80
|
+
RBCli supports both local and remote state storage. This is done by synchronizing a Hash with either the local disk or a remote database.
|
81
|
+
|
82
|
+
### Local State
|
83
|
+
|
84
|
+
RBCli can provide you with a unique hash that can be persisted to disk on any change to a top-level value.
|
85
|
+
|
86
|
+
Enable local state in `config/storage.rb`.
|
87
|
+
|
88
|
+
Then access it in your Standard Commands with `Rbcli.local_state[:yourkeyhere]`.
|
89
|
+
|
90
|
+
### Remote State
|
91
|
+
|
92
|
+
Similar to the Local State above, RBCli can provide you with a unique hash that can be persisted to a remote storage location.
|
93
|
+
|
94
|
+
Currently only AWS DynamoDB is supported, and credentials will be required for each user.
|
95
|
+
|
96
|
+
Enable remote state in `config/storage.rb`.
|
97
|
+
|
98
|
+
Then access it in your Standard Commands with `Rbcli.remote_state[:yourkeyhere]`.
|
99
|
+
|
100
|
+
|
101
|
+
## Userspace Configuration Files
|
102
|
+
|
103
|
+
RBCli provides an easy mechanism to generate and read configuration files from your users. You set the default values and help text with the __defaults chain__, and leverage the __user chain__ to read them.
|
104
|
+
|
105
|
+
You can set defaults either by placing a YAML file in the `userconf/` folder or by specifying individual options in `application/options.rb` (global) or `application/command/*.rb` (command-specific).
|
106
|
+
|
107
|
+
Users can generate a config file, complete with help text, by running your tool with the `--generate-config` option.
|
108
|
+
|
109
|
+
|
110
|
+
## Logging
|
111
|
+
|
112
|
+
RBCli's logger is configured in `config/logging.rb`.
|
113
|
+
|
114
|
+
```ruby
|
115
|
+
log_level :info
|
116
|
+
log_target 'stderr'
|
117
|
+
```
|
118
|
+
|
119
|
+
Then it can be accessed when writing your commands via:
|
120
|
+
|
121
|
+
```ruby
|
122
|
+
Rbcli::log.info { 'These logs can go to STDERR, STDOUT, or a file' }
|
123
|
+
```
|
124
|
+
|
125
|
+
The user will also be able to change the log level and target via their config file, if it is enabled.
|
126
|
+
|
127
|
+
|
128
|
+
## Automatic Update Check
|
129
|
+
|
130
|
+
RBCli can automatically notify users when an update is available. Two sources are currently supported: Github (including Enterprise) and RubyGems.
|
131
|
+
|
132
|
+
You can configure automatic updates in `config/autoupdate.rb` in your project.
|
133
|
+
|
134
|
+
|
135
|
+
## Development and Contributing
|
136
|
+
|
137
|
+
For more information about development and contributing, please see the [Official Development Documentation][documentation_development]
|
138
|
+
|
139
|
+
## License
|
140
|
+
|
141
|
+
The gem is available as open source under the terms of the [GPLv3](https://github.com/akhoury6/rbcli/blob/master/CODE_OF_CONDUCT.md).
|
142
|
+
|
143
|
+
## Full Documentation
|
144
|
+
|
145
|
+
[You can find the Official Documentation for RBCli Here.][documentation_home]
|
146
|
+
|
147
|
+
|
148
|
+
[documentation_home]: https://akhoury6.github.com/rbcli
|
149
|
+
[documentation_development]: https://akhoury6.github.com/rbcli/development/contributing/
|
150
|
+
[license_text]: https://github.com/akhoury6/rbcli/blob/master/LICENSE.txt
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# This is RBCli
|
2
|
+
|
3
|
+
|
4
|
+
As technologists today, we work with the command line a lot. We script a lot. We write tools to share with each other to make our lives easier. We even write applications to make up for missing features in the 3rd party software that we buy. Unfortunately, when writing CLI tools, this process has typically been very painful. We've been working with low-level frameworks for decades; frameworks like `getopt` (1980) and `curses` (1977). They fit their purpose well; they were both computationally lightweight for the computers of the day, and they gave engineers full control and flexibility when it came to how things were built. Over the years, we've used them to settle on several design patterns that we know work well. Patterns as to what a CLI command looks like, what a config file looks like, what remote execution looks like, and even how to use locks (mutexes, semaphores, etc) to control application flow and data atomicity. Yet we're stuck writing the same low-level code anytime we want to write our tooling. Not anymore.
|
5
|
+
|
6
|
+
Enter RBCli. RBCli is a framework to quickly develop advanced command-line tools in Ruby. It has been written from the ground up with the needs of the modern technologist in mind, designed to make advanced CLI tool development as painless as possible. In RBCli, low-level code has been wrapped and/or replaced with higher-level methods. Much of the functionality has even been reduced to single methods: for example, it takes just one declaration to define, load, and generate a user's config file at the appropriate times. Many other features are automated and require no work by the engineer. These make RBCli a fundamental re-thining of how we develop CLI tools, enabling the rapid development of applications for everyone from hobbyists to enterprises.
|
7
|
+
|
8
|
+
|
9
|
+
Some of its key features include:
|
10
|
+
|
11
|
+
* __Simple DSL Interface__: To cut down on the amount of code that needs to be written, RBCli has a DSL that is designed to cut to the chase. This makes the work a lot less tedious.
|
12
|
+
|
13
|
+
* __Multiple Levels of Parameters and Arguments__: Forget about writing parsers for command-line options, or about having to differentiate between parameters and arguments. All of that work is taken care of.
|
14
|
+
|
15
|
+
* __Config File Generation__: Easily piece together a default configuration even with declarations in different parts of the code. Then the user can generate their own configuration, and it gets stored in whatever location you'd like.
|
16
|
+
|
17
|
+
* __Multiple Hooks and Entry Points__: Define commands, pre-execution hooks, post-execution hooks, and first_run hooks to quickly and easily customize the flow of your application code.
|
18
|
+
|
19
|
+
* __Logging__: Keep track of all instances of your tool through logging. Logs can go to STDOUT, STDERR, or a given file, making them compatible with log aggregators such as Splunk, Logstash, and many others.
|
20
|
+
|
21
|
+
* __Local State Storage__: Easily manage a set of data that persists between runs. You get access to a hash that is automatically kept in-sync with a file on disk.
|
22
|
+
|
23
|
+
* __Remote State__: It works just like Local State Storage, but store the data on a remote server! It can be used in tandem with Local State Storage or on its own. Currently supports AWS DyanmoDB.
|
24
|
+
|
25
|
+
* __State Locking and Sharing__: Share remote state safely between users with built-in locking! When enabled, it makes sure that only one user is accessing the data at any given time.
|
26
|
+
|
27
|
+
* __Automatic Update Notifications__: Just provide the gem name or git repo, and RBCli will take care of notifying users!
|
28
|
+
|
29
|
+
* __External Script Wrapping__: High-level wrapping for Bash scripts, or any other applcication you'd like to wrap into a command.
|
30
|
+
|
31
|
+
* __Project Structure and Generators__: Create a well-defined project directory structure which organizes your code and allows you to package and distribute your application as a Gem. Generators can also help speed up the process of creating new commands, scripts, and hooks!
|
32
|
+
|
33
|
+
|
34
|
+
If you're just getting started with RBCli, take a look at the [Tutorial][tutorial]. Or take a look at the [Advanced] menu above to look through RBCli's additional featureset.
|
35
|
+
|
36
|
+
|
37
|
+
[tutorial]: ./tutorial/10-getting_started.md
|
38
|
+
[advanced]: ./advanced/user_config_files.md
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# Getting Started
|
2
|
+
|
3
|
+
Welcome to the RBCli getting started tutorial! In this tutorial we're going to cover the basics of RBCli and get a simple application up and running. It should take you between 30-60 minutes to complete, depending on your skill level with Ruby.
|
4
|
+
|
5
|
+
As you go throught the tutorial, you can either use the __Next__ and __Back__ buttons on the page to navigate, or use the menu directly.
|
6
|
+
|
7
|
+
## Supported Ruby Versions
|
8
|
+
|
9
|
+
You'll need Ruby installed before you can use RBCli. If you don't know how to install it, we recommend using either [rbenv][rbenv] (our favorite) or [rvm][rvm].
|
10
|
+
|
11
|
+
RBCli officially supports Ruby versions 2.5.0 and above. It may work on earlier releases even though we haven't tested them. If you do try it find any bugs that break compatibility, feel free to submit a github issue or pull request.
|
12
|
+
|
13
|
+
## Installation
|
14
|
+
|
15
|
+
RBCli is available on rubygems.org. You can add it to your application's `Gemfile` or `gemspec`, or install it manually by running:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
gem install rbcli
|
19
|
+
```
|
20
|
+
|
21
|
+
Then, `cd` to the folder you'd like to create your project under and run:
|
22
|
+
|
23
|
+
```bash
|
24
|
+
rbcli init -n mytool -d "A simple CLI tool"
|
25
|
+
```
|
26
|
+
|
27
|
+
where `mytool` can be replaced with any other command name you'd like. You should then see some output about generating a bunch of files. Once it finishes, run:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
cd mytool
|
31
|
+
ls -ahl
|
32
|
+
```
|
33
|
+
|
34
|
+
Congratulations! This is the beginning of your first project.
|
35
|
+
|
36
|
+
## Next Steps
|
37
|
+
|
38
|
+
Next, you will learn about the layout of an RBCli project and how to code with it.
|
39
|
+
|
40
|
+
[rbenv]: https://github.com/rbenv/rbenv
|
41
|
+
[rvm]: https://rvm.io
|
@@ -0,0 +1,115 @@
|
|
1
|
+
# The Project Layout
|
2
|
+
|
3
|
+
Now we will learn about what an RBCli project looks like and how to start using it.
|
4
|
+
|
5
|
+
## Project Initialization Types
|
6
|
+
|
7
|
+
RBCli can initialize a tool in three different modes:
|
8
|
+
|
9
|
+
- Project Mode (default)
|
10
|
+
- Mini Mode
|
11
|
+
- Micro Mode
|
12
|
+
|
13
|
+
### Project Mode
|
14
|
+
|
15
|
+
If you've been following along with the tutorial, you've already seen Project Mode. An RBCli Project consists of several folders, each of which has a specific function. The RBCli framework handles loading and parsing the code automatically. To generate a standard, full-featured RBCli project, run:
|
16
|
+
|
17
|
+
```bash
|
18
|
+
rbcli init -n mytool
|
19
|
+
```
|
20
|
+
|
21
|
+
where `mytool` can be replaced with any other command name you'd like. (We will continue using `mytool` in this tutorial though!)
|
22
|
+
|
23
|
+
Inside the newly created `mytool` folder you will see a bunch of files and folders related to your project. We will go over the structure later.
|
24
|
+
|
25
|
+
### Mini & Micro Modes
|
26
|
+
|
27
|
+
If you need to write a CLI tool but project mode feels a bit overkill for you -- if you think a single-file script is all that is needed -- that's where the Mini and Micro modes come in. Instead of generating a full directory tree, you get only a single file that contains most of the functionality of RBCli. To use it, run:
|
28
|
+
|
29
|
+
```bash
|
30
|
+
rbcli init -n mytool -t mini
|
31
|
+
# or
|
32
|
+
rbcli init -n mytool -t micro
|
33
|
+
```
|
34
|
+
|
35
|
+
The only difference between the two is that `mini` will show you all available options and some documentation to help you, while `micro` is for advanced users who just want the samllest file possible.
|
36
|
+
|
37
|
+
As far as documentation goes, every piece of code present in those files is identical to Project mode so it should be pretty easy to navigate.
|
38
|
+
|
39
|
+
## Project Mode Structure
|
40
|
+
|
41
|
+
An RBCli project has the following structure:
|
42
|
+
|
43
|
+
```text
|
44
|
+
<name>/
|
45
|
+
|--- application/
|
46
|
+
| |--- commands/
|
47
|
+
| | |--- scripts/
|
48
|
+
| |--- options.rb
|
49
|
+
|--- config/
|
50
|
+
|--- exe/
|
51
|
+
| |--- <name>
|
52
|
+
|--- hooks/
|
53
|
+
|--- lib/
|
54
|
+
|--- spec/
|
55
|
+
|--- userconf/
|
56
|
+
|--- .gitignore
|
57
|
+
|--- .rbcli
|
58
|
+
|--- .rspec
|
59
|
+
|--- CODE_OF_CONDUCT.md
|
60
|
+
|--- Gemfile
|
61
|
+
|--- README.md
|
62
|
+
|--- Rakefile
|
63
|
+
|--- <name>.gemspec
|
64
|
+
```
|
65
|
+
|
66
|
+
## Git, RubyGems, and rspec
|
67
|
+
|
68
|
+
A few files aren't part of RBCli itself, but are provided for your convenience. If you're experienced in Ruby and Git you can skip over this.
|
69
|
+
|
70
|
+
* `.gitignore`
|
71
|
+
* Specifies which files to ignore in git. If you don't use git you can delete this file
|
72
|
+
* `.rspec`
|
73
|
+
* Configures Rspec for testing your code
|
74
|
+
* `Gemfile`
|
75
|
+
* Allows declaring dependencies for when your users install your application
|
76
|
+
* `Gemspec`
|
77
|
+
* Same as above, but also lets you fill in more information so that you can publish your application as a gem
|
78
|
+
* `README.md`
|
79
|
+
* A skeleton README file that will appear as a front page documentation to your code in most source control systems (i.e. Github, Bitbucket)
|
80
|
+
* `CODE_OF_CONDUCT.md`
|
81
|
+
* Taken directly from the [contributor covenant][contributor_covenant] for your convenience
|
82
|
+
* `Rakefile`
|
83
|
+
* So you can run rspec tests as a rake task
|
84
|
+
|
85
|
+
There is a lot of controvesy online regarding using the `gemfile` vs the `gemspec`. If you are new to Ruby in general then I suggest declaring your dependencies in the gemspec and leaving the `gemfile` as-is. This keeps things simple and allows publishing and distributing your tool as a gem.
|
86
|
+
|
87
|
+
Additionally, note that a git repo is not created automatically. Using git is out of scope of this tutorial, but you can find tutorials [here][git_tutorials].
|
88
|
+
|
89
|
+
## RBCli Folders
|
90
|
+
|
91
|
+
* `application/`
|
92
|
+
* This is where the core of your application will live. You will define CLI options, commands, scripts, and hooks within this folder.
|
93
|
+
* `config/`
|
94
|
+
* This folder contains the configuration for RBCli's features; such as storage, logging, and automatic updates.
|
95
|
+
* `exe/`
|
96
|
+
* This folder contains the executable for your tool. You should not edit it; doing so may lead to unexpected behavior.
|
97
|
+
* `hooks/`
|
98
|
+
* RBCli has several hooks that can be used to run code at different times, such as the 'default' code that is run when no command is selected. This is where they are placed.
|
99
|
+
* `lib/`
|
100
|
+
* This folder is for you to write any additional code as you see fit, for importing into your commands, scripts, and hooks. It is automatically added to the $LOAD_PATH for you, so you can just use require statements like `require 'abc.rb'` without worrying about where they are located on the filesystem.
|
101
|
+
* `userconf/`
|
102
|
+
* This folder is for you to place the layout and defaults of any userspace config file. Acceptable formats are yaml and json, though we recommend YAML since it is by far easier to read and supports comments.
|
103
|
+
* `spec/`
|
104
|
+
* This folder is for your rspec tests.
|
105
|
+
* `.rbcli`
|
106
|
+
* This file is for internal use by RBCli. It should not be modified or deleted.
|
107
|
+
|
108
|
+
## Next Steps
|
109
|
+
|
110
|
+
For the purposes of getting started right now, you don't actually need to edit any of the defaults already present.
|
111
|
+
|
112
|
+
We just finished going through what an RBCli project looks like. Now let's create our first application with it!
|
113
|
+
|
114
|
+
[contributor_covenant]: http://contributor-covenant.org
|
115
|
+
[git_tutorials]: https://www.tutorialspoint.com/git/
|
@@ -0,0 +1,126 @@
|
|
1
|
+
# Your First Command
|
2
|
+
|
3
|
+
## Creating the Command
|
4
|
+
|
5
|
+
Creating the command is straightforward:
|
6
|
+
|
7
|
+
```bash
|
8
|
+
rbcli command --name=list
|
9
|
+
#or
|
10
|
+
rbcli command -n list
|
11
|
+
```
|
12
|
+
|
13
|
+
And there you have it! Now you can try out your command by typing:
|
14
|
+
|
15
|
+
```bash
|
16
|
+
./exe/mytool list
|
17
|
+
```
|
18
|
+
|
19
|
+
Congrats! You should now see a generic output listing the values of several variables. We'll get into what they mean in a bit, but first, let's make the tool's execution a bit easier.
|
20
|
+
|
21
|
+
|
22
|
+
Now that you know your way around a project, its time to create your first command! But before we do, let's make development just a little bit easier. Go to the base directory of the folder and type:
|
23
|
+
|
24
|
+
```bash
|
25
|
+
alias mytool="$(pwd)/exe/mytool"
|
26
|
+
```
|
27
|
+
|
28
|
+
And now you'll be able to execute your application as if it was already installed as a gem, without worrying about the working path. You can see this in action by running your application again, but without the path:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
mytool list
|
32
|
+
```
|
33
|
+
|
34
|
+
So, now let's take a more in-dpeth look at what the command code looks like.
|
35
|
+
|
36
|
+
## The Command Declaration
|
37
|
+
|
38
|
+
As mentioned in the previous section, you can find your commands listed under the `application/commands/` directory. Each command will appear as its own unique file with some base code to work from. Let's take a look at that code a little more in-depth:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
class List < Rbcli::Command # Declare a new command by subclassing Rbcli::Command
|
42
|
+
description 'TODO: Description goes here' # (Required) Short description for the global help
|
43
|
+
usage <<-EOF
|
44
|
+
TODO: Usage text goes here
|
45
|
+
EOF # (Required) Long description for the command-specific help
|
46
|
+
parameter :force, 'Force testing', type: :boolean, default: false, required: false # (Optional, Multiple) Add a command-specific CLI parameter. Can be called multiple times
|
47
|
+
|
48
|
+
config_default :myopt2, description: 'My Option #2', default: 'Default Value Here' # (Optional, Multiple) Specify an individual configuration parameter and set a default value. These will also be included in generated user config.
|
49
|
+
# Alternatively, you can simply create a yaml file in the `default_user_configs` directory in your project that specifies the default values of all options
|
50
|
+
|
51
|
+
action do |params, args, global_opts, config| # (Required) Block to execute if the command is called.
|
52
|
+
Rbcli::log.info { 'These logs can go to STDERR, STDOUT, or a file' } # Example log. Interface is identical to Ruby's logger
|
53
|
+
puts "\nArgs:\n#{args}" # Arguments that came after the command on the CLI (i.e.: `mytool test bar baz` will yield args=['bar', 'baz'])
|
54
|
+
puts "Params:\n#{params}" # Parameters, as described through the option statements above
|
55
|
+
puts "Global opts:\n#{global_opts}" # Global Parameters, as descirbed in the Configurate section
|
56
|
+
puts "Config:\n#{config}" # Config file values
|
57
|
+
puts "LocalState:\n#{Rbcli.local_state}" # Local persistent state storage (when available) -- if unsure use Rbcli.local_state.nil?
|
58
|
+
puts "RemoteState:\n#{Rbcli.remote_state}" # Remote persistent state storage (when available) -- if unsure use Rbcli.remote_state.nil?
|
59
|
+
puts "\nDone!!!"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
```
|
63
|
+
|
64
|
+
Commands are declared to RBCli simply by subclassing them from `Rbcli::Command` as shown above. Then, you have a list of declarations that tell RBCli information about it. They are:
|
65
|
+
|
66
|
+
* `description`
|
67
|
+
* A short description of the command, which will appear in the top-level help (when the user runs `mytool -h`).
|
68
|
+
* `usage`
|
69
|
+
* A description of how the command is meant to be used. This description can be as long as you want, and can be as in-depth as you'd like. It will show up as a long, multi-line description when the user runs the command-sepcific help (`mytool list -h`).
|
70
|
+
* `parameter`
|
71
|
+
* Command-line tags that the user can enter that are specific to only this command. We will get into these in the next section on [Options, Parameters, and Arguments][parameters_documentation]
|
72
|
+
* `config_default`
|
73
|
+
* This sets a single item in the config file that will be made available to the user. More information can be found in the documentation on [User Config Files][user_config_documentation]
|
74
|
+
* `action`
|
75
|
+
* This loads the block of code that will run when the command is called. It brings in all of the CLI and user config data as variables. We will also get into these in the next section [Options, Parameters, and Arguments][parameters_documentation]
|
76
|
+
|
77
|
+
There is an additional declaration not shown here, `extern`. You can find more information on it in the section on [Advanced Command Types][avanced_command_types_documentation]
|
78
|
+
|
79
|
+
|
80
|
+
## Creating the "list" Command
|
81
|
+
|
82
|
+
Now we're going to modify this command to list the contents of the current directory to the terminal. So let's change the code in that file to:
|
83
|
+
|
84
|
+
```ruby
|
85
|
+
class List < Rbcli::Command
|
86
|
+
description %q{List files in current directory}
|
87
|
+
usage <<-EOF
|
88
|
+
Ever wanted to see your files?
|
89
|
+
Now you can!
|
90
|
+
EOF
|
91
|
+
|
92
|
+
action do |params, args, global_opts, config|
|
93
|
+
filelist = []
|
94
|
+
|
95
|
+
# We store a list of the files in an array, including dotfiles if specified
|
96
|
+
Dir.glob "./*" do |filename|
|
97
|
+
outname = filename.split('/')[1]
|
98
|
+
outname += '/' if File.directory? filename
|
99
|
+
filelist.append outname
|
100
|
+
end
|
101
|
+
|
102
|
+
# Apply color
|
103
|
+
filelist.map! do |filename|
|
104
|
+
if File.directory? filename
|
105
|
+
filename.light_blue
|
106
|
+
elsif File.executable? filename
|
107
|
+
filename.light_green
|
108
|
+
else
|
109
|
+
filename
|
110
|
+
end
|
111
|
+
end if global_opts[:color]
|
112
|
+
|
113
|
+
puts filelist
|
114
|
+
end
|
115
|
+
end
|
116
|
+
```
|
117
|
+
|
118
|
+
Go ahead and test it out! The output doesn't show much obviously, just a list of names and nothing else. Don't worry though, we'll fix that in the next secion.
|
119
|
+
|
120
|
+
## Next Steps
|
121
|
+
|
122
|
+
Next we're going to take a look at options, parameters, and arguments, and we'll clean up our list command by using them. If you'd like to learn more about the additional command types in RBCli before continuing, see the [Advanced Command Types][avanced_command_types_documentation] documentation.
|
123
|
+
|
124
|
+
[parameters_documentation]: 40-options_parameters_and_arguments.md
|
125
|
+
[user_config_documentation]: ../advanced/user_config_files.md
|
126
|
+
[avanced_command_types_documentation]: ../advanced/command_types.md
|