squared 0.5.12 → 0.5.13

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: e711136d645a7a32cb93a09fc7562525a7fd9bc725436c5db5846fa217ac013c
4
- data.tar.gz: 9fe647b2d3021fb50a2d4d4a3983d12422ecbbdbcb92324461382faf5efcb4c7
3
+ metadata.gz: b3ed5681f473df27b02a4787101d56a1081c2c1bd6db77b2e9f39368b8b131dc
4
+ data.tar.gz: c968c299822d98c675f032f024d904305c5aaa045dccced2f8d02228b714bdc9
5
5
  SHA512:
6
- metadata.gz: 58dee7d115025166ad1326dc11e76f9708ce4af715f1d85b53e2d19799b07aab81118eb82283913a2fee9401b005c0eb9c883f1c820d3b7bfadf9eed2a845013
7
- data.tar.gz: 2bac7d7f87848d78327542d4be5f5535f4d8ed45e818afa27b5a408f921c90363655de8a88dcf4d49d5da44902b5c87c6628cc75b1afe8875eee5bdecc48e3c6
6
+ metadata.gz: 670b650344b8a956b15d90d3d24c0a60ee03a13c36875dddb2db51bc8a93919ff7f10c2270b01062418b3e36f285aa824d7ac87465a2499f1830b257d757fb08
7
+ data.tar.gz: dd50aee39f1bdd0def09334ea6383e835c56ca103cee67c0937c1bd0a963356d909196fc284f1ce2247078c4a230690b620b313b0a0bbf8a4613367f477f0fb7
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.13] - 2025-11-05
4
+
5
+ ### Fixed
6
+
7
+ - See `0.4.27`.
8
+
9
+ ## [0.4.27] - 2025-11-05
10
+
11
+ ### Changed
12
+
13
+ - OptionPartition does not add quotes when an option flag is detected.
14
+ - Common shell method argument option only parses options with values.
15
+ - Shell options with empty flags are treated as quoted strings.
16
+
17
+ ### Fixed
18
+
19
+ - OptionPartition did not detect flags with middle dashes.
20
+
3
21
  ## [0.5.12] - 2025-10-31
4
22
 
5
23
  ### Changed
@@ -1184,6 +1202,7 @@
1184
1202
 
1185
1203
  - Changelog was created.
1186
1204
 
1205
+ [0.5.13]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.13
1187
1206
  [0.5.12]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.12
1188
1207
  [0.5.11]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.11
1189
1208
  [0.5.10]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.10
@@ -1197,6 +1216,7 @@
1197
1216
  [0.5.2]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.2-ruby
1198
1217
  [0.5.1]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.1-ruby
1199
1218
  [0.5.0]: https://github.com/anpham6/squared-ruby/releases/tag/v0.5.0-ruby
