bashly 0.3.8 → 0.4.2
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 +77 -18
- data/lib/bashly/commands/generate.rb +10 -3
- data/lib/bashly/commands/preview.rb +2 -1
- data/lib/bashly/models/base.rb +2 -1
- data/lib/bashly/models/command.rb +10 -0
- data/lib/bashly/models/flag.rb +4 -0
- data/lib/bashly/models/script.rb +33 -0
- data/lib/bashly/templates/lib/config.sh +15 -4
- data/lib/bashly/templates/strings.yml +4 -1
- data/lib/bashly/version.rb +1 -1
- data/lib/bashly/views/argument/usage.erb +3 -0
- data/lib/bashly/views/command/inspect_args.erb +7 -2
- data/lib/bashly/views/command/master_script.erb +0 -4
- data/lib/bashly/views/command/parse_requirements.erb +1 -0
- data/lib/bashly/views/command/run.erb +1 -6
- data/lib/bashly/views/command/whitelist_filter.erb +13 -0
- data/lib/bashly/views/flag/case.erb +4 -4
- data/lib/bashly/views/flag/usage.erb +3 -0
- data/lib/bashly/views/script/header.erb +3 -0
- data/lib/bashly/views/script/wrapper.erb +6 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4d486637f9d7ec6604d0495aec9f2396f69153f8cd193c126d51bc7dbc329a62
|
4
|
+
data.tar.gz: 5c58b05ad9ccb84d432c42228b7594e678b033555e55ea275948d4e70be118c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 02fd6e6c50c5d370dde3d50047b0b6d317454c3d48531222711c6341c6e93d263cafa6a7d541bb939ff44a36b6025c9c8411e8f3820157c41e476312f4c64781
|
7
|
+
data.tar.gz: 031ea1db4c68fb6b780f01862b216178804cdc44f2e86fc66bc11f2910fff6d03ed250d7a01dd1c566d74c8f002ae6e9441bb13292f3e74620db455c993029e2
|
data/README.md
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
<div align='center'>
|
2
2
|
<img src='logo.svg' width=280>
|
3
3
|
|
4
|
-
Bashly - Bash CLI Framework and Generator
|
5
|
-
==================================================
|
4
|
+
# Bashly - Bash CLI Framework and Generator
|
6
5
|
|
7
6
|
Create beautiful bash scripts from simple YAML configuration
|
8
7
|
|
@@ -16,25 +15,46 @@ Create beautiful bash scripts from simple YAML configuration
|
|
16
15
|
|
17
16
|
</div>
|
18
17
|
|
18
|
+
## Table of Contents
|
19
|
+
|
20
|
+
- [Table of Contents](#table-of-contents)
|
21
|
+
- [Installation](#installation)
|
22
|
+
- [Prerequisites](#prerequisites)
|
23
|
+
- [What is Bashly](#what-is-bashly)
|
24
|
+
- [Usage](#usage)
|
25
|
+
- [Using the input arguemnts in your code](#using-the-input-arguemnts-in-your-code)
|
26
|
+
- [Examples](#examples)
|
27
|
+
- [Sample configuraiton for a script without commands](#sample-configuraiton-for-a-script-without-commands)
|
28
|
+
- [Sample configuraiton for a script with commands](#sample-configuraiton-for-a-script-with-commands)
|
29
|
+
- [Configuration Reference](#configuration-reference)
|
30
|
+
- [Command options](#command-options)
|
31
|
+
- [Argument options](#argument-options)
|
32
|
+
- [Flag options](#flag-options)
|
33
|
+
- [Environment Variable options](#environment-variable-options)
|
34
|
+
- [Real World Examples](#real-world-examples)
|
35
|
+
- [Contributing / Support](#contributing--support)
|
36
|
+
|
19
37
|
---
|
20
38
|
|
21
|
-
Installation
|
22
|
-
--------------------------------------------------
|
39
|
+
## Installation
|
23
40
|
|
24
41
|
```shell
|
25
42
|
$ gem install bashly
|
26
43
|
```
|
27
44
|
|
45
|
+
or with Docker:
|
28
46
|
|
29
|
-
|
30
|
-
|
47
|
+
```shell
|
48
|
+
$ alias bashly='docker run --rm -it --volume "$PWD:/app" dannyben/bashly'
|
49
|
+
```
|
50
|
+
|
51
|
+
## Prerequisites
|
31
52
|
|
32
53
|
The bash scripts generated by bashly require bash 4 or higher due to heavy
|
33
54
|
use of associative arrays.
|
34
55
|
|
35
56
|
|
36
|
-
What is Bashly
|
37
|
-
--------------------------------------------------
|
57
|
+
## What is Bashly
|
38
58
|
|
39
59
|
Bashly is a command line application (written in Ruby) that lets you generate
|
40
60
|
feature-rich bash command line tools.
|
@@ -61,9 +81,9 @@ Bahsly is responsible for:
|
|
61
81
|
- **Color output**.
|
62
82
|
- **Config file management** (INI format).
|
63
83
|
- **YAML parsing**.
|
84
|
+
- and more.
|
64
85
|
|
65
|
-
Usage
|
66
|
-
--------------------------------------------------
|
86
|
+
## Usage
|
67
87
|
|
68
88
|
In an empty directory, create a sample configuration file by running
|
69
89
|
|
@@ -93,9 +113,46 @@ Finally, edit the files in the `src` folder. Each of your script's commands
|
|
93
113
|
get their own file. Once you edit, run `bashly generate` again to merge the
|
94
114
|
content from your functions back into the script.
|
95
115
|
|
116
|
+
### Using the input arguemnts in your code
|
117
|
+
|
118
|
+
In order to access the parsed arguments in any of your partial scripts, you
|
119
|
+
may simply access the `$args` associative array.
|
120
|
+
|
121
|
+
For example:
|
122
|
+
|
123
|
+
1. Generate a minimal configuration with `bashly init --minimal`
|
124
|
+
2. Generate the bash script with `bashly generate`
|
125
|
+
3. Run the script with `./download hello --force`
|
126
|
+
|
127
|
+
You will notice that all the arguments of the associative array are printed
|
128
|
+
on screen. This is done by the `inspect_args` function that was inserted into
|
129
|
+
the generated partial script `src/root_command.sh`.
|
130
|
+
|
131
|
+
You can now access these variables by modifying `sec/root_command.sh` like
|
132
|
+
this:
|
96
133
|
|
97
|
-
|
98
|
-
|
134
|
+
|
135
|
+
```bash
|
136
|
+
# src/root_command.sh
|
137
|
+
source_url=${args[source]}
|
138
|
+
force=${args[--force]}
|
139
|
+
|
140
|
+
if [[ $force ]]; then
|
141
|
+
echo "downloading $source_url with --force"
|
142
|
+
else
|
143
|
+
echo "downloading $source_url"
|
144
|
+
fi
|
145
|
+
```
|
146
|
+
|
147
|
+
After editing the file, run `bashly generate` (or `bashly g` for short) and
|
148
|
+
run:
|
149
|
+
|
150
|
+
```
|
151
|
+
$ ./download a --force
|
152
|
+
downloading a with --force
|
153
|
+
```
|
154
|
+
|
155
|
+
## Examples
|
99
156
|
|
100
157
|
The `bashly.yml` file can be set up to generate two types of scripts:
|
101
158
|
|
@@ -123,8 +180,7 @@ See the [examples](examples) folder for more examples.
|
|
123
180
|
|
124
181
|
|
125
182
|
|
126
|
-
Configuration Reference
|
127
|
-
--------------------------------------------------
|
183
|
+
## Configuration Reference
|
128
184
|
|
129
185
|
The `bashly.yml` configuration file consists of these types:
|
130
186
|
|
@@ -167,6 +223,7 @@ bash function.
|
|
167
223
|
`help` | The message to display when using `--help`. Can have multiple lines.
|
168
224
|
`required` | Specify if this argument is required. Note that once you define an optional argument (without required: true) then you cannot define required arguments after it.
|
169
225
|
`default` | The value to use in case it is not provided by the user. Implies that this argument is optional.
|
226
|
+
`allowed` | Limit the allowed values by providing an array.
|
170
227
|
|
171
228
|
### Flag options
|
172
229
|
|
@@ -182,6 +239,7 @@ short form).
|
|
182
239
|
`arg` | If the flag requires an argument, specify its name here.
|
183
240
|
`required` | Specify if this flag is required.
|
184
241
|
`default` | The value to use in case it is not provided by the user. Implies that this flag is optional, and only makes sense when the flag has an argument.
|
242
|
+
`allowed` | For flags with an argument, you can limit the allowed values by providing an array.
|
185
243
|
|
186
244
|
#### Special handling for -v and -h
|
187
245
|
|
@@ -204,15 +262,14 @@ set.
|
|
204
262
|
`required` | Specify if this variable is required.
|
205
263
|
|
206
264
|
|
207
|
-
Real World Examples
|
208
|
-
--------------------------------------------------
|
265
|
+
## Real World Examples
|
209
266
|
|
210
267
|
- [Rush][rush] - a Personal Package Manager
|
211
268
|
- [Alf][alf] - a generator for bash aliases and sub-aliases
|
269
|
+
- [git-changelog][git-changelog] - a change log generator
|
212
270
|
|
213
271
|
|
214
|
-
Contributing / Support
|
215
|
-
--------------------------------------------------
|
272
|
+
## Contributing / Support
|
216
273
|
|
217
274
|
If you experience any issue, have a question or a suggestion, or if you wish
|
218
275
|
to contribute, feel free to [open an issue][issues].
|
@@ -220,4 +277,6 @@ to contribute, feel free to [open an issue][issues].
|
|
220
277
|
[issues]: https://github.com/DannyBen/bashly/issues
|
221
278
|
[rush]: https://github.com/DannyBen/rush-cli
|
222
279
|
[alf]: https://github.com/DannyBen/alf
|
280
|
+
[git-changelog]: https://github.com/DannyBen/git-changelog
|
281
|
+
|
223
282
|
|
@@ -3,14 +3,18 @@ module Bashly
|
|
3
3
|
class Generate < Base
|
4
4
|
help "Generate the bash script and required files"
|
5
5
|
|
6
|
-
usage "bashly generate [--force]"
|
6
|
+
usage "bashly generate [--force --wrap FUNCTION]"
|
7
7
|
usage "bashly generate (-h|--help)"
|
8
8
|
|
9
9
|
option "-f --force", "Overwrite existing files"
|
10
|
+
option "-w --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
|
10
11
|
|
11
12
|
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
|
12
13
|
environment "BASHLY_TARGET_DIR", "The path to use for creating the bash script [default: .]"
|
13
14
|
|
15
|
+
example "bashly generate --force"
|
16
|
+
example "bashly generate --wrap my_function"
|
17
|
+
|
14
18
|
def run
|
15
19
|
create_user_files
|
16
20
|
create_master_script
|
@@ -54,12 +58,15 @@ module Bashly
|
|
54
58
|
end
|
55
59
|
|
56
60
|
def create_master_script
|
57
|
-
|
58
|
-
File.write master_script_path, master_script
|
61
|
+
File.write master_script_path, script.code
|
59
62
|
FileUtils.chmod "+x", master_script_path
|
60
63
|
say "created !txtgrn!#{master_script_path}"
|
61
64
|
end
|
62
65
|
|
66
|
+
def script
|
67
|
+
@script ||= Models::Script.new(command, args['--wrap'])
|
68
|
+
end
|
69
|
+
|
63
70
|
def master_script_path
|
64
71
|
"#{Settings.target_dir}/#{command.name}"
|
65
72
|
end
|
data/lib/bashly/models/base.rb
CHANGED
@@ -175,6 +175,16 @@ module Bashly
|
|
175
175
|
verify_commands if commands.any?
|
176
176
|
end
|
177
177
|
|
178
|
+
# Returns an array of all the args with a whitelist
|
179
|
+
def whitelisted_args
|
180
|
+
args.select &:allowed
|
181
|
+
end
|
182
|
+
|
183
|
+
# Returns an array of all the flags with a whitelist arg
|
184
|
+
def whitelisted_flags
|
185
|
+
flags.select &:allowed
|
186
|
+
end
|
187
|
+
|
178
188
|
private
|
179
189
|
|
180
190
|
def verify_commands
|
data/lib/bashly/models/flag.rb
CHANGED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Bashly
|
2
|
+
module Models
|
3
|
+
class Script
|
4
|
+
include Renderable
|
5
|
+
|
6
|
+
attr_reader :command, :function_name
|
7
|
+
|
8
|
+
def initialize(command, function_name = nil)
|
9
|
+
@command, @function_name = command, function_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def code
|
13
|
+
if function_name
|
14
|
+
result = [header, render('wrapper')].join "\n"
|
15
|
+
else
|
16
|
+
result = [header, body].join "\n"
|
17
|
+
end
|
18
|
+
|
19
|
+
result.lint
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def header
|
25
|
+
@header ||= render('header')
|
26
|
+
end
|
27
|
+
|
28
|
+
def body
|
29
|
+
@body ||= command.render('master_script')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -21,7 +21,7 @@ config_init() {
|
|
21
21
|
# Usage: result=$(config_get hello)
|
22
22
|
config_get() {
|
23
23
|
key=$1
|
24
|
-
regex="^$key
|
24
|
+
regex="^$key *= *(.+)$"
|
25
25
|
|
26
26
|
config_init
|
27
27
|
|
@@ -44,7 +44,7 @@ config_set() {
|
|
44
44
|
|
45
45
|
config_init
|
46
46
|
|
47
|
-
regex="^($key)
|
47
|
+
regex="^($key) *= *.+$"
|
48
48
|
output=""
|
49
49
|
found_key=""
|
50
50
|
|
@@ -71,7 +71,7 @@ config_set() {
|
|
71
71
|
config_del() {
|
72
72
|
key=$1
|
73
73
|
|
74
|
-
regex="^($key)
|
74
|
+
regex="^($key) *="
|
75
75
|
output=""
|
76
76
|
|
77
77
|
config_init
|
@@ -100,7 +100,7 @@ config_show() {
|
|
100
100
|
# done
|
101
101
|
#
|
102
102
|
config_keys() {
|
103
|
-
regex="^(
|
103
|
+
regex="^([a-zA-Z0-9_\-\/\.]+) *="
|
104
104
|
|
105
105
|
config_init
|
106
106
|
|
@@ -113,3 +113,14 @@ config_keys() {
|
|
113
113
|
done < "$CONFIG_FILE"
|
114
114
|
echo "${keys[@]}"
|
115
115
|
}
|
116
|
+
|
117
|
+
# Returns true if the specified key exists in the config file
|
118
|
+
# Usage:
|
119
|
+
#
|
120
|
+
# if config_has_key "key" ; then
|
121
|
+
# echo "key exists"
|
122
|
+
# fi
|
123
|
+
#
|
124
|
+
config_has_key() {
|
125
|
+
[[ $(config_get "$1") ]]
|
126
|
+
}
|
@@ -15,16 +15,19 @@ command_shortcut: "Shortcut: %{short}"
|
|
15
15
|
default_command_summary: "%{summary} (default)"
|
16
16
|
required: "(required)"
|
17
17
|
default: "Default: %{value}"
|
18
|
+
allowed: "Allowed: %{values}"
|
18
19
|
|
19
20
|
# Fixed flags help text
|
20
21
|
help_flag_text: Show this help
|
21
22
|
version_flag_text: Show version number
|
22
23
|
|
23
24
|
# Error messages
|
24
|
-
flag_requires_an_argument: "%{
|
25
|
+
flag_requires_an_argument: "%{name} requires an argument: %{usage}"
|
25
26
|
invalid_argument: "invalid argument: %s"
|
26
27
|
invalid_flag: "invalid option: %s"
|
27
28
|
missing_required_argument: "missing required argument: %{arg}\\nusage: %{usage}"
|
28
29
|
missing_required_flag: "missing required flag: %{usage}"
|
29
30
|
missing_required_environment_variable: "missing required environment variable: %{var}"
|
30
31
|
missing_dependency: "missing dependency: %{dependency}"
|
32
|
+
disallowed_flag: "%{name} must be one of: %{allowed}"
|
33
|
+
disallowed_argument: "%{name} must be one of: %{allowed}"
|
data/lib/bashly/version.rb
CHANGED
@@ -1,6 +1,9 @@
|
|
1
1
|
# :argument.usage
|
2
2
|
echo " <%= name.upcase %>"
|
3
3
|
printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
|
4
|
+
<%- if allowed -%>
|
5
|
+
printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
|
6
|
+
<%- end -%>
|
4
7
|
<%- if default -%>
|
5
8
|
printf " <%= strings[:default] % { value: default } -%>\n"
|
6
9
|
<%- end -%>
|
@@ -1,5 +1,10 @@
|
|
1
1
|
# :command.inspect_args
|
2
2
|
inspect_args() {
|
3
|
-
|
4
|
-
|
3
|
+
readarray -t sorted_keys < <(printf '%s\n' "${!args[@]}" | sort)
|
4
|
+
if (( ${#args[@]} )); then
|
5
|
+
echo args:
|
6
|
+
for k in "${sorted_keys[@]}"; do echo "- \${args[$k]} = ${args[$k]}"; done
|
7
|
+
else
|
8
|
+
echo args: none
|
9
|
+
fi
|
5
10
|
}
|
@@ -12,6 +12,7 @@ parse_requirements() {
|
|
12
12
|
<%= render(:required_flags_filter).indent 2 %>
|
13
13
|
<%= render(:parse_requirements_while).indent 2 %>
|
14
14
|
<%= render(:default_assignments).indent 2 %>
|
15
|
+
<%= render(:whitelist_filter).indent 2 %>
|
15
16
|
}
|
16
17
|
|
17
18
|
<%- commands.each do |command| %>
|
@@ -14,12 +14,7 @@ run() {
|
|
14
14
|
fi
|
15
15
|
<% condition = "elif" %>
|
16
16
|
<%- end -%>
|
17
|
-
<%= condition %> [[ $
|
18
|
-
version_command
|
19
|
-
elif [[ ${args[--help]} ]]; then
|
20
|
-
long_usage=yes
|
21
|
-
<%= name %>_usage
|
22
|
-
elif [[ $action == "root" ]]; then
|
17
|
+
<%= condition %> [[ $action == "root" ]]; then
|
23
18
|
root_command
|
24
19
|
fi
|
25
20
|
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# :command.whitelist_filter
|
2
|
+
<%- whitelisted_args.each do |arg| -%>
|
3
|
+
if [[ ! ${args[<%= arg.name %>]} =~ ^(<%= arg.allowed.join '|' %>)$ ]]; then
|
4
|
+
printf "%s\n" "<%= strings[:disallowed_argument] % { name: arg.name, allowed: arg.allowed.join(', ') } %>"
|
5
|
+
exit 1
|
6
|
+
fi
|
7
|
+
<%- end -%>
|
8
|
+
<%- whitelisted_flags.each do |flag| -%>
|
9
|
+
if [[ ! ${args[<%= flag.name %>]} =~ ^(<%= flag.allowed.join '|' %>)$ ]]; then
|
10
|
+
printf "%s\n" "<%= strings[:disallowed_flag] % { name: flag.name, allowed: flag.allowed.join(', ') } %>"
|
11
|
+
exit 1
|
12
|
+
fi
|
13
|
+
<%- end -%>
|
@@ -1,16 +1,16 @@
|
|
1
1
|
# :flag.case
|
2
2
|
<%= aliases.join " | " %> )
|
3
3
|
<%- if arg -%>
|
4
|
-
if [[ $2
|
5
|
-
args[<%=
|
4
|
+
if [[ $2 ]]; then
|
5
|
+
args[<%= name %>]="$2"
|
6
6
|
shift
|
7
7
|
shift
|
8
8
|
else
|
9
|
-
printf "%s\n" "<%= strings[:flag_requires_an_argument] % {
|
9
|
+
printf "%s\n" "<%= strings[:flag_requires_an_argument] % { name: name, usage: usage_string } %>"
|
10
10
|
exit 1
|
11
11
|
fi
|
12
12
|
<%- else -%>
|
13
|
-
args[<%=
|
13
|
+
args[<%= name %>]=1
|
14
14
|
shift
|
15
15
|
<%- end -%>
|
16
16
|
;;
|
@@ -1,6 +1,9 @@
|
|
1
1
|
# :flag.usage
|
2
2
|
echo " <%= usage_string extended: true %>"
|
3
3
|
printf "<%= help.wrap(76).indent(4).sanitize_for_print %>\n"
|
4
|
+
<%- if allowed -%>
|
5
|
+
printf " <%= strings[:allowed] % { values: allowed.join(', ') } -%>\n"
|
6
|
+
<%- end -%>
|
4
7
|
<%- if default -%>
|
5
8
|
printf " <%= strings[:default] % { value: default } -%>\n"
|
6
9
|
<%- end -%>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bashly
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Danny Ben Shitrit
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-03-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colsole
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- lib/bashly/models/command.rb
|
81
81
|
- lib/bashly/models/environment_variable.rb
|
82
82
|
- lib/bashly/models/flag.rb
|
83
|
+
- lib/bashly/models/script.rb
|
83
84
|
- lib/bashly/polyfills/hash.rb
|
84
85
|
- lib/bashly/settings.rb
|
85
86
|
- lib/bashly/templates/bashly.yml
|
@@ -120,9 +121,12 @@ files:
|
|
120
121
|
- lib/bashly/views/command/usage_flags.erb
|
121
122
|
- lib/bashly/views/command/user_lib.erb
|
122
123
|
- lib/bashly/views/command/version_command.erb
|
124
|
+
- lib/bashly/views/command/whitelist_filter.erb
|
123
125
|
- lib/bashly/views/environment_variable/usage.erb
|
124
126
|
- lib/bashly/views/flag/case.erb
|
125
127
|
- lib/bashly/views/flag/usage.erb
|
128
|
+
- lib/bashly/views/script/header.erb
|
129
|
+
- lib/bashly/views/script/wrapper.erb
|
126
130
|
homepage: https://github.com/dannyben/bashly
|
127
131
|
licenses:
|
128
132
|
- MIT
|
@@ -142,7 +146,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
146
|
- !ruby/object:Gem::Version
|
143
147
|
version: '0'
|
144
148
|
requirements: []
|
145
|
-
rubygems_version: 3.
|
149
|
+
rubygems_version: 3.2.3
|
146
150
|
signing_key:
|
147
151
|
specification_version: 4
|
148
152
|
summary: Bash Command Line Tool Generator
|