chiark / gitweb /
Log and undo external modifications
[stgit] / stgit / out.py
1 # -*- coding: utf-8 -*-
2
3 __copyright__ = """
4 Copyright (C) 2007, Karl Hasselström <kha@treskal.com>
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License version 2 as
8 published by the Free Software Foundation.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 """
19
20 import sys, textwrap
21
22 class MessagePrinter(object):
23     def __init__(self, file = None):
24         class Output(object):
25             def __init__(self, write, flush):
26                 self.write = write
27                 self.flush = flush
28                 self.at_start_of_line = True
29                 self.level = 0
30             def new_line(self):
31                 """Ensure that we're at the beginning of a line."""
32                 if not self.at_start_of_line:
33                     self.write('\n')
34                     self.at_start_of_line = True
35             def single_line(self, msg, print_newline = True,
36                             need_newline = True):
37                 """Write a single line. Newline before and after are
38                 separately configurable."""
39                 if need_newline:
40                     self.new_line()
41                 if self.at_start_of_line:
42                     self.write('  '*self.level)
43                 self.write(msg)
44                 if print_newline:
45                     self.write('\n')
46                     self.at_start_of_line = True
47                 else:
48                     self.flush()
49                     self.at_start_of_line = False
50             def tagged_lines(self, tag, lines):
51                 tag += ': '
52                 width = 79 - 2*self.level - len(tag)
53                 lines = [wl for line in lines
54                          for wl in textwrap.wrap(line, width,
55                                                  break_long_words = False)]
56                 for line in lines:
57                     self.single_line(tag + line)
58                     tag = ' '*len(tag)
59             def write_line(self, line):
60                 """Write one line of text on a lines of its own, not
61                 indented."""
62                 self.new_line()
63                 self.write('%s\n' % line)
64                 self.at_start_of_line = True
65             def write_raw(self, string):
66                 """Write an arbitrary string, possibly containing
67                 newlines."""
68                 self.new_line()
69                 self.write(string)
70                 self.at_start_of_line = string.endswith('\n')
71         if file:
72             self.__stdout = self.__stderr = Output(file.write, file.flush)
73         else:
74             self.__stdout = Output(sys.stdout.write, sys.stdout.flush)
75             self.__stderr = Output(sys.stdout.write, sys.stdout.flush)
76         if file or sys.stdout.isatty():
77             self.__out = self.__stdout
78             self.__err = self.__stdout
79         else:
80             self.__out = Output(lambda msg: None, lambda: None)
81             self.__err = self.__stderr
82     def stdout(self, line):
83         """Write a line to stdout."""
84         self.__stdout.write_line(line)
85     def stdout_raw(self, string):
86         """Write a string possibly containing newlines to stdout."""
87         self.__stdout.write_raw(string)
88     def err_raw(self, string):
89         """Write a string possibly containing newlines to the error
90         output."""
91         self.__err.write_raw(string)
92     def info(self, *msgs):
93         for msg in msgs:
94             self.__out.single_line(msg)
95     def note(self, *msgs, **kw):
96         self.__out.tagged_lines(kw.get('title', 'Notice'), msgs)
97     def warn(self, *msgs, **kw):
98         self.__err.tagged_lines(kw.get('title', 'Warning'), msgs)
99     def error(self, *msgs, **kw):
100         self.__err.tagged_lines(kw.get('title', 'Error'), msgs)
101     def start(self, msg):
102         """Start a long-running operation."""
103         self.__out.single_line('%s ... ' % msg, print_newline = False)
104         self.__out.level += 1
105     def done(self, extramsg = None):
106         """Finish long-running operation."""
107         self.__out.level -= 1
108         if extramsg:
109             msg = 'done (%s)' % extramsg
110         else:
111             msg = 'done'
112         self.__out.single_line(msg, need_newline = False)
113
114 out = MessagePrinter()