aboutsummaryrefslogtreecommitdiff
path: root/cmd/fscrypt/format.go
diff options
context:
space:
mode:
Diffstat (limited to 'cmd/fscrypt/format.go')
-rw-r--r--cmd/fscrypt/format.go98
1 files changed, 57 insertions, 41 deletions
diff --git a/cmd/fscrypt/format.go b/cmd/fscrypt/format.go
index ef009d3..21253ad 100644
--- a/cmd/fscrypt/format.go
+++ b/cmd/fscrypt/format.go
@@ -25,12 +25,11 @@ import (
"bytes"
"fmt"
"os"
- "regexp"
"strings"
"unicode/utf8"
"github.com/urfave/cli"
- "golang.org/x/crypto/ssh/terminal"
+ "golang.org/x/term"
"github.com/google/fscrypt/util"
)
@@ -65,8 +64,8 @@ func init() {
flagPaddingLength = maxShortDisplay + 2*indentLength
// We use the width of the terminal unless we cannot get the width.
- width, _, err := terminal.GetSize(int(os.Stdout.Fd()))
- if err != nil {
+ width, _, err := term.GetSize(int(os.Stdout.Fd()))
+ if err != nil || width <= 0 {
lineLength = fallbackLineLength
} else {
lineLength = util.MinInt(width, maxLineLength)
@@ -74,7 +73,7 @@ func init() {
}
-// Flags that conform to this interface can be used with an urfave/cli
+// Flags that conform to this interface can be used with a urfave/cli
// application and can be printed in the correct format.
type prettyFlag interface {
cli.Flag
@@ -83,8 +82,10 @@ type prettyFlag interface {
}
// How a flag should appear on the command line. We have two formats:
-// --name
-// --name=ARG_NAME
+//
+// --name
+// --name=ARG_NAME
+//
// The ARG_NAME appears if the prettyFlag's GetArgName() method returns a
// non-empty string. The returned string from shortDisplay() does not include
// any leading or trailing whitespace.
@@ -97,22 +98,20 @@ func shortDisplay(f prettyFlag) string {
// How our flags should appear when displaying their usage. An example would be:
//
-// --help Prints help screen for commands and subcommands.
-//
-// If a default is specified, this if appended to the usage. Example:
+// --help Prints help screen for commands and subcommands.
//
-// --legacy Allow for support of older kernels with ext4
-// (before v4.8) and F2FS (before v4.6) filesystems.
-// (default: true)
+// If a default is specified, then it is appended to the usage. Example:
//
+// --time=TIME Calibrate passphrase hashing to take the
+// specified amount of TIME (default: 1s)
func longDisplay(f prettyFlag, defaultString ...string) string {
usage := f.GetUsage()
if len(defaultString) > 0 {
usage += fmt.Sprintf(" (default: %v)", defaultString[0])
}
- // We pad the the shortDisplay on the right with enough spaces to equal
- // the longest flag's display
+ // We pad the shortDisplay on the right with enough spaces to equal the
+ // longest flag's display
shortDisp := shortDisplay(f)
length := utf8.RuneCountInString(shortDisp)
shortDisp += strings.Repeat(" ", maxShortDisplay-length)
@@ -120,41 +119,58 @@ 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
-// contains a word which is too long, that word gets its own line.
+// contains a word which is too long, that word gets its own line. Paragraphs
+// and "code blocks" are preserved.
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
+ }
+
+ codeBlock := (words[0] == ">")
+ if codeBlock {
+ words[0] = " "
+ if filled != 0 {
+ buffer.WriteString("\n")
+ filled = 0
+ }
+ }
+ for _, word := range words {
+ wordLen := utf8.RuneCountInString(word)
+ // Write a newline if needed.
+ if filled != 0 && filled+1+wordLen > lineLength && !codeBlock {
+ 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
}
}