squared 0.0.10 → 0.0.12

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: 71eae17e75e9ebe9a4fbe250f49da6397b169f06ac85c7f77170b9fc575bd63e
4
- data.tar.gz: f68b5c36da52802d0b952c54a406d6d6bde3085308c465c2f058c8c944dce894
3
+ metadata.gz: 2d9e8c772c9f4d0ce5c54dbeb1b9583d2e477f155036faf34cfc547659c34ec4
4
+ data.tar.gz: 87de412a78c0071eabd4b26713cbf84978a92fca6ea1a6dfe18653ddf22c90ee
5
5
  SHA512:
6
- metadata.gz: 515aa7c65dd969fb9dd165a38716695a6c08ccbf0597ef3d7936bcd70750c2c54f661fc44e9dc303d34b8d99947d27939039654ca5ffd43afcf33f917deb2866
7
- data.tar.gz: cfe3827d03d56619de9d3c60a4df2b249ff1f802bc9a6be407b96c5db95fb14faf6b3719e657c83dc046287d62272f1cf2e676fdad67da345abc93675e511474
6
+ metadata.gz: '08475f426b15c41dab20fbead5d7c1ead70f5d80384e0a0772cbe7b101512a4402a1bb1231b2550f7da16aac2796f8411f6a6e3e570ae728d59b03f88fea5960'
7
+ data.tar.gz: 5c0334640b20dda82641925cd94b41d76be4cd4e603355fef593a5cd69731ac926febab67f3ffa494267291ec9d89efba2f8a9ac4dde978ab2814a0f8a481a67
data/README.ruby.md CHANGED
@@ -34,7 +34,14 @@ Projects from any accessible folder can be added either relative to `REPO_ROOT`
34
34
 
