libzypp  17.32.5
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
18 #include <zypp-core/base/Logger.h>
19 #include <zypp-core/base/String.h> // for toUpper()
20 
21 #include <zypp-tui/utils/colors.h>
23 
24 #include "OutNormal.h"
25 
26 using std::cout;
27 using std::cerr;
28 using std::endl;
29 
30 namespace ztui {
31 
33 : Out( TYPE_NORMAL, verbosity_r )
34 , _use_colors( false )
35 , _isatty( do_ttyout() )
36 , _newline( true )
37 , _oneup( false )
38 {}
39 
41 {}
42 
43 bool OutNormal::mine( Type type )
44 { return( type & Out::TYPE_NORMAL ); }
45 
46 bool OutNormal::infoWarningFilter( Verbosity verbosity_r, Type mask )
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 
62 void OutNormal::info( const std::string & msg_r, Verbosity verbosity_r, Type mask )
63 {
64  if ( infoWarningFilter( verbosity_r, mask ) )
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 
79 void OutNormal::infoLine( const TermLine & msg, Verbosity verbosity_r, Type mask )
80 { info( msg.get( termwidth() ), verbosity_r, mask ); }
81 
82 void OutNormal::warning( const std::string & msg, Verbosity verbosity_r, Type mask )
83 {
84  if ( infoWarningFilter( verbosity_r, mask ) )
85  return;
86 
88 
89  cout << ( ColorContext::MSG_WARNING << _("Warning: ") ) << msg << endl;
90  _newline = true;
91 }
92 
93 void OutNormal::error( const std::string & problem_desc, const std::string & hint )
94 {
96 
97  cerr << ( ColorContext::MSG_ERROR << problem_desc );
98  if ( !hint.empty() && verbosity() > Out::QUIET )
99  cerr << endl << hint;
100  cerr << endl;
101  _newline = true;
102 }
103 
104 // ----------------------------------------------------------------------------
105 
106 void OutNormal::error( const zypp::Exception & e, const std::string & problem_desc, const std::string & hint )
107 {
108  fixupProgressNL();
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 // ----------------------------------------------------------------------------
121 inline 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 
126 void 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 
157 void 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 // ----------------------------------------------------------------------------
181 void 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 
197 void 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 
210 void 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 )
216  cout << ColorContext::MSG_STATUS;
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 
271 void 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 
311 void OutNormal::dwnldProgressEnd( const zypp::Url & uri, long rate, zypp::TriBool error )
312 {
313  if ( verbosity() < NORMAL )
314  return;
315 
316  if ( bool(!error) && _use_colors )
317  cout << ColorContext::MSG_STATUS;
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 
357 void OutNormal::prompt( PromptId id, const std::string & prompt, const PromptOptions & poptions, const std::string & startdesc )
358 {
359  fixupProgressNL();
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 
415 void OutNormal::promptHelp( const PromptOptions & poptions )
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 
450 unsigned 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 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 fixupProgressNL()
Definition: OutNormal.cc:55
virtual std::string zyppExceptionReport(const zypp::Exception &e)
Return a Exception as a string suitable for output.
Definition: Out.cc:117
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 dwnldProgress(const zypp::Url &uri, int value, long rate) override
Reports download progress.
Definition: OutNormal.cc:271
boost::logic::tribool TriBool
3-state boolean logic (true, false and indeterminate).
Definition: String.h:30
Colored string if do_colors.
Definition: ansi.h:496
#define _(MSG)
Definition: Gettext.h:37
void progress(const std::string &id, const std::string &label, int value) override
Progress report for an on-going operation.
Definition: OutNormal.cc:197
Store and operate with byte count.
Definition: ByteCount.h:30
Base class for producing common (for now) zypper output.
Definition: Out.h:429
bool do_colors()
If output is done in colors (depends on config)
Definition: colors.cc:32
CCString< ColorContext::NEGATIVE > NEGATIVEString
Definition: colors.h:85
~OutNormal() override
Definition: OutNormal.cc:40
bool infoWarningFilter(Verbosity verbosity, Type mask)
Definition: OutNormal.cc:46
void warning(const std::string &msg, Verbosity verbosity, Type mask) override
Show a warning.
Definition: OutNormal.cc:82
char current() const
Definition: AliveCursor.h:29
bool _use_colors
Definition: OutNormal.h:65
String related utilities and Regular expression matching.
void error(const std::string &problem_desc, const std::string &hint) override
Show an error message and an optional hint.
Definition: OutNormal.cc:93
Example: PromptOptions popts; popts.setOptions(_("y/n/p"), 0 / * default reply * /); popts...
Definition: promptoptions.h:38
Verbosity verbosity() const
Get current verbosity.
Definition: Out.h:870
Convenient building of std::string with boost::format.
Definition: String.h:252
void displayProgress(const std::string &s, int percent)
Definition: OutNormal.cc:126
zypp::str::Str lhs
Definition: Out.h:367
const StrVector & options() const
Definition: promptoptions.h:64
CCString< ColorContext::CHANGE > CHANGEString
Definition: colors.h:84
unsigned PromptId
Definition: Out.h:453
bool mine(Type type) override
Determine whether the output is intended for the particular type.
Definition: OutNormal.cc:43
Default output verbosity level.
Definition: Out.h:436
bool do_ttyout()
True unless output is a dumb tty or file.
Definition: colors.cc:27
bool isDisabled(unsigned opt) const
Definition: promptoptions.h:82
virtual unsigned termwidth() const
Width for formatted output [0==unlimited].
Definition: Out.h:925
void dwnldProgressStart(const zypp::Url &uri) override
Reoprt start of a download.
Definition: OutNormal.cc:244
const EscapeSequence cursorUP
Cursor up 1 line.
Colored stream output if do_colors.
Definition: ansi.h:673
zypp::DefaultIntegral< int,-1 > percentHint
Definition: Out.h:365
std::string get() const
Return plain line made of lhs + rhs.
Definition: Out.h:372
plain text output
Definition: Out.h:445
bool helpEmpty() const
Definition: promptoptions.h:78
std::ostream & PROGRESS_FLUSH(std::ostream &str)
Definition: OutNormal.cc:121
zypp::str::Str rhs
Definition: Out.h:368
unsigned termwidth() const override
Width for formatted output [0==unlimited].
Definition: OutNormal.cc:450
virtual bool progressFilter()
Determine whether to show progress.
Definition: Out.cc:112
Only important messages (no progress or status, only the result).
Definition: Out.h:435
Verbosity
Verbosity levels.
Definition: Out.h:433
void dwnldProgressEnd(const zypp::Url &uri, long rate, zypp::TriBool error) override
Reports end of a download.
Definition: OutNormal.cc:311
ColorString optionString() const
Option string (may have embedded color codes)
Base class for Exception.
Definition: Exception.h:146
const std::string & optionHelp(unsigned opt) const
Definition: promptoptions.h:74
bool empty() const
Definition: promptoptions.h:71
std::string getPathName(EEncoding eflag=zypp::url::E_DECODED) const
Returns the path name from the URL.
Definition: Url.cc:608
const char * optBlankAfter(const std::string &str_r)
Definition: Out.h:74
void displayTick(const std::string &s)
Definition: OutNormal.cc:157
void infoLine(const TermLine &msg, Verbosity verbosity, Type mask) override
info taking a TermLine
Definition: OutNormal.cc:79
static const std::string & SGRReset()
ANSI SGR sesquence to reset all attributes.
Definition: ansi.h:291
TypeBit type() const
Return the type of the instance.
Definition: Out.h:901
OutNormal(Verbosity verbosity=NORMAL)
Definition: OutNormal.cc:32
const EscapeSequence clearLN
Clear entire line.
Info info()
Definition: Out.h:684
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 promptHelp(const PromptOptions &poptions) override
Print help for prompt, if available.
Definition: OutNormal.cc:415
Url manipulation class.
Definition: Url.h:91