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

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

Constructor Details

#initializeBasic

Returns a new instance of Basic.



140
141
142
143
144
# File 'lib/vagrant/ui.rb', line 140

def initialize
  super

  @lock = Mutex.new
end

Instance Method Details

#ask(message, opts = nil) ⇒ Object



158
159
160
161
162
163
164
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
# File 'lib/vagrant/ui.rb', line 158

def ask(message, opts=nil)
  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



214
215
216
217
218
219
# File 'lib/vagrant/ui.rb', line 214

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



250
251
252
# File 'lib/vagrant/ui.rb', line 250

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.



202
203
204
205
206
207
208
209
210
211
212
# File 'lib/vagrant/ui.rb', line 202

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.



223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/vagrant/ui.rb', line 223

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