squared 0.1.3 → 0.2.1

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: 11c047668befa13733be4f81fbac270909c72be73754f70b464e804c11f8204e
4
- data.tar.gz: fac920aa92d55210e48c2f780ea366b58f0c9ed870d524b5bf19eeeeb2628ab1
3
+ metadata.gz: ae7095bd3b6c80ac081ead2d7416fddd1f36b43ebcd94231058b1d8e172506b0
4
+ data.tar.gz: '0296f829c74cee76bcf72bf90c1b47e0d63747adf8cd790b7c3964795d4806ad'
5
5
  SHA512:
6
- metadata.gz: 78b3346cbf690fa4ce9a36431eaad0ffb24d464a46700810c19f6938b5e020c94c1ede8709f61e448f75443f3b8c9df8a00877e380e81beb7ce37732dc244289
7
- data.tar.gz: ee6b18f73590b38fa91a2f73852cbc6ccc467255bed2c5c540731d565dc43e15b1b6c103866003979518ef416fcb450beb5c58f5f1ad1c20119437d5f795aa84
6
+ metadata.gz: 3a4831abda159ce464a8ba38e3e2f16b232d6a95f84139f7ee21c6317917837eb5bed85177ab0f47131e749b63d5ee8662bcff5a48a96388e2c55c46df32b235
7
+ data.tar.gz: 25be7c05ccacd04b11daed4ce393c4a882535939c060aa2b5a24b7e515a2f3b984467e4e3f58ab5ee8b76876107bf1f04cbf7de4d7c0625eb8c690a31045e052
data/CHANGELOG.md CHANGED
@@ -1,5 +1,77 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.1] - 2025-01-08
4
+
5
+ ### Fixed
6
+
7
+ - Ruby command options were misquoted.
8
+
9
+ ## [0.2.0] - 2025-01-07
10
+
11
+ ### Added
12
+
13
+ - Event system when executing a base or extension command.
14
+ - Git extension module with clone command was created.
15
+ - Missing workspace projects can create generation tasks.
16
+ - Node copies over symlinks when global store is detected.
17
+ - Git command rebase was implemented.
18
+ - Ruby command copy uses resolve_feature_path for autodetect.
19
+ - Task descriptions can be transformed using Regexp.
20
+ - Python command outdated is SemVer stylized.
21
+ - Config viewer can pre-parse and autoload file types.
22
+ - Projects can use dependency injection to create tasks.
23
+ - Config viewer can load multiple files of the same type.
24
+ - Unused Project class sub-tasks can be excluded.
25
+ - Project method property version was created.
26
+ - Git pull and fetch action remote can include refspec.
27
+ - Project dependency graph displays version when printed.
28
+ - Git command diff actions between and contain were implemented.
29
+ - Event system was appled to all git commands.
30
+ - Python command depend with Distutils was implemented.
31
+ - Full executable path to programs can be defined in Common.
32
+ - Banners can be hidden by group or reference.
33
+ - Git command reset action patch was implemented.
34
+ - Git command branch was implemented.
35
+ - Project build graph can be created using group or reference.
36
+ - Git command restore action source was implemented.
37
+ - Gem install and update non-deprecated options are fully complete.
38
+ - Pip install options are fully complete.
39
+ - Node command bump action version was implemented.
40
+ - Node command add was implemented.
41
+ - Python command install can use single character options.
42
+ - Gem install and pristine options are fully complete.
43
+ - Gem command outdated was implemented.
44
+ - Git command checkout action track was implemented.
45
+ - Theme style current used with outdated was created.
46
+
47
+ ### Changed
48
+
49
+ - Task description uses a separate Application method.
50
+ - Project populate method base commands can be removed.
51
+ - Git pull and fetch options were revised.
52
+ - Git show actions were reduced to format and oneline.
53
+ - Common module System copy methods were renamed.
54
+ - Unused task arguments as placeholders were removed.
55
+ - Top-level namespaces are not used for standard gems.
56
+ - Task descriptions use a wrapper when calling Rake method.
57
+ - Git pull and fetch actions were reduced to origin and remote.
58
+ - Series class uses delegation for Application instance methods.
59
+ - Global constant alias to module Common was removed.
60
+ - Config viewer delegates task attributes to Project workspace.
61
+ - Global git commands pull-s and rebase-s were renamed using +s.
62
+ - Ruby command gem using pristine was implemented.
63
+ - Git class methods were given same name as command name.
64
+ - Abbreviated command options are no longer supported.
65
+ - Git commit hash uses string interpolation format.
66
+ - Git options ending with "!" use conventional "no-" prefix.
67
+ - Git pull and reset commands were reduced.
68
+
69
+ ### Fixed
70
+
71
+ - Workspace did not locate root folder when main was named.
72
+ - Node tasks without any action are not displayed.
73
+ - Git fetch commands that do not apply to pull are rejected.
74
+
3
75
  ## [0.1.3] - 2024-01-02
