theme-juice 0.6.18 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +106 -75
  3. data/bin/tj +5 -5
  4. data/lib/theme-juice.rb +32 -16
  5. data/lib/theme-juice/cli.rb +191 -298
  6. data/lib/theme-juice/command.rb +14 -13
  7. data/lib/theme-juice/commands/create.rb +214 -9
  8. data/lib/theme-juice/commands/delete.rb +45 -10
  9. data/lib/theme-juice/commands/deploy.rb +20 -0
  10. data/lib/theme-juice/config.rb +43 -0
  11. data/lib/theme-juice/env.rb +25 -0
  12. data/lib/theme-juice/io.rb +323 -0
  13. data/lib/theme-juice/project.rb +35 -0
  14. data/lib/theme-juice/task.rb +42 -0
  15. data/lib/theme-juice/tasks/create_confirm.rb +33 -0
  16. data/lib/theme-juice/tasks/create_success.rb +42 -0
  17. data/lib/theme-juice/tasks/database.rb +50 -0
  18. data/lib/theme-juice/tasks/delete_confirm.rb +24 -0
  19. data/lib/theme-juice/tasks/delete_success.rb +31 -0
  20. data/lib/theme-juice/tasks/dns.rb +45 -0
  21. data/lib/theme-juice/tasks/dot_env.rb +53 -0
  22. data/lib/theme-juice/tasks/entry.rb +50 -0
  23. data/lib/theme-juice/tasks/hosts.rb +43 -0
  24. data/lib/theme-juice/tasks/import_database.rb +28 -0
  25. data/lib/theme-juice/tasks/landrush.rb +33 -0
  26. data/lib/theme-juice/tasks/list.rb +50 -0
  27. data/lib/theme-juice/tasks/location.rb +23 -0
  28. data/lib/theme-juice/tasks/nginx.rb +51 -0
  29. data/lib/theme-juice/tasks/repo.rb +49 -0
  30. data/lib/theme-juice/tasks/synced_folder.rb +30 -0
  31. data/lib/theme-juice/tasks/theme.rb +34 -0
  32. data/lib/theme-juice/tasks/vm.rb +30 -0
  33. data/lib/theme-juice/tasks/vm_customfile.rb +42 -0
  34. data/lib/theme-juice/tasks/vm_location.rb +32 -0
  35. data/lib/theme-juice/tasks/vm_plugins.rb +32 -0
  36. data/lib/theme-juice/tasks/vm_provision.rb +39 -0
  37. data/lib/theme-juice/tasks/vm_restart.rb +25 -0
  38. data/lib/theme-juice/tasks/wp_cli.rb +52 -0
  39. data/lib/theme-juice/util.rb +45 -0
  40. data/lib/theme-juice/version.rb +1 -1
  41. metadata +66 -34
  42. data/LICENSE +0 -339
  43. data/lib/theme-juice/commands/install.rb +0 -16
  44. data/lib/theme-juice/commands/list.rb +0 -16
  45. data/lib/theme-juice/commands/subcommand.rb +0 -16
  46. data/lib/theme-juice/environment.rb +0 -15
  47. data/lib/theme-juice/interaction.rb +0 -445
  48. data/lib/theme-juice/interactions/create.rb +0 -278
  49. data/lib/theme-juice/interactions/delete.rb +0 -48
  50. data/lib/theme-juice/interactions/teejay.rb +0 -12
  51. data/lib/theme-juice/service.rb +0 -224
  52. data/lib/theme-juice/services/config.rb +0 -44
  53. data/lib/theme-juice/services/create.rb +0 -376
  54. data/lib/theme-juice/services/delete.rb +0 -113
  55. data/lib/theme-juice/services/list.rb +0 -40
@@ -1,19 +1,20 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module ThemeJuice
4
- class Command
5
- include ::Thor::Actions
6
- include ::Thor::Shell
4
+ class Command < Task
7
5
 
8
- #
9
- # @param {Hash} opts
10
- #
11
- # @return {Void}
12
- #
13
- def initialize(opts = {})
14
- @environment = ::ThemeJuice::Environment
15
- @interaction = ::ThemeJuice::Interaction
16
- @opts = opts
17
- end
6
+ def initialize(opts = {})
7
+ super
8
+
9
+ @list = Tasks::List.new
10
+ end
11
+
12
+ def execute
13
+ @tasks.each { |task| task.execute }
14
+ end
15
+
16
+ def unexecute
17
+ @tasks.each { |task| task.unexecute }
18
18
  end
