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