+struct Table
+{
+ void row( PoolQuery::const_iterator it_r )
+ {
+ //smax( _maxSID, );
+ smax( _maxNAME, it_r->ident().size() + it_r->edition().size() + it_r->arch().size() );
+ smax( _maxREPO, it_r->repository().name().size(), it_r->repository().name() );
+ //smax( _maxTIME, );
+ //smax( _maxVEND, it_r->vendor().size() );
+
+ std::vector<std::string> & details { _map[*it_r] };
+ for_( match, it_r.matchesBegin(), it_r.matchesEnd() ) {
+ details.push_back( match->inSolvAttr().asString().substr( 9, 3 )+": " +match->asString() );
+ }
+ }
+
+ std::ostream & dumpOn( std::ostream & str ) const
+ {
+ #define S " "
+
+ #define fmtSID "%*d"
+ #define argSID _maxSID, slv.id()
+
+ #define fmtNAME COL_B "%s" COL_OFF "-" COL_G "%s" COL_OFF ".%-*s"
+ #define argNAME slv.ident().c_str(), slv.edition().c_str(), _maxNAME-slv.ident().size()-slv.edition().size(), slv.arch().c_str()
+
+ #define fmtREPO "(%2d)%-*s"
+ #define argREPO slv.repository().info().priority(), _maxREPO, slv.repository().name().c_str()
+
+ #define fmtTIME "%10ld"
+ #define argTIME time_t( slv.isSystem() ? slv.installtime() : slv.buildtime() )
+
+ #define fmtVEND "%s"
+ #define argVEND slv.vendor().c_str()
+
+ std::string dind( _maxSID + _maxNAME+2/*-.*/ + 2*strlen(S), ' ' );
+
+ for ( const auto & el : _map ) {
+ sat::Solvable slv { el.first };
+ const char * tagCol = slv.isSystem() ? COL_M : ui::Selectable::get(slv)->identicalInstalled(PoolItem(slv)) ? COL_C : "";
+
+ str << str::form( "%s" fmtSID S fmtNAME S "%s" fmtREPO S fmtTIME S fmtVEND COL_OFF "\n",
+ tagCol, argSID, argNAME, tagCol, argREPO, argTIME, argVEND );
+
+ for ( const auto & d : el.second )
+ str << dind << d << endl;
+ }
+ return str;
+ }
+
+private:
+ static void smax( unsigned & var_r, unsigned val_r, std::string_view n = {} )
+ { if ( val_r > var_r ) var_r = val_r; }
+
+private:
+ unsigned _maxSID = 7; // size + indent
+ unsigned _maxNAME = 0;
+ unsigned _maxREPO = 0;
+ //unsigned _maxTIME = 10;
+ //unsigned _maxVEND = 0;
+ std::map<sat::Solvable, std::vector<std::string>, PQSort> _map;
+};
+
+inline std::ostream & operator<<( std::ostream & str, const Table & table_r )
+{ return table_r.dumpOn( str ); }
+