19
+ end
19
20
  end
@@ -1,16 +1,221 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module ThemeJuice
4
- class Command::Create < ::ThemeJuice::Command
4
+ module Commands
5
+ class Create < Command
5
6
 
6
- #
7
- # @param {Hash} opts
8
- #
9
- # @return {Void}
10
- #
11
- def initialize(opts = {})
12
- super
13
- ::ThemeJuice::Service::Create.new(@opts).create
7
+ def initialize(opts = {})
8
+ super
9
+
10
+ @project.use_defaults = @opts.fetch("use_defaults", false)
11
+ @project.bare = @opts.fetch("bare", false)
12
+ @project.skip_repo = @opts.fetch("skip_repo", false)
13
+ @project.skip_db = @opts.fetch("skip_db", false)
14
+ @project.no_wp = @opts.fetch("no_wp", false)
15
+ @project.no_db = @opts.fetch("no_db", false)
16
+ @project.name = @opts.fetch("name") { name }
17
+ @project.location = @opts.fetch("location") { location }
18
+ @project.url = @opts.fetch("url") { url }
19
+ @project.theme = @opts.fetch("theme") { theme }
20
+ @project.repository = @opts.fetch("repository") { repository }
21
+ @project.db_host = @opts.fetch("db_host") { db_host }
22
+ @project.db_name = @opts.fetch("db_name") { db_name }
23
+ @project.db_user = @opts.fetch("db_user") { db_user }
24
+ @project.db_pass = @opts.fetch("db_pass") { db_pass }
25
+ @project.db_import = @opts.fetch("db_import") { db_import }
26
+ @project.vm_root = vm_root
27
+ @project.vm_location = vm_location
28
+ @project.vm_srv = vm_srv
29
+
30
+ runner do |tasks|
31
+ tasks << Tasks::CreateConfirm.new
32
+ tasks << Tasks::Location.new
33
+ tasks << Tasks::Theme.new
34
+ tasks << Tasks::VM.new
35
+ tasks << Tasks::VMPlugins.new
36
+ tasks << Tasks::VMLocation.new
37
+ tasks << Tasks::VMCustomfile.new
38
+ tasks << Tasks::Hosts.new
39
+ tasks << Tasks::Database.new
40
+ tasks << Tasks::Nginx.new
41
+ tasks << Tasks::DotEnv.new
42
+ tasks << Tasks::Landrush.new
43
+ tasks << Tasks::SyncedFolder.new
44
+ tasks << Tasks::DNS.new
45
+ tasks << Tasks::WPCLI.new
46
+ tasks << Tasks::Repo.new
47
+ tasks << Tasks::CreateSuccess.new
48
+ tasks << Tasks::ImportDatabase.new
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ def name
55
+ if @env.yolo
56
+ name = Faker::Internet.domain_word
57
+ else
58
+ name = @io.prompt "What's the project name? (letters, numbers and dashes only)"
59
+ end
60
+
61
+ valid_name? name
62
+
63
+ name
64
+ end
65
+
66
+ def valid_name?(name)
67
+ if name.empty?
68
+ @io.error "Project name '#{name}' looks like it's empty. Aborting mission."
69
+ end
70
+
71
+ "#{name}".match /[^0-9A-Za-z.\-]/ do |char|
72
+ @io.error "Project name contains an invalid character '#{char}'. This name is used internally for a ton of stuff, so that's not gonna work. Aborting mission."
73
+ end
74
+
75
+ true
76
+ end
77
+
78
+ def clean_name
79
+ "#{@project.name}".gsub(/[^\w]/, "_")[0..10]
80
+ end
81
+
82
+ def location
83
+ path = "#{Dir.pwd}/"
84
+
85
+ if @project.use_defaults
86
+ location = File.expand_path path
87
+ else
88
+ location = File.expand_path @io.prompt("Where do you want to setup the project?", :default => path, :path => true)
89
+ end
90
+
91
+ location
92
+ end
93
+
94
+ def url
95
+ if @project.use_defaults
96
+ url = "#{@project.name}.dev"
97
+ else
98
+ url = @io.prompt "What do you want the development url to be? (this should end in '.dev')", :default => "#{@project.name}.dev"
99
+ end
100
+
101
+ valid_url? url
102
+
103
+ url
104
+ end
105
+
106
+ def valid_url?(url)
107
+ unless "#{url}".match /(.dev)$/
108
+ @io.error "Your development url '#{url}' doesn't end with '.dev'. This is used internally by Landrush, so that's not gonna work. Aborting mission."
109
+ end
110
+
111
+ true
112
+ end
113
+
114
+ def theme
115
+ return false if @project.bare
116
+
117
+ theme = nil
118
+ themes = {
119
+ "theme-juice/theme-juice-starter" => "https://github.com/ezekg/theme-juice-starter.git",
120
+ "other" => nil,
121
+ "none" => nil
122
+ }
123
+
124
+ if @project.use_defaults
125
+ theme = themes["theme-juice/theme-juice-starter"]
126
+ else
127
+ choice = @io.choose "Which starter theme would you like to use?", :blue, themes.keys
128
+
129
+ case choice
130
+ when "theme-juice/theme-juice-starter"
131
+ @io.success "Awesome choice!"
132
+ when "other"
133
+ themes[choice] = @io.prompt "What is the repository URL for the starter theme that you would like to clone?"
134
+ when "none"
135
+ @io.notice "Next time you need to create a project without a starter theme, you can just run the 'setup' command instead."
136
+ @project.bare = true
137
+ end
138
+
139
+ theme = themes[choice]
140
+ end
141
+
142
+ theme
143
+ end
144
+
145
+ def repository
146
+ return false if @project.skip_repo || @project.use_defaults
147
+
148
+ if @io.agree? "Would you like to initialize a new Git repository?"
149
+ repo = @io.prompt "What is the repository's remote URL?", :indent => 2
150
+ else
151
+ repo = false
152
+ end
153
+
154
+ repo
155
+ end
156
+
157
+ def db_host
158
+ return false if @project.no_db || @project.no_wp
159
+
160
+ if @project.skip_db || @project.use_defaults
161
+ db_host = "vvv"
162
+ else
163
+ db_host = @io.prompt "Database host", :default => "vvv"
164
+ end
165
+
166
+ db_host
167
+ end
168
+
169
+ def db_name
170
+ return false if @project.no_db || @project.no_wp
171
+
172
+ if @project.skip_db || @project.use_defaults
173
+ db_name = "#{clean_name}_db"
174
+ else
175
+ db_name = @io.prompt "Database name", :default => "#{clean_name}_db"
14
176
  end
