Class: Vagrant::UI::Basic

Inherits:
Interface show all
Includes:
Vagrant::Util::SafePuts
Defined in:
lib/vagrant/ui.rb

Overview

This is a UI implementation that outputs the text as is. It doesn't add any color.

Direct Known Subclasses

Colored, NonInteractive, Remote

Instance Attribute Summary

Attributes inherited from Interface

#opts, #stderr, #stdin, #stdout

Instance Method Summary collapse

Methods included from Vagrant::Util::SafePuts

#safe_puts

Methods inherited from Interface

#color?, inherited, #initialize_copy, #machine, #rewriting, #to_proto

Constructor Details

#initializeBasic

Returns a new instance of Basic.



156
157
158
159
160
# File 'lib/vagrant/ui.rb', line 156

def initialize
  super

  @lock = Mutex.new
end

Instance Method Details

#ask(message, **opts) ⇒ Object



174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/vagrant/ui.rb', line 174

def ask(message, **opts)
  super(message)

  # We can't ask questions when the output isn't a TTY.
  raise Errors::UIExpectsTTY if !@stdin.tty? && !Vagrant::Util::Platform.windows?

  # Setup the options so that the new line is suppressed
  opts ||= {}
  opts[:echo]     = true  if !opts.key?(:echo)
  opts[:new_line] = false if !opts.key?(:new_line)
  opts[:prefix]   = false if !opts.key?(:prefix)

  # Output the data
  say(:info, message, opts)

  input = nil
  if opts[:echo] || !@stdin.respond_to?(:noecho)
    input = @stdin.gets
  else
    begin
      input = @stdin.noecho(&:gets)

      # Output a newline because without echo, the newline isn't
      # echoed either.
      say(:info, "\n", opts)
    rescue Errno::EBADF
      # This means that stdin doesn't support echoless input.
      say(:info, "\n#{I18n.t("vagrant.stdin_cant_hide_input")}\n ", opts)

      # Ask again, with echo enabled
      input = ask(message, **opts.merge(echo: true))
    end
  end

  # Get the results and chomp off the newline. We do a logical OR
  # here because `gets` can return a nil, for example in the case
  # that ctrl-D is pressed on the input.
  (input || "").chomp
end

#clear_lineObject



230
231
232
233
234
235
# File 'lib/vagrant/ui.rb', line 230

def clear_line
  # See: https://en.wikipedia.org/wiki/ANSI_escape_code
  reset = "\r\033[K"

  info(reset, new_line: false)
end

#format_message(type, message, **opts) ⇒ Object



266
267
268
# File 'lib/vagrant/ui.rb', line 266

def format_message(type, message, **opts)
  Util::CredentialScrubber.desensitize(message)
end

#report_progress(progress, total, show_parts = true) ⇒ Object

This is used to output progress reports to the UI. Send this method progress/total and it will output it to the UI. Send clear_line to clear the line to show a continuous progress meter.



218
219
220
221
222
223
224
225
226
227
228
# File 'lib/vagrant/ui.rb', line 218

def report_progress(progress, total, show_parts=true)
  if total && total > 0
    percent = (progress.to_f / total.to_f) * 100
    line    = "Progress: #{percent.to_i}%"
    line   << " (#{progress} / #{total})" if show_parts
  else
    line    = "Progress: #{progress}"
  end

  info(line, new_line: false)
end

#say(type, message, opts = {}) ⇒ Object

This method handles actually outputting a message of a given type to the console.



239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
# File 'lib/vagrant/ui.rb', line 239

def say(type, message, opts={})
  defaults = { new_line: true, prefix: true }
  opts     = defaults.merge(@opts).merge(opts)

  # Don't output if we're hiding details
  return if type == :detail && opts[:hide_detail]

  # Determine whether we're expecting to output our
  # own new line or not.
  printer = opts[:new_line] ? :puts : :print

  # Determine the proper IO channel to send this message
  # to based on the type of the message
  channel = type == :error || opts[:channel] == :error ? @stderr : @stdout

  # Output! We wrap this in a lock so that it safely outputs only
  # one line at a time. We wrap this in a thread because as of Ruby 2.0
  # we can't acquire locks in a trap context (ctrl-c), so we have to
  # do this.
  Thread.new do
    @lock.synchronize do
      safe_puts(format_message(type, message, **opts),
                io: channel, printer: printer)
    end
  end.join(THREAD_MAX_JOIN_TIMEOUT)
end