monotone

monotone Mtn Source Tree

Root/ui.cc

1#include "config.h"
2#include "platform.hh"
3#include "sanity.hh"
4#include "ui.hh"
5#include "transforms.hh"
6
7#include <iostream>
8#include <boost/lexical_cast.hpp>
9
10// copyright (C) 2002, 2003 graydon hoare <graydon@pobox.com>
11// all rights reserved.
12// licensed to the public under the terms of the GNU GPL (>= 2)
13// see the file COPYING for details
14
15// this file contains a couple utilities to deal with the user
16// interface. the global user_interface object 'ui' owns clog, so no
17// writing to it directly!
18
19using namespace std;
20using boost::lexical_cast;
21struct user_interface ui;
22
23ticker::ticker(string const & tickname, std::string const & s, size_t mod) :
24 ticks(0),
25 mod(mod),
26 name(tickname),
27 shortname(s)
28{
29 I(ui.tickers.find(tickname) == ui.tickers.end());
30 ui.tickers.insert(make_pair(tickname,this));
31}
32
33ticker::~ticker()
34{
35 I(ui.tickers.find(name) != ui.tickers.end());
36 if (ui.some_tick_is_dirty)
37 {
38 ui.write_ticks();
39 }
40 ui.tickers.erase(name);
41 ui.finish_ticking();
42}
43
44void
45ticker::operator++()
46{
47 I(ui.tickers.find(name) != ui.tickers.end());
48 ticks++;
49 ui.some_tick_is_dirty = true;
50 if (ticks % mod == 0)
51 ui.write_ticks();
52}
53
54void
55ticker::operator+=(size_t t)
56{
57 I(ui.tickers.find(name) != ui.tickers.end());
58 size_t old = ticks;
59
60 ticks += t;
61 if (t != 0)
62 {
63 ui.some_tick_is_dirty = true;
64 if (ticks % mod == 0 || (ticks / mod) > (old / mod))
65 ui.write_ticks();
66 }
67}
68
69
70tick_write_count::tick_write_count() : last_tick_len(0)
71{
72}
73
74tick_write_count::~tick_write_count()
75{
76}
77
78void tick_write_count::write_ticks()
79{
80 string tickline = "\rmonotone: ";
81 for (map<string,ticker *>::const_iterator i = ui.tickers.begin();
82 i != ui.tickers.end(); ++i)
83 {
84 tickline +=
85 string("[")
86 + i->first + ": " + lexical_cast<string>(i->second->ticks)
87 + "] ";
88 }
89 tickline += ui.tick_trailer;
90
91 size_t curr_sz = tickline.size();
92 if (curr_sz < last_tick_len)
93 tickline += string(last_tick_len - curr_sz, ' ');
94 last_tick_len = curr_sz;
95
96 clog << tickline;
97 clog.flush();
98}
99
100
101tick_write_dot::tick_write_dot()
102{
103}
104
105tick_write_dot::~tick_write_dot()
106{
107}
108
109void tick_write_dot::write_ticks()
110{
111 string tickline1, tickline2;
112 bool first_tick = true;
113
114 if (ui.last_write_was_a_tick)
115 {
116 tickline1 = "";
117 tickline2 = "";
118 }
119 else
120 {
121 tickline1 = "monotone: ticks: ";
122 tickline2 = "\nmonotone: ";
123 }
124
125 for (map<string,ticker *>::const_iterator i = ui.tickers.begin();
126 i != ui.tickers.end(); ++i)
127 {
128 map<string,size_t>::const_iterator old = last_ticks.find(i->first);
129
130 if (!ui.last_write_was_a_tick)
131 {
132 if (!first_tick)
133 tickline1 += ", ";
134
135 tickline1 +=
136 i->second->shortname + "=\"" + i->second->name + "\""
137 + "/" + lexical_cast<string>(i->second->mod);
138 first_tick = false;
139 }
140
141 if (old == last_ticks.end()
142 || ((i->second->ticks / i->second->mod)
143 > (old->second / i->second->mod)))
144 {
145 tickline2 += i->second->shortname;
146
147 if (old == last_ticks.end())
148 last_ticks.insert(make_pair(i->first, i->second->ticks));
149 else
150 last_ticks[i->first] = i->second->ticks;
151 }
152 }
153
154 clog << tickline1 << tickline2;
155 clog.flush();
156}
157
158
159user_interface::user_interface() :
160 last_write_was_a_tick(false),
161 t_writer(0)
162{
163 clog.sync_with_stdio(false);
164 clog.unsetf(ios_base::unitbuf);
165 if (have_smart_terminal())
166 set_tick_writer(new tick_write_count);
167 else
168 set_tick_writer(new tick_write_dot);
169}
170
171user_interface::~user_interface()
172{
173 delete t_writer;
174}
175
176void
177user_interface::finish_ticking()
178{
179 if (tickers.size() == 0 &&
180 last_write_was_a_tick)
181 {
182 tick_trailer = "";
183 clog << endl;
184 last_write_was_a_tick = false;
185 }
186}
187
188void
189user_interface::set_tick_trailer(string const & t)
190{
191 tick_trailer = t;
192}
193
194void
195user_interface::set_tick_writer(tick_writer * t)
196{
197 if (t_writer != 0)
198 delete t_writer;
199 t_writer = t;
200}
201
202void
203user_interface::write_ticks()
204{
205 t_writer->write_ticks();
206 last_write_was_a_tick = true;
207 some_tick_is_dirty = false;
208}
209
210void
211user_interface::warn(string const & warning)
212{
213 if (issued_warnings.find(warning) == issued_warnings.end())
214 inform("warning: " + warning);
215 issued_warnings.insert(warning);
216}
217
218void
219user_interface::fatal(string const & fatal)
220{
221 inform("fatal: " + fatal);
222 inform("this is almost certainly a bug in monotone.\n");
223 inform("please send this error message, the output of 'monotone --full-version',\n");
224 inform("and a description of what you were doing to " PACKAGE_BUGREPORT ".\n");
225}
226
227
228static inline string
229sanitize(string const & line)
230{
231 // FIXME: you might want to adjust this if you're using a charset
232 // which has safe values in the sub-0x20 range. ASCII, UTF-8,
233 // and most ISO8859-x sets do not.
234 string tmp;
235 tmp.reserve(line.size());
236 for (size_t i = 0; i < line.size(); ++i)
237 {
238 if ((line[i] == '\n')
239 || (line[i] >= static_cast<char>(0x20)
240 && line[i] != static_cast<char>(0x7F)))
241 tmp += line[i];
242 else
243 tmp += ' ';
244 }
245 return tmp;
246}
247
248void
249user_interface::ensure_clean_line()
250{
251 if (last_write_was_a_tick)
252 {
253 write_ticks();
254 clog << endl;
255 }
256 last_write_was_a_tick = false;
257}
258
259void
260user_interface::inform(string const & line)
261{
262 string prefixedLine;
263 prefix_lines_with("monotone: ", line, prefixedLine);
264 ensure_clean_line();
265 clog << sanitize(prefixedLine) << endl;
266 clog.flush();
267}

Archive Download this file

Branches

Tags

Quick Links:     www.monotone.ca    -     Downloads    -     Documentation    -     Wiki    -     Code Forge    -     Build Status