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

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?, #initialize_copy, #machine, #rewriting

Constructor Details

#initializeBasic

Returns a new instance of Basic.


147
148
149
150
151
# File 'lib/vagrant/ui.rb', line 147

def initialize
  super

  @lock = Mutex.new
end

Instance Method Details

#ask(message, **opts) ⇒ Object


165
166
167
168
169
170
171
172
173
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
# File 'lib/vagrant/ui.rb', line 165

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


221
222
223
224
225
226
# File 'lib/vagrant/ui.rb', line 221

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


257
258
259
# File 'lib/vagrant/ui.rb', line 257

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.


209
210
211
212
213
214
215
216
217
218
219
# File 'lib/vagrant/ui.rb', line 209

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.


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/vagrant/ui.rb', line 230

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