yuyi 1.0.8 → 1.1.3

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.
data/lib/yuyi/cli.rb CHANGED
@@ -1,377 +1,46 @@
1
- require 'open3'
2
- require 'readline'
3
- require 'yaml'
1
+ require 'thor'
4
2
 
5
- module Yuyi::Cli
6
- # Configure readline
7
- Readline.completion_append_character = '/'
3
+ class Yuyi::Cli < Thor
4
+ desc 'list', 'Show all rolls available based on the sources defined in your menu.'
5
+ option :menu, :aliases => '-m', :desc => 'Path to your menu file'
6
+ def list
7
+ Yuyi::Menu.new options[:menu]
8
8
 
9
- # Define available command line options
10
- # Each key must start with a unique letter
11
- # Flags are automatically created based on the first letter (eg. -h, --help)
12
- #
13
- CLI_OPTIONS = {
14
- :help => 'Shows these options.',
15
- :list => 'List all rolls available to be included in your menu.',
16
- :version => 'Shows the current version of Yuyi.',
17
- :VERBOSE => 'Shows the output of all commands being run'
18
- }
19
-
20
- # Called by the install script
21
- #
22
- def init args
23
- # get the first argument as the command
24
- command, *rest = *args
25
-
26
- # if not an option, assume it is a custom path
27
- if command && command[0,1] != '-'
28
- @path = command
29
- command, *rest = *rest
30
- end
31
-
32
- # Call options method if valid argument is passed
33
- # This checks for the full name or the first letter, proceeded by '--' or '-' respectively
34
- CLI_OPTIONS.keys.each do |option|
35
- if command == "--#{option}" || command == "-#{option.to_s.chars.first}"
36
- begin
37
- send option.to_s.downcase, rest
38
- rescue
39
- send option.to_s.downcase
40
- end
41
- return
42
- end
43
- end
44
-
45
- # Show a warning if an invalid argument is passed and then show the help menu
46
- if command
47
- say 'INVALID ARGUMENT', :type => :fail
48
- send :help
49
- else
50
- start
51
- end
52
- end
53
-
54
- # Replacement for `puts` that accepts various stylistic arguments
55
- # type: => [symbol] Preset colors for [:fail, :success, :warn]
56
- # color: => [integer] See docs for #colorize for color codes
57
- # justify: => [center|ljust|rjust] The type of justification to use
58
- # padding: => [integer] The maximum string size to justify text in
59
- # indent: => [integer] The maximum string size to justify text in
60
- # newline: => [boolean] True if you want a newline after the output
61
- #
62
- def say text = '', args = {}
63
- # defaults
64
- args = {
65
- :newline => true
66
- }.merge args
67
-
68
- # Justify options
69
- if args[:justify] && args[:padding]
70
- text = text.send args[:justify], args[:padding]
71
- end
72
-
73
- # Type options
74
- # process last due to the addition of special color codes
75
- text = case args[:type]
76
- when :fail
77
- colorize text, 31
78
- when :success
79
- colorize text, 32
80
- when :warn
81
- colorize text, 33
82
- else
83
- colorize text, args[:color]
84
- end
85
-
86
- if args[:indent]
87
- text = (' ' * args[:indent]) + text
88
- end
89
-
90
- if args[:newline]
91
- STDOUT.puts text
92
- else
93
- STDOUT.print text
9
+ # Collect all rolls from all sources
10
+ #
11
+ rolls = []
12
+ Yuyi::Menu.sources.each do |source|
13
+ rolls |= source.rolls.keys
94
14
  end
95
- end
96
-
97
- # Accepts the same arguments as #say
98
- #
99
- def ask question, options = {}, &block
100
- prompt = '>>> '
101
- options = {
102
- :readline => false,
103
- :color => 1
104
- }.merge(options)
105
-
106
- say question, options
107
-
108
- output = if options[:readline]
109
- Readline.readline(prompt).chomp('/')
110
- else
111
- say prompt, :color => 1, :newline => false
112
- STDIN.gets
113
- end.rstrip
114
-
115
- say
116
- yield output if block
117
- end
118
15
 
119
- # Run a command and output formatting success/errors
120
- #
121
- def run command, args = {}
122
- # check if in verbose mode
123
- verbose = args[:verbose] || @verbose
124
- output = `echo | #{command} 2>&1`
125
- success = $?.success?
16
+ # alphabatize rolls
17
+ rolls = rolls.map(&:to_s).sort
126
18
 