4
76
 
5
77
  ### Fixed
@@ -29,7 +101,7 @@
29
101
  - Workspace did not check base project for Windows filename.
30
102
  - Regexp for SemVer did not recognize package names.
31
103
 
32
- ## [0.1.1] - 2024-12-14
104
+ ## [0.1.1] - 2025-12-14
33
105
 
34
106
  ### Added
35
107
 
@@ -79,6 +151,8 @@
79
151
 
80
152
  - Changelog was created.
81
153
 
154
+ [0.2.1]: https://github.com/anpham6/squared/releases/tag/v0.2.1-ruby
155
+ [0.2.0]: https://github.com/anpham6/squared/releases/tag/v0.2.0-ruby
82
156
  [0.1.3]: https://github.com/anpham6/squared/releases/tag/v0.1.3-ruby
83
157
  [0.1.2]: https://github.com/anpham6/squared/releases/tag/v0.1.2-ruby
84
158
  [0.1.1]: https://github.com/anpham6/squared/releases/tag/v0.1.1-ruby
data/README.md CHANGED
@@ -119,6 +119,9 @@ rake repo:init[latest] # squared
119
119
  rake repo:init[0.11.x] # e-mc
120
120
  # OR
121
121
  REPO_ROOT=/tmp/123 NODE_INSTALL=pnpm repo:init
122
+ # OR - without Repo
123
+ rake clone:node # master
124
+ rake clone # node + docs
122
125
  ```
123
126
 
124
127
  > [!TIP]
data/README.ruby.md CHANGED
@@ -1,4 +1,4 @@
1
- # squared 0.1
1
+ # squared 0.2
2
2
 
3
3
  * [source](https://github.com/anpham6/squared)
4
4
  * [manifest](https://github.com/anpham6/squared-repo)
@@ -6,9 +6,12 @@
6
6
 
7
7
  ## Version Compatibility
8
8
 
9
- | Date | squared | Ruby 2 | Ruby 3 |
10
- | :------: | ------: | -----: | -----: |
11
- | 12-07-24 | 0.1.0 | 2.4.0 | 3.0.0 |
9
+ | Date | squared | Min | Max |
10
+ | :--------: | ------: | -----: | -----: |
11
+ | 2024-12-07 | 0.1.0 | 2.4.0 | 3.3.6 |
12
+ | 2025-01-07 | 0.2.0 | 2.4.0 | 3.4.0 |
13
+
14
+ The range chart indicates the latest Ruby tested against at the time of release.
12
15
 
13
16
  ## Installation
14
17
 
@@ -77,7 +80,7 @@ Workspace::Application
77
80
  "CFLAGS" => "-fPIC -O1"
78
81
  })
79
82
  .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
80
- .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
83
+ .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.4.0/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
81
84
  .add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
82
85
  .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
83
86
  .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
@@ -89,8 +92,8 @@ Workspace::Application
89
92
  # OR
90
93
  add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
91
94
  end
92
- .add("squared/sqd", exclude: [:git]) do
93
- variable_set :script, "build:sqd" # Override detection
95
+ .add("squared/sqd", exclude: :git, pass: [:node, 'checkout', 'bump']) do # Skip initialize(:node) + squared:checkout:* + squared:bump:*
96
+ variable_set :script, "build:sqd" # Override detection
94
97
  variable_set :depend, false
95
98
  variable_set :clean, ["build/sqd/"]
96
99
  end
@@ -112,26 +115,71 @@ Workspace::Application
112
115
  # chrome = /workspaces/chrome-docs
113
116
 
114
117
  Workspace::Application
115
- .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
118
+ .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
116
119
  .group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
117
120
  pathname: {
118
- run: "rake compile" # rake rb:pathname:build
121
+ run: "rake compile" # rake rb:pathname:build
119
122
  }
120
123
  })
121
- .with(:python) do # ref=Symbol | group=String
122
- banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
123
- doc("make html") # rake rb:doc:python
124
- run(false) # rake rb:build:python (disabled)
125
- exclude(%i[base git]) # Project::Git.ref (superclass)
126
- add("android-docs", "android") # rake rb:android:doc
127
- add("chrome-docs", "chrome") # rake rb:chrome:doc
128
- end #
124
+ .with(:python) do # ref=Symbol | group=String
125
+ banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
126
+ doc("make html") # rake rb:doc:python
127
+ run(false) # rake rb:build:python (disabled)
128
+ exclude(%i[base git]) # Project::Git.ref (superclass)
129
+ add("android-docs", "android") # rake rb:android:doc
130
+ add("chrome-docs", "chrome") # rake rb:chrome:doc
131
+ end
129
132
  .style("inline", "bold")
130
133
  .build
131
134
  ```