177
+
178
+ db_name
179
+ end
180
+
181
+ def db_user
182
+ return false if @project.no_db || @project.no_wp
183
+
184
+ if @project.skip_db || @project.use_defaults
185
+ db_user = "#{clean_name}_user"
186
+ else
187
+ db_user = @io.prompt "Database username", :default => "#{clean_name}_user"
188
+ end
189
+
190
+ db_user
191
+ end
192
+
193
+ def db_pass
194
+ return false if @project.no_db || @project.no_wp
195
+
196
+ pass = Faker::Internet.password 24
197
+
198
+ if @project.skip_db || @project.use_defaults
199
+ db_pass = pass
200
+ else
201
+ db_pass = @io.prompt "Database password", :default => pass
202
+ end
203
+
204
+ db_pass
205
+ end
206
+
207
+ def db_import
208
+ return false if @project.no_db || @project.no_wp || @project.use_defaults
209
+
210
+ if @io.agree? "Would you like to import an existing database?"
211
+ db = @io.prompt "Where is the database file?", {
212
+ :indent => 2, :path => true }
213
+ else
214
+ db = false
215
+ end
216
+
217
+ db
218
+ end
15
219
  end
220
+ end
16
221
  end
@@ -1,16 +1,51 @@
1
1
  # encoding: UTF-8
2
2
 