127
- if verbose
128
- say "RUNNING: #{command}", :type => (success ? :success : :fail)
129
- say output
19
+ Yuyi.say 'Available Rolls', :type => :success
20
+ Yuyi.say '---------------', :type => :success
21
+ rolls.each do |roll|
22
+ Yuyi.say roll
130
23
  end
131
-
132
- args[:boolean] ? success : output
24
+ Yuyi.say
133
25
  end
134
26
 
135
- def command? command
136
- run command, :verbose => false, :boolean => true
27
+ desc 'version', 'Show the currently running version of yuyi'
28
+ def version
29
+ say "#{Yuyi::NAME} #{Yuyi::VERSION}"
137
30
  end
138
31
 
139
- # Write several lines to to an existing file
140
- #
141
- def write_to_file file, *text
142
- text.flatten!
143
-
144
- File.open(File.expand_path(file), 'a+') do |file|
145
- full_text = (text * "\n") + "\n"
146
-
147
- unless file.read.include? full_text
148
- file.write full_text
149
- end
150
- end
151
- end
152
-
153
- # Delete specific lines from an existing file
154
- #
155
- def delete_from_file file, *text
156
- text.flatten!
157
-
158
- # get file text
159
- new_text = File.read(File.expand_path(file))
160
-
161
- # iterate through text and remove it
162
- text.each do |t|
163
- regex = /^.*#{Regexp.escape(t)}.*\n/
164
- new_text.gsub!(regex, '')
165
- end
166
-
167
- # write new text back to file
168
- File.open(File.expand_path(file), 'w') { |f| f.write(new_text) }
169
- end
32
+ desc 'start', 'Run Yuyi'
33
+ option :verbose, :aliases => '-v', :type => :boolean, :desc => 'Run in verbose mode'
34
+ option :upgrade, :aliases => '-u', :type => :boolean, :desc => 'Check for upgrades for rolls on the menu that are already installed'
35
+ option :menu, :aliases => '-m', :desc => 'Path to your menu file'
36
+ def start
37
+ # enable verbose mode if flag is passed
38
+ Yuyi.verbose = true if options[:verbose]
39
+ Yuyi.upgrade = true if options[:upgrade]
40
+ Yuyi.menu_path = options[:menu]
170
41
 
171
- def osx_version
172
- run('/usr/bin/sw_vers -productVersion').chomp[/10\.\d+/].to_f
42
+ Yuyi.start
173
43
  end
174
44
 
