///////////////////////////////////////////////////////////////////
struct FileConflictsListFormater
{
- typedef out::DefaultGapedListLayout ListLayout;
+ typedef out::DefaultGapedListLayout NormalLayout;
- struct XmlFormater
- {
- std::string operator()( const sat::FileConflicts::Conflict & val_r ) const
- { str::Str str; dumpAsXmlOn( str.stream(), val_r ); return str; }
- };
+ std::string xmlListElement( const sat::FileConflicts::Conflict & val_r ) const
+ { str::Str str; dumpAsXmlOn( str.stream(), val_r ); return str; }
- std::string operator()( const sat::FileConflicts::Conflict & val_r ) const
+ std::string listElement( const sat::FileConflicts::Conflict & val_r ) const
{ return asUserString( val_r ); }
};
///////////////////////////////////////////////////////////////////
- /** \relates SolvableListFormater Conversion to sat::Solvable */
- template <class Tp_>
- sat::Solvable asSolvable( const Tp_ & val_r )
- { return sat::asSolvable( val_r ); }
-
- sat::Solvable asSolvable( int val_r ) // e.g. satQueues use int as SolvabeId
- { return sat::Solvable( val_r ); }
-
///////////////////////////////////////////////////////////////////
/// \class SolvableListFormater
/// \brief Printing Solvable based types in List (legacy format used in summary)
///////////////////////////////////////////////////////////////////
struct SolvableListFormater
{
- typedef out::CompressedListLayout ListLayout;
+ typedef out::CompressedListLayout NormalLayout;
- struct XmlFormater
- {
- template <class Tp_>
- std::string operator()( const Tp_ & val_r ) const
- { return operator()( makeResObject( asSolvable( val_r ) ) ); }
+ template <class Tp_>
+ std::string xmlListElement( const Tp_ & val_r ) const
+ { return xmlListElement( makeResObject( asSolvable( val_r ) ) ); }
- std::string operator()( ResObject::Ptr val_r, ResObject::Ptr old_r = nullptr ) const
+ std::string xmlListElement( const ResObject::Ptr & val_r ) const
+ {
+ str::Str ret;
+ ret << "<solvable";
+ ret << " type=\"" << val_r->kind() << "\"";
+ ret << " name=\"" << val_r->name() << "\"";
+ ret << " edition=\"" << val_r->edition() << "\"";
+ ret << " arch=\"" << val_r->arch() << "\"";
{
- str::Str ret;
- ret << "<solvable";
- ret << " type=\"" << val_r->kind() << "\"";
- ret << " name=\"" << val_r->name() << "\"";
- ret << " edition=\"" << val_r->edition() << "\"";
- ret << " arch=\"" << val_r->arch() << "\"";
- {
- const std::string & text( val_r->summary() );
- if ( ! text.empty() )
- ret << " summary=\"" << xml::escape( text ) << "\"";
- }
- {
- const std::string & text( val_r->description() );
- if ( ! text.empty() )
- ret << ">\n" << "<description>" << xml::escape( text ) << "</description>" << "</solvable>";
- else
- ret << "/>";
- }
- return ret;
+ const std::string & text( val_r->summary() );
+ if ( ! text.empty() )
+ ret << " summary=\"" << xml::escape( text ) << "\"";
}
- };
+ {
+ const std::string & text( val_r->description() );
+ if ( ! text.empty() )
+ ret << ">\n" << "<description>" << xml::escape( text ) << "</description>" << "</solvable>";
+ else
+ ret << "/>";
+ }
+ return ret;
+ }
- template <class Tp_>
- std::string operator()( const Tp_ & val_r ) const
- { return operator()( makeResObject( asSolvable( val_r ) ) ); }
+ template <class Tp>
+ std::string listElement( const Tp & val_r ) const
+ { return listElement( makeResObject( asSolvable( val_r ) ) ); }
- std::string operator()( ResObject::Ptr val_r, ResObject::Ptr old_r = nullptr ) const
+ std::string listElement( const ResObject::Ptr & val_r ) const
{ return val_r->ident().asString(); }
+
+ private:
+ template <class Tp_>
+ static sat::Solvable asSolvable( const Tp_ & val_r )
+ { return sat::asSolvable( val_r ); }
+
+ static sat::Solvable asSolvable( int val_r ) // e.g. satQueues use int as SolvabeId
+ { return sat::Solvable( val_r ); }
};
} // namespace out
using namespace zypp;
///////////////////////////////////////////////////////////////////
-namespace
+namespace out
{
- inline std::string get_string_for_table( const std::set<std::string> & attrvals )
+ struct LocksTableFormater : public TableFormater
{
- std::string ret;
- if ( attrvals.empty() )
- ret = _("(any)");
- else if ( attrvals.size() > 1 )
- ret = _("(multiple)");
- else
- ret = *attrvals.begin();
- return ret;
- }
-
- inline std::string getLockDetails( const PoolQuery & q )
- {
- if ( q.empty() )
- return "";
-
- PropertyTable p;
+ private:
+ /** LESS compare for MatchDetails */
+ struct MatchDetailCompare
{
- struct DoCompare
- {
- int operator()( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
- { return( doComapre( lhs, rhs ) < 0 ); }
+ bool operator()( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
+ { return( doComapre( lhs, rhs ) < 0 ); }
- int doComapre( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
- {
- // return sat::compareByNVRA( lhs, rhs );
- // do N(<) A(>) VR(>)
- int res = sat::compareByN( lhs, rhs ); // ascending l<r
- if ( res == 0 )
- res = rhs.arch().compare( lhs.arch() ); // descending r<l
+ int doComapre( const sat::Solvable & lhs, const sat::Solvable & rhs ) const
+ {
+ // do N(<) A(>) VR(>)
+ int res = sat::compareByN( lhs, rhs ); // ascending l<r
+ if ( res == 0 )
+ res = rhs.arch().compare( lhs.arch() ); // descending r<l
if ( res == 0 )
res = rhs.edition().compare( lhs.edition() ); // descending r<l
- if ( res == 0 )
- res = lhs.repository().asUserString().compare( rhs.repository().asUserString() ); // ascending l<r
- return res;
- }
- };
- std::set<sat::Solvable,DoCompare> i;
- std::set<sat::Solvable,DoCompare> a;
- for ( const auto & solv : q )
- { (solv.isSystem()?i:a).insert( solv ); }
-
- std::vector<std::string> names;
- names.reserve( std::max( i.size(), a.size() ) );
-
- if ( ! i.empty() )
- {
- //names.clear();
- for ( const auto & solv : i )
- { names.push_back( solv.asUserString() ); }
- // translators: property name; short; used like "Name: value"
- p.add( _("Keep installed"), names );
+ if ( res == 0 )
+ res = lhs.repository().asUserString().compare( rhs.repository().asUserString() ); // ascending l<r
+ return res;
}
- if ( ! a.empty() )
+ };
+ /** Ordered MatchDetails */
+ typedef std::set<sat::Solvable,MatchDetailCompare> MatchDetails;
+
+ /** MatchDetail representation */
+ struct MatchDetailFormater
+ {
+ std::string xmlListElement( const sat::Solvable & match_r ) const
{
- names.clear();
- for ( const auto & solv : a )
- { names.push_back( solv.asUserString() ); }
- // translators: property name; short; used like "Name: value"
- p.add( _("Do not install"), names );
+ str::Str str;
+ {
+ xmlout::Node lock( str.stream(), "match", {
+ { "kind", match_r.kind() },
+ { "name", match_r.name() },
+ { "edition", match_r.edition() },
+ { "arch", match_r.arch() },
+ { "installed", match_r.isSystem() },
+ { "repo", match_r.repository().alias() },
+ } );
+ }
+ return str;
}
- }
- return str::Str() << p;
- }
+ };
-} //namespace
-///////////////////////////////////////////////////////////////////
+ public:
+ std::string xmlListElement( const PoolQuery & q_r ) const
+ {
+ str::Str str;
+ // <lock>
+ {
+ ++_i;
+ xmlout::Node lock( str.stream(), "lock", { { "number", _i } } );
-void list_locks(Zypper & zypper)
-{
- shared_ptr<ListLocksOptions> listLocksOptions = zypper.commandOptionsOrDefaultAs<ListLocksOptions>();
+ // <name> (solvable_name)
+ for ( const std::string & val : q_r.attribute( sat::SolvAttr::name ) )
+ { *xmlout::Node( *lock, "name" ) << val; }
+ // <name> (query_string)
+ for ( const std::string & val : q_r.strings() )
+ { *xmlout::Node( *lock, "name" ) << val; }
- bool withSolvables = listLocksOptions->_withSolvables;
- bool withMatches = withSolvables||listLocksOptions->_withMatches;
+ // <type>
+ for ( const ResKind & kind : q_r.kinds() )
+ { *xmlout::Node( *lock, "type" ) << kind; }
- try
- {
- Locks & locks = Locks::instance();
- locks.read( Pathname::assertprefix( zypper.globalOpts().root_dir, ZConfig::instance().locksFile() ) );
+ // <repo>
+ for ( const std::string & repo : q_r.repos() )
+ { *xmlout::Node( *lock, "repo" ) << repo; }
- Table t;
+ if ( _withMatches )
+ {
+ // <matches>
+ xmlout::Node matches( *lock, "matches", xmlout::Node::optionalContent, { { "size", q_r.size() } } );
+ if ( _withSolvables && !q_r.empty() )
+ {
+ MatchDetails d;
+ getLockDetails( q_r, d );
+ xmlWriteContainer( *matches, d, MatchDetailFormater() );
+ }
+ }
+ }
+ return str;
+ }
- TableHeader th;
- th << "#" << _("Name");
- if ( withMatches )
- th << _("Matches");
- th << _("Type") << _("Repository");
- t << th;
+ TableHeader header() const
+ {
+ TableHeader th;
+ th << "#" << _("Name");
+ if ( _withMatches )
+ th << _("Matches");
+ th << _("Type") << _("Repository");
+ return th;
+ }
- unsigned i = 0;
- for ( const PoolQuery & q : locks )
+ TableRow row( const PoolQuery & q_r ) const
{
TableRow tr;
- ++i;
// #
- tr << str::numstring( i );
+ ++_i;
+ tr << str::numstring( _i );
- // name
- const PoolQuery::StrContainer & nameStings( q.attribute( sat::SolvAttr::name ) );
- const PoolQuery::StrContainer & globalStrings( q.strings() );
+ // Name
+ const PoolQuery::StrContainer & nameStings( q_r.attribute( sat::SolvAttr::name ) );
+ const PoolQuery::StrContainer & globalStrings( q_r.strings() );
if ( nameStings.size() + globalStrings.size() > 1 )
// translators: locks table value
tr << *nameStings.begin();
// opt Matches
- if ( withMatches )
- tr << q.size();
+ if ( _withMatches )
+ tr << q_r.size();
- // type
+ // Type
std::set<std::string> strings;
- for ( const ResKind & kind : q.kinds() )
+ for ( const ResKind & kind : q_r.kinds() )
strings.insert( kind.asString() );
tr << get_string_for_table( strings );
- // repo
+ // Repository
strings.clear();
- copy( q.repos().begin(), q.repos().end(), inserter(strings, strings.end()) );
+ copy( q_r.repos().begin(), q_r.repos().end(), inserter(strings, strings.end()) );
tr << get_string_for_table( strings );
- // opt Solvables
- if ( withSolvables )
+ // opt Solvables as detail
+ if ( _withSolvables && !q_r.empty() )
{
- tr.addDetail( getLockDetails( q ) );
+ MatchDetails i;
+ MatchDetails a;
+ getLockDetails( q_r, i, a );
+
+ PropertyTable p;
+ {
+ std::vector<std::string> names;
+ names.reserve( std::max( i.size(), a.size() ) );
+ if ( ! i.empty() )
+ {
+ //names.clear();
+ for ( const auto & solv : i )
+ { names.push_back( solv.asUserString() ); }
+ // translators: property name; short; used like "Name: value"
+ p.add( _("Keep installed"), names );
+ }
+ if ( ! a.empty() )
+ {
+ names.clear();
+ for ( const auto & solv : a )
+ { names.push_back( solv.asUserString() ); }
+ // translators: property name; short; used like "Name: value"
+ p.add( _("Do not install"), names );
+ }
+ }
+ tr.addDetail( (str::Str() << p).str() );
}
+ return tr;
+ }
+
+ LocksTableFormater( shared_ptr<ListLocksOptions> listLocksOptions_r )
+ : _withSolvables( listLocksOptions_r->_withSolvables )
+ , _withMatches( _withSolvables || listLocksOptions_r->_withMatches )
+ {}
- t << tr;
+ private:
+ static std::string get_string_for_table( const std::set<std::string> & attrvals_r )
+ {
+ std::string ret;
+ if ( attrvals_r.empty() )
+ ret = _("(any)");
+ else if ( attrvals_r.size() > 1 )
+ ret = _("(multiple)");
+ else
+ ret = *attrvals_r.begin();
+ return ret;
}
- if (t.empty())
- zypper.out().info(_("There are no package locks defined."));
- else
- cout << t;
+ static void getLockDetails( const PoolQuery & q_r, MatchDetails & i_r, MatchDetails & a_r )
+ { for ( const auto & solv : q_r ) { (solv.isSystem()?i_r:a_r).insert( solv ); } }
+
+ static void getLockDetails( const PoolQuery & q_r, MatchDetails & d_r )
+ { getLockDetails( q_r, d_r, d_r ); }
+
+ private:
+ bool _withSolvables :1; //< include match details (implies _withMatches)
+ bool _withMatches :1; //< include number of matches
+ mutable unsigned _i = 0; //< Lock Number
+ };
+} //namespace out
+///////////////////////////////////////////////////////////////////
+
+void list_locks( Zypper & zypper )
+{
+ Locks & locks( Locks::instance() );
+ try
+ {
+ locks.read( Pathname::assertprefix( zypper.globalOpts().root_dir, ZConfig::instance().locksFile() ) );
}
- catch(const Exception & e)
+ catch( const Exception & e )
{
- ZYPP_CAUGHT(e);
- zypper.out().error(e, _("Error reading the locks file:"));
- zypper.setExitCode(ZYPPER_EXIT_ERR_ZYPP);
+ throw( Out::Error( ZYPPER_EXIT_ERR_ZYPP, _("Error reading the locks file:"), e ) );
}
+
+ // show result
+ Out & out( zypper.out() );
+ out.gap();
+ out.table( "locks", locks.empty() ? _("There are no package locks defined.") : "",
+ locks, out::LocksTableFormater( zypper.commandOptionsOrDefaultAs<ListLocksOptions>() ) );
+ out.gap();
}
template <typename Target, typename Source>
#include "utils/richtext.h"
#include "output/prompt.h"
+inline char * asYesNo( bool val_r ) { return val_r ? _("Yes") : _("No"); }
+#include "Table.h"
+#define OSD ColorStream( std::cout, ColorContext::OSDEBUG )
+
using namespace zypp;
-class Table;
class Zypper;
-#define OSD ColorStream( std::cout, ColorContext::OSDEBUG )
-
-inline char * asYesNo( bool val_r )
-{ return val_r ? _("Yes") : _("No"); }
-
///////////////////////////////////////////////////////////////////
namespace out
{
static constexpr unsigned termwidthUnlimited = 0u;
+ unsigned defaultTermwidth(); // Zypper::instance()->out().termwidth()
} // namespace out
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
namespace out
{
- /** \relates ListFormater NORMAL representation of types in lists [no default] */
- template <class Tp_>
- std::string asListElement( const Tp_ & val_r );
-
- /** \relates ListFormater XML representation of types in lists [no default] */
- template <class Tp_>
- std::string asXmlListElement( const Tp_ & val_r );
-
///////////////////////////////////////////////////////////////////
/// \class ListLayout
/// \brief Basic list layout
///////////////////////////////////////////////////////////////////
struct ListLayout
{
+ template <class TFormater> struct Writer;
+
ListLayout( bool singleline_r, bool wrapline_r, bool gaped_r, unsigned indent_r )
: _singleline( singleline_r )
, _wrapline( wrapline_r )
template <bool singleline_, bool wrapline_, bool gaped_, unsigned indent_>
struct ListLayoutInit : public ListLayout { ListLayoutInit() : ListLayout( singleline_, wrapline_, gaped_, indent_ ) {} };
}
+
typedef detail::ListLayoutInit<true, false,false, 0U> XmlListLayout;
typedef detail::ListLayoutInit<true, true, false, 0U> DefaultListLayout; ///< one element per line, no indent
typedef detail::ListLayoutInit<true, true, true, 0U> DefaultGapedListLayout; ///< one element per line, no indent, gaped
typedef detail::ListLayoutInit<false,true, false, 2U> CompressedListLayout; ///< multiple elements per line, indented
///////////////////////////////////////////////////////////////////
- /// \class ListFormater
- /// \brief Default representation of types in Lists [asListElement|asXmlListElement]
+ /// \class TableLayout
+ /// \brief Basic table layout
///////////////////////////////////////////////////////////////////
- struct ListFormater
+ struct TableLayout
{
- typedef DefaultListLayout ListLayout; //< ListLayout for NORMAL lists
+ template <class TFormater> struct Writer;
+ };
- struct XmlFormater //< XML representation of element
- {
- template <class Tp_>
- std::string operator()( const Tp_ & val_r ) const
- { return asXmlListElement( val_r ); }
- };
+ typedef TableLayout DefaultTableLayout; ///< Simple Table
+
+ ///////////////////////////////////////////////////////////////////
+ // Either specialize per Type or define a custom Formater:
- template <class Tp_> //< NORMAL representation of element
- std::string operator()( const Tp_ & val_r ) const
+ /** \relates XmlFormater XML representation of types [no default] */
+ template <class Tp>
+ std::string asXmlListElement( const Tp & val_r );
+ inline std::string asXmlListElement( const std::string & val_r ){ return val_r; }
+ inline std::string asXmlListElement( const char * val_r ) { return val_r; }
+
+ /** \relates ListFormater NORMAL representation of types in lists [no default] */
+ template <class Tp>
+ std::string asListElement( const Tp & val_r );
+ inline std::string asListElement( const std::string & val_r ) { return val_r; }
+ inline std::string asListElement( const char * val_r ) { return val_r; }
+
+ /** \relates TableFormater NORMAL representation of types as TableHeader [no default] */
+ template <class Tp = void>
+ TableHeader asTableHeader();
+
+ template <>
+ inline TableHeader asTableHeader<void>()
+ { return TableHeader(); }
+
+ /** \relates TableFormater NORMAL representation of types as TableRow [no default] */
+ template <class Tp>
+ TableRow asTableRow( const Tp & val_r );
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class XmlFormater
+ /// \brief XML representation of types in container [asXmlListElement]
+ ///////////////////////////////////////////////////////////////////
+ struct XmlFormater
+ {
+ template <class Tp>
+ std::string xmlListElement( const Tp & val_r ) const//< XML representation of element
+ { return asXmlListElement( val_r ); }
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class ListFormater
+ /// \brief Default representation of types in Lists [asListElement]
+ ///////////////////////////////////////////////////////////////////
+ struct ListFormater : public XmlFormater
+ {
+ typedef DefaultListLayout NormalLayout; //< ListLayout for NORMAL lists
+
+ template <class Tp>
+ std::string listElement( const Tp & val_r ) const //< NORMAL representation of list element
{ return asListElement( val_r ); }
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class TableFormater
+ /// \brief Special list formater writing a Table [asTableHeader|asTableRow]
+ ///////////////////////////////////////////////////////////////////
+ struct TableFormater : public XmlFormater
+ {
+ typedef DefaultTableLayout NormalLayout; //< NORMAL layout as Table
+
+ TableHeader header() const //< TableHeader for TableRow representation
+ { return asTableHeader<>(); }
+
+ template <class Tp> //< Representation as TableRow
+ TableRow row( const Tp & val_r ) const
+ { return asTableRow( val_r ); }
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class XmlFormaterAdaptor
+ /// \brief Adaptor mapping xmlListElement->listElement for container XML output
+ ///////////////////////////////////////////////////////////////////
+ /** Adaptor */
+ template <class TFormater>
+ struct XmlFormaterAdaptor
+ {
+ typedef XmlListLayout NormalLayout; //< Layout as XML list
- std::string operator()( const std::string & val_r ) const
- { return val_r; }
+ template <class Tp>
+ std::string listElement( const Tp & val_r ) const //< use TFormater::asXmlListElement
+ { return _formater.xmlListElement( val_r ); }
- std::string operator()( const char * val_r ) const
- { return val_r; }
+ XmlFormaterAdaptor( const TFormater & formater_r )
+ : _formater( formater_r )
+ {}
+ private:
+ const TFormater & _formater;
};
} // namespace out
///////////////////////////////////////////////////////////////////
namespace out
{
- namespace detail
+ ///////////////////////////////////////////////////////////////////
+ /// \class ListLayout::Writer
+ /// \brief Write out a List according to the layout
+ // TODO: wrap singlelines; support for attributed text;
+ ///////////////////////////////////////////////////////////////////
+ template <class TFormater>
+ struct ListLayout::Writer
{
- // TODO: wrap singlelines; support for atttibuted text;
- struct BasicList
- {
- NON_COPYABLE( BasicList );
+ NON_COPYABLE( Writer );
+
+ Writer( std::ostream & str_r, ListLayout layout_r, const TFormater & formater_r )
+ : _str( str_r )
+ , _layout( layout_r )
+ , _formater( formater_r )
+ , _linewidth( defaultTermwidth() )
+ , _indent( _layout._indent, ' ' )
+ {}
- BasicList( ListLayout layout_r, unsigned linewidth_r )
- : _layout( std::move(layout_r) )
- , _linewidth( linewidth_r )
- , _indent( _layout._indent, ' ' )
- , _cpos( 0U )
- {}
+ ~Writer()
+ { if ( !_layout._singleline && _cpos ) _str << std::endl; }
- ~BasicList()
- { if ( !_layout._singleline && _cpos ) std::cout << std::endl; }
+ template <class Tp>
+ void operator<<( Tp && val_r ) const
+ {
+ const std::string & element( _formater.listElement( std::forward<Tp>(val_r) ) );
- void print( const std::string & val_r )
+ if ( _layout._singleline )
+ {
+ if ( _layout._gaped )
+ _str << std::endl;
+ _str << _indent << element << std::endl;
+ }
+ else
{
- if ( _layout._singleline )
+ if ( _cpos != 0 && ! fitsOnLine( 1/*' '*/ + element.size() ) )
+ endLine();
+
+ if ( _cpos == 0 )
{
- if ( _layout._gaped )
- std::cout << std::endl;
- std::cout << _indent << val_r << std::endl;
+ if ( !_indent.empty() )
+ printAndCount( _indent );
}
else
- {
- if ( _cpos != 0 && ! fitsOnLine( 1/*' '*/ + val_r.size() ) )
- endLine();
-
- if ( _cpos == 0 )
- {
- if ( !_indent.empty() )
- printAndCount( _indent );
- }
- else
- printAndCount( " " );
-
- printAndCount( val_r );
- }
+ printAndCount( " " );
+
+ printAndCount( element );
}
+ }
+
+ private:
+ bool fitsOnLine( unsigned size_r ) const
+ { return( !_layout._wrapline || _linewidth == out::termwidthUnlimited || _cpos + size_r <= _linewidth ); }
+
+ void printAndCount( const std::string & element_r ) const
+ { _cpos += element_r.size(); _str << element_r; }
+
+ void endLine() const
+ { _str << std::endl; _cpos = 0U; }
+
+ private:
+ std::ostream & _str;
+ const ListLayout & _layout;
+ const TFormater & _formater;
+ const unsigned _linewidth; ///< desired line width
+ const std::string _indent;
+ mutable unsigned _cpos = 0U;
+ };
+
+ ///////////////////////////////////////////////////////////////////
+ /// \class TableLayout::Writer
+ /// \brief Write out a Table according to the layout
+ ///////////////////////////////////////////////////////////////////
+ template <class TFormater>
+ struct TableLayout::Writer
+ {
+ NON_COPYABLE( Writer );
+
+ Writer( std::ostream & str_r, const TableLayout & layout_r, const TFormater & formater_r )
+ : _str( str_r )
+ , _layout( layout_r )
+ , _formater( formater_r )
+ {}
- private:
- bool fitsOnLine( unsigned val_r )
- { return( !_layout._wrapline || _linewidth == out::termwidthUnlimited || _cpos + val_r <= _linewidth ); }
+ ~Writer()
+ {
+ if ( !_t.empty() )
+ {
+ _t.setHeader( _formater.header() );
+ _str << _t;
+ }
+ }
- void printAndCount( const std::string & val_r )
- { _cpos += val_r.size(); std::cout << val_r; }
+ template <class Tp>
+ void operator<<( Tp && val_r ) const
+ { _t.add( _formater.row( std::forward<Tp>(val_r) ) ); }
+
+ private:
+ std::ostream & _str;
+ const TableLayout & _layout;
+ const TFormater & _formater;
+ mutable Table _t;
+ };
- void endLine()
- { std::cout << std::endl; _cpos = 0U; }
- private:
- const ListLayout _layout;
- unsigned _linewidth; ///< desired line width
- const std::string _indent;
- unsigned _cpos;
- };
+ /** Write formated container to stream */
+ template <class TContainer, class TFormater, class TLayout = typename TFormater::NormalLayout>
+ void writeContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r, const TLayout & layout_r = TLayout() )
+ {
+ typedef typename TLayout::template Writer<TFormater> Writer;
+ Writer writer( str_r, layout_r, formater_r );
+ for ( auto && el : container_r )
+ writer << el;
}
+
+ /** Write XML formated container to stream */
+ template <class TContainer, class TFormater>
+ void xmlWriteContainer( std::ostream & str_r, const TContainer & container_r, const TFormater & formater_r )
+ { writeContainer( str_r, container_r, out::XmlFormaterAdaptor<TFormater>(formater_r) ); }
+
} // namespace out
///////////////////////////////////////////////////////////////////
{ if ( out().typeNORMAL() && ! title_r.empty() ) std::cout << title_r << std::endl; }
};
- ///////////////////////////////////////////////////////////////////
- /// \class List<ListFormater>
- /// \brief Printing a list
- ///////////////////////////////////////////////////////////////////
- template <class ListFormater_ = out::ListFormater>
- struct List : protected ParentOut
- {
- List( Out & out_r, ListFormater_ formater_r, out::ListLayout layout_r = typename ListFormater_::ListLayout() )
- : ParentOut( out_r ), _formater( std::move(formater_r) ), _base( std::move(layout_r), out_r.termwidth() )
- {}
-
- template <class Tp_>
- List & operator<<( Tp_ && val_r )
- { _base.print( _formater( std::forward<Tp_>(val_r) ) ); return *this; }
-
- private:
- ListFormater_ _formater;
- out::detail::BasicList _base;
- };
- ///////////////////////////////////////////////////////////////////
-
-public:
- /** Write list from iterator pair */
- template <class Iterator_, class ListFormater_ = out::ListFormater>
- void list( Iterator_ begin_r, Iterator_ end_r, ListFormater_ && formater_r = ListFormater_() )
+private:
+ /** Write container creating a TitleNode with \c size="nnn" attribue and
+ * replacing optional \c %1% in \a title_r with size. */
+ template <class TContainer, class TFormater>
+ void container( const std::string & nodeName_r, const std::string & title_r,
+ const TContainer & container_r, const TFormater & formater_r )
{
+ TitleNode guard( XmlNode( *this, nodeName_r, XmlNode::Attr( "size", str::numstring( container_r.size() ) ) ),
+ str::FormatNAC( title_r ) % container_r.size() );
switch ( type() )
{
case TYPE_NORMAL:
- {
- List<ListFormater_> mlist( *this, std::forward<ListFormater_>(formater_r) );
- for_( it, begin_r, end_r ) mlist << ( *it );
- }
- break;
+ writeContainer( std::cout, container_r, formater_r );
+ break;
case TYPE_XML:
- {
- typedef typename ListFormater_::XmlFormater XmlFormater;
- List<XmlFormater> mlist( *this, XmlFormater(), out::XmlListLayout() );
- for_( it, begin_r, end_r ) mlist << ( *it );
- }
- break;
+ xmlWriteContainer( std::cout, container_r, formater_r );
+ break;
}
}
- /** Write list from constainer */
- template <class Container_, class ListFormater_ = out::ListFormater>
- void list( const Container_ & container_r, ListFormater_ && formater_r = ListFormater_() )
- { list( container_r.begin(), container_r.end(), std::forward<ListFormater_>(formater_r) ); }
-
- /** Write list from iterator pair enclosed by a \ref Node */
- template <class Iterator_, class ListFormater_ = out::ListFormater>
- void list( XmlNode && node_r, Iterator_ begin_r, Iterator_ end_r, ListFormater_ && formater_r = ListFormater_() )
- { XmlNode guard( std::move(node_r) ); list( begin_r, end_r, std::forward<ListFormater_>(formater_r) ); }
-
- /** Write list from constainer enclosed by a \ref Node */
- template <class Container_, class ListFormater_ = out::ListFormater>
- void list( XmlNode && node_r, const Container_ & container_r, ListFormater_ && formater_r = ListFormater_() )
- { XmlNode guard( std::move(node_r) ); list( container_r.begin(), container_r.end(), std::forward<ListFormater_>(formater_r) ); }
-
+public:
/** Write list from container creating a TitleNode with \c size="nnn" attribue and
* replacing optional \c %1% in \a title_r with size. */
- template <class Container_, class ListFormater_ = out::ListFormater>
- void list( const std::string & nodeName_r, const std::string & title_r, const Container_ & container_r, ListFormater_ && formater_r = ListFormater_() )
- {
- TitleNode guard( XmlNode( *this, nodeName_r, XmlNode::Attr( "size", str::numstring( container_r.size() ) ) ),
- str::FormatNAC( title_r ) % container_r.size() );
- list( container_r, std::forward<ListFormater_>(formater_r) );
- }
+ template <class TContainer, class TFormater = out::ListFormater>
+ void list( const std::string & nodeName_r, const std::string & title_r,
+ const TContainer & container_r, const TFormater & formater_r = TFormater() )
+ { container( nodeName_r, title_r, container_r, formater_r ); }
+
+ /** Write table from container creating a TitleNode with \c size="nnn" attribue and
+ * replacing optional \c %1% in \a title_r with size. */
+ template <class TContainer, class TFormater = out::TableFormater>
+ void table( const std::string & nodeName_r, const std::string & title_r,
+ const TContainer & container_r, const TFormater & formater_r = TFormater() )
+ { container( nodeName_r, title_r, container_r, formater_r ); }
public:
/** NORMAL: An empty line */
~Info()
{ out().info( _str->str() ); }
- template<class Tp_>
- std::ostream & operator<<( const Tp_ & val )
+ template<class Tp>
+ std::ostream & operator<<( const Tp & val )
{ return (*_str) << val; /*return *this;*/ }
private:
return ret;
}
-protected:
/** Width for formated output [0==unlimited]. */
virtual unsigned termwidth() const { return out::termwidthUnlimited; }
+protected:
+
/**
* Determine whether the output is intended for the particular type.
*/