Update Clara to v1.1.5 to fix TextFlow bugs

This commit is contained in:
Martin Hořeňovský 2018-10-26 18:48:28 +02:00
parent 544c7d7cbf
commit 779e83bc20
3 changed files with 290 additions and 272 deletions

View File

@ -5,7 +5,7 @@
// //
// See https://github.com/philsquared/Clara for more details // See https://github.com/philsquared/Clara for more details
// Clara v1.1.4 // Clara v1.1.5
#ifndef CATCH_CLARA_HPP_INCLUDED #ifndef CATCH_CLARA_HPP_INCLUDED
#define CATCH_CLARA_HPP_INCLUDED #define CATCH_CLARA_HPP_INCLUDED
@ -34,8 +34,8 @@
// //
// A single-header library for wrapping and laying out basic text, by Phil Nash // A single-header library for wrapping and laying out basic text, by Phil Nash
// //
// This work is licensed under the BSD 2-Clause license. // Distributed under the Boost Software License, Version 1.0. (See accompanying
// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
// This project is hosted at https://github.com/philsquared/textflowcpp // This project is hosted at https://github.com/philsquared/textflowcpp
@ -52,30 +52,32 @@
#endif #endif
namespace Catch { namespace clara { namespace TextFlow { namespace Catch {
namespace clara {
namespace TextFlow {
inline auto isWhitespace( char c ) -> bool { inline auto isWhitespace(char c) -> bool {
static std::string chars = " \t\n\r"; static std::string chars = " \t\n\r";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
inline auto isBreakableBefore( char c ) -> bool { inline auto isBreakableBefore(char c) -> bool {
static std::string chars = "[({<|"; static std::string chars = "[({<|";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
inline auto isBreakableAfter( char c ) -> bool { inline auto isBreakableAfter(char c) -> bool {
static std::string chars = "])}>.,:;*+-=&/\\"; static std::string chars = "])}>.,:;*+-=&/\\";
return chars.find( c ) != std::string::npos; return chars.find(c) != std::string::npos;
} }
class Columns; class Columns;
class Column { class Column {
std::vector<std::string> m_strings; std::vector<std::string> m_strings;
size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH; size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;
size_t m_indent = 0; size_t m_indent = 0;
size_t m_initialIndent = std::string::npos; size_t m_initialIndent = std::string::npos;
public: public:
class iterator { class iterator {
friend Column; friend Column;
@ -87,40 +89,38 @@ namespace Catch { namespace clara { namespace TextFlow {
size_t m_end = 0; size_t m_end = 0;
bool m_suffix = false; bool m_suffix = false;
iterator( Column const& column, size_t stringIndex ) iterator(Column const& column, size_t stringIndex)
: m_column( column ), : m_column(column),
m_stringIndex( stringIndex ) m_stringIndex(stringIndex) {}
{}
auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; } auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }
auto isBoundary( size_t at ) const -> bool { auto isBoundary(size_t at) const -> bool {
assert( at > 0 ); assert(at > 0);
assert( at <= line().size() ); assert(at <= line().size());
return at == line().size() || return at == line().size() ||
( isWhitespace( line()[at] ) && !isWhitespace( line()[at-1] ) ) || (isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||
isBreakableBefore( line()[at] ) || isBreakableBefore(line()[at]) ||
isBreakableAfter( line()[at-1] ); isBreakableAfter(line()[at - 1]);
} }
void calcLength() { void calcLength() {
assert( m_stringIndex < m_column.m_strings.size() ); assert(m_stringIndex < m_column.m_strings.size());
m_suffix = false; m_suffix = false;
auto width = m_column.m_width-indent(); auto width = m_column.m_width - indent();
m_end = m_pos; m_end = m_pos;
while( m_end < line().size() && line()[m_end] != '\n' ) while (m_end < line().size() && line()[m_end] != '\n')
++m_end; ++m_end;
if( m_end < m_pos + width ) { if (m_end < m_pos + width) {
m_len = m_end - m_pos; m_len = m_end - m_pos;
} } else {
else {
size_t len = width; size_t len = width;
while (len > 0 && !isBoundary(m_pos + len)) while (len > 0 && !isBoundary(m_pos + len))
--len; --len;
while (len > 0 && isWhitespace( line()[m_pos + len - 1] )) while (len > 0 && isWhitespace(line()[m_pos + len - 1]))
--len; --len;
if (len > 0) { if (len > 0) {
@ -138,85 +138,88 @@ namespace Catch { namespace clara { namespace TextFlow {
} }
auto addIndentAndSuffix(std::string const &plain) const -> std::string { auto addIndentAndSuffix(std::string const &plain) const -> std::string {
return std::string( indent(), ' ' ) + (m_suffix ? plain + "-" : plain); return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);
} }
public: public:
explicit iterator( Column const& column ) : m_column( column ) { using difference_type = std::ptrdiff_t;
assert( m_column.m_width > m_column.m_indent ); using value_type = std::string;
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); using pointer = value_type * ;
using reference = value_type & ;
using iterator_category = std::forward_iterator_tag;
explicit iterator(Column const& column) : m_column(column) {
assert(m_column.m_width > m_column.m_indent);
assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);
calcLength(); calcLength();
if( m_len == 0 ) if (m_len == 0)
m_stringIndex++; // Empty string m_stringIndex++; // Empty string
} }
auto operator *() const -> std::string { auto operator *() const -> std::string {
assert( m_stringIndex < m_column.m_strings.size() ); assert(m_stringIndex < m_column.m_strings.size());
assert( m_pos <= m_end ); assert(m_pos <= m_end);
if( m_pos + m_column.m_width < m_end )
return addIndentAndSuffix(line().substr(m_pos, m_len)); return addIndentAndSuffix(line().substr(m_pos, m_len));
else
return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
} }
auto operator ++() -> iterator& { auto operator ++() -> iterator& {
m_pos += m_len; m_pos += m_len;
if( m_pos < line().size() && line()[m_pos] == '\n' ) if (m_pos < line().size() && line()[m_pos] == '\n')
m_pos += 1; m_pos += 1;
else else
while( m_pos < line().size() && isWhitespace( line()[m_pos] ) ) while (m_pos < line().size() && isWhitespace(line()[m_pos]))
++m_pos; ++m_pos;
if( m_pos == line().size() ) { if (m_pos == line().size()) {
m_pos = 0; m_pos = 0;
++m_stringIndex; ++m_stringIndex;
} }
if( m_stringIndex < m_column.m_strings.size() ) if (m_stringIndex < m_column.m_strings.size())
calcLength(); calcLength();
return *this; return *this;
} }
auto operator ++(int) -> iterator { auto operator ++(int) -> iterator {
iterator prev( *this ); iterator prev(*this);
operator++(); operator++();
return prev; return prev;
} }
auto operator ==( iterator const& other ) const -> bool { auto operator ==(iterator const& other) const -> bool {
return return
m_pos == other.m_pos && m_pos == other.m_pos &&
m_stringIndex == other.m_stringIndex && m_stringIndex == other.m_stringIndex &&
&m_column == &other.m_column; &m_column == &other.m_column;
} }
auto operator !=( iterator const& other ) const -> bool { auto operator !=(iterator const& other) const -> bool {
return !operator==( other ); return !operator==(other);
} }
}; };
using const_iterator = iterator; using const_iterator = iterator;
explicit Column( std::string const& text ) { m_strings.push_back( text ); } explicit Column(std::string const& text) { m_strings.push_back(text); }
auto width( size_t newWidth ) -> Column& { auto width(size_t newWidth) -> Column& {
assert( newWidth > 0 ); assert(newWidth > 0);
m_width = newWidth; m_width = newWidth;
return *this; return *this;
} }
auto indent( size_t newIndent ) -> Column& { auto indent(size_t newIndent) -> Column& {
m_indent = newIndent; m_indent = newIndent;
return *this; return *this;
} }
auto initialIndent( size_t newIndent ) -> Column& { auto initialIndent(size_t newIndent) -> Column& {
m_initialIndent = newIndent; m_initialIndent = newIndent;
return *this; return *this;
} }
auto width() const -> size_t { return m_width; } auto width() const -> size_t { return m_width; }
auto begin() const -> iterator { return iterator( *this ); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return { *this, m_strings.size() }; } auto end() const -> iterator { return { *this, m_strings.size() }; }
inline friend std::ostream& operator << ( std::ostream& os, Column const& col ) { inline friend std::ostream& operator << (std::ostream& os, Column const& col) {
bool first = true; bool first = true;
for( auto line : col ) { for (auto line : col) {
if( first ) if (first)
first = false; first = false;
else else
os << "\n"; os << "\n";
@ -225,27 +228,27 @@ namespace Catch { namespace clara { namespace TextFlow {
return os; return os;
} }
auto operator + ( Column const& other ) -> Columns; auto operator + (Column const& other)->Columns;
auto toString() const -> std::string { auto toString() const -> std::string {
std::ostringstream oss; std::ostringstream oss;
oss << *this; oss << *this;
return oss.str(); return oss.str();
} }
}; };
class Spacer : public Column { class Spacer : public Column {
public: public:
explicit Spacer( size_t spaceWidth ) : Column( "" ) { explicit Spacer(size_t spaceWidth) : Column("") {
width( spaceWidth ); width(spaceWidth);
} }
}; };
class Columns { class Columns {
std::vector<Column> m_columns; std::vector<Column> m_columns;
public: public:
class iterator { class iterator {
friend Columns; friend Columns;
@ -255,85 +258,88 @@ namespace Catch { namespace clara { namespace TextFlow {
std::vector<Column::iterator> m_iterators; std::vector<Column::iterator> m_iterators;
size_t m_activeIterators; size_t m_activeIterators;
iterator( Columns const& columns, EndTag ) iterator(Columns const& columns, EndTag)
: m_columns( columns.m_columns ), : m_columns(columns.m_columns),
m_activeIterators( 0 ) m_activeIterators(0) {
{ m_iterators.reserve(m_columns.size());
m_iterators.reserve( m_columns.size() );
for( auto const& col : m_columns ) for (auto const& col : m_columns)
m_iterators.push_back( col.end() ); m_iterators.push_back(col.end());
} }
public: public:
explicit iterator( Columns const& columns ) using difference_type = std::ptrdiff_t;
: m_columns( columns.m_columns ), using value_type = std::string;
m_activeIterators( m_columns.size() ) using pointer = value_type * ;
{ using reference = value_type & ;
m_iterators.reserve( m_columns.size() ); using iterator_category = std::forward_iterator_tag;
for( auto const& col : m_columns ) explicit iterator(Columns const& columns)
m_iterators.push_back( col.begin() ); : m_columns(columns.m_columns),
m_activeIterators(m_columns.size()) {
m_iterators.reserve(m_columns.size());
for (auto const& col : m_columns)
m_iterators.push_back(col.begin());
} }
auto operator ==( iterator const& other ) const -> bool { auto operator ==(iterator const& other) const -> bool {
return m_iterators == other.m_iterators; return m_iterators == other.m_iterators;
} }
auto operator !=( iterator const& other ) const -> bool { auto operator !=(iterator const& other) const -> bool {
return m_iterators != other.m_iterators; return m_iterators != other.m_iterators;
} }
auto operator *() const -> std::string { auto operator *() const -> std::string {
std::string row, padding; std::string row, padding;
for( size_t i = 0; i < m_columns.size(); ++i ) { for (size_t i = 0; i < m_columns.size(); ++i) {
auto width = m_columns[i].width(); auto width = m_columns[i].width();
if( m_iterators[i] != m_columns[i].end() ) { if (m_iterators[i] != m_columns[i].end()) {
std::string col = *m_iterators[i]; std::string col = *m_iterators[i];
row += padding + col; row += padding + col;
if( col.size() < width ) if (col.size() < width)
padding = std::string( width - col.size(), ' ' ); padding = std::string(width - col.size(), ' ');
else else
padding = ""; padding = "";
} } else {
else { padding += std::string(width, ' ');
padding += std::string( width, ' ' );
} }
} }
return row; return row;
} }
auto operator ++() -> iterator& { auto operator ++() -> iterator& {
for( size_t i = 0; i < m_columns.size(); ++i ) { for (size_t i = 0; i < m_columns.size(); ++i) {
if (m_iterators[i] != m_columns[i].end()) if (m_iterators[i] != m_columns[i].end())
++m_iterators[i]; ++m_iterators[i];
} }
return *this; return *this;
} }
auto operator ++(int) -> iterator { auto operator ++(int) -> iterator {
iterator prev( *this ); iterator prev(*this);
operator++(); operator++();
return prev; return prev;
} }
}; };
using const_iterator = iterator; using const_iterator = iterator;
auto begin() const -> iterator { return iterator( *this ); } auto begin() const -> iterator { return iterator(*this); }
auto end() const -> iterator { return { *this, iterator::EndTag() }; } auto end() const -> iterator { return { *this, iterator::EndTag() }; }
auto operator += ( Column const& col ) -> Columns& { auto operator += (Column const& col) -> Columns& {
m_columns.push_back( col ); m_columns.push_back(col);
return *this; return *this;
} }
auto operator + ( Column const& col ) -> Columns { auto operator + (Column const& col) -> Columns {
Columns combined = *this; Columns combined = *this;
combined += col; combined += col;
return combined; return combined;
} }
inline friend std::ostream& operator << ( std::ostream& os, Columns const& cols ) { inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {
bool first = true; bool first = true;
for( auto line : cols ) { for (auto line : cols) {
if( first ) if (first)
first = false; first = false;
else else
os << "\n"; os << "\n";
@ -347,22 +353,25 @@ namespace Catch { namespace clara { namespace TextFlow {
oss << *this; oss << *this;
return oss.str(); return oss.str();
} }
}; };
inline auto Column::operator + ( Column const& other ) -> Columns { inline auto Column::operator + (Column const& other) -> Columns {
Columns cols; Columns cols;
cols += *this; cols += *this;
cols += other; cols += other;
return cols; return cols;
} }
}}} // namespace Catch::clara::TextFlow }
}
}
#endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED #endif // CATCH_CLARA_TEXTFLOW_HPP_INCLUDED
// ----------- end of #include from clara_textflow.hpp ----------- // ----------- end of #include from clara_textflow.hpp -----------
// ........... back in clara.hpp // ........... back in clara.hpp
#include <string>
#include <memory> #include <memory>
#include <set> #include <set>
#include <algorithm> #include <algorithm>

View File

@ -6732,7 +6732,7 @@ Matchers.tests.cpp:<line number>:
PASSED: PASSED:
CHECK_THAT( testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No) ) CHECK_THAT( testStringForMatching(), Contains("aBC", Catch::CaseSensitive::No) )
with expansion: with expansion:
"this string contains 'abc' as a substring" contains: "abc" (case insensitive) "this string contains 'abc' as a substring" contains: "abc" (case
insensitive) insensitive)
Matchers.tests.cpp:<line number>: Matchers.tests.cpp:<line number>:
@ -10865,7 +10865,7 @@ with expansion:
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
xmlentitycheck xmlentitycheck
embedded xml: <test>it should be possible to embed xml characters, such as <, embedded xml: <test>it should be possible to embed xml characters, such as <,
" or &, or even whole <xml>documents</xml> within an attribute</test> " or &, or even whole <xml>documents</xml> within an attribute
</test> </test>
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Misc.tests.cpp:<line number> Misc.tests.cpp:<line number>

23
third_party/clara.hpp vendored
View File

@ -5,7 +5,7 @@
// //
// See https://github.com/philsquared/Clara for more details // See https://github.com/philsquared/Clara for more details
// Clara v1.1.4 // Clara v1.1.5
#ifndef CLARA_HPP_INCLUDED #ifndef CLARA_HPP_INCLUDED
#define CLARA_HPP_INCLUDED #define CLARA_HPP_INCLUDED
@ -34,8 +34,8 @@
// //
// A single-header library for wrapping and laying out basic text, by Phil Nash // A single-header library for wrapping and laying out basic text, by Phil Nash
// //
// This work is licensed under the BSD 2-Clause license. // Distributed under the Boost Software License, Version 1.0. (See accompanying
// See the accompanying LICENSE file, or the one at https://opensource.org/licenses/BSD-2-Clause // file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
// //
// This project is hosted at https://github.com/philsquared/textflowcpp // This project is hosted at https://github.com/philsquared/textflowcpp
@ -142,6 +142,12 @@ namespace clara { namespace TextFlow {
} }
public: public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
explicit iterator( Column const& column ) : m_column( column ) { explicit iterator( Column const& column ) : m_column( column ) {
assert( m_column.m_width > m_column.m_indent ); assert( m_column.m_width > m_column.m_indent );
assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent ); assert( m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent );
@ -153,10 +159,7 @@ namespace clara { namespace TextFlow {
auto operator *() const -> std::string { auto operator *() const -> std::string {
assert( m_stringIndex < m_column.m_strings.size() ); assert( m_stringIndex < m_column.m_strings.size() );
assert( m_pos <= m_end ); assert( m_pos <= m_end );
if( m_pos + m_column.m_width < m_end )
return addIndentAndSuffix(line().substr(m_pos, m_len)); return addIndentAndSuffix(line().substr(m_pos, m_len));
else
return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos));
} }
auto operator ++() -> iterator& { auto operator ++() -> iterator& {
@ -266,6 +269,12 @@ namespace clara { namespace TextFlow {
} }
public: public:
using difference_type = std::ptrdiff_t;
using value_type = std::string;
using pointer = value_type*;
using reference = value_type&;
using iterator_category = std::forward_iterator_tag;
explicit iterator( Columns const& columns ) explicit iterator( Columns const& columns )
: m_columns( columns.m_columns ), : m_columns( columns.m_columns ),
m_activeIterators( m_columns.size() ) m_activeIterators( m_columns.size() )
@ -355,7 +364,7 @@ namespace clara { namespace TextFlow {
cols += other; cols += other;
return cols; return cols;
} }
}} // namespace clara::TextFlow }}
#endif // CLARA_TEXTFLOW_HPP_INCLUDED #endif // CLARA_TEXTFLOW_HPP_INCLUDED