175
- def verbose?; @verbose; end
176
-
177
- private
178
-
179
- def start
180
- header
181
- get_menu
182
- confirm_upgrade
183
- confirm_options
184
- authenticate
185
- Yuyi::Menu.instance.order_rolls
186
- end
187
-
188
- def header
189
- line_length = 50
190
- say
191
- say '-' * line_length, :color => 4
192
- say
193
- say '____ ____ __ __ ____ ____ __ ', :color => 31, :justify => :center, :padding => line_length
194
- say '\ \ / / | | | | \ \ / / | | ', :color => 32, :justify => :center, :padding => line_length
195
- say ' \ \/ / | | | | \ \/ / | | ', :color => 33, :justify => :center, :padding => line_length
196
- say ' \_ _/ | | | | \_ _/ | | ', :color => 34, :justify => :center, :padding => line_length
197
- say ' | | | `--\' | | | | | ', :color => 35, :justify => :center, :padding => line_length
198
- say ' |__| \______/ |__| |__| ', :color => 36, :justify => :center, :padding => line_length
199
- say
200
- say "VERSION #{Yuyi::VERSION}", :justify => :center, :padding => line_length
201
- say
202
- say '-' * line_length, :color => 4
203
- say
204
- end
205
-
206
- # Ask the user for a menu file to load
207
- #
208
- def get_menu
209
- until @path
210
- say 'Navigate to a menu file...', :type => :success
211
- @path = ask "...or just press enter to load `#{Yuyi::DEFAULT_MENU}`", :readline => true, :color => 36 do |path|
212
- path = path.empty? ? Yuyi::DEFAULT_MENU : path
213
-
214
- if Yuyi::Menu.load_from_file path
215
- say 'Downloading Sources... Please Wait', :type => :warn
216
- say
217
-
218
- path
219
- else
220
- say 'Invalid Path... Please check the location of your menu file', :type => :fail
221
- say
222
-
223
- nil
224
- end
225
- end
226
- end
227
-
228
- Yuyi::Menu.new @path
229
- end
230
-
231
- # Ask to check for upgrades
232
- #
233
- def confirm_upgrade
234
- ask 'Do you want to check for upgrades for already installed rolls? (Yn)', :type => :warn do |upgrade|
235
- Yuyi::Menu.upgrade? upgrade == 'Y'
236
- end
237
- end
238
-
239
- # If any rolls on the menu have options, confirm the options before continuing
240
- #
241
- def confirm_options
242
- confirm = false
243
- Yuyi::Menu.rolls.each do |name, roll|
244
-
245
- unless roll.class.options.empty?
246
- present_options roll
247
- confirm = true
248
- end
249
- end
250
-
251
- if confirm
252
- ask 'Hit any key when you have your options set correctly in your menu file', :type => :warn do
253
- Yuyi::Menu.load_from_file
254
- end
255
- end
256
- end
257
-
258
- def authenticate
259
- say 'Yuyi does not need your admin password, but some installations force a prompt.', :type => :warn
260
- say 'You may be asked to enter your password several times. ', :type => :warn
261
-
262
- # keep the sudo timestamp fresh
263
- Thread::new do
264
- loop do
265
- sleep 1.minute
266
- `sudo -v`
267
- end
268
- end
269
-
270
- say
271
- end
272
-
273
- # Show formatted options
274
- #
275
- def present_options roll, examples = true
276
- indent = 2
277
- longest_option = roll.options.keys.map(&:to_s).max_by(&:length).length + indent
278
-
279
- say "Available options for #{roll.title}...", :color => 32
280
-
281
- roll.option_defs.each do |k, v|
282
- option_color = v[:required] ? 31 : 36
283
-
284
- say "#{k.to_s.rjust(longest_option)}: ", :color => option_color, :newline => false
285
- say v[:description]
286
- say (' ' * (longest_option + indent)), :newline => false
287
- if v[:default]
288
- say 'default: ', :color => 36, :newline => false
289
- say v[:default]
290
- end
291
- end
292
-
293
- if examples
294
- examples_hash = {}
295
- example_indent = longest_option + indent
296
- options = roll.options.dup
297
-
298
- # merge examples from roll source in
299
- options.each do |option, value|
300
- if example = roll.option_defs[option][:example]
301
- options[option] = example
302
- end
303
- end
304
-
305
- examples_hash[roll.file_name.to_s] = options
306
-
307
-
308
- say
309
- say 'Example', :color => 33, :indent => example_indent, :newline => false
310
- say examples_hash.deep_stringify_keys!.to_yaml.sub('---', '').gsub(/\n(\s*)/, "\n\\1#{' ' * example_indent}")
311
- end
312
- end
313
-
314
- # Output text with a certain color (or style)
315
- # Reference for color codes
316
- # https://github.com/flori/term-ansicolor/blob/master/lib/term/ansicolor.rb
317
- #
318
- def colorize text, color_code
319
- return text unless color_code
320
- "\e[#{color_code}m#{text}\e[0m"
321
- end
322
-
323
- # METHODS FOR FLAGS
324
- #
325
- def help
326
- longest_option = CLI_OPTIONS.keys.map(&:to_s).max.length
327
-
328
- say
329
- CLI_OPTIONS.each do |option, description|
330
- string = ''
331
- string << "-#{option.to_s.chars.first}"
332
- string << ', '
333
- string << "--#{option.to_s.ljust(longest_option)}"
334
- string << ' '
335
- string << description
336
- say string
337
- end
338
- say
339
- end
340
-
341
- # List all available rolls
342
- #
343
- def list
344
- get_menu
345
- Yuyi::Menu.set_sources
346
-
347
- # Collect all rolls from all sources
348
- #
349
- rolls = []
350
- Yuyi::Menu.sources.each do |source|
351
- rolls |= source.available_rolls.keys
352
- end
353
-
354
- # alphabatize rolls
355
- rolls = rolls.map(&:to_s).sort.map(&:to_sym)
356
-
357
- say 'Available Rolls', :type => :success
358
- say '---------------', :type => :success
359
- rolls.each do |roll|
360
- say roll.to_s
361
- end
362
- say
363
- end
364
-
365
- # Return current version
366
- #
367
- def version
368
- say "#{Yuyi::NAME} #{Yuyi::VERSION}"
369
- end
370
-
371
- # Return current version
372
- #
373
- def verbose
374
- @verbose = true
375
- start
376
- end
45
+ default_task :start
377
46
  end
data/lib/yuyi/core.rb CHANGED
@@ -19,6 +19,10 @@ class Hash
19
19
  # to +to_sym+. This includes the keys from the root hash and from all
