bashly 1.3.6 → 1.3.7

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c216518e1752d66966dfa1b8efad9a24afb5d55119a350ac9ad460abea748be0
4
- data.tar.gz: 8626f99cfc41d424363969bbe46474fc86f8998f44c17d8196c03044281fbf6e
3
+ metadata.gz: 895095279e0e8793275a7f5c0e982b5ea9277881d73195d98212dab3303f682b
4
+ data.tar.gz: b7513cf9828698db23b417b7bff2941fc57045c28bc4968d5b33da2734834934
5
5
  SHA512:
6
- metadata.gz: 7b49310fec1d05dcf12504a8be34493d4e6d8af7ef9b2e35ea57da6424ca0820ee6abb7145ea54835ac31778db0ff89e6c6999050133f5851545ac67dc7f5b6c
7
- data.tar.gz: 0b443ed8497671ff9faf2c720961d3344a5bbfb670096c9a74388cb54541f782b4316a198e4b2dfc7ed17b45a83991df2894ce05f3d76f943f694a63aa090bb2
6
+ metadata.gz: e8eb40deb329c675f94bf1ec65d8832709c60dbdc15c76d7a3419c780852ccbb9d18110fb7fbda29d9f197a7329ffec49ae8781bd332f91ed8e49c379e5c98e7
7
+ data.tar.gz: 31fe31dbfb2445633b367210c415b9764ff7614b257ebcc4116b2128152cbdd2df0a528c3b8a44029f96b473e0528911e09339fca10ff6292af61ad8c0559664
data/README.md CHANGED
@@ -13,6 +13,8 @@ Create feature-rich bash scripts using simple YAML configuration
13
13
 
14
14
  </div>
15
15
 
