bashly 0.6.5 → 0.6.9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5b02a163470ebeb4c59a97f475b40b760477d36df16189addb48049b11b8842a
4
- data.tar.gz: 625b89b6a09fc59f6a4a19fceaf05f645dec0c45cc33cda3a445fe123f43dbb6
3
+ metadata.gz: c76c3000789b54fa2d9be8f7a61d93556e6a8665f4ea7769588797a25fa78f49
4
+ data.tar.gz: a5a0eae36b00cf879082836211f2aa21b38b280993e2dccfc907f3e6fcb99104
5
5
  SHA512:
6
- metadata.gz: 6e2bd2c31ab003d916efa2590e8571b7cbf3b6e88c3cee9122f5bc24d57b9624e52d7589bffdf2604132d55b040ff735effc02d49e4b6a8479817122ce98f612
7
- data.tar.gz: 8fe5d95ea5061d88fb0b0da02266b69ed6530379d3e030d5f71fd1edf8bd97c3690ea82a89c36bb55a27790363ccd52be4de9e4aa1ba5ae07cb0c8ce87b8fd89
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 ([example](https://github.com/DannyBen/bashly/blob/master/examples/minimal/download)).
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
 
@@ -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
- safe_copy_lib "sample_function.sh"
39
+ safe_copy_file "sample_function.sh"
38
40
  end
39
41
 
40
42
  def config_command
41
- safe_copy_lib "config.sh"
43
+ safe_copy_file "config.sh"
42
44
  end
43
45
 
44
46
  def colors_command
45
- safe_copy_lib "colors.sh"
47
+ safe_copy_file "colors.sh"
46
48
  end
47
49
 
48
50
  def yaml_command
49
- safe_copy_lib "yaml.sh"
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 safe_copy_lib(libfile)
72
- safe_copy asset("templates/lib/#{libfile}"), "#{Settings.source_dir}/lib/#{libfile}"
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
- say "run !txtpur!#{master_script_path} --help!txtrst! to test your bash script"
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
- say "creating user files in !txtgrn!#{Settings.source_dir}"
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
- say "skipped !txtgrn!#{file}!txtrst! (exists)"
58
+ quiet_say "skipped !txtgrn!#{file}!txtrst! (exists)"
54
59
  else
55
60
  File.write file, content
56
- say "created !txtgrn!#{file}"
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
- say "created !txtgrn!#{master_script_path}"
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
@@ -24,7 +24,7 @@ class String
24
24
  end
25
25
 
26
26
  def lint
27
- gsub(/\n{2,}/, "\n\n")
27
+ gsub(/\s+\n/m, "\n\n")
28
28
  end
29
29
 
30
30
  end
@@ -25,6 +25,7 @@ module Bashly
25
25
  parent_name
26
26
  required
27
27
  short
28
+ validate
28
29
  version
29
30
  ]
30
31
 
@@ -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
@@ -22,12 +22,30 @@ module Bashly
22
22
  private
23
23
 
24
24
  def header
25
- @header ||= render('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
- red() { printf "\e[31m%b\e[0m\n" "$*"; }
14
- green() { printf "\e[32m%b\e[0m\n" "$*"; }
15
- yellow() { printf "\e[33m%b\e[0m\n" "$*"; }
16
- blue() { printf "\e[34m%b\e[0m\n" "$*"; }
17
- magenta() { printf "\e[35m%b\e[0m\n" "$*"; }
18
- cyan() { printf "\e[36m%b\e[0m\n" "$*"; }
19
- bold() { printf "\e[1m%b\e[0m\n" "$*"; }
20
- underlined() { printf "\e[4m%b\e[0m\n" "$*"; }
21
- red_bold() { printf "\e[1;31m%b\e[0m\n" "$*"; }
22
- green_bold() { printf "\e[1;32m%b\e[0m\n" "$*"; }
23
- yellow_bold() { printf "\e[1;33m%b\e[0m\n" "$*"; }
24
- blue_bold() { printf "\e[1;34m%b\e[0m\n" "$*"; }
25
- magenta_bold() { printf "\e[1;35m%b\e[0m\n" "$*"; }
26
- cyan_bold() { printf "\e[1;36m%b\e[0m\n" "$*"; }
27
- red_underlined() { printf "\e[4;31m%b\e[0m\n" "$*"; }
28
- green_underlined() { printf "\e[4;32m%b\e[0m\n" "$*"; }
29
- yellow_underlined() { printf "\e[4;33m%b\e[0m\n" "$*"; }
30
- blue_underlined() { printf "\e[4;34m%b\e[0m\n" "$*"; }
31
- magenta_underlined() { printf "\e[4;35m%b\e[0m\n" "$*"; }
32
- cyan_underlined() { printf "\e[4;36m%b\e[0m\n" "$*"; }
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]}"
@@ -0,0 +1,3 @@
1
+ validate_dir_exists() {
2
+ [[ -d "$1" ]] || echo "must be an existing directory"
3
+ }
@@ -0,0 +1,3 @@
1
+ validate_file_exists() {
2
+ [[ -f "$1" ]] || echo "must be an existing file"
3
+ }
@@ -0,0 +1,3 @@
1
+ validate_integer() {
2
+ [[ "$1" =~ ^[0-9]+$ ]] || echo "must be an integer"
3
+ }
@@ -0,0 +1,3 @@
1
+ validate_not_empty() {
2
+ [[ -z "$1" ]] && echo "must not be empty"
3
+ }
@@ -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"
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = "0.6.5"
2
+ VERSION = "0.6.9"
3
3
  end