1219
+ [0.4.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.27
1200
1220
  [0.4.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.26
1201
1221
  [0.4.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.25
1202
1222
  [0.4.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.24
@@ -6,11 +6,14 @@ require 'shellwords'
6
6
  module Squared
7
7
  module Common
8
8
  module Shell
9
+ QUOTE_VALUE = /\A(["'])(.*)\1\z/m.freeze
10
+ private_constant :QUOTE_VALUE
11
+
9
12
  module_function
10
13
 
11
14
  def shell_escape(val, quote: false, force: false, double: false, option: false, override: false)
12
- if (r = /\A(--?)([^= ]+)((=|\s+)(["'])?(?(5)(.*)\5|(.*)))?\z/m.match(val = val.to_s))
13
- if (data = r[2].match(/\A(["'])(.+)\1\z/))
15
+ if (r = /\A(--?)([^=\s]+)((=|\s+)(["'])?(?(5)(.*)\5|(.*)))?\z/m.match(val = val.to_s))
16
+ if (data = r[2].match(QUOTE_VALUE))
14
17
  double = data[1] == '"'
15
18
  override = true
16
19
  elsif !r[3] || r[6]
@@ -25,9 +28,9 @@ module Squared
25
28
 
26
29
  r[7]
27
30
  end
28
- r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt, double: double, force: force, override: override)
29
- elsif option && val =~ /\A([^=]+)=(.+)\z/m
30
- return val if $2.match?(/\A(["']).+\1\z/m)
31
+ r[1] + (data ? data[2] : r[2]) + r[4] + shell_quote(opt, force: force, double: double, override: override)
32
+ elsif option && val =~ /\A(-{0,2}[^\[\]=\s-][^\[\]=\s]*)=(.+)\z/m
33
+ return val if $2.match?(QUOTE_VALUE)
31
34
 
32
35
  "#{$1}=%s" % if $2.include?(' ')
33
36
  shell_quote($2, option: false)
@@ -37,7 +40,7 @@ module Squared
37
40
  Shellwords.escape($2)
38
41
  end
39
42
  elsif Rake::Win32.windows?
40
- quote ? shell_quote(val, double: double, force: force) : val
43
+ quote ? shell_quote(val, force: force, double: double) : val
41
44
  elsif val.empty?
42
45
  ''
43
46
  else
@@ -45,48 +48,56 @@ module Squared
45
48
  end
46
49
  end
47
50
 
48
- def shell_quote(val, option: true, force: true, double: false, override: false)
51
+ def shell_quote(val, option: true, force: true, double: false, preserve: true, override: false)
49
52
  val = val.to_s
50
53
  return val if (!force && !val.include?(' ')) || val.empty?
51
54
 
52
- if option && val.match?(/(?:\A|\A[^=\s]+(?:=|\s+)|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/m)
53
- return val
55
+ if option
56
+ pat = /\A(?:-[^\[\]=\s-](?:=|\s+)?|(--)?[^\[\]=\s-][^\[\]=\s]*(?(1)(?:=|\s+)|=))(["']).+\2\z/m
57
+ return val if val.match?(pat)
54
58
  end
59
+ q = ->(s) { s.gsub("'\\\\''", "'") }
60
+ if val =~ QUOTE_VALUE
61
+ return val if $1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o)
55
62
 
63
+ base = $2 unless preserve
64
+ end
56
65
  if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
57
- "\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
66
+ "\"#{q.call(base || val).gsub(/(?<!\\)"/, '\\"')}\""
58
67
  else
59
- "'#{val.gsub("'", "'\\\\''")}'"
68
+ base ? val : "'#{q.call(val).gsub("'", "'\\\\''")}'"
60
69
  end
61
70
  end
62
71
 
63
72
  def shell_option(flag, val = nil, escape: true, quote: true, option: true, force: true, double: false,
64
73
  merge: false, override: false)
65
74
  flag = flag.to_s
66
- if flag =~ /\A(["'])(.+)\1\z/
75
+ if flag =~ QUOTE_VALUE
67
76
  double = $1 == '"'
68
77
  flag = $2
69
78
  escape = false
70
79
  override = true
71
80
  end
72
- b = if flag[0] == '-'
73
- flag[1] == '-' ? '=' : ' '
74
- elsif flag.size == 1
75
- a = '-'
76
- merge ? '' : ' '
77
- else
78
- a = '--'
79
- '='
80
- end
81
- "#{a}#{flag}#{unless val.nil?
82
- "#{b}#{if escape
83
- shell_escape(val, quote: quote, double: double, override: override)
84
- elsif quote
85
- shell_quote(val, option: option, force: force, double: double, override: override)
86
- else
87
- val
88
- end}"
89
- end}"
81
+ sep = unless flag.empty?
82
+ if flag[0] == '-'
83
+ flag[1] == '-' ? '=' : ' '
84
+ elsif flag.size == 1
85
+ pre = '-'
86
+ merge ? '' : ' '
87
+ else
88
+ pre = '--'
89
+ '='
90
+ end
91
+ end
92
+ "#{pre}#{flag}#{unless val.nil?
93
+ "#{sep}#{if escape
94
+ shell_escape(val, quote: quote, double: double, override: override)
95
+ elsif quote
96
+ shell_quote(val, option: option, force: force, double: double, override: override)
97
+ else
98
+ val
99
+ end}"
100
+ end}"
90
101
  end
91
102
 
92
103
  def shell_split(val, join: nil, **kwargs)
@@ -98,8 +109,8 @@ module Squared
98
109
 
99
110
  def shell_bin(name, env: true)
100
111
  key = name.upcase
101
- shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name, option: false, force: false,
102
- double: true)
112
+ shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
113
+ option: false, force: false, double: true)
103
114
  end
104
115
 
105
116
  def line_width(lines)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.5.12'
4
+ VERSION = '0.5.13'
5
5
  end
@@ -739,7 +739,7 @@ module Squared
739
739
  end
740
740
  break uri = url if data
741
741
  end
742
- unless data && (ext ||= URI.parse(uri).path[/\.(\w+)(?:\?|\z)/, 1])
742
+ unless data && (ext ||= URI.decode_www_form_component(URI.parse(uri).path[/\.([\w%]+)(?:\?|\z)/, 1]))
743
743
  raise_error("no content#{data ? ' type' : ''}", hint: uri)
744
744
  end
745
745
  end
@@ -10,9 +10,9 @@ module Squared
10
10
  include Common::Shell
11
11
  extend Forwardable
12
12
 
13
- OPT_NAME = /\A(?:(--)|-)((?(1)[A-Za-z\d]+|[A-Za-z\d]))\z/
14
- OPT_VALUE = /\A-{0,2}([^= ]+)(?: *= *| +)(.+)\z/
15
- OPT_SINGLE = /\A-([A-Za-z\d])(.+)\z/
13
+ OPT_NAME = /\A(?:(--)|-)((?(1)[^\[\]=\s-][^\[\]=\s]*|[^\[\]=\s-]))\z/
14
+ OPT_VALUE = /\A-{0,2}([^\[\]=\s-][^\[\]=\s]*)(?:\s*=\s*|\s+)(.+)\z/
15
+ OPT_SINGLE = /\A-([^\[\]=\s-])(.+)\z/
16
16
  private_constant :OPT_NAME, :OPT_VALUE, :OPT_SINGLE
17
17
 
18
18
  class << self
@@ -31,7 +31,9 @@ module Squared
31
31
  end
32
32
  if escape || quote
33
33
  ret.map! do |val|
34
- if escape
34
+ if opt?(val)
35
+ val
36
+ elsif escape
35
37
  shell_escape(val, quote: quote, double: double)
36
38
  else
37
39
  shell_quote(val, force: force, double: double)
@@ -91,6 +93,10 @@ module Squared
91
93
  r.any? { |pat| s.any?(pat) }
92
94
  end
93
95
 
96
+ def opt?(val)
97
+ val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
98
+ end
99
+
94
100
  def pattern?(val)
95
101
  val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
96
102
  end
@@ -415,7 +421,8 @@ module Squared
415
421
  end
416
422
 
417
423
  def add_quote(*args, **kwargs)
418
- merge(args.compact.map! { |val| val == '--' ? val : shell_quote(val, **kwargs) })
424
+ args.compact!
425
+ merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
419
426
  self
420
427
  end
421
428
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: squared
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.12
4
+ version: 0.5.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham