19#include <zypp-tui/Application> 
   27#undef  ZYPP_BASE_LOGGER_LOGGROUP 
   28#define ZYPP_BASE_LOGGER_LOGGROUP "zypper" 
   32const char * 
asYesNo( 
bool val_r ) { 
return val_r ? 
_(
"Yes") : 
_(
"No"); }
 
   36static const char * 
lines[][3] = {
 
   39  { 
"\xE2\x94\x82", 
"\xE2\x94\x80", 
"\xE2\x94\xBC" },   
 
   40  { 
"\xE2\x94\x83", 
"\xE2\x94\x81", 
"\xE2\x95\x8B" },   
 
   41  { 
"\xE2\x95\x91", 
"\xE2\x95\x90", 
"\xE2\x95\xAC" },   
 
   42  { 
"\xE2\x94\x86", 
"\xE2\x94\x84", 
"\xE2\x94\xBC" },   
 
   43  { 
"\xE2\x94\x87", 
"\xE2\x94\x85", 
"\xE2\x94\x8B" },   
 
   44  { 
"\xE2\x94\x82", 
"\xE2\x94\x81", 
"\xE2\x94\xBF" },   
 
   45  { 
"\xE2\x94\x82", 
"\xE2\x95\x90", 
"\xE2\x95\xAA" },   
 
   46  { 
"\xE2\x94\x83", 
"\xE2\x94\x80", 
"\xE2\x95\x82" },   
 
   47  { 
"\xE2\x95\x91", 
"\xE2\x94\x80", 
"\xE2\x95\xAB" },   
 
 
   54  inline int wccmp( 
const wchar_t & l, 
const wchar_t & r )
 
   55  { 
return l == r ? 0 : l < r ? -1 : 1; }
 
   58  inline int wccasecmp( 
const wchar_t & l, 
const wchar_t & r )
 
   59  { return ::wcsncasecmp( &l, &r, 1 ); }
 
   62  inline bool isZero( 
const wchar_t & ch )
 
   63  { 
return ch == L
'0'; }
 
   66  inline bool isDigit( 
const wchar_t & ch )
 
   67  { return ::iswdigit( ch ); }
 
   70  inline bool bothDigits( 
const wchar_t & l, 
const wchar_t & r )
 
   71  { 
return isDigit( l ) && isDigit( r ); }
 
   74  inline bool bothNotDigits( 
const wchar_t & l, 
const wchar_t & r )
 
   75  { 
return not ( isDigit( l ) || isDigit( r ) ); }
 
   79  { 
return lit.atEnd() && rit.atEnd(); }
 
   84    if ( isZero( *it ) ) {
 
   85      do { ++it; } 
while ( isZero( *it ) );
 
   97    for ( ;; ++lit, ++rit ) {
 
   98      if ( isDigit( *lit ) ) {
 
   99        if ( isDigit( *rit ) ) {
 
  100          if ( not diff && *lit != *rit )
 
  101            diff = *lit < *rit ? -1 : 1;
 
  107        if ( isDigit( *rit ) )
 
  118  auto wcharcmp = &wccmp; 
 
  128      if ( skipTrailingZeros( rit ) && not nbias ) 
return -1;
 
  129      return rit.atEnd() ? (nbias ? nbias : cbias) : -1;
 
  132      if ( skipTrailingZeros( lit ) && not nbias ) 
return 1;
 
  133      return lit.atEnd() ? (nbias ? nbias : cbias) : 1;
 
  137    if ( bothDigits( *lit, *rit ) ) {
 
  138      if ( isZero( *lit ) || isZero( *rit ) ) {
 
  140        while ( isZero( *lit ) ) { ++lit; --lead; }
 
  141        while ( isZero( *rit ) ) { ++rit; ++lead; }
 
  142        if ( not nbias && lead )
 
  143          nbias = bothAtEnd( lit, rit ) ? -lead : lead;  
 
  145      if ( (cmp = wcnumcmpValue( lit, rit )) )
 
  150      if ( (cmp = wcharcmp( *lit, *rit )) ) {
 
  151        if ( not cbias ) cbias = cmp; 
 
  153          if ( (cmp = wccasecmp( *lit, *rit )) )
 
  155          wcharcmp = &wccasecmp;
 
 
  183  bool seen_first = 
false;
 
  184  for ( container::const_iterator i = 
_columns.begin(); i != 
_columns.end(); ++i )
 
  192  return stream << std::endl;
 
 
  211  bool seen_first = 
false;
 
  213  stream.setf( std::ios::left, std::ios::adjustfield );
 
  214  stream << std::string( parent.
_margin, 
' ' );
 
  219  std::string::size_type editionSep( std::string::npos );
 
  222  const unsigned lastCol = 
_columns.size() - 1;
 
  223  for ( 
unsigned c = 0; i != e ; ++i, ++c )
 
  225    const std::string & s( *i );
 
  238        stream << std::endl << std::string( parent.
_margin + 2, 
' ' );
 
  243        stream << 
' ' << vline << 
' ';
 
  255      stream << ( 
_ctxt << cutstr ) << std::string(cutby - 
mbs_width( cutstr ), 
' ') << 
"->";
 
  263        if ( editionColumns.size() == 2 )
 
  266          if ( editionSep == std::string::npos )
 
  269                                            _columns[*(++editionColumns.begin())] );
 
  272          if ( editionSep == 0 )
 
  276          else if ( editionSep == s.size() )
 
  278            stream << ( 
_ctxt << s );
 
  288          editionSep = s.find( 
'-' );
 
  289          if ( editionSep != std::string::npos )
 
  295            stream << ( 
_ctxt << s );
 
  301        stream << ( 
_ctxt << s );
 
  303      stream.width( c == lastCol ? 0 : parent.
_max_width[c] - ssize );
 
 
  334  _rows.push_back( std::move(tr) );
 
 
  364  const auto &columns = tr.
columns();
 
  372  for ( 
const auto & col : columns )
 
 
  390  bool seen_first = 
false;
 
  393  stream << std::string(
_margin, 
' ' );
 
  394  for ( 
unsigned c = 0; c <= 
_max_col; ++c )
 
  397      stream << hline << cross << hline;
 
  400    for ( 
unsigned i = 0; i < 
_max_width[c]; ++i )
 
 
  411  for ( 
const auto & row : 
_rows )
 
  434    _header.dumpTo( stream, *
this );
 
  438  for ( 
const auto & row : 
_rows )
 
  439    row.dumpTo( stream, *
this );
 
 
  446  if ( force_break_after >= 0 )
 
 
  462    ERR << 
"margin of " << 
margin << 
" is greater than half of the screen" << std::endl;
 
 
static Application & instance()
TableRow & add(std::string s)
container _translatedColumns
std::ostream & dumpDetails(std::ostream &stream, const Table &parent) const
TableRow & addDetail(std::string s)
std::ostream & dumpTo(std::ostream &stream, const Table &parent) const
output with parent table attributes
std::ostream & dumbDumpTo(std::ostream &stream) const
tab separated output
TableRow()
Binary predicate for sorting.
const container & columns() const
void dumpRule(std::ostream &stream) const
Table & setHeader(TableHeader tr)
void updateColWidths(const TableRow &tr) const
std::ostream & dumpTo(std::ostream &stream) const
int _width
table width (columns)
void lineStyle(TableLineStyle st)
void wrap(int force_break_after=-1)
const TableHeader & header() const
std::vector< bool > _abbrev_col
whether to abbreviate the respective column if needed
std::vector< unsigned > _max_width
maximum width of respective columns
TableLineStyle _style
table line drawing style
void margin(unsigned margin)
int _screen_width
amount of space we have to print this table
unsigned _max_col
maximum column index seen in this table
int _force_break_after
if _do_wrap is set, first break the table at this column; If negative, wrap as needed.
unsigned _margin
left/right margin in number of spaces
bool _do_wrap
Whether to wrap the table if it exceeds _screen_width.
void allowAbbrev(unsigned column)
static TableLineStyle defaultStyle
Assign a vaiable a certain value when going out of scope.
Miscellaneous console utilities.
@ Edition
Editions with v-r setparator highlighted.
size_t mbs_width(boost::string_ref text_r)
Returns the column width of a multi-byte character string text_r.
std::string mbs_substr_by_width(boost::string_ref text_r, std::string::size_type colpos_r, std::string::size_type collen_r)
Returns a substring of a multi-byte character string text_r starting at screen column cpos_r and bein...
const char * asYesNo(bool val_r)
TableLineStyle
table drawing style
unsigned get_screen_width()
Reads COLUMNS environment variable or gets the screen width from readline, in that order.
static const char * lines[][3]
std::string::size_type commonPrefix(const C_Str &lhs, const C_Str &rhs)
Return size of the common prefix of lhs and rhs.
static int defaultStrComp(bool ci_r, const std::string &lhs, const std::string &rhs)
Natural('sort -V' like) [case insensitive] compare ignoring ANSI SGR chars.
MbsIterator skipping ANSI SGR
Write MBString optionally wrapped and indented.
void gotoParBegin()
Open a new paragraph if not atParBegin.
void writePar(boost::string_ref text_r)
Write text_r; starting a new paragraph and ending it after the text was written.