@@ -0,0 +1,8 @@
1
+ # :argument.validations
2
+ % if validate
3
+ if [[ -n $(validate_<%= validate %> "$1") ]]; then
4
+ printf "<%= strings[:validation_error] %>\n" "<%= name.upcase %>" "$(validate_<%= validate %> "$1")"
5
+ exit 1
6
+ fi
7
+
8
+ % end
@@ -4,10 +4,5 @@ initialize() {
4
4
  long_usage=''
5
5
  set -e
6
6
 
7
- if [[ "${BASH_VERSINFO:-0}" -lt 4 ]]; then
8
- printf "<%= strings[:unsupported_bash_version] -%>\n"
9
- exit 1
10
- fi
11
-
12
7
  <%= load_user_file("initialize.sh", placeholder: false).indent 2 %>
13
8
  }
@@ -1,6 +1,7 @@
1
1
  <%= render :root_command if commands.empty? %>
2
2
  <%= render :version_command %>
3
3
  <%= render :usage %>
4
+ <%= render :normalize_input %>
4
5
  <%= render :inspect_args %>
5
6
  <%= render :user_lib if user_lib.any? %>
6
7
  <%= render :command_functions %>
@@ -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 %> [[ ! ${args[<%= arg.name %>]} ]]; then
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"
@@ -1,6 +1,7 @@
1
1
  # :command.required_args_filter
2
2
  % required_args.each do |arg|
3
- if [[ $1 && $1 != -* ]]; then
3
+ if [[ -n ${1+x} && $1 != -* ]]; then
4
+ <%= arg.render(:validations).indent 2 %>
4
5
  args[<%= arg.name %>]=$1
5
6
  shift
6
7
  else
@@ -2,7 +2,9 @@
2
2
  run() {
3
3
  declare -A args
4
4
  declare -a other_args
5
- parse_requirements "$@"
5
+ declare -a input
6
+ normalize_input "$@"
7
+ parse_requirements "${input[@]}"
6
8
 
7
9
  <%- condition = "if" -%>
8
10
  <%- deep_commands.each do |command| -%>
@@ -1,7 +1,8 @@
1
1
  # :flag.case
2
2
  <%= aliases.join " | " %> )
3
3
  % if arg
4
- if [[ $2 ]]; then
4
+ if [[ -n ${2+x} ]]; then
5
+ <%= render(:validations).indent 4 %>
5
6
  args[<%= name %>]="$2"
6
7
  shift
7
8
  shift
@@ -0,0 +1,8 @@
1
+ # :flag.validations
2
+ % if validate
3
+ if [[ -n $(validate_<%= validate %> "$2") ]]; then
4
+ printf "<%= strings[:validation_error] %>\n" "<%= usage_string %>" "$(validate_<%= validate %> "$2")"
5
+ exit 1
6
+ fi
7
+
8
+ % end
@@ -0,0 +1,5 @@
1
+ # :script.bash3_bouncer
2
+ if [[ "${BASH_VERSINFO:-0}" -lt 4 ]]; then
3
+ printf "<%= strings[:unsupported_bash_version] -%>\n"
4
+ exit 1
5
+ fi
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env bash
2
2
  # This script was generated by bashly (https://github.com/DannyBen/bashly)
3
3
  # Modifying it manually is not recommended
4
+
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.5
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-09-03 00:00:00.000000000 Z
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