132
135
 
133
136
  **NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
134
137
 
138
+ ### Clone
139
+
140
+ The task is only active when the project directory is empty or does not exist.
141
+
142
+ ```ruby
143
+ Workspace::Application
144
+ .new(main: "squared")
145
+ .git(
146
+ "emc": "https://github.com/anpham6/e-mc", # rake emc:clone
147
+ "pir": { # rake pir:clone
148
+ uri: "https://github.com/anpham6/pi-r", #
149
+ options: { #
150
+ "origin": "github", # --origin='github'
151
+ "recurse-submodules": false, # --no-recurse-submodules
152
+ "shallow-exclude": ["v0.0.1", "v0.0.2"] # --shallow-exclude='v0.0.1' --shallow-exclude='v0.0.2'
153
+ }
154
+ }
155
+ )
156
+ .git("squared", "/path/to/squared", options: { local: true }) # Relative paths resolve from workspace root
157
+ .git(
158
+ {
159
+ emc: { uri: "e-mc", options: { "depth": 2 } }, # https://github.com/anpham6/e-mc
160
+ pir: "pi-r" # Maps task alias to repository folder
161
+ },
162
+ base: "https://github.com/anpham6", # Required
163
+ repo: ["squared", "android-docs", "chrome-docs"], # https://github.com/anpham6/squared
164
+ options: { # Only "repo"
165
+ "depth": 1,
166
+ "quiet": true
167
+ }
168
+ )
169
+ .with(:node) do # rake clone:node
170
+ add("e-mc", "emc") # https://github.com/anpham6/e-mc
171
+ add("pi-r", "pir") # https://github.com/anpham6/pi-r
172
+ add("squared") # https://github.com/anpham6/squared
173
+ end
174
+ .with(:python) do # rake clone:python
175
+ add("android-docs")
176
+ add("chrome-docs")
177
+ end
178
+ .git("https://github.com/anpham6") # Uses already defined root projects
179
+ .git("https://github.com/anpham6", ["emc", "pir"]) # Targets any defined project
180
+ .build(parallel: ["clone"]) # rake clone + rake clone:sync
181
+ ```
182
+
135
183
  ### Graph
136
184
 
