diff options
| author | Eric Biggers <ebiggers@google.com> | 2019-11-27 11:55:28 -0800 |
|---|---|---|
| committer | Eric Biggers <ebiggers@google.com> | 2019-11-27 11:55:28 -0800 |
| commit | e7d77aba6d717f995e65c74b5b85412bb13a28b0 (patch) | |
| tree | 39cdf99f86f83471b3057aef6423dbac198ac27c | |
| parent | 03d3a29b70c85f083adf3c12cba60c0374f06d3e (diff) | |
cmd/fscrypt: preserve paragraphs in wrapText()
Preserve empty lines rather than squashing them into a single space.
This allows having command descriptions that contain multiple
paragraphs. This also eliminates the need to have a special case for
ordered lists.
| -rw-r--r-- | cmd/fscrypt/format.go | 59 |
1 files changed, 33 insertions, 26 deletions
diff --git a/cmd/fscrypt/format.go b/cmd/fscrypt/format.go index c2a4fce..48a5a86 100644 --- a/cmd/fscrypt/format.go +++ b/cmd/fscrypt/format.go @@ -25,7 +25,6 @@ import ( "bytes" "fmt" "os" - "regexp" "strings" "unicode/utf8" @@ -120,9 +119,6 @@ func longDisplay(f prettyFlag, defaultString ...string) string { return indent + shortDisp + indent + wrapText(usage, flagPaddingLength) } -// Regex that determines if we are starting an ordered list -var listRegex = regexp.MustCompile(`^\([\d]+\)$`) - // Takes an input string text, and wraps the text so that each line begins with // padding spaces (except for the first line), ends with a newline (except the // last line), and each line has length less than lineLength. If the text @@ -130,31 +126,42 @@ var listRegex = regexp.MustCompile(`^\([\d]+\)$`) func wrapText(text string, padding int) string { // We use a buffer to format the wrapped text so we get O(n) runtime var buffer bytes.Buffer - spaceLeft := 0 - maxTextLen := lineLength - padding + filled := 0 delimiter := strings.Repeat(" ", padding) - for i, word := range strings.Fields(text) { - wordLen := utf8.RuneCountInString(word) - switch { - case i == 0: - // No delimiter for the first line - buffer.WriteString(word) - spaceLeft = maxTextLen - wordLen - case listRegex.Match([]byte(word)): - // Add an additional line to separate list items. - buffer.WriteString("\n") - fallthrough - case wordLen+1 > spaceLeft: - // If no room left, write the word on the next line. + + for _, line := range strings.Split(text, "\n") { + words := strings.Fields(line) + + // Preserve empty lines (paragraph separators). + if len(words) == 0 { + if filled != 0 { + buffer.WriteString("\n") + } buffer.WriteString("\n") - buffer.WriteString(delimiter) - buffer.WriteString(word) - spaceLeft = maxTextLen - wordLen - default: - // Write word on this line - buffer.WriteByte(' ') + filled = 0 + continue + } + + for _, word := range words { + wordLen := utf8.RuneCountInString(word) + // Write a newline if needed. + if filled != 0 && filled+1+wordLen > lineLength { + buffer.WriteString("\n") + filled = 0 + } + // Write a delimiter or space if needed. + if filled == 0 { + if buffer.Len() != 0 { + buffer.WriteString(delimiter) + } + filled += padding + } else { + buffer.WriteByte(' ') + filled++ + } + // Write the word. buffer.WriteString(word) - spaceLeft -= 1 + wordLen + filled += wordLen } } |