diff --git a/include/znc/Utils.h b/include/znc/Utils.h index c2a06a66..76f3717f 100644 --- a/include/znc/Utils.h +++ b/include/znc/Utils.h @@ -128,7 +128,7 @@ class CException { }; -/** Generate a grid-like output from a given input. +/** Generate a grid-like or list-like output from a given input. * * @code * CTable table; @@ -152,9 +152,25 @@ class CException { +-------+-------+ | hello | world | +-------+-------+@endverbatim + * + * If the table has at most two columns, one can switch to ListStyle output + * like so: + * @code + * CTable table; + * table.AddColumn("a"); + * table.AddColumn("b"); + * table.SetStyle(CTable::ListStyle); + * // ... + * @endcode + * + * This will yield the following (Note that the header is omitted; asterisks + * denote bold text): + * @verbatim +*hello*: world@endverbatim */ class CTable : protected std::vector> { public: + enum EStyle { GridStyle, ListStyle }; CTable() {} virtual ~CTable() {} @@ -162,10 +178,18 @@ class CTable : protected std::vector> { * Please note that you should add all columns before starting to fill * the table! * @param sName The name of the column. - * @return false if a column by that name already existed. + * @return false if a column by that name already existed or the current + * style does not allow this many columns. */ bool AddColumn(const CString& sName); + /** Selects the output style of the table. + * Select between different styles for printing. Default is GridStyle. + * @param eNewStyle Table style type. + * @return false if the style cannot be applied (usually too many columns). + */ + bool SetStyle(EStyle eNewStyle); + /** Adds a new row to the table. * After calling this you can fill the row with content. * @return The index of this row @@ -213,6 +237,7 @@ class CTable : protected std::vector> { std::vector m_vsHeaders; // Used to cache the width of a column std::map m_msuWidths; + EStyle eStyle = GridStyle; }; #ifdef HAVE_LIBSSL diff --git a/src/ClientCommand.cpp b/src/ClientCommand.cpp index f49cdacf..d0d8518d 100644 --- a/src/ClientCommand.cpp +++ b/src/ClientCommand.cpp @@ -1658,6 +1658,7 @@ void CClient::HelpUser(const CString& sFilter) { CTable Table; Table.AddColumn(t_s("Command", "helpcmd")); Table.AddColumn(t_s("Description", "helpcmd")); + Table.SetStyle(CTable::ListStyle); if (sFilter.empty()) { PutStatus( @@ -1670,7 +1671,8 @@ void CClient::HelpUser(const CString& sFilter) { if (sFilter.empty() || sCmd.StartsWith(sFilter) || sCmd.AsLower().WildCmp(sFilter.AsLower())) { Table.AddRow(); - Table.SetCell(t_s("Command", "helpcmd"), sCmd + " " + sArgs); + Table.SetCell(t_s("Command", "helpcmd"), + sCmd + (sArgs.empty() ? "" : " ") + sArgs); Table.SetCell(t_s("Description", "helpcmd"), sDesc); } }; diff --git a/src/Utils.cpp b/src/Utils.cpp index 29d28858..a5a6c9ba 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp @@ -760,6 +760,8 @@ void CUtils::SetMessageTags(CString& sLine, const MCString& mssTags) { } bool CTable::AddColumn(const CString& sName) { + if (eStyle == ListStyle && m_vsHeaders.size() >= 2) + return false; for (const CString& sHeader : m_vsHeaders) { if (sHeader.Equals(sName)) { return false; @@ -772,6 +774,19 @@ bool CTable::AddColumn(const CString& sName) { return true; } +bool CTable::SetStyle(EStyle eNewStyle) { + switch (eNewStyle) { + case GridStyle: + break; + case ListStyle: + if (m_vsHeaders.size() > 2) return false; + break; + } + + eStyle = eNewStyle; + return true; +} + CTable::size_type CTable::AddRow() { // Don't add a row if no headers are defined if (m_vsHeaders.empty()) { @@ -812,6 +827,20 @@ bool CTable::GetLine(unsigned int uIdx, CString& sLine) const { return false; } + if (eStyle == ListStyle) { + if (m_vsHeaders.size() > 2) return false; // definition list mode can only do up to two columns + if (uIdx >= size()) return false; + + const std::vector& mRow = (*this)[uIdx]; + ssRet << "\x02" << mRow[0] << "\x0f"; //bold first column + if (m_vsHeaders.size() >= 2 && mRow[1] != "") { + ssRet << ": " << mRow[1]; + } + + sLine = ssRet.str(); + return true; + } + if (uIdx == 1) { ssRet.fill(' '); ssRet << "| ";