diff options
author | Luke Dashjr <luke-jr+git@utopios.org> | 2016-02-03 05:16:49 +0000 |
---|---|---|
committer | Luke Dashjr <luke-jr+git@utopios.org> | 2016-02-03 05:38:43 +0000 |
commit | cc2095ecae3f4ff57d3981b5992e032e564ba65d (patch) | |
tree | 2e56a00c71225539366255f67cd64b3945cfeec3 /src | |
parent | cddffaf5e60f638b2acf4d33a4eb43c984825bba (diff) |
Rewrite FormatParagraph to handle newlines within input strings correctly
Diffstat (limited to 'src')
-rw-r--r-- | src/test/util_tests.cpp | 21 | ||||
-rw-r--r-- | src/utilstrencodings.cpp | 56 |
2 files changed, 49 insertions, 28 deletions
diff --git a/src/test/util_tests.cpp b/src/test/util_tests.cpp index 997dc31931..1bbd497f78 100644 --- a/src/test/util_tests.cpp +++ b/src/test/util_tests.cpp @@ -399,12 +399,27 @@ BOOST_AUTO_TEST_CASE(test_FormatParagraph) { BOOST_CHECK_EQUAL(FormatParagraph("", 79, 0), ""); BOOST_CHECK_EQUAL(FormatParagraph("test", 79, 0), "test"); - BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), "test"); + BOOST_CHECK_EQUAL(FormatParagraph(" test", 79, 0), " test"); BOOST_CHECK_EQUAL(FormatParagraph("test test", 79, 0), "test test"); BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 0), "test\ntest"); - BOOST_CHECK_EQUAL(FormatParagraph("testerde test ", 4, 0), "testerde\ntest"); + BOOST_CHECK_EQUAL(FormatParagraph("testerde test", 4, 0), "testerde\ntest"); BOOST_CHECK_EQUAL(FormatParagraph("test test", 4, 4), "test\n test"); - BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string."), "This is a very long test string. This is a second sentence in the very long\ntest string."); + + // Make sure we don't indent a fully-new line following a too-long line ending + BOOST_CHECK_EQUAL(FormatParagraph("test test\nabc", 4, 4), "test\n test\nabc"); + + BOOST_CHECK_EQUAL(FormatParagraph("This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length until it gets here", 79), "This_is_a_very_long_test_string_without_any_spaces_so_it_should_just_get_returned_as_is_despite_the_length\nuntil it gets here"); + + // Test wrap length is exact + BOOST_CHECK_EQUAL(FormatParagraph("a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "a b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p"); + BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p", 79), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\nf g h i j k l m n o p"); + // Indent should be included in length of lines + BOOST_CHECK_EQUAL(FormatParagraph("x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg h i j k", 79, 4), "x\na b c d e f g h i j k l m n o p q r s t u v w x y z 1 2 3 4 5 6 7 8 9 a b c de\n f g h i j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 a b c d e fg\n h i j k"); + + BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string. This is a second sentence in the very long test string.", 79), "This is a very long test string. This is a second sentence in the very long\ntest string."); + BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string."); + BOOST_CHECK_EQUAL(FormatParagraph("This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third sentence in the very long test string.", 79), "This is a very long test string.\n\nThis is a second sentence in the very long test string. This is a third\nsentence in the very long test string."); + BOOST_CHECK_EQUAL(FormatParagraph("Testing that normal newlines do not get indented.\nLike here.", 79), "Testing that normal newlines do not get indented.\nLike here."); } BOOST_AUTO_TEST_CASE(test_FormatSubVersion) diff --git a/src/utilstrencodings.cpp b/src/utilstrencodings.cpp index c5a2b5cdbb..a098c3e0a6 100644 --- a/src/utilstrencodings.cpp +++ b/src/utilstrencodings.cpp @@ -478,34 +478,40 @@ bool ParseDouble(const std::string& str, double *out) std::string FormatParagraph(const std::string& in, size_t width, size_t indent) { std::stringstream out; - size_t col = 0; size_t ptr = 0; - while(ptr < in.size()) + size_t indented = 0; + while (ptr < in.size()) { - // Find beginning of next word - ptr = in.find_first_not_of(' ', ptr); - if (ptr == std::string::npos) - break; - // Find end of next word - size_t endword = in.find_first_of(' ', ptr); - if (endword == std::string::npos) - endword = in.size(); - // Add newline and indentation if this wraps over the allowed width - if (col > 0) - { - if ((col + endword - ptr) > width) - { - out << '\n'; - for(size_t i=0; i<indent; ++i) - out << ' '; - col = 0; - } else - out << ' '; + size_t lineend = in.find_first_of('\n', ptr); + if (lineend == std::string::npos) { + lineend = in.size(); + } + const size_t linelen = lineend - ptr; + const size_t rem_width = width - indented; + if (linelen <= rem_width) { + out << in.substr(ptr, linelen + 1); + ptr = lineend + 1; + indented = 0; + } else { + size_t finalspace = in.find_last_of(" \n", ptr + rem_width); + if (finalspace == std::string::npos || finalspace < ptr) { + // No place to break; just include the entire word and move on + finalspace = in.find_first_of("\n ", ptr); + if (finalspace == std::string::npos) { + // End of the string, just add it and break + out << in.substr(ptr); + break; + } + } + out << in.substr(ptr, finalspace - ptr) << "\n"; + if (in[finalspace] == '\n') { + indented = 0; + } else if (indent) { + out << std::string(indent, ' '); + indented = indent; + } + ptr = finalspace + 1; } - // Append word - out << in.substr(ptr, endword - ptr); - col += endword - ptr + 1; - ptr = endword; } return out.str(); } |