35
35
  ```ruby
36
36
  require "squared"
37
- require "squared/workspace/repo" # Repo (optional)
37
+
38
+ require "squared/workspace"
39
+ require "squared/workspace/repo" # Optional
40
+ require "squared/workspace/project/node" #
41
+ require "squared/workspace/project/python" #
42
+ require "squared/workspace/project/ruby" #
43
+ # OR
44
+ require "squared/app" # All workspace related modules
38
45
 
39
46
  # NODE_ENV = production
40
47
  # REPO_ROOT = /workspaces
@@ -52,7 +59,7 @@ require "squared/workspace/repo" # Repo (optional)
52
59
 
53
60
  Workspace::Application
54
61
  .new(Dir.pwd, main: "squared") # Dir.pwd? (main? is implicitly basename)
55
- .banner("group", "project", styles: %i[yellow black], border: "bold") # name | project | path | ref | group?
62
+ .banner("group", "project", styles: ["yellow", "black"], border: "bold") # name | project | path | ref | group? | parent? | version?
56
63
  .repo("https://github.com/anpham6/squared-repo", "nightly", script: ["build:dev", "build:prod"], ref: :node) # Repo (optional)
57
64
  .run("rake install", ref: :ruby)
58
65
  .depend(false, group: "default")
@@ -63,13 +70,17 @@ Workspace::Application
63
70
  "CFLAGS" => "-fPIC -O1"
64
71
  })
65
72
  .add("optparse", doc: "rake rdoc", group: "default") # Uses bundler/gem_tasks (without C extensions)
66
- .add("logger", copy: { from: "lib", glob: "**/*.rb", gemdir: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
67
- .add("e-mc", "emc", copy: { from: "publish", into: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
68
- .add("pi-r", "pir", copy: { from: "publish", into: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
73
+ .add("logger", copy: { from: "lib", glob: "**/*.rb", into: "~/.rvm/gems/ruby-3.3.5/gems/logger-1.6.1" }, clean: ["tmp/"]) # autodetect: true
74
+ .add("e-mc", "emc", copy: { from: "publish", scope: "@e-mc", also: [:pir, "squared-express/"] }, ref: :node) # Node
75
+ .add("pi-r", "pir", copy: { from: "publish", scope: "@pi-r" }, clean: ["publish/**/*.js", "tmp/"]) # Trailing slash required for directories
69
76
  .add("squared", script: ["build:stage1", "build:stage2"], group: "app") do # Copy target (main)
70
- add("publish/sqd-cli", "cli", exclude: [:git])
71
- add("publish/sqd-serve")
77
+ add("publish/sqd-cli", "cli", exclude: [:git]) # rake cli:build
78
+ add("publish/sqd-serve") # rake sqd-serve:build
72
79
  add("publish/sqd-admin", group: "sqd", exclude: [:base])
80
+ # OR
81
+ with(exclude: [:base]) { add("publish/*", "packages") } # rake packages:sqd-serve:build
82
+ # OR
83
+ add(["publish/sqd-cli", "publish/sqd-serve", "publish/sqd-admin"], true, exclude: [:base]) # rake squared:sqd-serve:build
73
84
  end
74
85
  .add("squared/sqd", exclude: [:git]) do
75
86
  variable_set :script, "build:sqd" # Override detection
@@ -77,7 +88,7 @@ Workspace::Application
77
88
  variable_set :clean, ["build/sqd/"]
78
89
  end
79
90
  .style("banner", 255.255) # 256 colors (fg | fg.bg | -0.bg)
80
- .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean"]) do |workspace|
91
+ .build(default: "status", parallel: ["pull", "fetch", "rebase", "copy", "clean", "outdated:ruby"]) do |workspace|
81
92
  workspace
82
93
  .enable_aixterm
83
94
  .style({
@@ -97,28 +108,80 @@ Workspace::Application
97
108
  .new(ENV["SQUARED_HOME"], prefix: "rb", common: false) # Local styles
98
109
  .group("ruby", "default", run: "rake build", copy: "rake install", clean: "rake clean", ref: :ruby, override: {
99
110
  pathname: {
100
- run: "rake compile" # rake rb:pathname:build
111
+ run: "rake compile" # rake rb:pathname:build
101
112
  }
102
113
  })
103
- .with(:python) do # ref=Symbol | group=String
104
- banner("path", command: false, styles: "yellow") #
105
- doc("make html") # rake rb:doc:python
106
- run(false) # rake rb:build:python (disabled)
107
- exclude(%i[base git]) # Project::Git.ref (superclass)
108
- add("android-docs", "android") # rake rb:android:doc
109
- add("chrome-docs", "chrome") # rake rb:chrome:doc
110
- end #
114
+ .with(:python) do # ref=Symbol | group=String
115
+ banner([:name, ": ", :version], "path") # chrome-docs: 0.1.0 | /workspaces/chrome-docs
116
+ doc("make html") # rake rb:doc:python
117
+ run(false) # rake rb:build:python (disabled)
118
+ exclude(%i[base git]) # Project::Git.ref (superclass)
119
+ add("android-docs", "android") # rake rb:android:doc
120
+ add("chrome-docs", "chrome") # rake rb:chrome:doc
121
+ end #
111
122
  .style("inline", "bold")
112
123
  .build
113
124
  ```
114
125
 
115
- **NOTE**: The use of "**ref**" (class name) is only necessary when running `repo:init` for the first time into an empty directory.
126
+ **NOTE**: The use of "**ref**" (class name) is only necessary when initializing an empty directory (e.g. *rake repo:init*).
127
+
128
+ ### Graph
129
+
130
+ ```ruby
131
+ Workspace::Application
132
+ .new(main: "squared")
133
+ .with(:python) do
134
+ add("android-docs", "android")
135
+ add("chrome-docs", "chrome", graph: "android")
136
+ end
137
+ .with(:node) do
138
+ graph(["build", "copy"]) # Optional
139
+ add("e-mc", "emc")
140
+ add("pi-r", "pir", graph: "emc")
141
+ add("squared-express", "express", graph: "pir")
142
+ add("squared", graph: ["chrome", "express"])
143
+ end
144
+ .with(:ruby) do
145
+ add("pathname")
146
+ add("fileutils", graph: "pathname")
147
+ add("optparse")
148
+ add("rake", graph: ["fileutils", "optparse"])
149
+ end
150
+ .build
151
+ ```
152
+
153
+ ```sh
154
+ rake pir:graph # emc + pir
155
+ rake express:graph # emc + pir + express
156
+ rake chrome:graph # android + chrome
157
+ rake graph:python # same
158
+ rake squared:graph # android + chrome + emc + pir + express + squared
159
+ rake graph:node # same
160
+ rake rake:graph # pathname + fileutils + optparse + rake
161
+ rake graph:ruby # same
162
+ rake graph # graph:node + graph:ruby
163
+ ```
164
+
165
+ ### Batch
166
+
167
+ ```ruby
168
+ Workspace::Series.batch(:ruby, :node, {
169
+ stage: %i[graph test],
170
+ reset: %i[stash pull]
171
+ })
172
+ ```
173
+
174
+ ### Rename
175
+
176
+ ```ruby
177
+ Workspace::Series.rename("depend", "install")
178
+ ```
116
179
 
