Improve comments and names in TextFlow::Column

This commit is contained in:
Martin Hořeňovský 2021-11-01 19:14:37 +01:00
parent 455ae0c561
commit 70c4ec78fb
No known key found for this signature in database
GPG Key ID: DE48307B8B0D381A
2 changed files with 70 additions and 44 deletions

View File

@ -40,42 +40,50 @@ namespace Catch {
namespace TextFlow { namespace TextFlow {
void Column::const_iterator::calcLength() { void Column::const_iterator::calcLength() {
m_suffix = false; m_addHyphen = false;
auto width = m_column.m_width - indent(); const auto maxLineLength = m_column.m_width - indentSize();
m_end = m_pos; m_parsedTo = m_lineStart;
std::string const& current_line = m_column.m_string; std::string const& current_line = m_column.m_string;
if ( current_line[m_pos] == '\n' ) { if ( current_line[m_lineStart] == '\n' ) {
++m_end; ++m_parsedTo;
} }
while ( m_end < current_line.size() && while ( m_parsedTo < current_line.size() &&
current_line[m_end] != '\n' ) { current_line[m_parsedTo] != '\n' ) {
++m_end; ++m_parsedTo;
} }
if ( m_end < m_pos + width ) { // If we encountered a newline before the column is filled,
m_len = m_end - m_pos; // then we linebreak at the newline and consider this line
// finished.
if ( m_parsedTo < m_lineStart + maxLineLength ) {
m_lineLength = m_parsedTo - m_lineStart;
} else { } else {
size_t len = width; // Look for a natural linebreak boundary in the column
while ( len > 0 && !isBoundary( current_line, m_pos + len ) ) { // (We look from the end, so that the first found boundary is
--len; // the right one)
size_t newLineLength = maxLineLength;
while ( newLineLength > 0 && !isBoundary( current_line, m_lineStart + newLineLength ) ) {
--newLineLength;
} }
while ( len > 0 && while ( newLineLength > 0 &&
isWhitespace( current_line[m_pos + len - 1] ) ) { isWhitespace( current_line[m_lineStart + newLineLength - 1] ) ) {
--len; --newLineLength;
} }
if ( len > 0 ) { // If we found one, then that is where we linebreak
m_len = len; if ( newLineLength > 0 ) {
m_lineLength = newLineLength;
} else { } else {
m_suffix = true; // Otherwise we have to split text with a hyphen
m_len = width - 1; m_addHyphen = true;
m_lineLength = maxLineLength - 1;
} }
} }
} }
size_t Column::const_iterator::indent() const { size_t Column::const_iterator::indentSize() const {
auto initial = auto initial =
m_pos == 0 ? m_column.m_initialIndent : std::string::npos; m_lineStart == 0 ? m_column.m_initialIndent : std::string::npos;
return initial == std::string::npos ? m_column.m_indent : initial; return initial == std::string::npos ? m_column.m_indent : initial;
} }
@ -83,11 +91,11 @@ namespace Catch {
Column::const_iterator::addIndentAndSuffix( size_t position, Column::const_iterator::addIndentAndSuffix( size_t position,
size_t length ) const { size_t length ) const {
std::string ret; std::string ret;
const auto desired_indent = indent(); const auto desired_indent = indentSize();
ret.reserve( desired_indent + length + m_suffix ); ret.reserve( desired_indent + length + m_addHyphen );
ret.append( desired_indent, ' ' ); ret.append( desired_indent, ' ' );
ret.append( m_column.m_string, position, length ); ret.append( m_column.m_string, position, length );
if ( m_suffix ) { if ( m_addHyphen ) {
ret.push_back( '-' ); ret.push_back( '-' );
} }
@ -99,29 +107,29 @@ namespace Catch {
assert( m_column.m_initialIndent == std::string::npos || assert( m_column.m_initialIndent == std::string::npos ||
m_column.m_width > m_column.m_initialIndent ); m_column.m_width > m_column.m_initialIndent );
calcLength(); calcLength();
if ( m_len == 0 ) { if ( m_lineLength == 0 ) {
m_pos = m_column.m_string.size(); m_lineStart = m_column.m_string.size();
} }
} }
std::string Column::const_iterator::operator*() const { std::string Column::const_iterator::operator*() const {
assert( m_pos <= m_end ); assert( m_lineStart <= m_parsedTo );
return addIndentAndSuffix( m_pos, m_len ); return addIndentAndSuffix( m_lineStart, m_lineLength );
} }
Column::const_iterator& Column::const_iterator::operator++() { Column::const_iterator& Column::const_iterator::operator++() {
m_pos += m_len; m_lineStart += m_lineLength;
std::string const& current_line = m_column.m_string; std::string const& current_line = m_column.m_string;
if ( m_pos < current_line.size() && current_line[m_pos] == '\n' ) { if ( m_lineStart < current_line.size() && current_line[m_lineStart] == '\n' ) {
m_pos += 1; m_lineStart += 1;
} else { } else {
while ( m_pos < current_line.size() && while ( m_lineStart < current_line.size() &&
isWhitespace( current_line[m_pos] ) ) { isWhitespace( current_line[m_lineStart] ) ) {
++m_pos; ++m_lineStart;
} }
} }
if ( m_pos != current_line.size() ) { if ( m_lineStart != current_line.size() ) {
calcLength(); calcLength();
} }
return *this; return *this;

View File

@ -18,31 +18,49 @@ namespace Catch {
class Columns; class Columns;
/**
* Represents a column of text with specific width and indentation
*
* When written out to a stream, it will perform linebreaking
* of the provided text so that the written lines fit within
* target width.
*/
class Column { class Column {
// String to be written out
std::string m_string; std::string m_string;
// Width of the column for linebreaking
size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1; size_t m_width = CATCH_CONFIG_CONSOLE_WIDTH - 1;
// Indentation of other lines (including first if initial indent is unset)
size_t m_indent = 0; size_t m_indent = 0;
// Indentation of the first line
size_t m_initialIndent = std::string::npos; size_t m_initialIndent = std::string::npos;
public: public:
/**
* Iterates "lines" in `Column` and return sthem
*/
class const_iterator { class const_iterator {
friend Column; friend Column;
struct EndTag {}; struct EndTag {};
Column const& m_column; Column const& m_column;
size_t m_pos = 0; // Where does the current line start?
size_t m_lineStart = 0;
size_t m_len = 0; // How long should the current line be?
size_t m_end = 0; size_t m_lineLength = 0;
bool m_suffix = false; // How far have we checked the string to iterate?
size_t m_parsedTo = 0;
// Should a '-' be appended to the line?
bool m_addHyphen = false;
const_iterator( Column const& column, EndTag ): const_iterator( Column const& column, EndTag ):
m_column( column ), m_pos( m_column.m_string.size() ) {} m_column( column ), m_lineStart( m_column.m_string.size() ) {}
// Calculates the length of the current line
void calcLength(); void calcLength();
// Returns current indention width // Returns current indention width
size_t indent() const; size_t indentSize() const;
// Creates an indented and (optionally) suffixed string from // Creates an indented and (optionally) suffixed string from
// current iterator position, indentation and length. // current iterator position, indentation and length.
@ -64,7 +82,7 @@ namespace Catch {
const_iterator operator++( int ); const_iterator operator++( int );
bool operator==( const_iterator const& other ) const { bool operator==( const_iterator const& other ) const {
return m_pos == other.m_pos && &m_column == &other.m_column; return m_lineStart == other.m_lineStart && &m_column == &other.m_column;
} }
bool operator!=( const_iterator const& other ) const { bool operator!=( const_iterator const& other ) const {
return !operator==( other ); return !operator==( other );