bashly 1.1.6 → 1.1.8

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: 412b8737b7f30c9851116b020bafbb220bb001fcf148d4baf3bc383a32ad3e0d
4
- data.tar.gz: 0b4595b01191d2899f50ab7d74f6f7f9d0ec4901f17daebf57304d197b8e8ccd
3
+ metadata.gz: d11d229ff42dc84aa910ee8292e145b63641c5520315583e92d5aa0747e6e578
4
+ data.tar.gz: 61a2ddcb970af41f7a086da0a75d0452a637e3fe650569e2768f1a0eefe49849
5
5
  SHA512:
6
- metadata.gz: 9af37fd9a1a5883e8c05ff88d3fd1de2b0689586e9717072b17e15dcb55a9c8f228e963e2131aa8828a1fd1d12a51c8373bdf28f650f8e13369dcf84bec3a68a
7
- data.tar.gz: 51a9db127eb74ebbe7e3d55aa8fb6e7f17479c587e632061d62330503103dbed7ca7c405f01d3090036459aaf5a529960156c66d6248849f936aff5be0bcd6d7
6
+ metadata.gz: b9ffdaa7a7a862b11d932e6533d4b7e1b1e76407292bbaf5ca8afdc192249b0f51ea504adfc459e37b712074291ef612fc5b29965700043676bc94709062e696
7
+ data.tar.gz: 629b81b7ef43fa64523a465968828d74192fbd17440e9f20f724a6ef040ebe0c805bed339f899ca6047f53043c29d88537829075bd60be2f752a69e09eaaee55
data/README.md CHANGED
@@ -27,15 +27,6 @@ usually handled by a framework in any other programming language.
27
27
  It is available both as a [ruby gem](https://rubygems.org/gems/bashly) and as
28
28
  a [docker image](https://hub.docker.com/r/dannyben/bashly).
29
29
 
30
- ## Bashly is Sponsored By
31
-
32
- <table>
33
- <tr>
34
- <td><a href="https://rhodecode.com/"><img src='support/img/RhodeCode-logo.png' width=240></a></td>
35
- </tr>
36
- </table>
37
-
38
-
39
30
  ## Documentation
40
31
 
41
32
  - [Bashly Homepage][docs]
@@ -0,0 +1,45 @@
1
+ module Bashly
2
+ # A helper class, used by the `Array#indent` extension.
3
+ # It will return the array of strings with all strings prefixed by `indentation`
4
+ # unless the line is within a heredoc block.
5
+ class IndentationHelper
6
+ attr_reader :marker, :indentation
7
+
8
+ def initialize(indentation)
9
+ @indentation = indentation
10
+ @marker = nil
11
+ end
12
+
13
+ def indent(line)
14
+ if inside_heredoc?
15
+ reset_marker if heredoc_closed?(line)
16
+ line
17
+ else
18
+ set_heredoc_state(line)
19
+ "#{indentation}#{line}"
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def reset_marker
26
+ @marker = nil
27
+ end
28
+
29
+ def inside_heredoc?
30
+ !!marker
31
+ end
32
+
33
+ def set_heredoc_state(line)
34
+ @marker = extract_heredoc_marker(line)
35
+ end
36
+
37
+ def extract_heredoc_marker(line)
38
+ line =~ /<<-?\s*(\w+)/ ? $1 : nil
39
+ end
40
+
41
+ def heredoc_closed?(line)
42
+ inside_heredoc? && /^#{marker}\n?$/.match?(line)
43
+ end
44
+ end
45
+ end
@@ -1,9 +1,13 @@
1
+ require 'bashly/concerns/indentation_helper'
2
+
1
3
  class Array
2
4
  def indent(offset)
3
5
  return self unless offset.positive?
4
6
 
5
7
  indentation = ' ' * offset
6
- map { |line| "#{indentation}#{line}" }
8
+ indenter = Bashly::IndentationHelper.new indentation
9
+
10
+ map { |line| indenter.indent line }
7
11
  end
8
12
 
9
13
  def nonuniq
@@ -1,7 +1,10 @@
1
- # approvals.bash v0.4.0
1
+ # approvals.bash v0.5.0
2
2
  #
3
3
  # Interactive approval testing for Bash.
4
4
  # https://github.com/DannyBen/approvals.bash
5
+ #
6
+ # shellcheck disable=SC2059
7
+ # Disabling SC2059 (quoted format string) because we use dynamic format strings
5
8
  approve() {
6
9
  local expected approval approval_file actual cmd
7
10
  approvals_dir=${APPROVALS_DIR:=approvals}
@@ -9,8 +12,8 @@ approve() {
9
12
  cmd=$1
10
13
  last_exit_code=0
11
14
  actual=$(eval "$cmd" 2>&1) || last_exit_code=$?
12
- if [[ "$allow_diff_regex" ]]; then
13
- actual=$(echo "$actual" | sed "s/$allow_diff_regex/*/g")
15
+ if [[ -v allow_diff_regex && "$allow_diff_regex" ]]; then
16
+ actual=$(echo "$actual" | sed -E "s/$allow_diff_regex/*/g")
14
17
  unset allow_diff_regex
15
18
  fi
16
19
  approval=$(printf "%b" "$cmd" | tr -s -c "[:alnum:]" _)
@@ -21,9 +24,9 @@ approve() {
21
24
  if [[ -f "$approval_file" ]]; then
22
25
  expected=$(cat "$approval_file")
23
26
  else
24
- echo "--- [$(blue "new: $cmd")] ---"
27
+ printf -- "$new_diff_string\n" "$cmd"
25
28
  printf "%b\n" "$actual"
26
- echo "--- [$(blue "new: $cmd")] ---"
29
+ printf -- "$new_diff_string\n" "$cmd"
27
30
  expected="$actual"
28
31
  user_approval "$cmd" "$actual" "$approval_file"
29
32
  return
@@ -32,9 +35,9 @@ approve() {
32
35
  if [[ "$(printf "%b" "$actual")" = "$(printf "%b" "$expected")" ]]; then
33
36
  pass "$cmd"
34
37
  else
35
- echo "--- [$(blue "diff: $cmd")] ---"
38
+ printf -- "$changed_diff_string\n" "$cmd"
36
39
  $diff_cmd <(printf "%b" "$expected\n") <(printf "%b" "$actual\n") | tail -n +4
37
- echo "--- [$(blue "diff: $cmd")] ---"
40
+ printf -- "$changed_diff_string\n" "$cmd"
38
41
  user_approval "$cmd" "$actual" "$approval_file"
39
42
  fi
40
43
  }
@@ -44,22 +47,20 @@ allow_diff() {
44
47
  }
45
48
 
46
49
  describe() {
47
- echo
48
- blue "= $*"
50
+ printf "$describe_string\n" "$*"
49
51
  }
50
52
 
51
53
  context() {
52
- echo
53
- magenta "= $*"
54
+ printf "$context_string\n" "$*"
54
55
  }
55
56
 
56
57
  fail() {
57
- red " FAILED: $*"
58
+ printf "$fail_string\n" "$*"
58
59
  exit 1
59
60
  }
60
61
 
61
62
  pass() {
62
- green " approved: $*"
63
+ printf "$pass_string\n" "$*"
63
64
  return 0
64
65
  }
65
66
 
@@ -67,15 +68,17 @@ expect_exit_code() {
67
68
  if [[ $last_exit_code == "$1" ]]; then
68
69
  pass "exit $last_exit_code"
69
70
  else
70
- fail "Expected exit code $1, got $last_exit_code"
71
+ fail "expected exit code $1, got $last_exit_code"
71
72
  fi
72
73
  }
73
74
 
74
- red() { printf "\e[31m%b\e[0m\n" "$*"; }
75
- green() { printf "\e[32m%b\e[0m\n" "$*"; }
75
+ bold() { printf "\e[1m%b\e[0m\n" "$*"; }
76
76
  blue() { printf "\e[34m%b\e[0m\n" "$*"; }
77
- magenta() { printf "\e[35m%b\e[0m\n" "$*"; }
78
77
  cyan() { printf "\e[36m%b\e[0m\n" "$*"; }
78
+ green() { printf "\e[32m%b\e[0m\n" "$*"; }
79
+ magenta() { printf "\e[35m%b\e[0m\n" "$*"; }
80
+ red() { printf "\e[31m%b\e[0m\n" "$*"; }
81
+ yellow() { printf "\e[33m%b\e[0m\n" "$*"; }
79
82
 
80
83
  # Private
81
84
 
@@ -89,9 +92,9 @@ user_approval() {
89
92
  fi
90
93
 
91
94
  echo
92
- printf "[A]pprove? \n"
95
+ printf "$approval_string"
93
96
  response=$(bash -c "read -n 1 key; echo \$key")
94
- printf "\r"
97
+ printf "\b%.s" $(seq 1 $((${#approval_string} + 1)))
95
98
  if [[ $response =~ [Aa] ]]; then
96
99
  printf "%b\n" "$actual" >"$approval_file"
97
100
  pass "$cmd"
@@ -103,21 +106,32 @@ user_approval() {
103
106
  onexit() {
104
107
  exitcode=$?
105
108
  if [[ "$exitcode" == 0 ]]; then
106
- green "\nFinished successfully"
109
+ printf "$exit_success_string\n" "$0"
107
110
  else
108
- red "\nFinished with failures"
111
+ printf "$exit_failed_string\n" "$0"
109
112
  fi
113
+ echo
110
114
  exit $exitcode
111
115
  }
112
116
 
113
117
  onerror() {
114
- fail "Caller: $(caller)"
118
+ fail "caller: $(caller)"
115
119
  }
116
120
 
117
121
  set -e
118
122
  trap 'onexit' EXIT
119
123
  trap 'onerror' ERR
120
124
 
125
+ describe_string="$(blue ▌ describe) %s"
126
+ context_string="$(magenta ▌ context) %s"
127
+ fail_string=" $(red FAILED) %s"
128
+ pass_string=" $(green approved) %s"
129
+ exit_success_string="$(green ▌ exit) $(bold %s finished successfully)"
130
+ exit_failed_string="$(red ▌ exit) $(bold %s finished with errors)"
131
+ new_diff_string="────┤ $(yellow new): $(bold %s)) ├────"
132
+ changed_diff_string="────┤ $(cyan changed): $(bold %s)) ├────"
133
+ approval_string="[A]pprove? "
134
+
121
135
  if diff --help | grep -- --color >/dev/null 2>&1; then
122
136
  diff_cmd="diff --unified --color=always"
123
137
  else
@@ -1,41 +1,43 @@
1
- module ComposeRefinements
2
- refine Hash do
3
- def compose(keyword = 'import')
4
- result = {}
5
- each do |k, v|
6
- if k.to_s == keyword
7
- sub = safe_load_yaml(v).compose keyword
8
- if sub.is_a? Array
9
- result = sub
1
+ module Bashly
2
+ module ComposeRefinements
3
+ refine Hash do
4
+ def compose(keyword = 'import')
5
+ result = {}
6
+ each do |k, v|
7
+ if k.to_s == keyword
8
+ sub = safe_load_yaml(v).compose keyword
9
+ if sub.is_a? Array
10
+ result = sub
11
+ else
12
+ result.merge! sub
13
+ end
14
+ elsif v.respond_to? :compose
15
+ result[k] = v.compose keyword
10
16
  else
11
- result.merge! sub
17
+ result[k] = v
12
18
  end
13
- elsif v.respond_to? :compose
14
- result[k] = v.compose keyword
15
- else
16
- result[k] = v
17
19
  end
20
+ result
18
21
  end
19
- result
20
- end
21
22
 
22
- def safe_load_yaml(path)
23
- loaded = YAML.load_erb_file path
24
- return loaded if loaded.is_a?(Array) || loaded.is_a?(Hash)
23
+ def safe_load_yaml(path)
24
+ loaded = YAML.load_erb_file path
25
+ return loaded if loaded.is_a?(Array) || loaded.is_a?(Hash)
25
26
 
26
- raise Bashly::ConfigurationError, "Cannot find a valid YAML in g`#{path}`"
27
- rescue Errno::ENOENT
28
- raise Bashly::ConfigurationError, "Cannot find import file g`#{path}`"
27
+ raise Bashly::ConfigurationError, "Cannot find a valid YAML in g`#{path}`"
28
+ rescue Errno::ENOENT
29
+ raise Bashly::ConfigurationError, "Cannot find import file g`#{path}`"
30
+ end
29
31
  end
30
- end
31
32
 
32
- refine Array do
33
- def compose(keyword = 'import')
34
- map do |x|
35
- if x.respond_to? :compose
36
- x.compose keyword
37
- else
38
- x
33
+ refine Array do
34
+ def compose(keyword = 'import')
35
+ map do |x|
36
+ if x.respond_to? :compose
37
+ x.compose keyword
38
+ else
39
+ x
40
+ end
39
41
  end
40
42
  end
41
43
  end
@@ -322,12 +322,17 @@ module Bashly
322
322
  @user_lib ||= Dir["#{Settings.full_lib_dir}/**/*.#{Settings.partials_extension}"]
323
323
  end
324
324
 
325
+ # Returns a mixed array of Argument and Flag objects that have validations
326
+ def validatables
327
+ @validatables ||= args.select(&:validate) + flags.select(&:validate)
328
+ end
329
+
325
330
  # Returns an array of all the args with a whitelist
326
331
  def whitelisted_args
327
332
  args.select(&:allowed)
328
333
  end
329
334
 
330
- # Returns an array of all the environemnt_variables with a whitelist arg
335
+ # Returns an array of all the environment_variables with a whitelist arg
331
336
  def whitelisted_environment_variables
332
337
  environment_variables.select(&:allowed)
333
338
  end
@@ -1,3 +1,3 @@
1
1
  module Bashly
2
- VERSION = '1.1.6'
2
+ VERSION = '1.1.8'
3
3
  end
@@ -1,4 +1,4 @@
1
- # View Tempaltes
1
+ # View Templates
2
2
 
3
3
  These are [GTX](https://github.com/dannyben/gtx) templates.
4
4
 
@@ -1,11 +1,22 @@
1
1
  if validate
2
+ = view_marker
2
3
 
3
- = view_marker
4
-
5
- > if [[ -n $(validate_{{ validate }} "$1") ]]; then
6
- > printf "{{ strings[:validation_error] }}\n" "{{ name.upcase }}" "$(validate_{{ validate }} "$1")" >&2
7
- > exit 1
8
- > fi
9
- >
4
+ if repeatable
5
+ > if [[ -v args['{{ name }}'] ]]; then
6
+ > eval "values=(${args['{{ name }}']})"
7
+ > for value in "${values[@]}"; do
8
+ > if [[ -n $(validate_{{ validate }} "$value") ]]; then
9
+ > printf "{{ strings[:validation_error] }}\n" "{{ name.upcase }}" "$(validate_{{ validate }} "$value")" >&2
10
+ > exit 1
11
+ > fi
12
+ > done
13
+ > fi
14
+ else
15
+ > if [[ -v args['{{ name }}'] && -n $(validate_{{ validate }} "${args['{{ name }}']:-}") ]]; then
16
+ > printf "{{ strings[:validation_error] }}\n" "{{ name.upcase }}" "$(validate_{{ validate }} "${args['{{ name }}']:-}")" >&2
17
+ > exit 1
18
+ > fi
19
+ >
20
+ end
10
21
 
11
22
  end
@@ -27,3 +27,4 @@ end
27
27
  > shift
28
28
  > done
29
29
  > }
30
+ >
@@ -15,6 +15,7 @@ end
15
15
  = render(:required_flags_filter).indent 2
16
16
  = render(:catch_all_filter).indent 2
17
17
  = render(:default_assignments).indent 2
18
+ = render(:validations).indent 2
18
19
  = render(:whitelist_filter).indent 2
19
20
  = render(:user_filter).indent 2
20
21
 
@@ -4,7 +4,6 @@ if args.any?
4
4
  condition = "if"
5
5
  args.each do |arg|
6
6
  > {{ condition }} [[ -z ${args['{{ arg.name }}']+x} ]]; then
7
- = arg.render(:validations).indent 2
8
7
  > args['{{ arg.name }}']=$1
9
8
  > shift
10
9
 
@@ -2,7 +2,6 @@
2
2
 
3
3
  condition = "if"
4
4
  args.each do |arg|
5
- = arg.render(:validations)
6
5
  > {{ condition }} [[ -z ${args['{{ arg.name }}']+x} ]]; then
7
6
  if arg.repeatable
8
7
  > args['{{ arg.name }}']="\"$1\""
@@ -4,7 +4,6 @@ if args.any?
4
4
  condition = "if"
5
5
  args.each do |arg|
6
6
  > {{ condition }} [[ -z ${args['{{ arg.name }}']+x} ]]; then
7
- > {{ arg.render(:validations).indent 2 }}
8
7
  > args['{{ arg.name }}']=$1
9
8
  > shift
10
9
 
@@ -0,0 +1,7 @@
1
+ if validatables.any?
2
+ = view_marker
3
+
4
+ validatables.each do |arg_or_flag|
5
+ = arg_or_flag.render(:validations)
6
+ end
7
+ end
@@ -1,7 +1,6 @@
1
1
  = view_marker
2
2
 
3
3
  > if [[ -n ${2+x} ]]; then
4
- = render(:validations).indent 2
5
4
 
6
5
  if repeatable
7
6
  > if [[ -z ${args['{{ name }}']+x} ]]; then
@@ -1,11 +1,22 @@
1
1
  if validate
2
-
3
2
  = view_marker
4
3
 
5
- > if [[ -n $(validate_{{ validate }} "$2") ]]; then
6
- > printf "{{ strings[:validation_error] }}\n" "{{ usage_string }}" "$(validate_{{ validate }} "$2")" >&2
7
- > exit 1
8
- > fi
9
- >
4
+ if repeatable
5
+ > if [[ -v args['{{ long }}'] ]]; then
6
+ > eval "values=(${args['{{ long }}']})"
7
+ > for value in "${values[@]}"; do
8
+ > if [[ -n $(validate_{{ validate }} "$value") ]]; then
9
+ > printf "{{ strings[:validation_error] }}\n" "{{ usage_string }}" "$(validate_{{ validate }} "$value")" >&2
10
+ > exit 1
11
+ > fi
12
+ > done
13
+ > fi
14
+ else
15
+ > if [[ -v args['{{ long }}'] && -n $(validate_{{ validate }} "${args['{{ long }}']:-}") ]]; then
16
+ > printf "{{ strings[:validation_error] }}\n" "{{ usage_string }}" "$(validate_{{ validate }} "${args['{{ long }}']:-}")" >&2
17
+ > exit 1
18
+ > fi
19
+ >
20
+ end
10
21
 
11
22
  end
data/lib/bashly.rb CHANGED
@@ -1,5 +1,5 @@
1
- if ENV['BYEBUG']
2
- require 'byebug'
1
+ if ENV['DEBUGGER']
2
+ require 'debug'
3
3
  require 'lp'
4
4
  end
5
5
 
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: 1.1.6
4
+ version: 1.1.8
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: 2023-12-29 00:00:00.000000000 Z
11
+ date: 2024-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colsole
@@ -161,6 +161,7 @@ files:
161
161
  - lib/bashly/completions/completely.yaml.gtx
162
162
  - lib/bashly/concerns/asset_helper.rb
163
163
  - lib/bashly/concerns/completions.rb
164
+ - lib/bashly/concerns/indentation_helper.rb
164
165
  - lib/bashly/concerns/renderable.rb
165
166
  - lib/bashly/concerns/validation_helpers.rb
166
167
  - lib/bashly/config.rb
@@ -265,6 +266,7 @@ files:
265
266
  - lib/bashly/views/command/user_filter.gtx
266
267
  - lib/bashly/views/command/user_hooks.gtx
267
268
  - lib/bashly/views/command/user_lib.gtx
269
+ - lib/bashly/views/command/validations.gtx
268
270
  - lib/bashly/views/command/version_command.gtx
269
271
  - lib/bashly/views/command/whitelist_filter.gtx
270
272
  - lib/bashly/views/environment_variable/usage.gtx
@@ -301,7 +303,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
301
303
  - !ruby/object:Gem::Version
302
304
  version: '0'
303
305
  requirements: []
304
- rubygems_version: 3.3.26
306
+ rubygems_version: 3.5.6
305
307
  signing_key:
306
308
  specification_version: 4
307
309
  summary: Bash Command Line Tool Generator