theme-juice 0.5.0 → 0.6.0
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 +4 -4
- data/README.md +3 -3
- data/bin/tj +5 -13
- data/lib/theme-juice/cli.rb +172 -343
- data/lib/theme-juice/command.rb +14 -0
- data/lib/theme-juice/commands/create.rb +17 -0
- data/lib/theme-juice/commands/delete.rb +17 -0
- data/lib/theme-juice/commands/install.rb +17 -0
- data/lib/theme-juice/commands/list.rb +17 -0
- data/lib/theme-juice/commands/subcommand.rb +17 -0
- data/lib/theme-juice/environment.rb +14 -0
- data/lib/theme-juice/interaction.rb +446 -0
- data/lib/theme-juice/interactions/create_site_options.rb +288 -0
- data/lib/theme-juice/interactions/delete_site_options.rb +58 -0
- data/lib/theme-juice/interactions/teejay.rb +6 -0
- data/lib/theme-juice/service.rb +190 -0
- data/lib/theme-juice/services/config_file.rb +44 -0
- data/lib/theme-juice/services/create_site.rb +387 -0
- data/lib/theme-juice/services/delete_site.rb +114 -0
- data/lib/theme-juice/services/list_sites.rb +40 -0
- data/lib/theme-juice/version.rb +1 -1
- data/lib/theme-juice.rb +19 -6
- metadata +33 -6
- data/lib/theme-juice/executor.rb +0 -804
- data/lib/theme-juice/ui.rb +0 -227
- data/lib/theme-juice/utilities.rb +0 -56
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Command::Create < ::ThemeJuice::Command
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize(opts = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
::ThemeJuice::Service::CreateSite.new(@opts).create
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Command::Delete < ::ThemeJuice::Command
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize(opts = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
::ThemeJuice::Service::DeleteSite.new(@opts).delete
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Command::Install < ::ThemeJuice::Command
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize(opts = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
::ThemeJuice::Service::ConfigFile.new.install
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Command::List < ::ThemeJuice::Command
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize(opts = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
::ThemeJuice::Service::ListSites.new.list
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
class Command::Subcommand < ::ThemeJuice::Command
|
5
|
+
|
6
|
+
#
|
7
|
+
# @param {Hash} opts
|
8
|
+
#
|
9
|
+
# @return {Void}
|
10
|
+
#
|
11
|
+
def initialize(opts = {})
|
12
|
+
super
|
13
|
+
|
14
|
+
::ThemeJuice::Service::ConfigFile.new.subcommand @opts[:subcommand], @opts[:commands]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
module Environment
|
5
|
+
class << self
|
6
|
+
attr_accessor :vvv_path
|
7
|
+
attr_accessor :no_unicode
|
8
|
+
attr_accessor :no_colors
|
9
|
+
attr_accessor :no_animations
|
10
|
+
attr_accessor :boring
|
11
|
+
attr_accessor :yolo
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,446 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
module ThemeJuice
|
4
|
+
module Interaction
|
5
|
+
|
6
|
+
# Icons
|
7
|
+
ICONS = {
|
8
|
+
|
9
|
+
# Unicode
|
10
|
+
:success => "\u2713",
|
11
|
+
:error => "\u2191",
|
12
|
+
:notice => "\u2192",
|
13
|
+
:question => "\u2022",
|
14
|
+
:general => "\u2022",
|
15
|
+
:log => "\u2026",
|
16
|
+
:restart => "\u21AA",
|
17
|
+
:selected => "\u2022",
|
18
|
+
:unselected => "\u25CB",
|
19
|
+
|
20
|
+
# Fallback
|
21
|
+
:nu_success => "+",
|
22
|
+
:nu_error => "!",
|
23
|
+
:nu_notice => "-",
|
24
|
+
:nu_question => "?",
|
25
|
+
:nu_general => "-",
|
26
|
+
:nu_log => "...",
|
27
|
+
:nu_restart => "!",
|
28
|
+
:nu_selected => "[x]",
|
29
|
+
:nu_unselected => "[ ]"
|
30
|
+
}
|
31
|
+
|
32
|
+
# Escape sequences
|
33
|
+
KEYS = {
|
34
|
+
"\e[A" => "up",
|
35
|
+
"\e[B" => "down",
|
36
|
+
"\e[C" => "right",
|
37
|
+
"\e[D" => "left",
|
38
|
+
"\003" => "ctrl+c",
|
39
|
+
"\004" => "ctrl+d",
|
40
|
+
"\e" => "escape",
|
41
|
+
"\n" => "linefeed",
|
42
|
+
"\r" => "return",
|
43
|
+
" " => "space"
|
44
|
+
}
|
45
|
+
|
46
|
+
# Get the environment
|
47
|
+
@environment = ::ThemeJuice::Environment
|
48
|
+
|
49
|
+
class << self
|
50
|
+
include ::Thor::Actions
|
51
|
+
include ::Thor::Shell
|
52
|
+
|
53
|
+
#
|
54
|
+
# Output formatted message
|
55
|
+
#
|
56
|
+
# @param {String} message
|
57
|
+
# @param {Hash} opts
|
58
|
+
#
|
59
|
+
# @return {Void}
|
60
|
+
#
|
61
|
+
def speak(message, opts = {})
|
62
|
+
format_message message, opts
|
63
|
+
output_message
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# Ask a question
|
68
|
+
#
|
69
|
+
# @param {String} question
|
70
|
+
# @param {Hash} opts
|
71
|
+
#
|
72
|
+
# @return {Void}
|
73
|
+
#
|
74
|
+
def prompt(question, *opts)
|
75
|
+
format_message question, {
|
76
|
+
:color => :blue,
|
77
|
+
:icon => :question
|
78
|
+
}
|
79
|
+
|
80
|
+
opts.each do |opt|
|
81
|
+
|
82
|
+
# if opt[:default]
|
83
|
+
# opt[:default] = set_color(opt[:default], :black, :bold) unless @environment.no_colors
|
84
|
+
# end
|
85
|
+
|
86
|
+
if opt[:indent]
|
87
|
+
set(question) { |str| (" " * opt[:indent]) << str }
|
88
|
+
end
|
89
|
+
|
90
|
+
break
|
91
|
+
end
|
92
|
+
|
93
|
+
ask("#{question} :", *opts).gsub /\e\[\d+m/, ""
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Ask a yes or no question
|
98
|
+
#
|
99
|
+
# @param {String} question
|
100
|
+
# @param {Hash} opts
|
101
|
+
#
|
102
|
+
# @return {Bool}
|
103
|
+
#
|
104
|
+
def agree?(question, opts = {})
|
105
|
+
|
106
|
+
format_message question, {
|
107
|
+
:color => opts[:color] || :blue,
|
108
|
+
:icon => :question
|
109
|
+
}
|
110
|
+
|
111
|
+
if opts[:simple]
|
112
|
+
yes? " :", if opts[:color] then opts[:color] end
|
113
|
+
else
|
114
|
+
yes? "#{question} (y/N) :"
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
#
|
119
|
+
# Output log message
|
120
|
+
#
|
121
|
+
# @param {String} message
|
122
|
+
#
|
123
|
+
# @return {Void}
|
124
|
+
#
|
125
|
+
def log(message)
|
126
|
+
speak message, {
|
127
|
+
:color => :yellow,
|
128
|
+
:icon => :log
|
129
|
+
}
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Output success message
|
134
|
+
#
|
135
|
+
# @param {String} message
|
136
|
+
#
|
137
|
+
# @return {Void}
|
138
|
+
#
|
139
|
+
def success(message)
|
140
|
+
speak message, {
|
141
|
+
:color => [:black, :on_green, :bold],
|
142
|
+
:icon => :success,
|
143
|
+
:row => true
|
144
|
+
}
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# Output notice message
|
149
|
+
#
|
150
|
+
# @param {String} message
|
151
|
+
#
|
152
|
+
# @return {Void}
|
153
|
+
#
|
154
|
+
def notice(message)
|
155
|
+
speak message, {
|
156
|
+
:color => [:black, :on_yellow],
|
157
|
+
:icon => :notice,
|
158
|
+
:row => true
|
159
|
+
}
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Output error message and exit. Allows a block to be passed
|
164
|
+
# as well, which will be executed before exiting
|
165
|
+
#
|
166
|
+
# @param {String} message
|
167
|
+
#
|
168
|
+
# @return {Void}
|
169
|
+
#
|
170
|
+
def error(message)
|
171
|
+
speak message, {
|
172
|
+
:color => [:white, :on_red],
|
173
|
+
:icon => :error,
|
174
|
+
:row => true
|
175
|
+
}
|
176
|
+
|
177
|
+
yield if block_given?
|
178
|
+
|
179
|
+
exit 1
|
180
|
+
end
|
181
|
+
|
182
|
+
#
|
183
|
+
# Output greeting
|
184
|
+
#
|
185
|
+
# @param {Hash} opts ({})
|
186
|
+
#
|
187
|
+
# @return {Void}
|
188
|
+
#
|
189
|
+
def hello(opts = {})
|
190
|
+
speak "Welcome to Theme Juice!", {
|
191
|
+
:color => [:black, :on_green, :bold],
|
192
|
+
:row => true
|
193
|
+
}.merge(opts)
|
194
|
+
end
|
195
|
+
|
196
|
+
#
|
197
|
+
# Output goodbye and exit with interupt code
|
198
|
+
#
|
199
|
+
# @param {Hash} opts ({})
|
200
|
+
#
|
201
|
+
# @return {Void}
|
202
|
+
#
|
203
|
+
def goodbye(opts = {})
|
204
|
+
speak "Bye bye!", {
|
205
|
+
:color => :yellow,
|
206
|
+
:icon => :general,
|
207
|
+
:newline => true
|
208
|
+
}.merge(opts)
|
209
|
+
|
210
|
+
exit 130
|
211
|
+
end
|
212
|
+
|
213
|
+
#
|
214
|
+
# Output a list of messages
|
215
|
+
#
|
216
|
+
# @param {String} header
|
217
|
+
# @param {Symbol} color
|
218
|
+
# @param {Array} list
|
219
|
+
#
|
220
|
+
# @return {Void}
|
221
|
+
#
|
222
|
+
def list(header, color, list)
|
223
|
+
speak header, {
|
224
|
+
:color => [:black, :"on_#{color}"],
|
225
|
+
:icon => :notice,
|
226
|
+
:row => true
|
227
|
+
}
|
228
|
+
|
229
|
+
list.each do |item|
|
230
|
+
speak item, {
|
231
|
+
:color => :"#{color}",
|
232
|
+
:icon => :general
|
233
|
+
}
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
#
|
238
|
+
# Create a shell select menu
|
239
|
+
#
|
240
|
+
# @param {String} header
|
241
|
+
# @param {Symbol} color
|
242
|
+
# @param {Array} list
|
243
|
+
#
|
244
|
+
# @return {String}
|
245
|
+
#
|
246
|
+
def choose(header, color, list)
|
247
|
+
speak "#{header} (use arrow keys and press enter)", {
|
248
|
+
:color => :"#{color}",
|
249
|
+
:icon => :question
|
250
|
+
}
|
251
|
+
|
252
|
+
print "\n" * list.size
|
253
|
+
|
254
|
+
selected = 0
|
255
|
+
update_list_selection(list, color, selected)
|
256
|
+
|
257
|
+
loop do
|
258
|
+
case key = read_key
|
259
|
+
when "up"
|
260
|
+
selected -= 1
|
261
|
+
selected = list.size - 1 if selected < 0
|
262
|
+
update_list_selection(list, color, selected)
|
263
|
+
when "down"
|
264
|
+
selected += 1
|
265
|
+
selected = 0 if selected > list.size - 1
|
266
|
+
update_list_selection(list, color, selected)
|
267
|
+
when "return", "linefeed", "space"
|
268
|
+
return list[selected]
|
269
|
+
when "esc", "ctrl+c"
|
270
|
+
goodbye(newline: false)
|
271
|
+
# else
|
272
|
+
# speak "You pressed: #{chr.inspect}", { color: :yellow }
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
private
|
278
|
+
|
279
|
+
#
|
280
|
+
# Destructively format message
|
281
|
+
#
|
282
|
+
# @param {String} message
|
283
|
+
# @param {Hash} opts
|
284
|
+
#
|
285
|
+
# @return {String}
|
286
|
+
#
|
287
|
+
def format_message(message, opts = {})
|
288
|
+
@message, @opts = message, opts
|
289
|
+
|
290
|
+
format_message_icon
|
291
|
+
format_message_newline
|
292
|
+
format_message_row
|
293
|
+
format_message_width
|
294
|
+
format_message_color
|
295
|
+
format_message_indent
|
296
|
+
|
297
|
+
@message
|
298
|
+
end
|
299
|
+
|
300
|
+
#
|
301
|
+
# Run destructive block against string
|
302
|
+
#
|
303
|
+
# @param {String} string
|
304
|
+
#
|
305
|
+
# @return {String}
|
306
|
+
#
|
307
|
+
def set(string)
|
308
|
+
str = yield(string); string.clear; string << str
|
309
|
+
end
|
310
|
+
|
311
|
+
#
|
312
|
+
# Force message to use icon (if environment allows)
|
313
|
+
#
|
314
|
+
# @return {String}
|
315
|
+
#
|
316
|
+
def format_message_icon
|
317
|
+
icon = if @environment.no_unicode then "nu_#{@opts[:icon]}" else "#{@opts[:icon]}" end
|
318
|
+
|
319
|
+
if @opts[:icon]
|
320
|
+
set(@message) { |msg| " #{ICONS[:"#{icon}"]}" << if @opts[:empty] then nil else " #{msg}" end }
|
321
|
+
else
|
322
|
+
set(@message) { |msg| " " << msg }
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
#
|
327
|
+
# Force message on newline, unless already on newline
|
328
|
+
#
|
329
|
+
# @return {String}
|
330
|
+
#
|
331
|
+
def format_message_newline
|
332
|
+
set(@message) { |msg| "\n" << msg } if @opts[:newline]
|
333
|
+
end
|
334
|
+
|
335
|
+
#
|
336
|
+
# Force message to use colors (if environment allows)
|
337
|
+
#
|
338
|
+
# @return {String}
|
339
|
+
#
|
340
|
+
def format_message_color
|
341
|
+
unless @environment.no_colors
|
342
|
+
set(@message) { |msg| set_color(msg, *@opts[:color]) } if @opts[:color]
|
343
|
+
end
|
344
|
+
end
|
345
|
+
|
346
|
+
#
|
347
|
+
# Force message to take up width of terminal window
|
348
|
+
#
|
349
|
+
# @return {String}
|
350
|
+
#
|
351
|
+
def format_message_row
|
352
|
+
set(@message) { |msg| msg.ljust(terminal_width) } if @opts[:row]
|
353
|
+
end
|
354
|
+
|
355
|
+
#
|
356
|
+
# Force message width
|
357
|
+
#
|
358
|
+
# @return {String}
|
359
|
+
#
|
360
|
+
def format_message_width
|
361
|
+
set(@message) { |msg| msg.ljust(@opts[:width]) } if @opts[:width]
|
362
|
+
end
|
363
|
+
|
364
|
+
#
|
365
|
+
# Force message indentation
|
366
|
+
#
|
367
|
+
# @return {String}
|
368
|
+
#
|
369
|
+
def format_message_indent
|
370
|
+
set(@message) { |str| (" " * @opts[:indent]) << str } if @opts[:indent]
|
371
|
+
end
|
372
|
+
|
373
|
+
#
|
374
|
+
# Output message to terminal, unless quiet
|
375
|
+
#
|
376
|
+
# @return {String|Void}
|
377
|
+
#
|
378
|
+
def output_message
|
379
|
+
if @opts[:quiet] then @message else say @message end
|
380
|
+
end
|
381
|
+
|
382
|
+
#
|
383
|
+
# Output list with updated selection
|
384
|
+
#
|
385
|
+
# @return {Void}
|
386
|
+
#
|
387
|
+
def update_list_selection(list, color, selected = 0)
|
388
|
+
print "\e[#{list.size}A"
|
389
|
+
|
390
|
+
list.each_with_index do |item, i|
|
391
|
+
icon = if i == selected then "selected" else "unselected" end
|
392
|
+
speak "#{item}", {
|
393
|
+
:color => :"#{color}",
|
394
|
+
:icon => :"#{icon}",
|
395
|
+
:indent => 2
|
396
|
+
}
|
397
|
+
end
|
398
|
+
end
|
399
|
+
|
400
|
+
#
|
401
|
+
# Read input
|
402
|
+
#
|
403
|
+
# @see http://www.alecjacobson.com/weblog/?p=75
|
404
|
+
#
|
405
|
+
# @return {String}
|
406
|
+
#
|
407
|
+
def read_key
|
408
|
+
save_state
|
409
|
+
raw_no_echo_mode
|
410
|
+
|
411
|
+
key = STDIN.getc.chr
|
412
|
+
|
413
|
+
if key == "\e"
|
414
|
+
thread = Thread.new { key += STDIN.getc.chr + STDIN.getc.chr }
|
415
|
+
thread.join(0.001)
|
416
|
+
thread.kill
|
417
|
+
end
|
418
|
+
|
419
|
+
KEYS[key] || key
|
420
|
+
ensure
|
421
|
+
restore_state
|
422
|
+
end
|
423
|
+
|
424
|
+
#
|
425
|
+
# Get the current state of stty
|
426
|
+
#
|
427
|
+
def save_state
|
428
|
+
@state = %x(stty -g)
|
429
|
+
end
|
430
|
+
|
431
|
+
#
|
432
|
+
# Disable echoing and enable raw mode
|
433
|
+
#
|
434
|
+
def raw_no_echo_mode
|
435
|
+
%x(stty raw -echo)
|
436
|
+
end
|
437
|
+
|
438
|
+
#
|
439
|
+
# Restore state of stty
|
440
|
+
#
|
441
|
+
def restore_state
|
442
|
+
%x(stty #{@state})
|
443
|
+
end
|
444
|
+
end
|
445
|
+
end
|
446
|
+
end
|