137
185
  ```ruby
@@ -143,17 +191,30 @@ Workspace::Application
143
191
  add("chrome-docs", "chrome", graph: "android")
144
192
  end
145
193
  .with(:node) do
146
- graph(["build", "copy"]) # Overrides "git"
147
- add("e-mc", "emc")
148
- add("pi-r", "pir", graph: "emc")
194
+ graph(["build", "copy"], on: { # Overrides "git"
195
+ first: proc { puts "1" },
196
+ last: proc { puts "2" }
197
+ })
198
+ add("e-mc", "emc") do
199
+ first("build", "emc:clean", "emc:depend") # rake emc:clean; rake emc:depend; rake emc:build; puts "123";
200
+ last("build", out: "123") { |out: nil| puts out } #
201
+ error("build") { |err: nil| log.debug err } #
202
+ end
203
+ add("pi-r", "pir", graph: "emc", first: {
204
+ build: proc { puts self.name } # puts "pir"
205
+ })
149
206
  add("squared-express", "express", graph: "pir")
150
- add("squared", graph: ["chrome", "express"])
207
+ add("squared", graph: ["chrome", "express"]) do
208
+ first("git:ls-files") { puts path }
209
+ last("git:ls-files") { puts workspace.root }
210
+ end
151
211
  end
152
212
  .with(:ruby) do
153
213
  add("pathname")
154
214
  add("fileutils", graph: "pathname")
155
215
  add("optparse")
156
216
  add("rake", graph: ["fileutils", "optparse"])
217
+ banner(command: false) # Always hide banner
157
218
  end
158
219
  .build
159
220
  ```
@@ -188,27 +249,30 @@ Workspace::Series.rename("depend", "install")
188
249
  ## Usage
189
250
 
190
251
  ```sh
191
- rake -T # List tasks
192
- rake # rake status (usually "build")
252
+ rake -T # List tasks
253
+ rake # rake status (usually "build")
193
254
 
194
255
  # GIT_OPTIONS=rebase
195
- rake pull # All except "default" + "app"
196
- rake pull:ruby # pathname + optparse + logger
197
- rake pull:default # pathname + optparse
198
- rake pull:app # squared
199
- rake pull:node # emc + pir + squared
200
-
201
- rake build # All except "android"
202
- rake doc # optparse + android
203
- rake depend # All except "default"
204
-
205
- rake build:ruby # rake compile + rake install + rake install
206
-
207
- rake clean # All except "default" + "app"
208
- rake clean:ruby # rake clean + rake clean + ["tmp/"]
209
- rake clean:default # rake clean + rake clean + skip
210
- rake clean:app # none + skip + ["build/"]
211
- rake clean:node # none + ["publish/**/*.js", "tmp/"] + ["build/"]
256
+ rake pull # All except "default" + "app"
257
+ rake pull:ruby # pathname + optparse + logger
258
+ rake pull:default # pathname + optparse
259
+ rake pull:app # squared
260
+ rake pull:node # emc + pir + squared
261
+
262
+ rake build # All except "android"
263
+ rake doc # optparse + android
264
+ rake depend # All except "default"
265
+
266
+ rake build:ruby # rake compile + rake install + rake install
267
+
268
+ rake clean # All except "default" + "app"
269
+ rake clean:ruby # rake clean + rake clean + ["tmp/"]
270
+ rake clean:default # rake clean + rake clean + skip
271
+ rake clean:app # none + skip + ["build/"]
272
+ rake clean:node # none + ["publish/**/*.js", "tmp/"] + ["build/"]
273
+
274
+ rake squared:run[#] # List scripts (node)
275
+ rake squared:rake[#] # List tasks (ruby)
212
276
  ```
213
277
 
214
278
  ```sh
@@ -242,6 +306,7 @@ Non-task:
242
306
  * header
243
307
  * active
244
308
  * inline
309
+ * current
245
310
  * major
246
311
  * red
247
312
  * yellow
@@ -249,6 +314,21 @@ Non-task:
249
314
 
250
315
  ## Environment
251
316
 
317
+ ### Path
318
+
319
+ All project executable programs can have their binary path set to a non-global alias.
320
+
321
+ ```ruby
322
+ Common::PATH.merge!({
323
+ GIT: '/usr/bin/git',
324
+ GEM: '~/.rvm/rubies/ruby-3.4.0/bin/gem',
325
+ BUNDLE: '~/.rvm/gems/ruby-3.4.0/bin/bundle',
326
+ RAKE: '~/.rvm/gems/ruby-3.4.0/bin/rake',
327
+ NPM: '/opt/node/v22.0.0/bin/npm',
328
+ PYTHON: "#{ENV['PYTHONPATH']}/bin/python"
329
+ })
330
+ ```
331
+
252
332
  ### Build
253
333
 
254
334
  ```ruby