16
+ ![repocard](https://repocard.dannyben.com/svg/bashly.svg)
17
+
16
18
  Bashly is a command line application (written in Ruby) that lets you
17
19
  generate feature-rich bash command line tools.
18
20
 
@@ -193,6 +193,7 @@ module Bashly
193
193
  assert_optional_string "#{key}.group", value['group']
194
194
  assert_optional_string "#{key}.filename", value['filename']
195
195
  assert_optional_string "#{key}.function", value['function']
196
+ assert_optional_string "#{key}.argfile", value['argfile']
196
197
 
197
198
  assert_boolean "#{key}.private", value['private']
198
199
  assert_default_command "#{key}.default", value['default']
@@ -42,6 +42,7 @@ white() { print_in_color "\e[37m" "$*"; }
42
42
 
43
43
  bold() { print_in_color "\e[1m" "$*"; }
44
44
  underlined() { print_in_color "\e[4m" "$*"; }
45
+ bold_underlined() { print_in_color "\e[1;4m" "$*"; }
45
46
 
46
47
  red_bold() { print_in_color "\e[1;31m" "$*"; }
47
48
  green_bold() { print_in_color "\e[1;32m" "$*"; }
@@ -47,7 +47,7 @@ ini_load() {
47
47
  elif [[ $line =~ $key_regex ]]; then
48
48
  key="${BASH_REMATCH[1]}"
49
49
  value="${BASH_REMATCH[2]}"
50
- [[ $value == *\$* ]] && eval "value=\"$value\""
50
+ [[ $value == *\$* ]] && value=$(envsubst <<<"$value")
51
51
  ini["${section}${key}"]="$value"
52
52
  fi
53
53
  done <"$ini_file"
@@ -121,21 +121,6 @@ strings:
121
121
  - source: "strings/strings.yml"
122
122
  target: "%{user_source_dir}/bashly-strings.yml"
123
123
 
124
- test:
125
- help: Add approval testing.
126
- files:
127
- - source: "test/approvals.bash"
128
- target: "%{user_target_dir}/test/approvals.bash"
129
- - source: "test/approve"
130
- target: "%{user_target_dir}/test/approve"
131
-
132
- post_install_message: |
133
- Edit your tests in g`test/approve` and then run:
134
-
135
- m`$ test/approve`
136
-
137
- Docs: bu`https://github.com/DannyBen/approvals.bash`
138
-
139
124
  validations:
140
125
  help: Add argument validation functions to the lib directory.
141
126
  files:
@@ -159,6 +159,17 @@ enable_env_var_names_array: always
159
159
  enable_sourcing: development
160
160
 
161
161
 
162
+ #-------------------------------------------------------------------------------
163
+ # DEVELOPER OPTIONS
164
+ #-------------------------------------------------------------------------------
165
+
166
+ # When true, use filesystem evented watching instead of polling
167
+ watch_evented: false
168
+
169
+ # File change detection latency (seconds)
170
+ watch_latency: 1.0
171
+
172
+
162
173
  #-------------------------------------------------------------------------------
163
174
  # SCRIPTING OPTIONS
164
175
  #-------------------------------------------------------------------------------
@@ -14,7 +14,7 @@ module Bashly
14
14
  class << self
15
15
  def option_keys
16
16
  @option_keys ||= %i[
17
- alias args catch_all commands completions
17
+ alias argfile args catch_all commands completions
18
18
  default dependencies environment_variables examples
19
19
  extensible expose filename filters flags
20
20
  footer function group help help_header_override name
@@ -7,6 +7,11 @@ module Bashly
7
7
  deep_commands(include_self: true).any? { |x| x.catch_all.enabled? }
8
8
  end
9
9
 
10
+ # Returns true if the command or any of its descendants has `argfile`
11
+ def argfile_used_anywhere?
12
+ deep_commands(include_self: true).any?(&:argfile)
13
+ end
14
+
10
15
  # Returns a full list of the Command names and aliases combined
11
16
  def command_aliases
12
17
  commands.map(&:aliases).flatten
@@ -28,9 +28,15 @@ module Bashly
28
28
  :target_dir,
29
29
  :usage_colors,
30
30
  :var_aliases,
31
+ :watch_evented,
32
+ :watch_latency,
31
33
  :word_wrap
32
34
  )
33
35
 
36
+ def all_lib_dirs
37
+ @all_lib_dirs = [full_lib_dir] + extra_lib_dirs
38
+ end
39
+
34
40
  def commands_dir
35
41
  @commands_dir ||= get :commands_dir
36
42
  end
@@ -89,6 +95,17 @@ module Bashly
89
95
  @env = value&.to_sym
90
96
  end
91
97
 
98
+ def extra_lib_dirs
99
+ @extra_lib_dirs ||= begin
100
+ dirs = get :extra_lib_dirs
101
+ case dirs
102
+ when Array then dirs
103
+ when String then dirs.split(',').map(&:strip)
104
+ else []
105
+ end
106
+ end
107
+ end
108
+
92
109
  def formatter
93
110
  @formatter ||= get :formatter
94
111
  end
@@ -109,21 +126,6 @@ module Bashly
109
126
  @lib_dir ||= get :lib_dir
110
127
  end
111
128
 
112
- def extra_lib_dirs
113
- @extra_lib_dirs ||= begin
114
- dirs = get :extra_lib_dirs
115
- case dirs
116
- when Array then dirs
117
- when String then dirs.split(',').map(&:strip)
118
- else []
119
- end
120
- end
121
- end
122
-
123
- def all_lib_dirs
124
- @all_lib_dirs = [full_lib_dir] + extra_lib_dirs
125
- end
126
-
127
129
  def partials_extension
128
130
  @partials_extension ||= get :partials_extension
129
131
  end
@@ -174,6 +176,14 @@ module Bashly
174
176
  @var_aliases ||= get :var_aliases
175
177
  end
176
178
 
179
+ def watch_evented
180
+ @watch_evented ||= get :watch_evented
181
+ end
182
+
183
+ def watch_latency
184
+ @watch_latency ||= get :watch_latency
185
+ end
186
+
177
187
  def word_wrap
178
188
  @word_wrap ||= get :word_wrap
179
189
  end
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = '1.3.6'
2
+ VERSION = '1.3.7'
3
3
  end
@@ -0,0 +1,5 @@
1
+ = view_marker
2
+
3
+ > load_command_argfile "{{ argfile }}" "$@"
4
+ > set -- "${argfile_input[@]}"
5
+ >
@@ -0,0 +1,36 @@
1
+ = view_marker
2
+
3
+ > load_command_argfile() {
4
+ > local argfile_path line arg
5
+ > argfile_path="$1"
6
+ > shift
7
+ > argfile_input=()
8
+ >
9
+ > if [[ ! -f "$argfile_path" ]]; then
10
+ > argfile_input=("$@")
11
+ > return
12
+ > fi
13
+ >
14
+ > while IFS= read -r line || [[ -n "$line" ]]; do
15
+ > line="${line#"${line%%[![:space:]]*}"}"
16
+ > line="${line%"${line##*[![:space:]]}"}"
17
+ >
18
+ > [[ -z "$line" || "${line:0:1}" == "#" ]] && continue
19
+ >
20
+ > if [[ "$line" =~ ^(-{1,2}[^[:space:]]+)[[:space:]]+(.+)$ ]]; then
21
+ > for arg in "${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}"; do
22
+ > arg="${arg#"${arg%%[![:space:]]*}"}"
23
+ > arg="${arg%"${arg##*[![:space:]]}"}"
24
+ > [[ "$arg" =~ ^\"(.*)\"$ || "$arg" =~ ^\'(.*)\'$ ]] && arg="${BASH_REMATCH[1]}"
25
+ > argfile_input+=("$arg")
26
+ > done
27
+ > else
28
+ > arg="$line"
29
+ > [[ "$arg" =~ ^\"(.*)\"$ || "$arg" =~ ^\'(.*)\'$ ]] && arg="${BASH_REMATCH[1]}"
30
+ > argfile_input+=("$arg")
31
+ > fi
32
+ > done <"$argfile_path"
33
+ >
34
+ > argfile_input+=("$@")
35
+ > }
36
+ >
@@ -4,6 +4,7 @@
4
4
  = render :version_command
5
5
  = render :usage
6
6
  = render :normalize_input
7
+ = render :argfile_helpers if argfile_used_anywhere?
7
8
  = render :inspect_args if Settings.enabled? :inspect_args
8
9
  = render :user_lib if user_lib.any?
9
10
  = render :command_functions
@@ -8,6 +8,7 @@ end
8
8
  > local key
9
9
  >
10
10
 
11
+ = render(:argfile_filter).indent 2 if argfile
11
12
  = render(:fixed_flags_filter).indent 2
12
13
  = render(:environment_variables_filter).indent 2
13
14
  = render(:dependencies_filter).indent 2
data/lib/bashly/watch.rb CHANGED
@@ -5,13 +5,8 @@ module Bashly
5
5
  class Watch
6
6
  attr_reader :dirs, :options
7
7
 
8
- DEFAULT_OPTIONS = {
9
- force_polling: true,
10
- latency: 1.0,
11
- }.freeze
12
-
13
8
  def initialize(*dirs, **options)
14
- @options = DEFAULT_OPTIONS.merge(options).freeze
9
+ @options = default_options.merge(options).freeze
15
10
  @dirs = dirs.empty? ? ['.'] : dirs
16
11
  end
17
12
 
@@ -24,10 +19,20 @@ module Bashly
24
19
 
25
20
  private
26
21
 
27
- def build_listener
28
- listen.to(*dirs, **options) do |modified, added, removed|
29
- yield changes(modified, added, removed)
30
- end
22
+ def default_options
23
+ {
24
+ force_polling: force_polling?,
25
+ latency: latency,
26
+ }
27
+ end
28
+
29
+ def force_polling?
30
+ !Settings.watch_evented
31
+ end
32
+
33
+ def latency
34
+ value = Settings.watch_latency.to_f
35
+ value.positive? ? value : 0.1
31
36
  end
32
37
 
33
38
  def start(&block)
@@ -42,16 +47,22 @@ module Bashly
42
47
  @listener = nil
43
48
  end
44
49
 
45
- def changes(modified, added, removed)
46
- { modified:, added:, removed: }
47
- end
48
-
49
50
  def wait
50
51
  sleep
51
52
  rescue ::Interrupt => e
52
53
  raise Bashly::Interrupt, cause: e
53
54
  end
54
55
 
56
+ def build_listener
57
+ listen.to(*dirs, **options) do |modified, added, removed|
58
+ yield changes(modified, added, removed)
59
+ end
60
+ end
61
+
62
+ def changes(modified, added, removed)
63
+ { modified:, added:, removed: }
64
+ end
65
+
55
66
  def listen = Listen
56
67
  end
57
68
  end
data/lib/bashly.rb CHANGED
@@ -1,8 +1,3 @@
1
- if ENV['DEBUGGER']
2
- require 'debug'
3
- require 'lp'
4
- end
5
-
6
1
  require 'requires'
7
2
  requires 'bashly/extensions'
8
3
  requires 'bashly/exceptions'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bashly
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.6
4
+ version: 1.3.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Danny Ben Shitrit
@@ -206,8 +206,6 @@ files:
206
206
  - lib/bashly/libraries/settings/settings.yml
207
207
  - lib/bashly/libraries/stacktrace/stacktrace.sh
208
208
  - lib/bashly/libraries/strings/strings.yml
209
- - lib/bashly/libraries/test/approvals.bash
210
- - lib/bashly/libraries/test/approve
211
209
  - lib/bashly/libraries/validations/validate_dir_exists.sh
212
210
  - lib/bashly/libraries/validations/validate_file_exists.sh
213
211
  - lib/bashly/libraries/validations/validate_integer.sh
@@ -248,6 +246,8 @@ files:
248
246
  - lib/bashly/views/argument/case_repeatable.gtx
249
247
  - lib/bashly/views/argument/usage.gtx
250
248
  - lib/bashly/views/argument/validations.gtx
249
+ - lib/bashly/views/command/argfile_filter.gtx
250
+ - lib/bashly/views/command/argfile_helpers.gtx
251
251
  - lib/bashly/views/command/catch_all_filter.gtx
252
252
  - lib/bashly/views/command/command_fallback.gtx
253
253
  - lib/bashly/views/command/command_filter.gtx
@@ -1,172 +0,0 @@
1
- # approvals.bash v0.5.1
2
- #
3
- # Interactive approval testing for Bash.
4
- # https://github.com/DannyBen/approvals.bash
5
- #
6
- # shellcheck disable=SC2059
7
- # Disabling SC2059 (quoted format string) because we use dynamic format strings
8
- approve() {
9
- local expected approval approval_file actual cmd
10
- approvals_dir=${APPROVALS_DIR:=approvals}
11
-
12
- cmd=$1
13
- last_exit_code=0
14
- actual=$(eval "$cmd" 2>&1) || last_exit_code=$?
15
- if [[ -v allow_diff_regex && "$allow_diff_regex" ]]; then
16
- actual=$(echo "$actual" | sed -E "s/$allow_diff_regex/*/g")
17
- unset allow_diff_regex
18
- fi
19
- approval=$(printf "%b" "$cmd" | tr -s -c "[:alnum:]" _)
20
- approval_file="$approvals_dir/${2:-"$approval"}"
21
-
22
- [[ -d "$approvals_dir" ]] || mkdir "$approvals_dir"
23
-
24
- if [[ -f "$approval_file" ]]; then
25
- expected=$(cat "$approval_file")
26
- else
27
- printf -- "$new_diff_string\n" "$cmd"
28
- printf "%b\n" "$actual"
29
- printf -- "$new_diff_string\n" "$cmd"
30
- expected="$actual"
31
- user_approval "$cmd" "$actual" "$approval_file"
32
- return
33
- fi
34
-
35
- if [[ "$(printf "%b" "$actual")" = "$(printf "%b" "$expected")" ]]; then
36
- pass "$cmd"
37
- else
38
- printf -- "$changed_diff_string\n" "$cmd"
39
- $diff_cmd <(printf "%b" "$expected\n") <(printf "%b" "$actual\n") | tail -n +4
40
- printf -- "$changed_diff_string\n" "$cmd"
41
- user_approval "$cmd" "$actual" "$approval_file"
42
- fi
43
- }
44
-
45
- allow_diff() {
46
- allow_diff_regex="$1"
47
- }
48
-
49
- describe() {
50
- printf "$describe_string\n" "$*"
51
- }
52
-
53
- context() {
54
- printf "$context_string\n" "$*"
55
- }
56
-
57
- it() {
58
- printf "$it_string\n" "$*"
59
- }
60
-
61
- fail() {
62
- printf "$fail_string\n" "$*"
63
- exit 1
64
- }
65
-
66
- pass() {
67
- printf "$pass_string\n" "$*"
68
- return 0
69
- }
70
-
71
- expect_exit_code() {
72
- if [[ $last_exit_code == "$1" ]]; then
73
- pass "exit $last_exit_code"
74
- else
75
- fail "expected exit code $1, got $last_exit_code"
76
- fi
77
- }
78
-
79
- # Private
80
-
81
- print_in_color() {
82
- local color="$1"
83
- shift
84
- if [[ -z ${NO_COLOR+x} ]]; then
85
- printf "$color%b\e[0m\n" "$*"
86
- else
87
- printf "%b\n" "$*"
88
- fi
89
- }
90
-
91
- red() { print_in_color "\e[31m" "$*"; }
92
- green() { print_in_color "\e[32m" "$*"; }
93
- yellow() { print_in_color "\e[33m" "$*"; }
94
- blue() { print_in_color "\e[34m" "$*"; }
95
- magenta() { print_in_color "\e[35m" "$*"; }
96
- cyan() { print_in_color "\e[36m" "$*"; }
97
- bold() { print_in_color "\e[1m" "$*"; }
98
- underlined() { print_in_color "\e[4m" "$*"; }
99
- red_bold() { print_in_color "\e[1;31m" "$*"; }
100
- green_bold() { print_in_color "\e[1;32m" "$*"; }
101
- yellow_bold() { print_in_color "\e[1;33m" "$*"; }
102
- blue_bold() { print_in_color "\e[1;34m" "$*"; }
103
- magenta_bold() { print_in_color "\e[1;35m" "$*"; }
104
- cyan_bold() { print_in_color "\e[1;36m" "$*"; }
105
- red_underlined() { print_in_color "\e[4;31m" "$*"; }
106
- green_underlined() { print_in_color "\e[4;32m" "$*"; }
107
- yellow_underlined() { print_in_color "\e[4;33m" "$*"; }
108
- blue_underlined() { print_in_color "\e[4;34m" "$*"; }
109
- magenta_underlined() { print_in_color "\e[4;35m" "$*"; }
110
- cyan_underlined() { print_in_color "\e[4;36m" "$*"; }
111
-
112
- user_approval() {
113
- local cmd="$1"
114
- local actual="$2"
115
- local approval_file="$3"
116
-
117
- if [[ -v CI || -v GITHUB_ACTIONS ]] && [[ -z "${AUTO_APPROVE+x}" ]]; then
118
- fail "$cmd"
119
- fi
120
-
121
- if [[ -v AUTO_APPROVE ]]; then
122
- response=a
123
- else
124
- echo
125
- printf "$approval_string"
126
- response=$(bash -c "read -n 1 key; echo \$key")
127
- printf "\b%.s" $(seq 1 $((${#approval_string} + 1)))
128
- fi
129
-
130
- if [[ $response =~ [Aa] ]]; then
131
- printf "%b\n" "$actual" >"$approval_file"
132
- pass "$cmd"
133
- else
134
- fail "$cmd"
135
- fi
136
- }
137
-
138
- onexit() {
139
- exitcode=$?
140
- if [[ "$exitcode" == 0 ]]; then
141
- printf "$exit_success_string\n" "$0"
142
- else
143
- printf "$exit_failed_string\n" "$0"
144
- fi
145
- echo
146
- exit $exitcode
147
- }
148
-
149
- onerror() {
150
- fail "caller: $(caller)"
151
- }
152
-
153
- set -e
154
- trap 'onexit' EXIT
155
- trap 'onerror' ERR
156
-
157
- describe_string="$(bold ▌ describe) %s"
158
- context_string="$(bold ▌ context) %s"
159
- it_string="$(bold ▌ it) %s"
160
- fail_string=" $(red_bold failed) %s"
161
- pass_string=" $(green approved) %s"
162
- exit_success_string="$(green ▌ exit) $(bold %s finished successfully)"
163
- exit_failed_string="$(red_bold ▌ exit) $(bold %s finished with errors)"
164
- new_diff_string="────┤ $(yellow new): $(bold %s) ├────"
165
- changed_diff_string="────┤ $(blue changed): $(bold %s) ├────"
166
- approval_string="[A]pprove? "
167
-
168
- if diff --help | grep -- --color >/dev/null 2>&1; then
169
- diff_cmd="diff --unified --color=always"
170
- else
171
- diff_cmd="diff --unified"
172
- fi
@@ -1,25 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Run this from the root directory
3
-
4
- cd ./test || exit
5
- source approvals.bash
6
-
7
- # Update me
8
- cli=./download
9
-
10
- # Tests (context, describe and indentation are optional)
11
- context "when DEBUG is on"
12
- export DEBUG=1
13
-
14
- describe "root command"
15
- approve "$cli"
16
- approve "$cli --help"
17
-
18
- context "when DEBUG is off"
19
- unset DEBUG
20
-
21
- describe "some other command"
22
- approve "$cli other"
23
- approve "$cli other --help"
24
-
25
- # ...more tests...