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