117
180
  ## Usage
118
181
 
119
182
  ```sh
120
- rake -T # List tasks
121
- rake # rake status (usually "build")
183
+ rake -T # List tasks
184
+ rake # rake status (usually "build")
122
185
 
123
186
  # GIT_OPTIONS=rebase
124
187
  rake pull # All except "default" + "app"
@@ -145,6 +208,7 @@ rake build:app # squared + cli + sqd-serve
145
208
  rake squared:build:workspace # cli + sqd-serve
146
209
  rake pull:sqd # sqd-admin
147
210
  rake squared:pull:workspace # sqd-serve + sqd-admin
211
+ rake squared:outdated:workspace # cli + sqd-serve + sqd-admin
148
212
  ```
149
213
 
150
214
  ## Methods
@@ -153,6 +217,7 @@ Task:
153
217
 
154
218
  * run
155
219
  * depend
220
+ * graph
156
221
  * test
157
222
  * doc
158
223
  * clean
@@ -179,14 +244,21 @@ Non-task:
179
244
  ### Build
180
245
 
181
246
  ```ruby
247
+ # :env :run :opts
182
248
  # LD_LIBRARY_PATH="path/to/lib" CFLAGS="-Wall" gcc a.c -o a.o -c
183
249
  BUILD_${NAME} # gcc a.c -o a.o
184
- BUILD_${NAME}_OPTS # -c
185
- BUILD_${NAME}_ENV # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (json)
186
-
187
- # Scripts
188
- BUILD_${NAME}_DEV # pattern,0,1
189
- BUILD_${NAME}_PROD # pattern,0,1
250
+ BUILD_OPTS_${NAME} # -c
251
+ BUILD_ENV_${NAME} # {"LD_LIBRARY_PATH":"path/to/lib","CFLAGS":"-Wall"} (hash/json)
252
+
253
+ # :env :opts :script
254
+ # NODE_ENV="production" NO_COLOR="1" npm run --loglevel=error --workspaces=false build:dev
255
+ BUILD_${NAME} # build:dev
256
+ BUILD_OPTS_${NAME} # --loglevel=error --workspaces=false
257
+ BUILD_ENV_${NAME} # {"NODE_ENV":"production","NO_COLOR":"1"} (hash/json)
258
+ BUILD_DEV_${NAME} # pattern,0,1 (:dev)
259
+ BUILD_PROD_${NAME} # pattern,0,1 (:prod)
260
+
261
+ BUILD_${NAME}=0 # skip project
190
262
  ```
191
263
 
192
264
  These options also support the project specific suffix `${NAME}`. (e.g. LOG_FILE_SQUARED)
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'workspace'
4
+ require_relative 'workspace/repo'
5
+ require_relative 'workspace/project/node'
6
+ require_relative 'workspace/project/python'
7
+ require_relative 'workspace/project/ruby'
8
+ require_relative 'config'
9
+
10
+ Common = Squared::Common
@@ -2,10 +2,16 @@
2
2
 
3
3
  module Squared
4
4
  module Common