3
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
- ::ThemeJuice::Service::Delete.new(@opts).delete
4
+ module Commands
5
+ class Delete < Command
6
+
7
+ def initialize(opts = {})
8
+ super
9
+
10
+ @project.name = @opts.fetch("name") { name }
11
+ @project.url = @opts.fetch("url") { url }
12
+ @project.db_drop = @opts.fetch("db_drop", false)
13
+ @project.vm_restart = @opts.fetch("vm_restart", false)
14
+ @project.vm_root = vm_root
15
+ @project.vm_location = vm_location
16
+ @project.vm_srv = vm_srv
17
+
18
+ runner do |tasks|
19
+ tasks << Tasks::DeleteConfirm.new
20
+ tasks << Tasks::Database.new
21
+ tasks << Tasks::VMLocation.new
22
+ tasks << Tasks::SyncedFolder.new
23
+ tasks << Tasks::DNS.new
24
+ tasks << Tasks::DeleteSuccess.new
25
+ end
26
+ end
27
+
28
+ private
29
+
30
+ def name
31
+ name = @io.prompt "What's the project name?"
32
+
33
+ unless @list.projects.include? name
34
+ @io.error "Project '#{name}' doesn't exist"
35
+ end
36
+
37
+ name
38
+ end
39
+
40
+ def url
41
+ url = @io.prompt "What is the project's development url?", :default => "#{@project.name}.dev"
42
+
43
+ unless @list.urls.include? url
44
+ @io.notice "Project url '#{url}' doesn't exist within DNS records. Skipping..."
14
45
  end
46
+
47
+ url
48
+ end
15
49
  end
50
+ end
16
51
  end