data/lib/squared/app.rb CHANGED
@@ -6,5 +6,3 @@ require_relative 'workspace/project/node'
6
6
  require_relative 'workspace/project/python'
7
7
  require_relative 'workspace/project/ruby'
8
8
  require_relative 'config'
9
-
10
- Common = Squared::Common
@@ -2,6 +2,7 @@
2
2
 
3
3
  module Squared
4
4
  module Common
5
+ PATH = {}
5
6
  ARG = {
6
7
  PIPE: 1,
7
8
  OUT: nil,
@@ -11,6 +12,7 @@ module Squared
11
12
  BANNER: true,
12
13
  SPACE: ' => ',
13
14
  GRAPH: ['│', '─', '├', '└', '┬'],
15
+ VIEW: 'view',
14
16
  COLOR: ENV.fetch('NO_COLOR', '').empty?
15
17
  }
16
18
  VAR = {
@@ -35,29 +37,31 @@ module Squared
35
37
  },
36
38
  theme: {
37
39
  workspace: {
38
- header: %i[bold],
39
- active: %i[bold],
40
- inline: %i[bold],
41
- major: %i[bold]
40
+ header: [:bold],
41
+ active: [:bold],
42
+ inline: [:bold],
43
+ current: nil,
44
+ major: [:bold]
42
45
  },
43
46
  project: {},
44
47
  viewer: {
45
- banner: %i[blue bold],
46
- key: %i[bold],
47
- value: %i[green],
48
- string: %i[yellow],
48
+ banner: [:bold],
49
+ border: [:blue],
50
+ key: nil,
51
+ value: [:green],
52
+ string: [:yellow],
49
53
  hash: %i[green black!],
50
54
  array: %i[blue black!],
51
- number: %i[magenta],
55
+ number: [:magenta],
52
56
  undefined: %i[red italic]
53
57
  },
54
58
  logger: {
55
- unknown: %i[cyan],
59
+ unknown: [:cyan],
56
60
  fatal: %i[white bold red!],
57
61
  error: %i[red bold],
58
62
  warn: %i[yellow bold],
59
- info: %i[blue],
60
- debug: %i[green]
63
+ info: [:blue],
64
+ debug: [:green]
61
65
  }
62
66
  }
63
67
  }.compare_by_identity
@@ -76,6 +80,7 @@ module Squared
76
80
  end
77
81
 
78
82
  def __freeze__
83
+ PATH.freeze
79
84
  ARG.freeze
80
85
  VAR.each_value(&:freeze)
81
86
  VAR[:theme].each_value(&:freeze)
@@ -84,7 +89,7 @@ module Squared
84
89
 
85
90
  module_function
86
91
 
87
- def as_a(obj, meth = nil, flat: nil, compact: false)
92
+ def as_a(obj, meth = nil, flat: nil, compact: false, &blk)
88
93
  return [] if obj.nil?
89
94
 
90
95
  unless obj.is_a?(::Array)
@@ -96,7 +101,8 @@ module Squared
96
101
  end
97
102
  obj = obj.flatten(flat.is_a?(::Numeric) ? flat : nil) if flat
98
103
  obj = obj.compact if compact
99
- meth ? obj.map(&meth) : obj
104
+ obj = obj.map(&meth) if meth
105
+ block_given? ? obj.select(&blk) : obj
100
106
  end
101
107
  end
102
108
  end
@@ -34,11 +34,28 @@ module Squared
34
34
  super.match(/[^:]+\z/)[0]
35
35
  end
36
36
 
37
+ attr_reader :delim
38
+
37
39
  def initialize(data = [], delim: ' ')
38
40
  super(data.compact)
39
41
  @delim = delim
40
42
  end
41
43
 
44
+ def pass(&blk)
45
+ ret = to_a.map!(&:to_s).reject(&:empty?)
46
+ block_given? ? ret.reject(&blk) : ret
47
+ end
48
+
49
+ def temp(*args, &blk)
50
+ args.compact!
51
+ ret = pass(&blk)
52
+ unless args.empty?
53
+ ret += args
54
+ ret = Set.new(ret).to_a
55
+ end
56
+ ret.join(@delim)
57
+ end
58
+
42
59
  def done