5
- KEY = {
5
+ ARG = {
6
6
  PIPE: 1,
7
+ OUT: nil,
8
+ VERBOSE: nil,
7
9
  FAIL: false,
8
- COMMON: true
10
+ COMMON: true,
11
+ BANNER: true,
12
+ SPACE: ' => ',
13
+ GRAPH: ['│', '─', '├', '└', '┬'],
14
+ COLOR: ENV.fetch('NO_COLOR', '').empty?
9
15
  }
10
16
  VAR = {
11
17
  project: {},
@@ -70,6 +76,7 @@ module Squared
70
76
  end
71
77
 
72
78
  def __freeze__
79
+ ARG.freeze
73
80
  VAR.each_value(&:freeze)
74
81
  VAR[:theme].each_value(&:freeze)
75
82
  VAR.freeze
@@ -77,30 +84,19 @@ module Squared
77
84
 
78
85
  module_function
79
86
 
80
- def env(key, default = nil, equals: nil, ignore: nil, **)
81
- ret = ENV.fetch(key, '')
82
- return ret == equals.to_s unless equals.nil?
83
-
84
- ret.empty? || (ignore && as_a(ignore).any? { |val| ret == val.to_s }) ? default : ret
85
- end
86
-
87
- def message(*args, hint: nil)
88
- args.reject(&:empty?).join(' => ') + (hint ? " (#{hint})" : '')
89
- end
90
-
91
87
  def as_a(obj, meth = nil, flat: nil, compact: false)
92
88
  return [] if obj.nil?
93
89
 
94
90
  unless obj.is_a?(::Array)
95
- obj = if !obj.is_a?(::Hash) && obj.respond_to?(:to_a) && (val = obj.to_a).is_a?(::Array)
91
+ obj = if obj.respond_to?(:to_a) && !obj.is_a?(::Hash) && (val = obj.to_a).is_a?(::Array)
96
92
  val
97
93
  else
98
94
  [obj]
99
95
  end
100
96
  end
101
97
  obj = obj.flatten(flat.is_a?(::Numeric) ? flat : nil) if flat
102
- obj = obj.map(&meth) if meth
103
- compact ? obj.compact : obj
98
+ obj = obj.compact if compact
99
+ meth ? obj.map(&meth) : obj
104
100
  end
105
101
  end
106
102
  end
@@ -1,12 +1,37 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'set'
4
+ require 'forwardable'
4
5
 
5
6
  module Squared
6
7
  module Common
8
+ class SymSet
9
+ extend Forwardable
10
+
11
+ def self.to_s
12
+ super.match(/[^:]+$/)[0]
13
+ end
14
+
15
+ def_delegators :@data, :+, :each, :each_with_index, :entries, :to_a, :include?
16
+
17
+ def initialize(data = [])
18
+ @data = ::Set.new(data)
19
+ end
20
+
21
+ def add(val)
22
+ @data.add(val.to_sym)
23
+ end
24
+
25
+ def to_s
26
+ @data.to_s.sub('Set', SymSet.to_s)
27
+ end
28
+
29
+ alias inspect to_s
30
+ end
31
+
7
32
  class JoinSet < ::Set
8
33
  def self.to_s
9
- super.to_s.match(/[^:]+$/)[0]
34
+ super.match(/[^:]+$/)[0]
10
35
  end
11
36
 
12
37
  def initialize(data = [], delim: ' ')
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pathname'
3
4
  require 'logger'
4
5
 
5
6
  require_relative 'base'
@@ -40,7 +41,7 @@ module Squared
40
41
  private
41
42
 
42
43
  def sub_style(val, *args, styles: nil, pat: nil, index: 1)
43
- return val unless ENV.fetch('NO_COLOR', '').empty? && !__get__(:no_color)
44
+ return val unless ARG[:COLOR]
44
45
 
45
46
  if pat && index != 0
46
47
  return val unless (data = pat.match(val))
@@ -106,7 +107,7 @@ module Squared
106
107
  out
107
108
  end
108
109
 
109
- def check_style(*args, empty: true)
110
+ def check_style(args, empty: true)
110
111
  ret = []
111
112
  colors = __get__(:colors)
112
113
  as_a(args, flat: true, compact: true).each do |val|
@@ -123,7 +124,7 @@ module Squared
123
124
  ret if empty || !ret.empty?
124
125
  end
125
126
 
126
- def apply_style(data, key, *args, empty: true)
127
+ def apply_style(data, key, args, empty: true)
127
128
  return if data.is_a?(::Symbol) && (data = __get__(:theme)[data]).nil?
128
129
 
129
130
  set = ->(k, v) { data[k] = check_style(v, empty: empty) }
@@ -137,15 +138,15 @@ module Squared
137
138
  def log_sym(level)
138
139
  if level.is_a?(::Numeric)
139
140
  case level
140
- when Logger::DEBUG
141
+ when ::Logger::DEBUG
141
142
  :debug
142
- when Logger::INFO
143
+ when ::Logger::INFO
143
144
  :info
144
- when Logger::WARN
145
+ when ::Logger::WARN
145
146
  :warn
146
- when Logger::ERROR
147
+ when ::Logger::ERROR
147
148
  :error
148
- when Logger::FATAL
149
+ when ::Logger::FATAL
149
150
  :fatal
150
151
  else
151
152
  :unknown
@@ -155,7 +156,7 @@ module Squared
155
156
  end
156
157
  end
157
158
 
158
- def log_title(level, color: true)
159
+ def log_title(level, color: ARG[:COLOR])
159
160
  theme = __get__(:theme)[:logger]
160
161
  styles = theme[level = log_sym(level)] || theme[level = :unknown]
161
162
  case (ret = +level.to_s.upcase)
@@ -165,7 +166,7 @@ module Squared
165
166
  color ? sub_style(ret, *styles) : ret
166
167
  end
167
168
 
168
- def log_message(level, *args, subject: nil, hint: nil, color: true)
169
+ def log_message(level, *args, subject: nil, hint: nil, color: ARG[:COLOR])
169
170
  args = args.map(&:to_s)
170
171
  if args.size > 1
171
172
  title = log_title(level, color: false)
@@ -183,49 +184,103 @@ module Squared
183
184
  end
184
185
  end
185
186
 
186
- def raise_error(*args, hint: nil, kind: ArgumentError)
187
- raise kind, message(*args, hint: hint)
187
+ def puts_oe(*args, pipe: 1)
188
+ if pipe.is_a?(::Pathname)
189
+ begin
190
+ ::File.open(pipe, 'a') do |f|
191
+ br = ::File::SEPARATOR == '\\' ? "\r\n" : "\n"
192
+ args.flatten.each { |val| f.write("#{strip_style(val.chomp)}#{br}") }
193
+ end
194
+ return
195
+ rescue StandardError
196
+ pipe = 2
197
+ end
198
+ end
199
+ (pipe == 2 ? $stderr : $stdout).puts(*args)
188
200
  end
189
201
 
190
202
  module_function
191
203
 
192
- def emphasize(val, title: nil, cols: nil, sub: nil, pipe: nil)
204
+ def message(*args, hint: nil, empty: false)
205
+ (empty ? args.reject { |val| val.nil? || val.empty? } : args).join(ARG[:SPACE]) + (hint ? " (#{hint})" : '')
206
+ end
207
+
208
+ def emphasize(val, title: nil, footer: nil, right: false, cols: nil, sub: nil, border: nil, pipe: nil)
193
209
  n = 0
194
- if title
195
- title = title.to_s
196
- n = title.size
210
+ max = ->(v) { n = [n, v.max_by(&:size).size].max }
211
+ set = lambda do |v|
212
+ ret = as_a(v, :to_s)
213
+ max.(ret)
214
+ ret
197
215
  end
216
+ title &&= set.(title)
217
+ footer &&= set.(footer)
198
218
  if val.is_a?(::Array)
199
- lines = val
219
+ lines = val.map(&:to_s)
200
220
  else
201
221
  lines = val.to_s.lines.map(&:chomp)
202
- lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(::StandardError))
222
+ lines[0] = "#{val.class}: #{lines.first}" if (err = val.is_a?(StandardError))
203
223
  end
204
- n = cols || [n, lines.max_by(&:size).size].max
224
+ n = cols || max.(lines)
205
225
  if $stdout.tty?
206
226
  require 'io/console'
207
227
  (n = [n, $stdout.winsize[1] - 4].min) rescue nil
208
228
  end
209
229
  out = []
210
230
  bord = '-' * (n + 4)
211
- sub = [sub] if sub && !sub.is_a?(::Array)
231
+ bord = sub_style(bord, styles: border) if border
232
+ sub = as_a(sub)
212
233
  pr = lambda do |line|
213
234
  s = line.ljust(n)
214
- sub&.each { |h| s = sub_style(s, **h) }
215
- "| #{s} |"
235
+ sub.each { |h| s = sub_style(s, **h) }
236
+ s = "| #{s} |"
237
+ if border
238
+ s = sub_style(s, pat: /^(\|)(.+)$/m, styles: border)
239
+ s = sub_style(s, pat: /^(.+)(\|)$/m, styles: border, index: 2)
240
+ end
241
+ s
216
242
  end
217
243
  out << bord
218
- out << pr.(title) << bord if title
244
+ if title
245
+ out += title.map { |t| pr.(t) }
246
+ out << bord
247
+ end
219
248
  lines.each { |line| out << pr.(line) }
220
249
  out << bord
250
+ if footer
251
+ unless sub.empty? && !right
252
+ footer.map! do |s|
253
+ s = s.rjust(n + 4) if right
254
+ sub.each { |h| s = sub_style(s, **h) }
255
+ s
256
+ end
257
+ end
258
+ out += footer
259
+ end
221
260
  if block_given?
222
261
  yield out
223
- elsif pipe.respond_to?(:puts)
262
+ elsif pipe
263
+ case pipe
264
+ when 0
265
+ pipe = $stdin
266
+ when 2
267
+ pipe = $stderr
268
+ else
269
+ pipe = $stdout unless pipe.respond_to?(:puts)
270
+ end
224
271
  pipe.puts out
225
272
  else
226
273
  err ? warn(out) : puts(out)
227
274
  end
228
275
  end
276
+
277
+ def strip_style(val)
278
+ val.gsub(/\x1B\[(\d+;?)+m/, '')
279
+ end
280
+
281
+ def raise_error(*args, hint: nil, kind: ArgumentError)
282
+ raise kind, message(*args, hint: hint, empty: true)
283
+ end
229
284
  end
230
285
  end
231
286
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Squared
4
+ module Common
5
+ module Prompt
6
+ module_function
7
+
8
+ def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
9
+ require 'readline'
10
+ require 'timeout'
11
+ agree = /^#{agree}$/i if agree.is_a?(::String)
12
+ cancel = /^#{cancel}$/i if cancel.is_a?(::String)
13
+ Timeout.timeout(timeout) do
14
+ begin
15
+ while (ch = Readline.readline(msg, true))
16
+ ch = ch.chomp
17
+ case (ch.empty? ? default : ch)
18
+ when agree
19
+ return true
20
+ when cancel
21
+ return false
22
+ end
23
+ attempts -= 1
24
+ exit 1 unless attempts >= 0
25
+ end
26
+ rescue Interrupt
27
+ puts
28
+ exit 0
29
+ else
30
+ false
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -9,9 +9,10 @@ module Squared
9
9
  module_function
10
10
 
11
11
  def shell_escape(val, quote: false)
12
- return Shellwords.escape(val) unless ::Rake::Win32.windows?
12
+ val = val.to_s
13
+ return ::Shellwords.escape(val) unless ::Rake::Win32.windows?
13
14
 
14
- quote ? shell_quote(opt, force: false) : opt
15
+ quote ? shell_quote(val, force: false) : val
15
16
  end
16
17
 
17
18
  def shell_quote(val, force: true)
@@ -22,7 +23,7 @@ module Squared
22
23
  end
23
24
 
24
25
  def shell_split(val, quote: false, join: false)
25
- ret = Shellwords.split(val).map do |opt|
26
+ ret = ::Shellwords.split(val).map do |opt|
26
27
  if (data = /^(--?[^= ]+)(=|\s+)?(["'])?(.+?)\3?$/m.match(opt))
27
28
  next opt unless data[2] && !data[3]
28
29
 
@@ -8,67 +8,37 @@ module Squared
8
8
  module System
9
9
  module_function
10
10
 
11
- def shell(*cmd, **kwargs)
11
+ def shell(*args, **kwargs)
12
12
  if RUBY_VERSION =~ /^2\.[0-5]\./
13
13
  exception = kwargs.delete(:exception)
14
- ret = system(*cmd, **kwargs)
15
- raise $?.to_s if !ret && exception
14
+ ret = system(*args, **kwargs)
15
+ return ret if ret || !exception
16
16
 
17
- ret
17
+ raise $?.to_s
18
18
  else
19
- system(*cmd, **kwargs)
20
- end
21
- end
22
-
23
- def confirm(msg, default = nil, agree: 'Y', cancel: 'N', attempts: 5, timeout: 15)
24
- require 'readline'
25
- require 'timeout'
26
- agree = /^#{agree}$/i if agree.is_a?(::String)
27
- cancel = /^#{cancel}$/i if cancel.is_a?(::String)
28
- Timeout.timeout(timeout) do
29
- begin
30
- while (ch = Readline.readline(msg, true))
31
- ch = ch.chomp
32
- ch = default if ch.empty?
33
- case ch
34
- when agree
35
- return true
36
- when cancel
37
- return false
38
- end
39
- attempts -= 1
40
- exit 1 unless attempts >= 0
41
- end
42
- rescue Interrupt
43
- puts
44
- exit 0
45
- else
46
- false
47
- end
19
+ system(*args, **kwargs)
48
20
  end
49
21
  end
50
22
 
51
23
  def copy_d(src, dest, glob: ['**/*'], create: false, verbose: true)
52
- src = Pathname.new(src)
53
- dest = Pathname.new(dest)
24
+ src = ::Pathname.new(src)
25
+ dest = ::Pathname.new(dest)
54
26
  raise "#{dest} (not found)" if !create && !dest.exist?
55
27
 
56
28
  subdir = []
57
29
  files = 0
58
30
  dest.mkpath if create
59
- glob = [glob] unless glob.is_a?(::Array)
60
- glob.each do |val|
61
- Dir.glob(src.join(val)) do |path|
62
- ent = Pathname.new(path)
63
- next if ent.directory?
31
+ (glob.is_a?(::Array) ? glob : [glob]).each do |val|
32
+ ::Dir.glob(src.join(val)) do |path|
33
+ next if (path = ::Pathname.new(path)).directory?
64
34
 
65
- target = dest.join(ent.relative_path_from(src))
35
+ target = dest.join(path.relative_path_from(src))
66
36
  dir = target.dirname
67
37
  unless subdir.include?(dir.to_s)
68
38
  dir.mkpath
69
39
  subdir << dir.to_s
70
40
  end
71
- copy_f ent, target
41
+ copy_f path, target
72
42
  files += 1
73
43
  end
74
44
  end
@@ -77,15 +47,13 @@ module Squared
77
47
 
78
48
  def copy_f(src, dest, overwrite: true, verbose: false)
79
49
  unless overwrite
80
- path = Pathname.new(dest)
81
- if path.directory?
82
- src = [src] unless src.is_a?(::Array)
83
- src = src.reject { |val| path.join(File.basename(val)).exist? }
50
+ if (path = ::Pathname.new(dest)).directory?
51
+ src = (src.is_a?(::Array) ? src : [src]).reject { |val| path.join(::File.basename(val)).exist? }
84
52
  elsif path.exist?
85
53
  return
86
54
  end
87
55
  end
88
- FileUtils.cp(src, dest, verbose: verbose)
56
+ ::FileUtils.cp(src, dest, verbose: verbose)
89
57
  end
90
58
  end
91
59
  end