theme-juice 0.6.18 → 0.7.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.
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