wrap.cpp 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include "wrap.h"
  2. #include <library/cpp/colorizer/colors.h>
  3. #include <util/generic/string.h>
  4. #include <util/stream/str.h>
  5. #include <util/charset/utf8.h>
  6. #include <cctype>
  7. namespace NLastGetopt {
  8. TString Wrap(ui32 width, TStringBuf text, TStringBuf indent, size_t* lastLineLen, bool* hasParagraphs) {
  9. if (width == 0) {
  10. return TString(text);
  11. }
  12. if (width >= indent.size()) {
  13. width -= indent.size();
  14. }
  15. if (hasParagraphs) {
  16. *hasParagraphs = false;
  17. }
  18. TString res;
  19. auto os = TStringOutput(res);
  20. const char* spaceBegin = text.begin();
  21. const char* wordBegin = text.begin();
  22. const char* wordEnd = text.begin();
  23. const char* end = text.end();
  24. size_t lenSoFar = 0;
  25. bool isPreParagraph = false;
  26. do {
  27. spaceBegin = wordBegin = wordEnd;
  28. while (wordBegin < end && *wordBegin == ' ') {
  29. wordBegin++;
  30. }
  31. if (wordBegin == end) {
  32. break;
  33. }
  34. wordEnd = wordBegin;
  35. while (wordEnd < end && *wordEnd != ' ' && *wordEnd != '\n') {
  36. wordEnd++;
  37. }
  38. auto spaces = TStringBuf(spaceBegin, wordBegin);
  39. auto word = TStringBuf(wordBegin, wordEnd);
  40. size_t spaceLen = spaces.size();
  41. size_t wordLen = 0;
  42. if (!GetNumberOfUTF8Chars(word.data(), word.size(), wordLen)) {
  43. wordLen = word.size(); // not a utf8 string -- just use its binary size
  44. }
  45. wordLen -= NColorizer::TotalAnsiEscapeCodeLen(word);
  46. // Empty word means we've found a bunch of whitespaces followed by newline.
  47. // We don't want to print trailing whitespaces.
  48. if (word) {
  49. // We can't fit this word into the line -- insert additional line break.
  50. // We shouldn't insert line breaks if we're at the beginning of a line, hence `lenSoFar` check.
  51. if (lenSoFar && lenSoFar + spaceLen + wordLen > width) {
  52. os << Endl << indent << word;
  53. lenSoFar = wordLen;
  54. } else {
  55. os << spaces << word;
  56. lenSoFar += spaceLen + wordLen;
  57. }
  58. isPreParagraph = false;
  59. }
  60. if (wordEnd != end && *wordEnd == '\n') {
  61. os << Endl << indent;
  62. lenSoFar = 0;
  63. wordEnd++;
  64. if (hasParagraphs && isPreParagraph) {
  65. *hasParagraphs = true;
  66. } else {
  67. isPreParagraph = true;
  68. }
  69. continue;
  70. }
  71. } while (wordEnd < end);
  72. if (lastLineLen) {
  73. *lastLineLen = lenSoFar;
  74. }
  75. return res;
  76. }
  77. }