bashly 0.6.5 → 0.6.9
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 +4 -2
- data/lib/bashly/commands/add.rb +18 -6
- data/lib/bashly/commands/generate.rb +11 -6
- data/lib/bashly/concerns/completions.rb +5 -1
- data/lib/bashly/extensions/string.rb +1 -1
- data/lib/bashly/models/base.rb +1 -0
- data/lib/bashly/models/command.rb +2 -2
- data/lib/bashly/models/script.rb +19 -1
- data/lib/bashly/templates/lib/colors.sh +34 -21
- data/lib/bashly/templates/lib/config.sh +16 -13
- data/lib/bashly/templates/lib/validations/validate_dir_exists.sh +3 -0
- data/lib/bashly/templates/lib/validations/validate_file_exists.sh +3 -0
- data/lib/bashly/templates/lib/validations/validate_integer.sh +3 -0
- data/lib/bashly/templates/lib/validations/validate_not_empty.sh +3 -0
- data/lib/bashly/templates/strings.yml +1 -0
- data/lib/bashly/version.rb +1 -1
- data/lib/bashly/views/argument/validations.erb +8 -0
- data/lib/bashly/views/command/initialize.erb +0 -5
- data/lib/bashly/views/command/master_script.erb +1 -0
- data/lib/bashly/views/command/normalize_input.erb +24 -0
- data/lib/bashly/views/command/parse_requirements_case.erb +2 -1
- data/lib/bashly/views/command/required_args_filter.erb +2 -1
- data/lib/bashly/views/command/run.erb +3 -1
- data/lib/bashly/views/flag/case.erb +2 -1
- data/lib/bashly/views/flag/validations.erb +8 -0
- data/lib/bashly/views/script/bash3_bouncer.erb +5 -0
- data/lib/bashly/views/script/header.erb +1 -0
- metadata +10 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c76c3000789b54fa2d9be8f7a61d93556e6a8665f4ea7769588797a25fa78f49
|
4
|
+
data.tar.gz: a5a0eae36b00cf879082836211f2aa21b38b280993e2dccfc907f3e6fcb99104
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae77cd9b8fa000d9e12f2948fb5c41bd02e34bd6bdcdd91f3a3a627778f66c9472e956e92fb65b502fa78fe2e77ba6c4dfb12c1f35abed36f1012ce502b7cab9
|
7
|
+
data.tar.gz: 5e14659441abf6b11ca53a5d0d656e5097519acc7a2e842f3cdfb6374fd52a0403c6ddeacf4f193da1ab18687de909b074e4d581ce4700c9fc28e2b589ef961d
|
data/README.md
CHANGED
@@ -40,7 +40,7 @@ a [docker image](https://hub.docker.com/r/dannyben/bashly).
|
|
40
40
|
file for you ([example](https://github.com/DannyBen/bashly/tree/master/examples/minimal#bashlyyml)).
|
41
41
|
2. Bashly then automatically generates a bash script (when you run
|
42
42
|
`bashly generate`) that can parse and validate user input, provide help
|
43
|
-
messages, and run your code for each command
|
43
|
+
messages, and run your code for each command.
|
44
44
|
3. Your code for each command is kept in a separate file, and can be merged
|
45
45
|
again if you change it ([example](https://github.com/DannyBen/bashly/blob/master/examples/minimal/src/root_command.sh)).
|
46
46
|
|
@@ -67,11 +67,13 @@ Bashly is responsible for:
|
|
67
67
|
## Contributing / Support
|
68
68
|
|
69
69
|
If you experience any issue, have a question or a suggestion, or if you wish
|
70
|
-
to contribute, feel free to [open an issue][issues]
|
70
|
+
to contribute, feel free to [open an issue][issues] or
|
71
|
+
[start a discussion][discussions].
|
71
72
|
|
72
73
|
|
73
74
|
|
74
75
|
[issues]: https://github.com/DannyBen/bashly/issues
|
76
|
+
[discussions]: https://github.com/DannyBen/bashly/discussions
|
75
77
|
[docs]: https://bashly.dannyb.co/
|
76
78
|
[examples]: https://github.com/DannyBen/bashly/tree/master/examples#bashly-examples
|
77
79
|
|
data/lib/bashly/commands/add.rb
CHANGED
@@ -8,6 +8,7 @@ module Bashly
|
|
8
8
|
usage "bashly add config [--force]"
|
9
9
|
usage "bashly add colors [--force]"
|
10
10
|
usage "bashly add yaml [--force]"
|
11
|
+
usage "bashly add validations [--force]"
|
11
12
|
usage "bashly add comp FORMAT [OUTPUT]"
|
12
13
|
usage "bashly add (-h|--help)"
|
13
14
|
|
@@ -21,6 +22,7 @@ module Bashly
|
|
21
22
|
command "config", "Add standard functions for handling INI files to the lib directory."
|
22
23
|
command "colors", "Add standard functions for printing colorful and formatted text to the lib directory."
|
23
24
|
command "yaml", "Add standard functions for reading YAML files to the lib directory."
|
25
|
+
command "validations", "Add argument validation functions to the lib directory."
|
24
26
|
command "comp", "Generate a bash completions script or function."
|
25
27
|
|
26
28
|
example "bashly add strings --force"
|
@@ -34,19 +36,23 @@ module Bashly
|
|
34
36
|
end
|
35
37
|
|
36
38
|
def lib_command
|
37
|
-
|
39
|
+
safe_copy_file "sample_function.sh"
|
38
40
|
end
|
39
41
|
|
40
42
|
def config_command
|
41
|
-
|
43
|
+
safe_copy_file "config.sh"
|
42
44
|
end
|
43
45
|
|
44
46
|
def colors_command
|
45
|
-
|
47
|
+
safe_copy_file "colors.sh"
|
46
48
|
end
|
47
49
|
|
48
50
|
def yaml_command
|
49
|
-
|
51
|
+
safe_copy_file "yaml.sh"
|
52
|
+
end
|
53
|
+
|
54
|
+
def validations_command
|
55
|
+
safe_copy_dir "validations"
|
50
56
|
end
|
51
57
|
|
52
58
|
def comp_command
|
@@ -68,8 +74,14 @@ module Bashly
|
|
68
74
|
|
69
75
|
private
|
70
76
|
|
71
|
-
def
|
72
|
-
|
77
|
+
def safe_copy_dir(dir)
|
78
|
+
Dir[asset("templates/lib/#{dir}/*.sh")].sort.each do |file|
|
79
|
+
safe_copy_file "#{dir}/#{File.basename file}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def safe_copy_file(file)
|
84
|
+
safe_copy asset("templates/lib/#{file}"), "#{Settings.source_dir}/lib/#{file}"
|
73
85
|
end
|
74
86
|
|
75
87
|
def safe_copy(source, target)
|
@@ -3,11 +3,12 @@ module Bashly
|
|
3
3
|
class Generate < Base
|
4
4
|
help "Generate the bash script and required files"
|
5
5
|
|
6
|
-
usage "bashly generate [--force --wrap FUNCTION]"
|
6
|
+
usage "bashly generate [--force --quiet --wrap FUNCTION]"
|
7
7
|
usage "bashly generate (-h|--help)"
|
8
8
|
|
9
9
|
option "-f --force", "Overwrite existing files"
|
10
10
|
option "-w --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
|
11
|
+
option "-q --quiet", "Disable on-screen progress report"
|
11
12
|
|
12
13
|
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
|
13
14
|
environment "BASHLY_TARGET_DIR", "The path to use for creating the bash script [default: .]"
|
@@ -18,13 +19,17 @@ module Bashly
|
|
18
19
|
def run
|
19
20
|
create_user_files
|
20
21
|
create_master_script
|
21
|
-
|
22
|
+
quiet_say "run !txtpur!#{master_script_path} --help!txtrst! to test your bash script"
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
25
26
|
|
27
|
+
def quiet_say(message)
|
28
|
+
say message unless args['--quiet']
|
29
|
+
end
|
30
|
+
|
26
31
|
def create_user_files
|
27
|
-
|
32
|
+
quiet_say "creating user files in !txtgrn!#{Settings.source_dir}"
|
28
33
|
|
29
34
|
create_file "#{Settings.source_dir}/initialize.sh", command.render(:default_initialize_script)
|
30
35
|
|
@@ -50,17 +55,17 @@ module Bashly
|
|
50
55
|
|
51
56
|
def create_file(file, content)
|
52
57
|
if File.exist? file and !args['--force']
|
53
|
-
|
58
|
+
quiet_say "skipped !txtgrn!#{file}!txtrst! (exists)"
|
54
59
|
else
|
55
60
|
File.write file, content
|
56
|
-
|
61
|
+
quiet_say "created !txtgrn!#{file}"
|
57
62
|
end
|
58
63
|
end
|
59
64
|
|
60
65
|
def create_master_script
|
61
66
|
File.write master_script_path, script.code
|
62
67
|
FileUtils.chmod "+x", master_script_path
|
63
|
-
|
68
|
+
quiet_say "created !txtgrn!#{master_script_path}"
|
64
69
|
end
|
65
70
|
|
66
71
|
def script
|
@@ -31,12 +31,16 @@ module Bashly
|
|
31
31
|
flags.map(&:name) + flags.map(&:short)
|
32
32
|
end
|
33
33
|
|
34
|
+
def completion_allowed_args
|
35
|
+
flags.map(&:allowed).flatten + args.map(&:allowed).flatten
|
36
|
+
end
|
37
|
+
|
34
38
|
def completion_words(with_version: false)
|
35
39
|
trivial_flags = %w[--help -h]
|
36
40
|
trivial_flags += %w[--version -v] if with_version
|
37
41
|
all = (
|
38
42
|
command_names + trivial_flags +
|
39
|
-
completion_flag_names
|
43
|
+
completion_flag_names + completion_allowed_args
|
40
44
|
)
|
41
45
|
|
42
46
|
all += completions if completions
|
data/lib/bashly/models/base.rb
CHANGED
@@ -209,7 +209,7 @@ module Bashly
|
|
209
209
|
# This is meant to provide the user with the ability to add custom
|
210
210
|
# functions
|
211
211
|
def user_lib
|
212
|
-
@user_lib ||= Dir["#{Settings.source_dir}/lib/**/*.sh"]
|
212
|
+
@user_lib ||= Dir["#{Settings.source_dir}/lib/**/*.sh"].sort
|
213
213
|
end
|
214
214
|
|
215
215
|
# Raise an exception if there are some serious issues with the command
|
@@ -238,4 +238,4 @@ module Bashly
|
|
238
238
|
|
239
239
|
end
|
240
240
|
end
|
241
|
-
end
|
241
|
+
end
|
data/lib/bashly/models/script.rb
CHANGED
@@ -22,12 +22,30 @@ module Bashly
|
|
22
22
|
private
|
23
23
|
|
24
24
|
def header
|
25
|
-
@header ||=
|
25
|
+
@header ||= header!
|
26
|
+
end
|
27
|
+
|
28
|
+
def header!
|
29
|
+
if File.exist? custom_header_path
|
30
|
+
File.read custom_header_path
|
31
|
+
else
|
32
|
+
default_header
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def default_header
|
37
|
+
result = render('header')
|
38
|
+
result += render('bash3_bouncer') unless function_name
|
39
|
+
result
|
26
40
|
end
|
27
41
|
|
28
42
|
def body
|
29
43
|
@body ||= command.render('master_script')
|
30
44
|
end
|
45
|
+
|
46
|
+
def custom_header_path
|
47
|
+
@custom_header_path ||= "#{Settings.source_dir}/header.sh"
|
48
|
+
end
|
31
49
|
end
|
32
50
|
end
|
33
51
|
end
|
@@ -4,29 +4,42 @@
|
|
4
4
|
#
|
5
5
|
# Usage:
|
6
6
|
# Use any of the functions below to color or format a portion of a string.
|
7
|
-
#
|
7
|
+
#
|
8
8
|
# echo "before $(red this is red) after"
|
9
9
|
# echo "before $(green_bold this is green_bold) after"
|
10
10
|
#
|
11
|
+
# Color output will be disabled if `NO_COLOR` environment variable is set
|
12
|
+
# in compliance with https://no-color.org/
|
13
|
+
#
|
11
14
|
# ---
|
12
15
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
16
|
+
print_in_color() {
|
17
|
+
local color="$1"
|
18
|
+
shift
|
19
|
+
if [[ -z ${NO_COLOR+x} ]]; then
|
20
|
+
printf "$color%b\e[0m\n" "$*";
|
21
|
+
else
|
22
|
+
printf "%b\n" "$*";
|
23
|
+
fi
|
24
|
+
}
|
25
|
+
|
26
|
+
red() { print_in_color "\e[31m" "$*"; }
|
27
|
+
green() { print_in_color "\e[32m" "$*"; }
|
28
|
+
yellow() { print_in_color "\e[33m" "$*"; }
|
29
|
+
blue() { print_in_color "\e[34m" "$*"; }
|
30
|
+
magenta() { print_in_color "\e[35m" "$*"; }
|
31
|
+
cyan() { print_in_color "\e[36m" "$*"; }
|
32
|
+
bold() { print_in_color "\e[1m" "$*"; }
|
33
|
+
underlined() { print_in_color "\e[4m" "$*"; }
|
34
|
+
red_bold() { print_in_color "\e[1;31m" "$*"; }
|
35
|
+
green_bold() { print_in_color "\e[1;32m" "$*"; }
|
36
|
+
yellow_bold() { print_in_color "\e[1;33m" "$*"; }
|
37
|
+
blue_bold() { print_in_color "\e[1;34m" "$*"; }
|
38
|
+
magenta_bold() { print_in_color "\e[1;35m" "$*"; }
|
39
|
+
cyan_bold() { print_in_color "\e[1;36m" "$*"; }
|
40
|
+
red_underlined() { print_in_color "\e[4;31m" "$*"; }
|
41
|
+
green_underlined() { print_in_color "\e[4;32m" "$*"; }
|
42
|
+
yellow_underlined() { print_in_color "\e[4;33m" "$*"; }
|
43
|
+
blue_underlined() { print_in_color "\e[4;34m" "$*"; }
|
44
|
+
magenta_underlined() { print_in_color "\e[4;35m" "$*"; }
|
45
|
+
cyan_underlined() { print_in_color "\e[4;36m" "$*"; }
|
@@ -20,8 +20,9 @@ config_init() {
|
|
20
20
|
# Get a value from the config.
|
21
21
|
# Usage: result=$(config_get hello)
|
22
22
|
config_get() {
|
23
|
-
key=$1
|
24
|
-
regex="^$key *= *(.+)$"
|
23
|
+
local key=$1
|
24
|
+
local regex="^$key *= *(.+)$"
|
25
|
+
local value=""
|
25
26
|
|
26
27
|
config_init
|
27
28
|
|
@@ -38,15 +39,16 @@ config_get() {
|
|
38
39
|
# Add or update a key=value pair in the config.
|
39
40
|
# Usage: config_set key value
|
40
41
|
config_set() {
|
41
|
-
key=$1
|
42
|
+
local key=$1
|
42
43
|
shift
|
43
|
-
value="$*"
|
44
|
+
local value="$*"
|
44
45
|
|
45
46
|
config_init
|
46
47
|
|
47
|
-
regex="^($key) *= *.+$"
|
48
|
-
output=""
|
49
|
-
found_key=""
|
48
|
+
local regex="^($key) *= *.+$"
|
49
|
+
local output=""
|
50
|
+
local found_key=""
|
51
|
+
local newline
|
50
52
|
|
51
53
|
while IFS= read -r line || [ -n "$line" ]; do
|
52
54
|
newline=$line
|
@@ -69,15 +71,14 @@ config_set() {
|
|
69
71
|
# Delete a key from the config.
|
70
72
|
# Usage: config_del key
|
71
73
|
config_del() {
|
72
|
-
key=$1
|
74
|
+
local key=$1
|
73
75
|
|
74
|
-
regex="^($key) *="
|
75
|
-
output=""
|
76
|
+
local regex="^($key) *="
|
77
|
+
local output=""
|
76
78
|
|
77
79
|
config_init
|
78
80
|
|
79
81
|
while IFS= read -r line || [ -n "$line" ]; do
|
80
|
-
newline=$line
|
81
82
|
if [[ $line ]] && [[ ! $line =~ $regex ]]; then
|
82
83
|
output="$output$line\n"
|
83
84
|
fi
|
@@ -100,11 +101,13 @@ config_show() {
|
|
100
101
|
# done
|
101
102
|
#
|
102
103
|
config_keys() {
|
103
|
-
regex="^([a-zA-Z0-9_\-\/\.]+) *="
|
104
|
+
local regex="^([a-zA-Z0-9_\-\/\.]+) *="
|
104
105
|
|
105
106
|
config_init
|
106
107
|
|
107
|
-
keys=()
|
108
|
+
local keys=()
|
109
|
+
local key
|
110
|
+
|
108
111
|
while IFS= read -r line || [ -n "$line" ]; do
|
109
112
|
if [[ $line =~ $regex ]]; then
|
110
113
|
key="${BASH_REMATCH[1]}"
|
@@ -32,3 +32,4 @@ missing_dependency: "missing dependency: %{dependency}"
|
|
32
32
|
disallowed_flag: "%{name} must be one of: %{allowed}"
|
33
33
|
disallowed_argument: "%{name} must be one of: %{allowed}"
|
34
34
|
unsupported_bash_version: "bash version 4 or higher is required"
|
35
|
+
validation_error: "validation error in %s:\\n%s"
|
data/lib/bashly/version.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# :command.normalize_input
|
2
|
+
normalize_input() {
|
3
|
+
local arg flags
|
4
|
+
|
5
|
+
while [[ $# -gt 0 ]]; do
|
6
|
+
arg="$1"
|
7
|
+
if [[ $arg =~ ^(--[a-zA-Z0-9_\-]+)=(.+)$ ]]; then
|
8
|
+
input+=("${BASH_REMATCH[1]}")
|
9
|
+
input+=("${BASH_REMATCH[2]}")
|
10
|
+
elif [[ $arg =~ ^(-[a-zA-Z0-9])=(.+)$ ]]; then
|
11
|
+
input+=("${BASH_REMATCH[1]}")
|
12
|
+
input+=("${BASH_REMATCH[2]}")
|
13
|
+
elif [[ $arg =~ ^-([a-zA-Z0-9][a-zA-Z0-9]+)$ ]]; then
|
14
|
+
flags="${BASH_REMATCH[1]}"
|
15
|
+
for (( i=0 ; i < ${#flags} ; i++ )); do
|
16
|
+
input+=("-${flags:i:1}")
|
17
|
+
done
|
18
|
+
else
|
19
|
+
input+=("$arg")
|
20
|
+
fi
|
21
|
+
|
22
|
+
shift
|
23
|
+
done
|
24
|
+
}
|
@@ -2,7 +2,8 @@
|
|
2
2
|
% if args.any?
|
3
3
|
% condition = "if"
|
4
4
|
% args.each do |arg|
|
5
|
-
<%= condition %> [[
|
5
|
+
<%= condition %> [[ -z ${args[<%= arg.name %>]+x} ]]; then
|
6
|
+
<%= arg.render(:validations).indent 2 %>
|
6
7
|
args[<%= arg.name %>]=$1
|
7
8
|
shift
|
8
9
|
% condition = "elif"
|
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.6.
|
4
|
+
version: 0.6.9
|
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: 2021-
|
11
|
+
date: 2021-10-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colsole
|
@@ -101,11 +101,16 @@ files:
|
|
101
101
|
- lib/bashly/templates/lib/colors.sh
|
102
102
|
- lib/bashly/templates/lib/config.sh
|
103
103
|
- lib/bashly/templates/lib/sample_function.sh
|
104
|
+
- lib/bashly/templates/lib/validations/validate_dir_exists.sh
|
105
|
+
- lib/bashly/templates/lib/validations/validate_file_exists.sh
|
106
|
+
- lib/bashly/templates/lib/validations/validate_integer.sh
|
107
|
+
- lib/bashly/templates/lib/validations/validate_not_empty.sh
|
104
108
|
- lib/bashly/templates/lib/yaml.sh
|
105
109
|
- lib/bashly/templates/minimal.yml
|
106
110
|
- lib/bashly/templates/strings.yml
|
107
111
|
- lib/bashly/version.rb
|
108
112
|
- lib/bashly/views/argument/usage.erb
|
113
|
+
- lib/bashly/views/argument/validations.erb
|
109
114
|
- lib/bashly/views/command/catch_all_filter.erb
|
110
115
|
- lib/bashly/views/command/command_fallback.erb
|
111
116
|
- lib/bashly/views/command/command_filter.erb
|
@@ -122,6 +127,7 @@ files:
|
|
122
127
|
- lib/bashly/views/command/initialize.erb
|
123
128
|
- lib/bashly/views/command/inspect_args.erb
|
124
129
|
- lib/bashly/views/command/master_script.erb
|
130
|
+
- lib/bashly/views/command/normalize_input.erb
|
125
131
|
- lib/bashly/views/command/parse_requirements.erb
|
126
132
|
- lib/bashly/views/command/parse_requirements_case.erb
|
127
133
|
- lib/bashly/views/command/parse_requirements_while.erb
|
@@ -142,6 +148,8 @@ files:
|
|
142
148
|
- lib/bashly/views/environment_variable/usage.erb
|
143
149
|
- lib/bashly/views/flag/case.erb
|
144
150
|
- lib/bashly/views/flag/usage.erb
|
151
|
+
- lib/bashly/views/flag/validations.erb
|
152
|
+
- lib/bashly/views/script/bash3_bouncer.erb
|
145
153
|
- lib/bashly/views/script/header.erb
|
146
154
|
- lib/bashly/views/script/wrapper.erb
|
147
155
|
homepage: https://github.com/dannyben/bashly
|