bashly 0.7.8 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/bashly/cli.rb +2 -1
- data/lib/bashly/commands/add.rb +41 -33
- data/lib/bashly/commands/base.rb +21 -3
- data/lib/bashly/commands/generate.rb +23 -11
- data/lib/bashly/commands/preview.rb +5 -4
- data/lib/bashly/commands/validate.rb +7 -1
- data/lib/bashly/concerns/renderable.rb +8 -1
- data/lib/bashly/concerns/validation_helpers.rb +69 -0
- data/lib/bashly/config_validator.rb +28 -41
- data/lib/bashly/deprecation.rb +25 -0
- data/lib/bashly/extensions/array.rb +5 -0
- data/lib/bashly/extensions/string.rb +6 -0
- data/lib/bashly/extensions/yaml.rb +2 -0
- data/lib/bashly/libraries.yml +13 -9
- data/lib/bashly/script/argument.rb +13 -1
- data/lib/bashly/script/base.rb +7 -29
- data/lib/bashly/script/catch_all.rb +4 -0
- data/lib/bashly/script/command.rb +35 -7
- data/lib/bashly/script/environment_variable.rb +6 -0
- data/lib/bashly/script/flag.rb +9 -0
- data/lib/bashly/script/wrapper.rb +11 -7
- data/lib/bashly/settings.rb +34 -5
- data/lib/bashly/templates/bashly.yml +2 -2
- data/lib/bashly/templates/settings.yml +24 -0
- data/lib/bashly/templates/strings.yml +1 -1
- data/lib/bashly/version.rb +1 -1
- data/lib/bashly/views/argument/usage.erb +2 -2
- data/lib/bashly/views/argument/validations.erb +1 -1
- data/lib/bashly/views/command/catch_all_filter.erb +1 -1
- data/lib/bashly/views/command/command_fallback.erb +1 -1
- data/lib/bashly/views/command/command_filter.erb +1 -1
- data/lib/bashly/views/command/command_functions.erb +1 -1
- data/lib/bashly/views/command/default_assignments.erb +1 -1
- data/lib/bashly/views/command/dependencies_filter.erb +1 -1
- data/lib/bashly/views/command/environment_variables_filter.erb +1 -1
- data/lib/bashly/views/command/fixed_flags_filter.erb +1 -1
- data/lib/bashly/views/command/footer.erb +1 -0
- data/lib/bashly/views/command/function.erb +1 -1
- data/lib/bashly/views/command/initialize.erb +1 -1
- data/lib/bashly/views/command/inspect_args.erb +1 -1
- data/lib/bashly/views/command/master_script.erb +1 -0
- data/lib/bashly/views/command/normalize_input.erb +1 -1
- data/lib/bashly/views/command/parse_requirements.erb +1 -1
- data/lib/bashly/views/command/parse_requirements_case.erb +5 -23
- data/lib/bashly/views/command/parse_requirements_case_catch_all.erb +18 -0
- data/lib/bashly/views/command/parse_requirements_case_repeatable.erb +18 -0
- data/lib/bashly/views/command/parse_requirements_case_simple.erb +18 -0
- data/lib/bashly/views/command/parse_requirements_while.erb +1 -1
- data/lib/bashly/views/command/required_args_filter.erb +1 -1
- data/lib/bashly/views/command/required_flags_filter.erb +1 -1
- data/lib/bashly/views/command/root_command.erb +1 -1
- data/lib/bashly/views/command/run.erb +1 -1
- data/lib/bashly/views/command/usage.erb +3 -3
- data/lib/bashly/views/command/usage_args.erb +1 -1
- data/lib/bashly/views/command/usage_commands.erb +1 -1
- data/lib/bashly/views/command/usage_environment_variables.erb +1 -1
- data/lib/bashly/views/command/usage_examples.erb +1 -1
- data/lib/bashly/views/command/usage_fixed_flags.erb +1 -1
- data/lib/bashly/views/command/usage_flags.erb +1 -1
- data/lib/bashly/views/command/user_filter.erb +1 -1
- data/lib/bashly/views/command/user_lib.erb +2 -2
- data/lib/bashly/views/command/version_command.erb +1 -1
- data/lib/bashly/views/command/whitelist_filter.erb +11 -1
- data/lib/bashly/views/environment_variable/usage.erb +1 -1
- data/lib/bashly/views/flag/case.erb +2 -28
- data/lib/bashly/views/flag/case_arg.erb +19 -0
- data/lib/bashly/views/flag/case_no_arg.erb +8 -0
- data/lib/bashly/views/flag/conflicts.erb +1 -1
- data/lib/bashly/views/flag/usage.erb +1 -1
- data/lib/bashly/views/flag/validations.erb +1 -1
- data/lib/bashly/views/wrapper/bash3_bouncer.erb +1 -1
- data/lib/bashly/views/wrapper/wrapper.erb +1 -1
- 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: d3d0126229189987753e653a635054113961b1e9e0244d4cdb956beb1d5aff94
|
|
4
|
+
data.tar.gz: 886987a65edc65d16d2134589cbb4ee9f3fcb9e0b1819c8a87211bcd2d164d0c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 880579e8bb650c8835cc7992054f3f4dd3e765ddc1b7072f83ed6fc9049d4b56b38c4a64220c3dd154f8fdbf199462cca1ef955d36d465a0d57ecc00715bd85e
|
|
7
|
+
data.tar.gz: efa2f73f9eed6d5ba1ebb432e37ef639e618bc1556ba83059ccad4804b6568b407d86f91fe11faa3335b69103e368fdb9bf1339f90af1fd15cb742b91163b911
|
data/lib/bashly/cli.rb
CHANGED
|
@@ -6,7 +6,8 @@ module Bashly
|
|
|
6
6
|
class CLI
|
|
7
7
|
def self.runner
|
|
8
8
|
runner = MisterBin::Runner.new version: Bashly::VERSION,
|
|
9
|
-
header: "Bashly - Bash CLI Generator"
|
|
9
|
+
header: "Bashly - Bash CLI Generator",
|
|
10
|
+
footer: "Help: !txtpur!bashly COMMAND --help!txtrst!\nDocs: !undblu!https://bashly.dannyb.co"
|
|
10
11
|
|
|
11
12
|
runner.route 'init', to: Commands::Init
|
|
12
13
|
runner.route 'preview', to: Commands::Preview
|
data/lib/bashly/commands/add.rb
CHANGED
|
@@ -3,14 +3,15 @@ module Bashly
|
|
|
3
3
|
class Add < Base
|
|
4
4
|
help "Add extra features and customization to your script"
|
|
5
5
|
|
|
6
|
-
usage "bashly add strings [--force]"
|
|
7
|
-
usage "bashly add lib [--force]"
|
|
8
|
-
usage "bashly add config [--force]"
|
|
9
6
|
usage "bashly add colors [--force]"
|
|
10
|
-
usage "bashly add yaml [--force]"
|
|
11
|
-
usage "bashly add validations [--force]"
|
|
12
|
-
usage "bashly add test [--force]"
|
|
13
7
|
usage "bashly add comp FORMAT [OUTPUT --force]"
|
|
8
|
+
usage "bashly add config [--force]"
|
|
9
|
+
usage "bashly add lib [--force]"
|
|
10
|
+
usage "bashly add settings [--force]"
|
|
11
|
+
usage "bashly add strings [--force]"
|
|
12
|
+
usage "bashly add test [--force]"
|
|
13
|
+
usage "bashly add validations [--force]"
|
|
14
|
+
usage "bashly add yaml [--force]"
|
|
14
15
|
usage "bashly add (-h|--help)"
|
|
15
16
|
|
|
16
17
|
option "-f --force", "Overwrite existing files"
|
|
@@ -18,14 +19,15 @@ module Bashly
|
|
|
18
19
|
param "FORMAT", "Output format, can be one of:\n function : generate a function file to be included in your script.\n script : generate a standalone bash completions script.\n yaml : generate a yaml compatible with completely."
|
|
19
20
|
param "OUTPUT", "For the 'comp function' command: Name of the generated function.\nFor the 'comp script' or 'comp yaml' commands: path to output file.\nIn all cases, this is optional and will have sensible defaults."
|
|
20
21
|
|
|
21
|
-
command "strings", "Copy an additional configuration file to your project, allowing you to customize all the tips and error strings."
|
|
22
|
-
command "lib", "Create the additional lib directory for additional user scripts. All *.sh scripts in this folder will be included in the final bash script."
|
|
23
|
-
command "config", "Add standard functions for handling INI files to the lib directory."
|
|
24
22
|
command "colors", "Add standard functions for printing colorful and formatted text to the lib directory."
|
|
25
|
-
command "yaml", "Add standard functions for reading YAML files to the lib directory."
|
|
26
|
-
command "validations", "Add argument validation functions to the lib directory."
|
|
27
|
-
command "test", "Add approval testing."
|
|
28
23
|
command "comp", "Generate a bash completions script or function."
|
|
24
|
+
command "config", "Add standard functions for handling INI files to the lib directory."
|
|
25
|
+
command "lib", "Create the additional lib directory for additional user scripts. All *.sh scripts in this folder will be included in the final bash script."
|
|
26
|
+
command "settings", "Copy a sample settings.yml file to your project, allowing you to customize some bashly options."
|
|
27
|
+
command "strings", "Copy an additional configuration file to your project, allowing you to customize all the tips and error strings."
|
|
28
|
+
command "test", "Add approval testing."
|
|
29
|
+
command "validations", "Add argument validation functions to the lib directory."
|
|
30
|
+
command "yaml", "Add standard functions for reading YAML files to the lib directory."
|
|
29
31
|
|
|
30
32
|
example "bashly add strings --force"
|
|
31
33
|
example "bashly add comp function"
|
|
@@ -34,45 +36,51 @@ module Bashly
|
|
|
34
36
|
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
|
|
35
37
|
environment "BASHLY_LIB_DIR", "The path to use for creating the library files, relative to the source dir [default: lib]"
|
|
36
38
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
+
attr_reader :skip_src_check
|
|
40
|
+
|
|
41
|
+
def colors_command
|
|
42
|
+
add_lib 'colors'
|
|
39
43
|
end
|
|
40
44
|
|
|
41
|
-
def
|
|
42
|
-
|
|
45
|
+
def comp_command
|
|
46
|
+
format = args['FORMAT']
|
|
47
|
+
output = args['OUTPUT']
|
|
48
|
+
|
|
49
|
+
case format
|
|
50
|
+
when "script" then add_lib 'completions_script', output
|
|
51
|
+
when "function" then add_lib 'completions', output
|
|
52
|
+
when "yaml" then add_lib 'completions_yaml', output
|
|
53
|
+
else raise Error, "Unrecognized format: #{format}"
|
|
54
|
+
end
|
|
43
55
|
end
|
|
44
56
|
|
|
45
57
|
def config_command
|
|
46
58
|
add_lib 'config'
|
|
47
59
|
end
|
|
48
60
|
|
|
49
|
-
def
|
|
50
|
-
|
|
61
|
+
def settings_command
|
|
62
|
+
@skip_src_check = true
|
|
63
|
+
add_lib 'settings'
|
|
51
64
|
end
|
|
52
65
|
|
|
53
|
-
def
|
|
54
|
-
add_lib '
|
|
66
|
+
def strings_command
|
|
67
|
+
add_lib 'strings'
|
|
55
68
|
end
|
|
56
69
|
|
|
57
|
-
def
|
|
58
|
-
add_lib '
|
|
70
|
+
def lib_command
|
|
71
|
+
add_lib 'lib'
|
|
59
72
|
end
|
|
60
73
|
|
|
61
74
|
def test_command
|
|
62
75
|
add_lib 'test'
|
|
63
76
|
end
|
|
64
77
|
|
|
65
|
-
def
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
case format
|
|
70
|
-
when "script" then add_lib 'completions_script', output
|
|
71
|
-
when "function" then add_lib 'completions', output
|
|
72
|
-
when "yaml" then add_lib 'completions_yaml', output
|
|
73
|
-
else raise Error, "Unrecognized format: #{format}"
|
|
74
|
-
end
|
|
78
|
+
def yaml_command
|
|
79
|
+
add_lib 'yaml'
|
|
80
|
+
end
|
|
75
81
|
|
|
82
|
+
def validations_command
|
|
83
|
+
add_lib 'validations'
|
|
76
84
|
end
|
|
77
85
|
|
|
78
86
|
private
|
|
@@ -89,7 +97,7 @@ module Bashly
|
|
|
89
97
|
end
|
|
90
98
|
|
|
91
99
|
def safe_write(path, content)
|
|
92
|
-
if !Dir.exist? Settings.source_dir
|
|
100
|
+
if !skip_src_check and !Dir.exist? Settings.source_dir
|
|
93
101
|
raise InitError, "Directory !txtgrn!#{Settings.source_dir}!txtrst! does not exist\nRun !txtpur!bashly init!txtrst! first"
|
|
94
102
|
end
|
|
95
103
|
|
data/lib/bashly/commands/base.rb
CHANGED
|
@@ -6,10 +6,28 @@ module Bashly
|
|
|
6
6
|
class Base < MisterBin::Command
|
|
7
7
|
include AssetHelper
|
|
8
8
|
|
|
9
|
+
def config
|
|
10
|
+
@config ||= Config.new "#{Settings.source_dir}/bashly.yml"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def config_validator
|
|
14
|
+
@config_validator ||= ConfigValidator.new config
|
|
15
|
+
end
|
|
16
|
+
|
|
9
17
|
def validate_config
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
18
|
+
config_validator.validate
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def with_valid_config
|
|
22
|
+
validate_config
|
|
23
|
+
yield
|
|
24
|
+
show_deprecations
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def show_deprecations
|
|
28
|
+
return if config_validator.deprecations.empty? or ENV['BASHLY_HIDE_DEPRECATIONS']
|
|
29
|
+
messages = "\n" + config_validator.deprecations.map(&:message).join("\n\n") + "\n\n"
|
|
30
|
+
say! messages
|
|
13
31
|
end
|
|
14
32
|
end
|
|
15
33
|
end
|
|
@@ -3,28 +3,38 @@ module Bashly
|
|
|
3
3
|
class Generate < Base
|
|
4
4
|
help "Generate the bash script and required files"
|
|
5
5
|
|
|
6
|
-
usage "bashly generate [
|
|
6
|
+
usage "bashly generate [options]"
|
|
7
7
|
usage "bashly generate (-h|--help)"
|
|
8
8
|
|
|
9
9
|
option "-f --force", "Overwrite existing files"
|
|
10
10
|
option "-q --quiet", "Disable on-screen progress report"
|
|
11
11
|
option "-u --upgrade", "Upgrade all added library functions"
|
|
12
12
|
option "-w --wrap FUNCTION", "Wrap the entire script in a function so it can also be sourced"
|
|
13
|
+
option "-e --env ENV", "Force the generation environment (see BASHLY_ENV)"
|
|
13
14
|
|
|
14
15
|
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
|
|
15
16
|
environment "BASHLY_TARGET_DIR", "The path to use for creating the bash script [default: .]"
|
|
16
17
|
environment "BASHLY_LIB_DIR", "The path to use for upgrading library files, relative to the source dir [default: lib]"
|
|
17
18
|
environment "BASHLY_STRICT", "When not empty, enable bash strict mode (set -euo pipefail)"
|
|
19
|
+
environment "BASHLY_TAB_INDENT", "When not empty, the generated script will use tab indentation instead of spaces (every 2 leading spaces will be converted to a tab character)"
|
|
20
|
+
environment "BASHLY_ENV", <<~EOF
|
|
21
|
+
Set to 'production' or 'development':
|
|
22
|
+
- production generate a smaller script, without file markers
|
|
23
|
+
- development generate with file markers
|
|
24
|
+
|
|
25
|
+
Can be overridden with --env [default: development]
|
|
26
|
+
EOF
|
|
18
27
|
|
|
19
28
|
example "bashly generate --force"
|
|
20
29
|
example "bashly generate --wrap my_function"
|
|
21
30
|
|
|
22
31
|
def run
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
with_valid_config do
|
|
33
|
+
Settings.env = args['--env'] if args['--env']
|
|
34
|
+
quiet_say "creating !txtgrn!production!txtrst! version" if Settings.production?
|
|
35
|
+
generate_all_files
|
|
36
|
+
quiet_say "run !txtpur!#{master_script_path} --help!txtrst! to test your bash script"
|
|
37
|
+
end
|
|
28
38
|
end
|
|
29
39
|
|
|
30
40
|
private
|
|
@@ -33,6 +43,12 @@ module Bashly
|
|
|
33
43
|
say message unless args['--quiet']
|
|
34
44
|
end
|
|
35
45
|
|
|
46
|
+
def generate_all_files
|
|
47
|
+
create_user_files
|
|
48
|
+
upgrade_libs if args['--upgrade']
|
|
49
|
+
create_master_script
|
|
50
|
+
end
|
|
51
|
+
|
|
36
52
|
def upgrade_libs
|
|
37
53
|
generated_files.each do |file|
|
|
38
54
|
content = File.read file
|
|
@@ -104,7 +120,7 @@ module Bashly
|
|
|
104
120
|
end
|
|
105
121
|
|
|
106
122
|
def create_master_script
|
|
107
|
-
File.write master_script_path, script.code
|
|
123
|
+
File.write master_script_path, script.code(tab_indent: Settings.tab_indent)
|
|
108
124
|
FileUtils.chmod "+x", master_script_path
|
|
109
125
|
quiet_say "!txtgrn!created!txtrst! #{master_script_path}"
|
|
110
126
|
end
|
|
@@ -117,10 +133,6 @@ module Bashly
|
|
|
117
133
|
"#{Settings.target_dir}/#{command.name}"
|
|
118
134
|
end
|
|
119
135
|
|
|
120
|
-
def config
|
|
121
|
-
@config ||= Config.new "#{Settings.source_dir}/bashly.yml"
|
|
122
|
-
end
|
|
123
|
-
|
|
124
136
|
def command
|
|
125
137
|
@command ||= Script::Command.new config
|
|
126
138
|
end
|
|
@@ -9,10 +9,11 @@ module Bashly
|
|
|
9
9
|
environment "BASHLY_SOURCE_DIR", "The path containing the bashly configuration and source files [default: src]"
|
|
10
10
|
|
|
11
11
|
def run
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
with_valid_config do
|
|
13
|
+
command = Script::Command.new config
|
|
14
|
+
script = Script::Wrapper.new command
|
|
15
|
+
puts script.code
|
|
16
|
+
end
|
|
16
17
|
end
|
|
17
18
|
end
|
|
18
19
|
end
|
|
@@ -10,7 +10,13 @@ module Bashly
|
|
|
10
10
|
|
|
11
11
|
def run
|
|
12
12
|
validate_config
|
|
13
|
-
|
|
13
|
+
show_deprecations
|
|
14
|
+
deprecations = config_validator.deprecations
|
|
15
|
+
if deprecations.empty?
|
|
16
|
+
say "!txtgrn!OK"
|
|
17
|
+
else
|
|
18
|
+
say "!txtred!WARNING!txtrst! Found #{deprecations.count} deprecations"
|
|
19
|
+
end
|
|
14
20
|
end
|
|
15
21
|
end
|
|
16
22
|
end
|
|
@@ -4,13 +4,20 @@ module Bashly
|
|
|
4
4
|
module Renderable
|
|
5
5
|
def render(view)
|
|
6
6
|
template = File.read view_path(view)
|
|
7
|
-
ERB.new(template, trim_mode: '%-')
|
|
7
|
+
erb = ERB.new(template, trim_mode: '%-')
|
|
8
|
+
erb.filename = "#{views_subfolder}.#{view}"
|
|
9
|
+
erb.result binding
|
|
8
10
|
end
|
|
9
11
|
|
|
10
12
|
def strings
|
|
11
13
|
@strings ||= MessageStrings.new
|
|
12
14
|
end
|
|
13
15
|
|
|
16
|
+
def view_marker(id = nil)
|
|
17
|
+
id ||= ":#{caller_locations.first.path}"
|
|
18
|
+
"# #{id}" unless Settings.production?
|
|
19
|
+
end
|
|
20
|
+
|
|
14
21
|
private
|
|
15
22
|
|
|
16
23
|
def view_path(view)
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
module Bashly
|
|
2
|
+
# This is a `ConfigValidator` concern responsible for providing basic
|
|
3
|
+
# assertion methods.
|
|
4
|
+
module ValidationHelpers
|
|
5
|
+
|
|
6
|
+
def deprecations
|
|
7
|
+
@deprecations ||= []
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
protected
|
|
11
|
+
|
|
12
|
+
def assert(valid, message)
|
|
13
|
+
raise ConfigurationError, message unless valid
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def refute(invalid, message)
|
|
17
|
+
assert !invalid, message
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def deprecate(key, **options)
|
|
21
|
+
deprecations.push Deprecation.new(key, **options)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def assert_string(key, value)
|
|
25
|
+
assert value.is_a?(String), "#{key} must be a string"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def assert_optional_string(key, value)
|
|
29
|
+
assert_string key, value if value
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def assert_boolean(key, value)
|
|
33
|
+
assert [true, false, nil].include?(value), "#{key} must be a boolean"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def assert_array(key, value, of: nil)
|
|
37
|
+
return unless value
|
|
38
|
+
assert value.is_a?(Array), "#{key} must be an array"
|
|
39
|
+
if of
|
|
40
|
+
value.each_with_index do |val, i|
|
|
41
|
+
send "assert_#{of}".to_sym, "#{key}[#{i}]", val
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def assert_hash(key, value, whitelist = nil)
|
|
47
|
+
assert value.is_a?(Hash), "#{key} must be a hash"
|
|
48
|
+
|
|
49
|
+
if whitelist
|
|
50
|
+
invalid_keys = value.keys.map(&:to_sym) - whitelist
|
|
51
|
+
assert invalid_keys.empty?, "#{key} contains invalid options: #{invalid_keys.join(', ')}"
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def assert_uniq(key, value, array_key)
|
|
56
|
+
return unless value
|
|
57
|
+
list = value.map { |c| c[array_key] }.compact.flatten
|
|
58
|
+
assert list.uniq?, "#{key} cannot have elements with similar #{array_key} values"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def assert_string_or_array(key, value)
|
|
62
|
+
return unless value
|
|
63
|
+
assert [Array, String].include?(value.class),
|
|
64
|
+
"#{key} must be a string or an array"
|
|
65
|
+
|
|
66
|
+
assert_array key, value, of: :string if value.is_a? Array
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
module Bashly
|
|
2
2
|
class ConfigValidator
|
|
3
|
+
include ValidationHelpers
|
|
4
|
+
|
|
3
5
|
attr_reader :data
|
|
4
6
|
|
|
5
7
|
def initialize(data)
|
|
@@ -12,40 +14,6 @@ module Bashly
|
|
|
12
14
|
|
|
13
15
|
private
|
|
14
16
|
|
|
15
|
-
def assert(valid, message)
|
|
16
|
-
raise ConfigurationError, message unless valid
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def refute(invalid, message)
|
|
20
|
-
assert !invalid, message
|
|
21
|
-
end
|
|
22
|
-
|
|
23
|
-
def assert_string(key, value)
|
|
24
|
-
assert value.is_a?(String), "#{key} must be a string"
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def assert_optional_string(key, value)
|
|
28
|
-
assert_string key, value if value
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def assert_boolean(key, value)
|
|
32
|
-
assert [true, false, nil].include?(value), "#{key} must be a boolean"
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
def assert_array(key, value, of: nil)
|
|
36
|
-
return unless value
|
|
37
|
-
assert value.is_a?(Array), "#{key} must be an array"
|
|
38
|
-
if of
|
|
39
|
-
value.each_with_index do |val, i|
|
|
40
|
-
send "assert_#{of}".to_sym, "#{key}[#{i}]", val
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
def assert_hash(key, value)
|
|
46
|
-
assert value.is_a?(Hash), "#{key} must be a hash"
|
|
47
|
-
end
|
|
48
|
-
|
|
49
17
|
def assert_version(key, value)
|
|
50
18
|
return unless value
|
|
51
19
|
assert [String, Integer, Float].include?(value.class),
|
|
@@ -61,6 +29,7 @@ module Bashly
|
|
|
61
29
|
end
|
|
62
30
|
|
|
63
31
|
def assert_catch_all_hash(key, value)
|
|
32
|
+
assert_hash key, value, Script::CatchAll.option_keys
|
|
64
33
|
assert_string "#{key}.label", value['label']
|
|
65
34
|
assert_optional_string "#{key}.help", value['help']
|
|
66
35
|
assert_boolean "#{key}.required", value['required']
|
|
@@ -73,7 +42,7 @@ module Bashly
|
|
|
73
42
|
end
|
|
74
43
|
|
|
75
44
|
def assert_arg(key, value)
|
|
76
|
-
assert_hash key, value
|
|
45
|
+
assert_hash key, value, Script::Argument.option_keys
|
|
77
46
|
assert_string "#{key}.name", value['name']
|
|
78
47
|
assert_optional_string "#{key}.help", value['help']
|
|
79
48
|
assert_optional_string "#{key}.default", value['default']
|
|
@@ -89,7 +58,7 @@ module Bashly
|
|
|
89
58
|
end
|
|
90
59
|
|
|
91
60
|
def assert_flag(key, value)
|
|
92
|
-
assert_hash key, value
|
|
61
|
+
assert_hash key, value, Script::Flag.option_keys
|
|
93
62
|
assert value['short'] || value['long'], "#{key} must have at least one of long or short name"
|
|
94
63
|
|
|
95
64
|
assert_optional_string "#{key}.long", value['long']
|
|
@@ -99,6 +68,7 @@ module Bashly
|
|
|
99
68
|
assert_optional_string "#{key}.default", value['default']
|
|
100
69
|
assert_optional_string "#{key}.validate", value['validate']
|
|
101
70
|
|
|
71
|
+
assert_boolean "#{key}.repeatable", value['repeatable']
|
|
102
72
|
assert_boolean "#{key}.required", value['required']
|
|
103
73
|
assert_array "#{key}.allowed", value['allowed'], of: :string
|
|
104
74
|
assert_array "#{key}.conflicts", value['conflicts'], of: :string
|
|
@@ -119,7 +89,7 @@ module Bashly
|
|
|
119
89
|
end
|
|
120
90
|
|
|
121
91
|
def assert_env_var(key, value)
|
|
122
|
-
assert_hash key, value
|
|
92
|
+
assert_hash key, value, Script::EnvironmentVariable.option_keys
|
|
123
93
|
assert_string "#{key}.name", value['name']
|
|
124
94
|
assert_optional_string "#{key}.help", value['help']
|
|
125
95
|
assert_optional_string "#{key}.default", value['default']
|
|
@@ -127,21 +97,22 @@ module Bashly
|
|
|
127
97
|
end
|
|
128
98
|
|
|
129
99
|
def assert_command(key, value)
|
|
130
|
-
assert_hash key, value
|
|
100
|
+
assert_hash key, value, Script::Command.option_keys
|
|
131
101
|
|
|
132
102
|
refute value['commands'] && value['args'], "#{key} cannot have both commands and args"
|
|
133
103
|
refute value['commands'] && value['flags'], "#{key} cannot have both commands and flags"
|
|
134
|
-
|
|
104
|
+
|
|
135
105
|
assert_string "#{key}.name", value['name']
|
|
136
|
-
assert_optional_string "#{key}.short", value['short']
|
|
137
106
|
assert_optional_string "#{key}.help", value['help']
|
|
138
107
|
assert_optional_string "#{key}.footer", value['footer']
|
|
139
108
|
assert_optional_string "#{key}.group", value['group']
|
|
140
109
|
assert_optional_string "#{key}.filename", value['filename']
|
|
141
110
|
|
|
111
|
+
assert_boolean "#{key}.private", value['private']
|
|
142
112
|
assert_boolean "#{key}.default", value['default']
|
|
143
113
|
assert_version "#{key}.version", value['version']
|
|
144
114
|
assert_catch_all "#{key}.catch_all", value['catch_all']
|
|
115
|
+
assert_string_or_array "#{key}.alias", value['alias']
|
|
145
116
|
assert_extensible "#{key}.extensible", value['extensible']
|
|
146
117
|
|
|
147
118
|
assert_array "#{key}.args", value['args'], of: :arg
|
|
@@ -153,8 +124,19 @@ module Bashly
|
|
|
153
124
|
assert_array "#{key}.environment_variables", value['environment_variables'], of: :env_var
|
|
154
125
|
assert_array "#{key}.examples", value['examples'], of: :string
|
|
155
126
|
|
|
127
|
+
assert_uniq "#{key}.commands", value['commands'], 'name'
|
|
128
|
+
assert_uniq "#{key}.commands", value['commands'], 'alias'
|
|
129
|
+
assert_uniq "#{key}.flags", value['flags'], 'long'
|
|
130
|
+
assert_uniq "#{key}.flags", value['flags'], 'short'
|
|
131
|
+
assert_uniq "#{key}.args", value['args'], 'name'
|
|
132
|
+
|
|
133
|
+
if value['catch_all'] and value['args']
|
|
134
|
+
repeatable_arg = value['args'].select { |a| a['repeatable'] }.first&.dig 'name'
|
|
135
|
+
refute repeatable_arg, "#{key}.catch_all makes no sense with repeatable arg (#{repeatable_arg})"
|
|
136
|
+
end
|
|
137
|
+
|
|
156
138
|
if key == "root"
|
|
157
|
-
refute value['
|
|
139
|
+
refute value['alias'], "#{key}.alias makes no sense"
|
|
158
140
|
refute value['group'], "#{key}.group makes no sense"
|
|
159
141
|
refute value['default'], "#{key}.default makes no sense"
|
|
160
142
|
refute value['private'], "#{key}.private makes no sense"
|
|
@@ -162,6 +144,11 @@ module Bashly
|
|
|
162
144
|
refute value['version'], "#{key}.version makes no sense"
|
|
163
145
|
refute value['extensible'], "#{key}.extensible makes no sense"
|
|
164
146
|
end
|
|
147
|
+
|
|
148
|
+
# DEPRECATION 0.8.0
|
|
149
|
+
if value['short']
|
|
150
|
+
deprecate "#{key}.short", replacement: "alias", reference: "https://github.com/DannyBen/bashly/pull/220"
|
|
151
|
+
end
|
|
165
152
|
end
|
|
166
153
|
end
|
|
167
154
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Bashly
|
|
2
|
+
class Deprecation
|
|
3
|
+
attr_reader :old, :replacement, :reference
|
|
4
|
+
|
|
5
|
+
def initialize(old, replacement: nil, reference: nil)
|
|
6
|
+
@old, @replacement, @reference = old, replacement, reference
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def message
|
|
10
|
+
result = ["Deprecation Warning:", "!txtred!#{old}!txtrst! is deprecated"]
|
|
11
|
+
result.push "use !txtgrn!#{replacement}!txtrst! instead" if replacement
|
|
12
|
+
result.push "see !undblu!#{reference}!txtrst!" if reference
|
|
13
|
+
|
|
14
|
+
result.map { |line| "!txtred!▐!txtrst! #{line}"}.join("\n")
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def to_h
|
|
18
|
+
{
|
|
19
|
+
old: old,
|
|
20
|
+
replacement: replacement,
|
|
21
|
+
reference: reference
|
|
22
|
+
}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/bashly/libraries.yml
CHANGED
|
@@ -3,21 +3,25 @@ colors:
|
|
|
3
3
|
- source: "templates/lib/colors.sh"
|
|
4
4
|
target: "%{user_lib_dir}/colors.sh"
|
|
5
5
|
|
|
6
|
+
completions: :CompletionsFunction
|
|
7
|
+
completions_script: :CompletionsScript
|
|
8
|
+
completions_yaml: :CompletionsYAML
|
|
9
|
+
|
|
6
10
|
config:
|
|
7
11
|
files:
|
|
8
12
|
- source: "templates/lib/config.sh"
|
|
9
13
|
target: "%{user_lib_dir}/config.sh"
|
|
10
14
|
|
|
11
|
-
yaml:
|
|
12
|
-
files:
|
|
13
|
-
- source: "templates/lib/yaml.sh"
|
|
14
|
-
target: "%{user_lib_dir}/yaml.sh"
|
|
15
|
-
|
|
16
15
|
lib:
|
|
17
16
|
files:
|
|
18
17
|
- source: "templates/lib/sample_function.sh"
|
|
19
18
|
target: "%{user_lib_dir}/sample_function.sh"
|
|
20
19
|
|
|
20
|
+
settings:
|
|
21
|
+
files:
|
|
22
|
+
- source: "templates/settings.yml"
|
|
23
|
+
target: "settings.yml"
|
|
24
|
+
|
|
21
25
|
strings:
|
|
22
26
|
files:
|
|
23
27
|
- source: "templates/strings.yml"
|
|
@@ -37,7 +41,6 @@ test:
|
|
|
37
41
|
|
|
38
42
|
Docs: !undblu!https://github.com/DannyBen/approvals.bash
|
|
39
43
|
|
|
40
|
-
|
|
41
44
|
validations:
|
|
42
45
|
files:
|
|
43
46
|
- source: "templates/lib/validations/validate_dir_exists.sh"
|
|
@@ -49,6 +52,7 @@ validations:
|
|
|
49
52
|
- source: "templates/lib/validations/validate_not_empty.sh"
|
|
50
53
|
target: "%{user_lib_dir}/validations/validate_not_empty.sh"
|
|
51
54
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
+
yaml:
|
|
56
|
+
files:
|
|
57
|
+
- source: "templates/lib/yaml.sh"
|
|
58
|
+
target: "%{user_lib_dir}/yaml.sh"
|
|
@@ -1,8 +1,20 @@
|
|
|
1
1
|
module Bashly
|
|
2
2
|
module Script
|
|
3
3
|
class Argument < Base
|
|
4
|
+
class << self
|
|
5
|
+
def option_keys
|
|
6
|
+
@option_keys ||= %i[
|
|
7
|
+
allowed default help name repeatable required validate
|
|
8
|
+
]
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
4
12
|
def usage_string
|
|
5
|
-
required ?
|
|
13
|
+
required ? label : "[#{label}]"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def label
|
|
17
|
+
repeatable ? "#{name.upcase}..." : name.upcase
|
|
6
18
|
end
|
|
7
19
|
end
|
|
8
20
|
end
|