~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/ui/text.py

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
"""Text UI, write output to the console.
19
19
"""
20
20
 
 
21
import codecs
21
22
import getpass
22
23
import os
23
24
import sys
82
83
                # end-of-file; possibly should raise an error here instead
83
84
                return None
84
85
 
 
86
    def get_integer(self, prompt):
 
87
        while True:
 
88
            self.prompt(prompt)
 
89
            line = self.stdin.readline()
 
90
            try:
 
91
                return int(line)
 
92
            except ValueError:
 
93
                pass
 
94
 
85
95
    def get_non_echoed_password(self):
86
96
        isatty = getattr(self.stdin, 'isatty', None)
87
97
        if isatty is not None and isatty():
146
156
        else:
147
157
            return NullProgressView()
148
158
 
 
159
    def _make_output_stream_explicit(self, encoding, encoding_type):
 
160
        if encoding_type == 'exact':
 
161
            # force sys.stdout to be binary stream on win32; 
 
162
            # NB: this leaves the file set in that mode; may cause problems if
 
163
            # one process tries to do binary and then text output
 
164
            if sys.platform == 'win32':
 
165
                fileno = getattr(self.stdout, 'fileno', None)
 
166
                if fileno:
 
167
                    import msvcrt
 
168
                    msvcrt.setmode(fileno(), os.O_BINARY)
 
169
            return TextUIOutputStream(self, self.stdout)
 
170
        else:
 
171
            encoded_stdout = codecs.getwriter(encoding)(self.stdout,
 
172
                errors=encoding_type)
 
173
            # For whatever reason codecs.getwriter() does not advertise its encoding
 
174
            # it just returns the encoding of the wrapped file, which is completely
 
175
            # bogus. So set the attribute, so we can find the correct encoding later.
 
176
            encoded_stdout.encoding = encoding
 
177
            return TextUIOutputStream(self, encoded_stdout)
 
178
 
149
179
    def note(self, msg):
150
180
        """Write an already-formatted message, clearing the progress bar if necessary."""
151
181
        self.clear_term()
231
261
        self._total_byte_count = 0
232
262
        self._bytes_since_update = 0
233
263
        self._fraction = 0
 
264
        # force the progress bar to be off, as at the moment it doesn't 
 
265
        # correspond reliably to overall command progress
 
266
        self.enable_bar = False
234
267
 
235
268
    def _show_line(self, s):
236
269
        # sys.stderr.write("progress %r\n" % s)
237
 
        n = self._width - 1
238
 
        self._term_file.write('\r%-*.*s\r' % (n, n, s))
 
270
        if self._width is not None:
 
271
            n = self._width - 1
 
272
            s = '%-*.*s' % (n, n, s)
 
273
        self._term_file.write('\r' + s + '\r')
239
274
 
240
275
    def clear(self):
241
276
        if self._have_output:
244
279
 
245
280
    def _render_bar(self):
246
281
        # return a string for the progress bar itself
247
 
        if (self._last_task is None) or self._last_task.show_bar:
 
282
        if self.enable_bar and (
 
283
            (self._last_task is None) or self._last_task.show_bar):
248
284
            # If there's no task object, we show space for the bar anyhow.
249
285
            # That's because most invocations of bzr will end showing progress
250
286
            # at some point, though perhaps only after doing some initial IO.
365
401
            self._bytes_since_update = 0
366
402
            self._last_transport_msg = msg
367
403
            self._repaint()
 
404
 
 
405
 
 
406
class TextUIOutputStream(object):
 
407
    """Decorates an output stream so that the terminal is cleared before writing.
 
408
 
 
409
    This is supposed to ensure that the progress bar does not conflict with bulk
 
410
    text output.
 
411
    """
 
412
    # XXX: this does not handle the case of writing part of a line, then doing
 
413
    # progress bar output: the progress bar will probably write over it.
 
414
    # one option is just to buffer that text until we have a full line;
 
415
    # another is to save and restore it
 
416
 
 
417
    # XXX: might need to wrap more methods
 
418
 
 
419
    def __init__(self, ui_factory, wrapped_stream):
 
420
        self.ui_factory = ui_factory
 
421
        self.wrapped_stream = wrapped_stream
 
422
        # this does no transcoding, but it must expose the underlying encoding
 
423
        # because some callers need to know what can be written - see for
 
424
        # example unescape_for_display.
 
425
        self.encoding = getattr(wrapped_stream, 'encoding', None)
 
426
 
 
427
    def flush(self):
 
428
        self.ui_factory.clear_term()
 
429
        self.wrapped_stream.flush()
 
430
 
 
431
    def write(self, to_write):
 
432
        self.ui_factory.clear_term()
 
433
        self.wrapped_stream.write(to_write)
 
434
 
 
435
    def writelines(self, lines):
 
436
        self.ui_factory.clear_term()
 
437
        self.wrapped_stream.writelines(lines)