20
20
  # nested hashes.
21
21
  #
22
+ # DEPRECATION
23
+ # required for: ruby 1.8.7
24
+ # can be replaced with activesupport ~4.0
25
+ #
22
26
  def deep_symbolize_keys!
23
27
  deep_transform_keys!{ |key| key.to_sym rescue key }
24
28
  end
data/lib/yuyi/dsl.rb ADDED
@@ -0,0 +1,131 @@
1
+ require 'open3'
2
+ require 'readline'
3
+ require 'yaml'
4
+
5
+ module Yuyi::Dsl
6
+ # Configure readline
7
+ Readline.completion_append_character = '/'
8
+
9
+ attr_accessor :verbose, :upgrade, :menu_path
10
+
11
+ # Replacement for `puts` that accepts various stylistic arguments
12
+ # type: => [symbol] Preset colors for [:fail, :success, :warn]
13
+ # color: => [integer] See docs for #colorize for color codes
14
+ # justify: => [center|ljust|rjust] The type of justification to use
15
+ # padding: => [integer] The maximum string size to justify text in
16
+ # indent: => [integer] The maximum string size to justify text in
17
+ # newline: => [boolean] True if you want a newline after the output
18
+ #
19
+ def say text = '', args = {}
20
+ # defaults
21
+ args = {
22
+ :newline => true
23
+ }.merge args
24
+
25
+ # Justify options
26
+ if args[:justify] && args[:padding]
27
+ text = text.send args[:justify], args[:padding]
28
+ end
29
+
30
+ # Type options
31
+ # process last due to the addition of special color codes
32
+ text = case args[:type]
33
+ when :fail
34
+ Yuyi.colorize text, 31
35
+ when :success
36
+ Yuyi.colorize text, 32
37
+ when :warn
38
+ Yuyi.colorize text, 33
39
+ else
40
+ Yuyi.colorize text, args[:color]
41
+ end
42
+
43
+ if args[:indent]
44
+ text = (' ' * args[:indent]) + text
45
+ end
46
+
47
+ if args[:newline]
48
+ STDOUT.puts text
49
+ else
50
+ STDOUT.print text
51
+ end
52
+ end
53
+
54
+ # Accepts the same arguments as #say
55
+ #
56
+ def ask question, options = {}, &block
57
+ prompt = '>>> '
58
+ options = {
59
+ :readline => false,
60
+ :color => 1
61
+ }.merge(options)
62
+
63
+ say question, options
64
+
65
+ output = if options[:readline]
66
+ Readline.readline(prompt).chomp('/')
67
+ else
68
+ say prompt, :color => 1, :newline => false
69
+ STDIN.gets
70
+ end.rstrip
71
+
72
+ say
73
+ yield output if block
74
+ end
75
+
76
+ # Run a command and output formatting success/errors
77
+ #
78
+ def run command, args = {}
79
+ # check if in verbose mode
80
+ verbose = args[:verbose] || @verbose
81
+ output = `echo | #{command} 2>&1`
82
+ success = $?.success?
83
+
84
+ if verbose
85
+ say "RUNNING: #{command}", :type => (success ? :success : :fail)
86
+ say output
87
+ end
88
+
89
+ args[:boolean] ? success : output
90
+ end
91
+
92
+ def command? command
93
+ run command, :verbose => false, :boolean => true
94
+ end
95
+
96
+ # Write several lines to to an existing file
97
+ #
98
+ def write_to_file file, *text
99
+ text.flatten!
100
+
101
+ File.open(File.expand_path(file), 'a+') do |file|
102
+ full_text = (text * "\n") + "\n"
103
+
104
+ unless file.read.include? full_text
105
+ file.write full_text
106
+ end
107
+ end
108
+ end
109
+
110
+ # Delete specific lines from an existing file
111
+ #
112
+ def delete_from_file file, *text
113
+ text.flatten!
114
+
115
+ # get file text
116
+ new_text = File.read(File.expand_path(file))
117
+
118
+ # iterate through text and remove it
119
+ text.each do |t|
120
+ regex = /^.*#{Regexp.escape(t)}.*\n/
121
+ new_text.gsub!(regex, '')
122
+ end
123
+
124
+ # write new text back to file
125
+ File.open(File.expand_path(file), 'w') { |f| f.write(new_text) }
126
+ end
127
+
128
+ def osx_version
129
+ run('/usr/bin/sw_vers -productVersion').chomp[/10\.\d+/].to_f
130
+ end
131
+ end