@@ -0,0 +1,20 @@
1
+ # encoding: UTF-8
2
+
3
+ module ThemeJuice
4
+ module Commands
5
+ class Deploy < Command
6
+
7
+ def initialize(opts = {})
8
+ super
9
+
10
+ @project.vm_root = vm_root
11
+ @project.vm_location = vm_location
12
+ @project.vm_srv = vm_srv
13
+
14
+ runner do |tasks|
15
+ @io.error "Not implemented"
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: UTF-8
2
+
3
+ module ThemeJuice
4
+ module Config
5
+ @env = Env
6
+ @io = IO
7
+ @project = Project
8
+ @util = Util.new
9
+
10
+ def method_missing(method, *args, &block)
11
+ @project.location ||= Dir.pwd
12
+
13
+ config.fetch("commands", {})
14
+ .fetch(method.to_s) { @io.error("Command '#{method}' not found in config") }
15
+ .each { |cmd| run "#{cmd} #{args.join(" ") unless args.empty?}" }
16
+ end
17
+
18
+ private
19
+
20
+ def run(command)
21
+ @util.inside @project.location do
22
+ @util.run command, :verbose => @env.verbose
23
+ end
24
+ end
25
+
26
+ def config
27
+ begin
28
+ YAML.load_file Dir["#{@project.location}/*"].select { |f| regex =~ File.basename(f) }.last ||
29
+ @io.error("Config file not found in '#{@project.location}'")
30
+ rescue ::Psych::SyntaxError => err
31
+ @io.error "Config file is invalid" do
32
+ puts err
33
+ end
34
+ end
35
+ end
36
+
37
+ def regex
38
+ %r{^((\.)?(tj.y(a)?ml)|((J|j)uicefile))}
39
+ end
40
+
41
+ extend self
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: UTF-8
2
+
3
+ module ThemeJuice
4
+ module Env
5
+ attr_accessor :vm_path
6
+ attr_accessor :vm_ip
7
+ attr_accessor :yolo
8
+ attr_accessor :boring
9
+ attr_accessor :no_unicode
10
+ attr_accessor :no_colors
11
+ attr_accessor :no_animations
12
+ attr_accessor :no_landrush
13
+ attr_accessor :vm_prefix
14
+ attr_accessor :verbose
15
+ attr_accessor :dryrun
16
+
17
+ def inspect
18
+ res = []
19
+ self.instance_variables.each { |k, _| res << "#{k[1..-1]}: #{instance_variable_get(k)}" }
20
+ res.sort
21
+ end
22
+
23
+ extend self
24
+ end
25
+ end
@@ -0,0 +1,323 @@
1
+ # encoding: UTF-8
2
+
3
+ module ThemeJuice
4
+ module IO
5
+ include Thor::Shell
6
+
7
+ ICONS = {
8
+ :success => "✓", # "\u2713",
9
+ :error => "↑", # "\u2191",
10
+ :notice => "→", # "\u2192",
11
+ :question => "•", # "\u2022",
12
+ :general => "›", # "\u203A",
13
+ :log => "…", # "\u2026",
14
+ :restart => "↪", # "\u21AA",
15
+ :selected => "•", # "\u2022",
16
+ :unselected => "○", # "\u25CB",
17
+ :fallback_success => "+",
18
+ :fallback_error => "!",
19
+ :fallback_notice => "!",
20
+ :fallback_question => "?",
21
+ :fallback_general => "-",
22
+ :fallback_log => "...",
23
+ :fallback_restart => "!",
24
+ :fallback_selected => "[x]",
25
+ :fallback_unselected => "[ ]",
26
+ }
27
+
28
+ KEYS = {
29
+ "\e[A" => "up",
30
+ "\e[B" => "down",
31
+ "\e[C" => "right",
32
+ "\e[D" => "left",
33
+ "\003" => "ctrl+c",
34
+ "\004" => "ctrl+d",
35
+ "\e" => "escape",
36
+ "\n" => "linefeed",
37
+ "\r" => "return",
38
+ " " => "space",
39
+ }
40
+
41
+ @state = nil
42
+ @env = Env
43
+
44
+ def speak(message, opts = {})
45
+ format_message message, opts
46
+ output_message
47
+ end
48
+
49
+ def prompt(question, *opts)
50
+ format_message question, {
51
+ :color => :blue,
52
+ :icon => :question
53
+ }
54
+
55
+ opts.each do |opt|
56
+
57
+ # if opt[:default]
58
+ # opt[:default] = set_color(opt[:default], :black, :bold) unless @env.no_colors
59
+ # end
60
+
61
+ if opt[:indent]
62
+ with(question) { |str| (" " * opt[:indent]) << str }
63
+ end
64
+
65
+ break
66
+ end
67
+
68
+ ask("#{question} :", *opts).gsub /\e\[\d+m/, ""
69
+ end
70
+
71
+ def agree?(question, opts = {})
72
+ format_message question, {
73
+ :color => opts.fetch("color", :blue),
74
+ :icon => :question
75
+ }
76
+
77
+ if opts[:simple]
78
+ yes? " :", opts.fetch("color", {})
79
+ else
80
+ yes? "#{question} (y/N) :"
81
+ end
82
+ end
83
+
84
+ def log(message)
85
+ speak message, {
86
+ :color => :yellow,
87
+ :icon => :log
88
+ }
89
+ end
90
+
91
+ def success(message)
92
+ speak message, {
93
+ :color => [:black, :on_green, :bold],
94
+ :icon => :success,
95
+ :row => true
96
+ }
97
+ end
98
+
99
+ def notice(message)
100
+ speak message, {
101
+ :color => [:black, :on_yellow],
102
+ :icon => :notice,
103
+ :row => true
104
+ }
105
+ end
106
+
107
+ def error(message)
108
+ speak message, {
109
+ :color => [:white, :on_red],
110
+ :icon => :error,
111
+ :row => true
112
+ }
113
+
114
+ yield if block_given?
115
+
116
+ exit 1
117
+ end
118
+
119
+ def hello(opts = {})
120
+ speak "Welcome to Theme Juice!", {
121
+ :color => [:black, :on_green, :bold],
122
+ :row => true
123
+ }.merge(opts)
124
+ end
125
+
126
+ def goodbye(opts = {})
127
+
128
+ # Have some fun?
129
+ goodbyes = [
130
+ "Bye, bye, bye",
131
+ "Adios, muchachos",
132
+ "See ya later, alligator",
133
+ "Peace...",
134
+ "Later, homes",
135
+ "I'll be back",
136
+ "Victory is ours!",
137
+ "May the force be with you",
138
+ "Take a break, man...",
139
+ "It's not me, it's you",
140
+ "Go home, developer, you're drunk",
141
+ "Okay, this is getting a little out of hand...",
142
+ "I don't like it when you press my buttons",
143
+ "Ouch!",
144
+ ":(",
145
+ ]
146
+
147
+ speak goodbyes.sample, {
148
+ :color => :yellow,
149
+ :newline => true
150
+ }.merge(opts)
151
+
152
+ exit 130
153
+ end
154
+
155
+ def open_project(url)
156
+ speak "Do you want to open up your new project at 'http://#{url}' now? (y/N)", {
157
+ :color => [:black, :on_blue],
158
+ :icon => :restart,
159
+ :row => true
160
+ }
161
+
162
+ if agree? "", { :simple => true }
163
+ OS.open_file_command "http://#{url}"
164
+ end
165
+ end
166
+
167
+ def list(header, color, list)
168
+ speak header, {
169
+ :color => [:black, :"on_#{color}"],
170
+ :icon => :notice,
171
+ :row => true
172
+ }
173
+
174
+ list.each do |item|
175
+ speak item, {
176
+ :color => :"#{color}",
177
+ :icon => :general
178
+ }
179
+ end
180
+ end
181
+
182
+ def choose(header, color, list)
183
+ if OS.windows?
184
+ ask header, {
185
+ :limited_to => list,
186
+ :color => color
187
+ }
188
+ else
189
+ speak "#{header} (use arrow keys and press enter)", {
190
+ :color => :"#{color}",
191
+ :icon => :question
192
+ }
193
+
194
+ print "\n" * list.size
195
+
196
+ selected = 0
197
+ update_list_selection(list, color, selected)
198
+
199
+ loop do
200
+ key = read_key
201
+ case key
202
+ when "up"
203
+ selected -= 1
204
+ selected = list.size - 1 if selected < 0
205
+ update_list_selection(list, color, selected)
206
+ when "down"
207
+ selected += 1
208
+ selected = 0 if selected > list.size - 1
209
+ update_list_selection(list, color, selected)
210
+ when "return", "linefeed", "space"
211
+ return list[selected]
212
+ when "esc", "ctrl+c"
213
+ goodbye(:newline => false)
214
+ # else
215
+ # speak key.inspect, { :color => :yellow }
216
+ end
217
+ end
218
+ end
219
+ end
220
+
221
+ private
222
+
223
+ def update_list_selection(list, color, selected = 0)
224
+ print "\e[#{list.size}A"
225
+
226
+ list.each_with_index do |item, i|
227
+ icon = i == selected ? "selected" : "unselected"
228
+ speak "#{item}", {
229
+ :color => :"#{color}",
230
+ :icon => :"#{icon}",
231
+ :indent => 2
232
+ }
233
+ end
234
+ end
235
+
236
+ #
237
+ # @see http://www.alecjacobson.com/weblog/?p=75
238
+ #
239
+ def read_key
240
+ save_stty_state
241
+ raw_stty_mode
242
+
243
+ key = STDIN.getc.chr
244
+
245
+ if key == "\e"
246
+ thread = Thread.new { key += STDIN.getc.chr + STDIN.getc.chr }
247
+ thread.join(0.001)
248
+ thread.kill
249
+ end
250
+
251
+ KEYS[key] || key
252
+ ensure
253
+ restore_stty_state
254
+ end
255
+
256
+ def save_stty_state
257
+ @state = %x(stty -g)
258
+ end
259
+
260
+ def raw_stty_mode
261
+ %x(stty raw -echo)
262
+ end
263
+
264
+ def restore_stty_state
265
+ %x(stty #{@state})
266
+ end
267
+
268
+ def format_message(message, opts = {})
269
+ @message, @opts = message, opts
270
+
271
+ format_message_icon
272
+ format_message_newline
273
+ format_message_row
274
+ format_message_width
275
+ format_message_color
276
+ format_message_indent
277
+
278
+ @message
279
+ end
280
+
281
+ def with(string)
282
+ str = yield(string); string.clear; string << str
283
+ end
284
+
285
+ def format_message_icon
286
+ icon = @env.no_unicode ? "fallback_#{@opts[:icon]}" : "#{@opts[:icon]}"
287
+
288
+ if @opts[:icon]
289
+ with(@message) { |msg| "#{ICONS[:"#{icon}"]}" << (@opts[:empty] ? nil : " #{msg}") }
290
+ else
291
+ with(@message) { |msg| "" << msg }
292
+ end
293
+ end
294
+
295
+ def format_message_newline
296
+ with(@message) { |msg| "\n" << msg } if @opts[:newline]
297
+ end
298
+
299
+ def format_message_color
300
+ unless @env.no_colors
301
+ with(@message) { |msg| set_color(msg, *@opts[:color]) } if @opts[:color]
302
+ end
303
+ end
304
+
305
+ def format_message_row
306
+ with(@message) { |msg| msg.ljust(terminal_width) } if @opts[:row]
307
+ end
308
+
309
+ def format_message_width
310
+ with(@message) { |msg| msg.ljust(@opts[:width]) } if @opts[:width]
311
+ end
312
+
313
+ def format_message_indent
314
+ with(@message) { |str| (" " * @opts[:indent]) << str } if @opts[:indent]
315
+ end
316
+
317
+ def output_message
318
+ @opts[:quiet] ? @message : say(@message)
319
+ end
320
+
321
+ extend self
322
+ end
323
+ end