43
60
  ret = to_s
44
61
  clear
@@ -46,7 +63,7 @@ module Squared
46
63
  end
47
64
 
48
65
  def to_s
49
- to_a.map!(&:to_s).reject(&:empty?).join(@delim)
66
+ pass.join(@delim)
50
67
  end
51
68
  end
52
69
  end
@@ -138,15 +138,15 @@ module Squared
138
138
  def log_sym(level)
139
139
  if level.is_a?(::Numeric)
140
140
  case level
141
- when ::Logger::DEBUG
141
+ when Logger::DEBUG
142
142
  :debug
143
- when ::Logger::INFO
143
+ when Logger::INFO
144
144
  :info
145
- when ::Logger::WARN
145
+ when Logger::WARN
146
146
  :warn
147
- when ::Logger::ERROR
147
+ when Logger::ERROR
148
148
  :error
149
- when ::Logger::FATAL
149
+ when Logger::FATAL
150
150
  :fatal
151
151
  else
152
152
  :unknown
@@ -185,10 +185,10 @@ module Squared
185
185
  end
186
186
 
187
187
  def puts_oe(*args, pipe: 1)
188
- if pipe.is_a?(::Pathname)
188
+ if pipe.is_a?(Pathname)
189
189
  begin
190
- ::File.open(pipe, 'a') do |f|
191
- br = ::File::SEPARATOR == '\\' ? "\r\n" : "\n"
190
+ File.open(pipe, 'a') do |f|
191
+ br = File::SEPARATOR == '\\' ? "\r\n" : "\n"
192
192
  args.flatten.each { |val| f.write("#{strip_style(val.chomp)}#{br}") }
193
193
  end
194
194
  return
@@ -279,7 +279,7 @@ module Squared
279
279
  end
280
280
 
281
281
  def raise_error(*args, hint: nil, kind: ArgumentError)
282
- raise kind, message(*args, hint: hint, empty: true)
282
+ raise kind, message(*args, hint: hint, empty: true), caller_locations(1)
283
283
  end
284
284
  end
285
285
  end
@@ -27,7 +27,7 @@ module Squared
27
27
 
28
28
  def shell_quote(val, force: true)
29
29
  val = val.to_s
30
- return val if (!force && !val.include?(' ')) || val =~ /(?:^|\S=|[^=]\s+)(["']).+\1\z/m
30
+ return val if (!force && !val.include?(' ')) || val.match?(/(?:^|\S=|[^=]\s+)(["']).+\1\z/m)
31
31
 
32
32
  Rake::Win32.windows? ? "\"#{double_quote(val)}\"" : "'#{single_quote(val)}'"
33
33
  end
@@ -40,13 +40,14 @@ module Squared
40
40
  end
41
41
 
42
42
  def shell_option(flag, val = nil, quote: false, escape: true)
43
- "--#{flag}#{if val
44
- "=#{if escape
45
- shell_escape(val, quote: quote)
46
- else
47
- quote ? shell_quote(val) : val
48
- end}"
49
- end}"
43
+ a, b = flag.size == 1 ? ['-', ' '] : ['--', '=']
44
+ "#{a}#{flag}#{if val
45
+ "#{b}#{if escape
46
+ shell_escape(val, quote: quote)
47
+ else
48
+ quote ? shell_quote(val) : val
49
+ end}"
50
+ end}"
50
51
  end
51
52
 
52
53
  def fill_option(val)
@@ -55,6 +56,14 @@ module Squared
55
56
  shell_escape(val.start_with?('-') ? val : "--#{val}")
56
57
  end
57
58
 
59
+ def quote_option(flag, val)
60
+ shell_option(flag, val, escape: false, quote: true)
61
+ end
62
+
63
+ def basic_option(flag, val)
64
+ shell_option(flag, val, escape: false)
65
+ end
66
+
58
67
  def single_quote(val)
59
68
  val.gsub("'", "'\\\\''")
60
69
  end