libzypp 17.34.0
OutNormal.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8----------------------------------------------------------------------*/
9
10#include <iostream>
11#include <fstream>
12#include <sstream>
13
14#include <unistd.h>
15
16#include <zypp-core/Pathname.h>
17#include <zypp-core/ByteCount.h> // for download progress reporting
19#include <zypp-core/base/String.h> // for toUpper()
20
23
24#include "OutNormal.h"
25
26using std::cout;
27using std::cerr;
28using std::endl;
29
30namespace ztui {
31
33: Out( TYPE_NORMAL, verbosity_r )
34, _use_colors( false )
35, _isatty( do_ttyout() )
36, _newline( true )
37, _oneup( false )
38{}
39
42
43bool OutNormal::mine( Type type )
44{ return( type & Out::TYPE_NORMAL ); }
45
47{
48 if ( !mine( mask ) )
49 return true;
50 if ( verbosity() < verbosity_r )
51 return true;
52 return false;
53}
54
56{
57 if ( !_newline ) // An active Progress bar is not NL terminated
58 cout << ansi::tty::clearLN; // Wipe it before writing out a normal line to the screen
59 // Alternative : cout << endl; to Keep the progress bar visible.
60}
61
62void OutNormal::info( const std::string & msg_r, Verbosity verbosity_r, Type mask )
63{
65 return;
66
68
70 if ( verbosity_r == Out::QUIET )
72 else if ( verbosity_r == Out::DEBUG )
74
75 cout << msg << endl;
76 _newline = true;
77}
78
80{ info( msg.get( termwidth() ), verbosity_r, mask ); }
81
82void OutNormal::warning( const std::string & msg, Verbosity verbosity_r, Type mask )
83{
85 return;
86
88
89 cout << ( ColorContext::MSG_WARNING << _("Warning: ") ) << msg << endl;
90 _newline = true;
91}
92
93void OutNormal::error( const std::string & problem_desc, const std::string & hint )
94{
96
98 if ( !hint.empty() && verbosity() > Out::QUIET )
99 cerr << endl << hint;
100 cerr << endl;
101 _newline = true;
102}
103
104// ----------------------------------------------------------------------------
105
106void OutNormal::error( const zypp::Exception & e, const std::string & problem_desc, const std::string & hint )
107{
109
110 // problem and cause
111 cerr << ( ColorContext::MSG_ERROR << problem_desc << endl << zyppExceptionReport(e) ) << endl;
112
113 // hint
114 if ( !hint.empty() && verbosity() > Out::QUIET )
115 cerr << hint << endl;
116
117 _newline = true;
118}
119
120// ----------------------------------------------------------------------------
121inline std::ostream & PROGRESS_FLUSH( std::ostream & str ) {
122 static const bool dbg = getenv("ZYPPER_PBD"); // every progress bar redraw on a single line
123 return (dbg ? str << std::endl : str << std::flush );
124}
125
126void OutNormal::displayProgress ( const std::string & s, int percent )
127{
128 static AliveCursor cursor;
129
130 if ( _isatty )
131 {
133 outstr.lhs << s << ' ';
134
135 // dont display percents if invalid
136 if ( percent >= 0 && percent <= 100 )
137 {
138 outstr.percentHint = percent;
139 }
140 ++cursor;
141 outstr.rhs << '[' << cursor.current() << ']';
142
143 if ( _oneup )
145 cout << ansi::tty::clearLN;
146
147 std::string outline( outstr.get( termwidth() ) );
148 cout << outline << PROGRESS_FLUSH;
149 // no _oneup if CRUSHed // _oneup = ( outline.length() > termwidth() );
150 }
151 else
152 cout << '.' << std::flush;
153}
154
155// ----------------------------------------------------------------------------
156
157void OutNormal::displayTick( const std::string & s )
158{
159 static AliveCursor cursor;
160
161 if ( _isatty )
162 {
164 ++cursor;
165 outstr.lhs << s << ' ';
166 outstr.rhs << '[' << cursor.current() << ']';
167
168 if( _oneup )
170 cout << ansi::tty::clearLN;
171
172 std::string outline( outstr.get( termwidth() ) );
173 cout << outline << PROGRESS_FLUSH;
174 // no _oneup if CRUSHed // _oneup = ( outline.length() > termwidth() );
175 }
176 else
177 cout << '.' << std::flush;
178}
179
180// ----------------------------------------------------------------------------
181void OutNormal::progressStart( const std::string & id, const std::string & label, bool is_tick )
182{
183 if ( progressFilter() )
184 return;
185
186 if ( !_isatty )
187 cout << label << " [";
188
189 if ( is_tick )
190 displayTick( label );
191 else
192 displayProgress( label, 0 );
193
194 _newline = false;
195}
196
197void OutNormal::progress( const std::string & id, const std::string & label, int value )
198{
199 if (progressFilter())
200 return;
201
202 if (value)
203 displayProgress(label, value);
204 else
205 displayTick(label);
206
207 _newline = false;
208}
209
210void OutNormal::progressEnd( const std::string & id, const std::string & label, const std::string & donetag, bool error )
211{
212 if ( progressFilter() )
213 return;
214
215 if ( !error && _use_colors )
217
219 if ( _isatty )
220 {
221 if ( _oneup )
222 {
224 _oneup = false;
225 }
226 cout << ansi::tty::clearLN;
227
228 outstr.lhs << label << ' ';
229 outstr.rhs << '[';
230 }
231 // else: just write the donetag
232
233 outstr.rhs << donetag << ']';
234
235 std::string outline( outstr.get( termwidth() ) );
236 cout << outline << endl << std::flush;
237 _newline = true;
238
239 if ( !error && _use_colors )
240 cout << ColorContext::DEFAULT;
241}
242
243// progress with download rate
245{
246 if ( verbosity() < NORMAL )
247 return;
248
249 if ( _isatty )
250 cout << ansi::tty::clearLN;
251
253 outstr.lhs << _("Retrieving:") << ' ';
254 if ( verbosity() == DEBUG )
255 outstr.lhs << uri;
256 else
257 outstr.lhs << zypp::Pathname(uri.getPathName()).basename();
258 outstr.lhs << ' ';
259 if (_isatty)
260 outstr.rhs << '[' << _("starting") << ']';
261 else
262 outstr.rhs << '[' ;
263
264 std::string outline( outstr.get( termwidth() ) );
265 cout << outline << PROGRESS_FLUSH;
266 // no _oneup if CRUSHed // _oneup = (outline.length() > termwidth());
267
268 _newline = false;
269}
270
271void OutNormal::dwnldProgress( const zypp::Url & uri, int value, long rate )
272{
273 if ( verbosity() < NORMAL )
274 return;
275
276 if ( !_isatty )
277 {
278 cout << '.' << std::flush;
279 return;
280 }
281
282 if( _oneup )
284 cout << ansi::tty::clearLN;
285
287 outstr.lhs << _("Retrieving:") << " ";
288 if ( verbosity() == DEBUG )
289 outstr.lhs << uri;
290 else
291 outstr.lhs << zypp::Pathname(uri.getPathName()).basename();
292 outstr.lhs << ' ';
293
294 // dont display percents if invalid
295 if ( value >= 0 && value <= 100 )
296 outstr.percentHint = value;
297
298 static AliveCursor cursor;
299 ++cursor;
300 outstr.rhs << '[' << cursor.current();
301 if ( rate > 0 )
302 outstr.rhs << " (" << zypp::ByteCount(rate) << "/s)";
303 outstr.rhs << ']';
304
305 std::string outline( outstr.get( termwidth() ) );
306 cout << outline << PROGRESS_FLUSH;
307 // no _oneup if CRUSHed // _oneup = (outline.length() > termwidth());
308 _newline = false;
309}
310
312{
313 if ( verbosity() < NORMAL )
314 return;
315
316 if ( bool(!error) && _use_colors )
318
320 if ( _isatty )
321 {
322 if( _oneup )
324 cout << ansi::tty::clearLN;
325 outstr.lhs << _("Retrieving:") << " ";
326 if ( verbosity() == DEBUG )
327 outstr.lhs << uri;
328 else
329 outstr.lhs << zypp::Pathname(uri.getPathName()).basename();
330 outstr.lhs << ' ';
331 outstr.rhs << '[';
332 if ( zypp::indeterminate( error ) )
333 // Translator: download progress bar result: "........[not found]"
334 outstr.rhs << CHANGEString(_("not found") );
335 else if ( error )
336 // Translator: download progress bar result: "............[error]"
337 outstr.rhs << NEGATIVEString(_("error") );
338 else
339 // Translator: download progress bar result: ".............[done]"
340 outstr.rhs << _("done");
341 }
342 else
343 outstr.rhs << ( zypp::indeterminate( error ) ? _("not found") : ( error ? _("error") : _("done") ) );
344
345 if ( rate > 0 )
346 outstr.rhs << " (" << zypp::ByteCount(rate) << "/s)";
347 outstr.rhs << ']';
348
349 std::string outline( outstr.get( termwidth() ) );
350 cout << outline << endl << std::flush;
351 _newline = true;
352
353 if ( bool(!error) && _use_colors )
354 cout << ColorContext::DEFAULT;
355}
356
357void OutNormal::prompt( PromptId id, const std::string & prompt, const PromptOptions & poptions, const std::string & startdesc )
358{
360
361 if ( startdesc.empty() )
362 {
363 if ( _isatty )
364 cout << ansi::tty::clearLN;
365 }
366 else
367 cout << startdesc << endl;
368
369 std::ostringstream pstr;
370 ColorStream cout( pstr, ColorContext::PROMPT ); // scoped color on std::cout
371
372 cout << prompt;
373 if ( ! poptions.empty() )
374 cout << text::optBlankAfter(prompt) << ColorString( poptions.optionString() );
375 cout << ": ";
376
377 if ( do_colors() )
378 {
379 // bsc#948566: Terminal is dumb and simply counts the amount of printable
380 // characters. If the number of printable characters within ansi SGR sequences
381 // is not a multiple of 8, tab stops are not computed correctly. We use
382 // superfluous resets ("\033[0m"; 3 printable chars) to fill up.
383 // Better ideas are welcome.
384 size_t invis = 0;
385 bool insgr = false;
386 for ( char ch : pstr.str() )
387 {
388 if ( insgr )
389 {
390 ++invis;
391 if ( ch == 'm' )
392 insgr = false;
393 }
394 else if ( ch == '\033' )
395 insgr = true;
396 }
397 invis %= 8;
398
399 if ( invis )
400 {
401 // "\033[0m" has 3 printable chars:
402 // ( resets[to fill] * 3 ) % 8 == to fill
403 // 0 1 2 3 4 5 6 7
404 static const size_t resets[] = { 0,3,6,1,4,7,2,5 };
405 for ( size_t i = resets[8-invis]; i; --i )
406 cout << ansi::Color::SGRReset();
407 }
408 }
409
410 std::cout << pstr.str() << std::flush;
411 // prompt ends with newline (user hits <enter>) unless exited abnormaly
412 _newline = true;
413}
414
416{
417 cout << endl;
418
419 if ( poptions.helpEmpty() )
420 cout << _("No help available for this prompt.") << endl;
421
422 // Nevertheless list all option names and their '#NUM' shortcut
423 unsigned pos = 0; // Userland counter #NUM (starts with #1)
424
425 zypp::str::Format fopt { "#%-2d: %-10s" };
426 for ( unsigned idx = 0; idx < poptions.options().size(); ++idx )
427 {
428 if ( poptions.isDisabled(idx) )
429 continue;
430
431 cout << ( fopt % ++pos % poptions.options()[idx] );
432 if ( ! poptions.helpEmpty() )
433 {
434 const std::string & help { poptions.optionHelp(idx) };
435 cout << " - ";
436 if ( help.empty() )
437 cout << ( ColorContext::LOWLIGHT << "(" << _("no help available for this option") << ")" );
438 else
439 cout << help;
440 }
441 cout << endl;
442 }
443
444 ColorStream cout( std::cout, ColorContext::PROMPT ); // scoped color on std::cout
445 cout << endl << ColorString( poptions.optionString() ) << ": " << std::flush;
446 // prompt ends with newline (user hits <enter>) unless exited abnormaly
447 _newline = true;
448}
449
450unsigned OutNormal::termwidth() const
451{
452 if ( _isatty )
453 {
454 struct winsize wns;
455 if ( !ioctl( 1, TIOCGWINSZ, &wns ) )
456 return wns.ws_col;
457 }
458 return Out::termwidth(); // unlimited
459}
460
461}
void fixupProgressNL()
Definition OutNormal.cc:55
void displayTick(const std::string &s)
Definition OutNormal.cc:157
void dwnldProgressStart(const zypp::Url &uri) override
Reoprt start of a download.
Definition OutNormal.cc:244
void error(const std::string &problem_desc, const std::string &hint) override
Show an error message and an optional hint.
Definition OutNormal.cc:93
OutNormal(Verbosity verbosity=NORMAL)
Definition OutNormal.cc:32
void progressEnd(const std::string &id, const std::string &label, const std::string &donetag, bool error) override
End of an operation with reported progress.
Definition OutNormal.cc:210
void prompt(PromptId id, const std::string &prompt, const PromptOptions &poptions, const std::string &startdesc) override
Prompt the user for a decision.
Definition OutNormal.cc:357
void displayProgress(const std::string &s, int percent)
Definition OutNormal.cc:126
void infoLine(const TermLine &msg, Verbosity verbosity, Type mask) override
info taking a TermLine
Definition OutNormal.cc:79
unsigned termwidth() const override
Width for formatted output [0==unlimited].
Definition OutNormal.cc:450
void dwnldProgress(const zypp::Url &uri, int value, long rate) override
Reports download progress.
Definition OutNormal.cc:271
bool infoWarningFilter(Verbosity verbosity, Type mask)
Definition OutNormal.cc:46
void promptHelp(const PromptOptions &poptions) override
Print help for prompt, if available.
Definition OutNormal.cc:415
void progressStart(const std::string &id, const std::string &label, bool is_tick) override
Start of an operation with reported progress.
Definition OutNormal.cc:181
void progress(const std::string &id, const std::string &label, int value) override
Progress report for an on-going operation.
Definition OutNormal.cc:197
void warning(const std::string &msg, Verbosity verbosity, Type mask) override
Show a warning.
Definition OutNormal.cc:82
~OutNormal() override
Definition OutNormal.cc:40
void dwnldProgressEnd(const zypp::Url &uri, long rate, zypp::TriBool error) override
Reports end of a download.
Definition OutNormal.cc:311
bool mine(Type type) override
Determine whether the output is intended for the particular type.
Definition OutNormal.cc:43
Base class for producing common (for now) zypper output.
Definition Out.h:430
Verbosity verbosity() const
Get current verbosity.
Definition Out.h:870
Info info()
Definition Out.h:684
virtual unsigned termwidth() const
Width for formatted output [0==unlimited].
Definition Out.h:925
Verbosity
Verbosity levels.
Definition Out.h:434
@ QUIET
Only important messages (no progress or status, only the result).
Definition Out.h:435
@ NORMAL
Default output verbosity level.
Definition Out.h:436
@ DEBUG
Definition Out.h:439
virtual bool progressFilter()
Determine whether to show progress.
Definition Out.cc:112
TypeBit type() const
Return the type of the instance.
Definition Out.h:901
virtual std::string zyppExceptionReport(const zypp::Exception &e)
Return a Exception as a string suitable for output.
Definition Out.cc:117
unsigned PromptId
Definition Out.h:453
@ TYPE_NORMAL
plain text output
Definition Out.h:445
Example: PromptOptions popts; popts.setOptions(_("y/n/p"), 0 / * default reply * /); popts....
Colored stream output if do_colors.
Definition ansi.h:674
Colored string if do_colors.
Definition ansi.h:497
static const std::string & SGRReset()
ANSI SGR sesquence to reset all attributes.
Definition ansi.h:291
Reference counted access to a Tp object calling a custom Dispose function when the last AutoDispose h...
Definition AutoDispose.h:95
Store and operate with byte count.
Definition ByteCount.h:32
Base class for Exception.
Definition Exception.h:147
Url manipulation class.
Definition Url.h:92
std::string basename() const
Return the last component of this path.
Definition Pathname.h:130
String related utilities and Regular expression matching.
const EscapeSequence cursorUP
Cursor up 1 line.
const EscapeSequence clearLN
Clear entire line.
const char * optBlankAfter(const std::string &str_r)
Definition Out.h:74
CCString< ColorContext::NEGATIVE > NEGATIVEString
Definition colors.h:85
CCString< ColorContext::CHANGE > CHANGEString
Definition colors.h:84
std::ostream & PROGRESS_FLUSH(std::ostream &str)
Definition OutNormal.cc:121
bool do_ttyout()
True unless output is a dumb tty or file.
Definition colors.cc:27
bool do_colors()
If output is done in colors (depends on config)
Definition colors.cc:32
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition String.h:30
std::string get() const
Return plain line made of lhs + rhs.
Definition Out.h:372
Convenient building of std::string with boost::format.
Definition String.h:253
#define _(MSG)
Definition Gettext.h:39