squared 0.4.26 → 0.4.27

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: 31cca2889400b4e4b51df7249ac426d782a9905cc69e731d0766ef1012002651
4
- data.tar.gz: 4353d4d765dc14916e6db6c9605cc0b02fe48b353adc0ed274c08f01e0cc6f25
3
+ metadata.gz: 570209d462189db6296821f539a7b2a3a088c627fa890b25144bbc3c92e1b197
4
+ data.tar.gz: d92b3f063d0504a2a1962c0a2b096e8ebe8062da8c33e1a16799edf0c806e1a1
5
5
  SHA512:
6
- metadata.gz: 6fda0932de949193edfc82bb533c3b21b39624b2d1d8fc3b1762b0c8e93ce47807e9a34c8b378896d6f4f92c18d06ae82b217dfd42539667cb0df3de5d98cd5c
7
- data.tar.gz: 411bba4daeb35c641b67306bba13502a78cab65c09e94d3a5fcef0f7ad213f5a8a75886b641a32d4e1dce83b6c697784ca438d4c570a30dd3d331ae8b25541c0
6
+ metadata.gz: 6c1f4387eafc98bd80390bc284127fd1018bd191b65dde56666941094609743e44bf82247cc9a3ac39b192ae72f89adf4ef93a9d06ede529fa4201237e74be97
7
+ data.tar.gz: 1d1117d69bd95cf81964b52b7cf0c7c67d9a693bc3716767da0daeb5b1a1a6d8f9016c0d0e01f74dac392aee66af74b7e85a67528d06f99c99d6e2921384e155
data/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.27] - 2025-11-05
4
+
5
+ ### Changed
6
+
7
+ - OptionPartition does not add quotes when an option flag is detected.
8
+ - Common shell method argument option only parses options with values.
9
+ - Shell options with empty flags are treated as quoted strings.
10
+
11
+ ### Fixed
12
+
13
+ - OptionPartition did not detect flags with middle dashes.
14
+
3
15
  ## [0.4.26] - 2025-10-31
4
16
 
5
17
  ### Added
@@ -1064,6 +1076,7 @@
1064
1076
 
1065
1077
  - Changelog was created.
1066
1078
 
1079
+ [0.4.27]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.27
1067
1080
  [0.4.26]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.26
1068
1081
  [0.4.25]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.25
1069
1082
  [0.4.24]: https://github.com/anpham6/squared-ruby/releases/tag/v0.4.24
@@ -6,11 +6,14 @@ require 'rake'
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)
@@ -35,54 +38,64 @@ module Squared
35
38
  Rake::Win32.windows? ? $2 : Shellwords.escape($2)
36
39
  end
37
40
  elsif Rake::Win32.windows?
38
- quote ? shell_quote(val, double: double, force: force) : val
41
+ quote ? shell_quote(val, force: force, double: double) : val
42
+ elsif val.empty?
43
+ ''
39
44
  else
40
- val.empty? ? '' : Shellwords.escape(val)
45
+ Shellwords.escape(val)
41
46
  end
42
47
  end
43
48
 
44
- def shell_quote(val, option: true, force: true, double: false, override: false)
49
+ def shell_quote(val, option: true, force: true, double: false, preserve: true, override: false)
45
50
  val = val.to_s
46
51
  return val if (!force && !val.include?(' ')) || val.empty?
47
52
 
