Compile and run the following:
#define CATCH_CONFIG_MAIN
#include "catch.hpp"
TEST_CASE("Demonstrate the bug in word wrapping") {
const auto long_string = std::string(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl \n"
"massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in \n"
"convallis posuere, libero nisi ultricies orci, nec lobortis.\n");
const auto even_longer_string = long_string + '\n';
// This will fail; that's intentional.
REQUIRE(long_string == even_longer_string);
}
When ran, this produces the following output:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
a.out is a Catch v2.4.1 host application.
Run with -? for options
-------------------------------------------------------------------------------
Demonstrate the bug in word wrapping
-------------------------------------------------------------------------------
main.cpp:4
...............................................................................
main.cpp:19: FAILED:
REQUIRE( long_string == even_longer_string )
with expansion:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in
in
convallis posuere, libero nisi ultricies orci, nec lobortis.
"
==
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam in
in
convallis posuere, libero nisi ultricies orci, nec lobortis.
"
===============================================================================
test cases: 1 | 1 failed
assertions: 1 | 1 failed
Notice that this output contains "quam in in convallis", whereas the original code only contains "quam in convallis".
After few hours of debugging I found that this is actually issue with clara::TextFlow::Column::iterator formatting with the indentation. In this case the second line has 81 characters which is longer than console width. Basically the problem will occur here
auto operator *() const -> std::string {
assert( m_stringIndex < m_column.m_strings.size() );
assert( m_pos <= m_end );
if( m_pos + m_column.m_width < m_end ) // 155 < 155
return addIndentAndSuffix(line().substr(m_pos, m_len));
else
return addIndentAndSuffix(line().substr(m_pos, m_end - m_pos)); // m_end - m_pos is 79 or m_column.m_width
}
Seems that it should be enough to change the condition to <= instead of <.
With this change the result is:
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis.
"
==
"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Pellentesque nisl
massa, luctus ut ligula vitae, suscipit tempus velit. Vivamus sodales, quam
in
convallis posuere, libero nisi ultricies orci, nec lobortis."
@JoeyGrajciar Thanks.
Will you open up a PR against Clara?
@horenmar Yes i will create one soon :) Probably it will be different as i am not really sure if that condition is needed.
This has been fixed in the dependency, now it needs to find its way upward.
Fixed in 779e83bc2080729da97f2890598e898a4c751c9b
Thank you very much!
Most helpful comment
After few hours of debugging I found that this is actually issue with clara::TextFlow::Column::iterator formatting with the indentation. In this case the second line has 81 characters which is longer than console width. Basically the problem will occur here
Seems that it should be enough to change the condition to
<=instead of<.With this change the result is: