# # # patch "commands.cc" # from [9c2de6b3b3ca5e47667bc0d2195e62410b059677] # to [7c1d8a3d567bb3f9ffd826800e73f8c851a98e92] # # patch "simplestring_xform.cc" # from [4d9df66d29c1e2b1ec4ef1717b271de71fd3d941] # to [c365ced7930603fa9ac400b7d32eaf305ef31c3d] # # patch "simplestring_xform.hh" # from [a3d2b3c5201493b1609578d624070636688c989e] # to [e83fbfd81cd0bd0f6470abc818dc3b26a6a10156] # ============================================================ --- commands.cc 9c2de6b3b3ca5e47667bc0d2195e62410b059677 +++ commands.cc 7c1d8a3d567bb3f9ffd826800e73f8c851a98e92 @@ -241,15 +241,39 @@ namespace commands static void describe(const string & tag, const string & abstract, size_t colabstract, ostream & out) { + // The algorithm below avoids printing an space on entry (note that + // there are two before the tag but just one after it) and considers + // that the colabstract is always one unit less than that given on + // entry because it always prints a single space before each word. + assert(colabstract > 0); + size_t col = 0; - out << " " << tag << " "; - col += display_width(utf8(tag + " ")); + out << " " << tag << " "; + col += display_width(utf8(tag + " ")); - // TODO: Properly wrap long lines. + while (col++ < colabstract - 1) + out << ' '; + col = colabstract - 1; - while (col++ < colabstract) - out << ' '; - out << abstract << std::endl; + vector words; + split_into_words(abstract, words); + + const size_t maxcol = terminal_width(); + for (vector::const_iterator i = words.begin(); + i != words.end(); i++) { + string const & word = *i; + + if (col + word.length() + 1 >= maxcol) { + out << std::endl; + col = 0; + while (col++ < colabstract - 1) + out << ' '; + } + + out << ' ' << word; + col += word.length() + 1; + } + out << std::endl; } static void explain_cmdgroups(ostream & out ) ============================================================ --- simplestring_xform.cc 4d9df66d29c1e2b1ec4ef1717b271de71fd3d941 +++ simplestring_xform.cc c365ced7930603fa9ac400b7d32eaf305ef31c3d @@ -104,7 +104,36 @@ split_into_lines(string const & in, split_into_lines(in, constants::default_encoding, out); } +void split_into_words(string const & in, + string const & encoding, + vector & out) +{ + string lc_encoding = lowercase(encoding); + out.clear(); + + string::size_type begin = 0; + string::size_type end = in.find_first_of(" ", begin); + + while (end != string::npos && end >= begin) + { + out.push_back(in.substr(begin, end-begin)); + begin = end + 1; + if (begin >= in.size()) + break; + end = in.find_first_of(" ", begin); + } + if (begin < in.size()) + out.push_back(in.substr(begin, in.size() - begin)); +} + void +split_into_words(string const & in, + vector & out) +{ + split_into_words(in, constants::default_encoding, out); +} + +void join_lines(vector const & in, string & out, string const & linesep) @@ -221,6 +250,26 @@ UNIT_TEST(simplestring_xform, join_lines BOOST_CHECK(joined == "hi\nthere\nuser\n"); } +UNIT_TEST(simplestring_xform, split_into_words) +{ + vector words; + + words.clear(); + split_into_words("", words); + BOOST_CHECK(words.size() == 0); + + words.clear(); + split_into_words("foo", words); + BOOST_CHECK(words.size() == 1); + BOOST_CHECK(words[0] == "foo"); + + words.clear(); + split_into_words("foo bar", words); + BOOST_CHECK(words.size() == 2); + BOOST_CHECK(words[0] == "foo"); + BOOST_CHECK(words[1] == "bar"); +} + UNIT_TEST(simplestring_xform, strip_ws) { BOOST_CHECK(trim_ws("\n leading space") == "leading space"); ============================================================ --- simplestring_xform.hh a3d2b3c5201493b1609578d624070636688c989e +++ simplestring_xform.hh e83fbfd81cd0bd0f6470abc818dc3b26a6a10156 @@ -14,6 +14,13 @@ void split_into_lines(std::string const std::string const & encoding, std::vector & out); +void split_into_words(std::string const & in, + std::vector & out); + +void split_into_words(std::string const & in, + std::string const & encoding, + std::vector & out); + void join_lines(std::vector const & in, std::string & out, std::string const & linesep);