48
- if option && val.match?(/(?:\A|\A[^=\s]+(?:=|\s+)|#{Rake::Win32.windows? ? '[\\\/]' : '\/'})(["']).+\1\z/m)
49
- return val
53
+ if option
54
+ pat = /\A(?:-[^\[\]=\s-](?:=|\s+)?|(--)?[^\[\]=\s-][^\[\]=\s]*(?(1)(?:=|\s+)|=))(["']).+\2\z/m
55
+ return val if val.match?(pat)
50
56
  end
57
+ q = ->(s) { s.gsub("'\\\\''", "'") }
58
+ if val =~ QUOTE_VALUE
59
+ return val if $1 == '"' && Rake::Win32.windows? && val.match?(/(?:[#{File::SEPARATOR} ]|\\")/o)
51
60
 
61
+ base = $2 unless preserve
62
+ end
52
63
  if double || Rake::Win32.windows? || (ARG[:QUOTE] == '"' && !override)
53
- "\"#{val.gsub(/(?<!\\)"/, '\\"')}\""
64
+ "\"#{q.call(base || val).gsub(/(?<!\\)"/, '\\"')}\""
54
65
  else
55
- "'#{val.gsub("'", "'\\\\''")}'"
66
+ base ? val : "'#{q.call(val).gsub("'", "'\\\\''")}'"
56
67
  end
57
68
  end
58
69
 
59
70
  def shell_option(flag, val = nil, escape: true, quote: true, option: true, force: true, double: false,
60
71
  merge: false, override: false)
61
72
  flag = flag.to_s
62
- if flag =~ /\A(["'])(.+)\1\z/
73
+ if flag =~ QUOTE_VALUE
63
74
  double = $1 == '"'
64
75
  flag = $2
65
76
  escape = false
66
77
  override = true
67
78
  end
68
- b = if flag[0] == '-'
69
- flag[1] == '-' ? '=' : ' '
70
- elsif flag.size == 1
71
- a = '-'
72
- merge ? '' : ' '
73
- else
74
- a = '--'
75
- '='
76
- end
77
- "#{a}#{flag}#{unless val.nil?
78
- "#{b}#{if escape
79
- shell_escape(val, quote: quote, double: double, override: override)
80
- elsif quote
81
- shell_quote(val, option: option, force: force, double: double, override: override)
82
- else
83
- val
84
- end}"
85
- end}"
79
+ sep = unless flag.empty?
80
+ if flag[0] == '-'
81
+ flag[1] == '-' ? '=' : ' '
82
+ elsif flag.size == 1
83
+ pre = '-'
84
+ merge ? '' : ' '
85
+ else
86
+ pre = '--'
87
+ '='
88
+ end
89
+ end
90
+ "#{pre}#{flag}#{unless val.nil?
91
+ "#{sep}#{if escape
92
+ shell_escape(val, quote: quote, double: double, override: override)
93
+ elsif quote
94
+ shell_quote(val, option: option, force: force, double: double, override: override)
95
+ else
96
+ val
97
+ end}"
98
+ end}"
86
99
  end
87
100
 
88
101
  def shell_split(val, quote: false, force: false, join: nil)
@@ -94,8 +107,8 @@ module Squared
94
107
 
95
108
  def shell_bin(name, env: true)
96
109
  key = name.upcase
97
- shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name, option: false, force: false,
98
- double: true)
110
+ shell_quote((env && ENV["PATH_#{key}"]) || PATH[key] || PATH[key.to_sym] || name,
111
+ option: false, force: false, double: true)
99
112
  end
100
113
 
101
114
  def fill_option(val, **kwargs)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Squared
4
- VERSION = '0.4.26'
4
+ VERSION = '0.4.27'
5
5
  end
@@ -697,7 +697,7 @@ module Squared
697
697
  end
698
698
  break uri = url if data
699
699
  end
700
- unless data && (ext ||= URI.parse(uri).path[/\.(\w+)(?:\?|\z)/, 1])
700
+ unless data && (ext ||= URI.decode_www_form_component(URI.parse(uri).path[/\.([\w%]+)(?:\?|\z)/, 1]))
701
701
  raise_error("no content#{data ? ' type' : ''}", hint: uri)
702
702
  end
703
703
  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)
@@ -90,6 +92,10 @@ module Squared
90
92
  Array(target).compact.any? { |val| r.any? { |pat| pat.match?(val.to_s) } }
91
93
  end
92
94
 
95
+ def opt?(val)
96
+ val.start_with?('-') && (OPT_NAME.match?(val) || OPT_VALUE.match?(val) || OPT_SINGLE.match?(val))
97
+ end
98
+
93
99
  def pattern?(val)
94
100
  val.match?(/(?:\A\^|\$\z)/) || val.match?(/(?:\.[*+]|\(\?:|\\[dsw]|\[.+\]|\{\d+,?\d*\})/)
95
101
  end
@@ -380,7 +386,8 @@ module Squared
380
386
  end
381
387
 
382
388
  def add_quote(*args, **kwargs)
383
- merge(args.map! { |val| shell_quote(val, **kwargs) })
389
+ args.compact!
390
+ merge(args.map! { |val| val == '--' || OptionPartition.opt?(val) ? val : shell_quote(val, **kwargs) })
384
391
  self
385
392
  end
386
393
 
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.4.26
4
+ version: 0.4.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - An Pham