aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormkishere <[email protected]>2018-03-28 23:43:57 +0800
committerEric Paris <[email protected]>2018-03-28 08:43:57 -0700
commitad68c28ee799163e627e77fcc6e8ecaa866e3535 (patch)
treedbe07a2cee11b82a9ed2f27dfb3b16a38810ef21
parent45e82a3a9c6b20fe3159b3dc2eb28d80a3b2ee67 (diff)
Add multiline wrapping support (#155)
* Add multiline wrapping support With reference to golang/go#20799, pflag now will respect newline in usage string and do wrap accordingly. Also add test cases for testing * Break at \n only if \n pos<wrap
-rw-r--r--flag.go15
-rw-r--r--printusage_test.go74
2 files changed, 83 insertions, 6 deletions
diff --git a/flag.go b/flag.go
index 28538c0..7f460b5 100644
--- a/flag.go
+++ b/flag.go
@@ -586,11 +586,14 @@ func wrapN(i, slop int, s string) (string, string) {
return s, ""
}
- w := strings.LastIndexAny(s[:i], " \t")
+ w := strings.LastIndexAny(s[:i], " \t\n")
if w <= 0 {
return s, ""
}
-
+ nlPos := strings.LastIndex(s[:i], "\n")
+ if nlPos > 0 && nlPos < w {
+ return s[:nlPos], s[nlPos+1:]
+ }
return s[:w], s[w+1:]
}
@@ -599,7 +602,7 @@ func wrapN(i, slop int, s string) (string, string) {
// caller). Pass `w` == 0 to do no wrapping
func wrap(i, w int, s string) string {
if w == 0 {
- return s
+ return strings.Replace(s, "\n", "\n"+strings.Repeat(" ", i), -1)
}
// space between indent i and end of line width w into which
@@ -617,7 +620,7 @@ func wrap(i, w int, s string) string {
}
// If still not enough space then don't even try to wrap.
if wrap < 24 {
- return s
+ return strings.Replace(s, "\n", r, -1)
}
// Try to avoid short orphan words on the final line, by
@@ -629,14 +632,14 @@ func wrap(i, w int, s string) string {
// Handle first line, which is indented by the caller (or the
// special case above)
l, s = wrapN(wrap, slop, s)
- r = r + l
+ r = r + strings.Replace(l, "\n", "\n"+strings.Repeat(" ", i), -1)
// Now wrap the rest
for s != "" {
var t string
t, s = wrapN(wrap, slop, s)
- r = r + "\n" + strings.Repeat(" ", i) + t
+ r = r + "\n" + strings.Repeat(" ", i) + strings.Replace(t, "\n", "\n"+strings.Repeat(" ", i), -1)
}
return r
diff --git a/printusage_test.go b/printusage_test.go
new file mode 100644
index 0000000..df982aa
--- /dev/null
+++ b/printusage_test.go
@@ -0,0 +1,74 @@
+package pflag
+
+import (
+ "bytes"
+ "io"
+ "testing"
+)
+
+const expectedOutput = ` --long-form Some description
+ --long-form2 Some description
+ with multiline
+ -s, --long-name Some description
+ -t, --long-name2 Some description with
+ multiline
+`
+
+func setUpPFlagSet(buf io.Writer) *FlagSet {
+ f := NewFlagSet("test", ExitOnError)
+ f.Bool("long-form", false, "Some description")
+ f.Bool("long-form2", false, "Some description\n with multiline")
+ f.BoolP("long-name", "s", false, "Some description")
+ f.BoolP("long-name2", "t", false, "Some description with\n multiline")
+ f.SetOutput(buf)
+ return f
+}
+
+func TestPrintUsage(t *testing.T) {
+ buf := bytes.Buffer{}
+ f := setUpPFlagSet(&buf)
+ f.PrintDefaults()
+ res := buf.String()
+ if res != expectedOutput {
+ t.Errorf("Expected \n%s \nActual \n%s", expectedOutput, res)
+ }
+}
+
+func setUpPFlagSet2(buf io.Writer) *FlagSet {
+ f := NewFlagSet("test", ExitOnError)
+ f.Bool("long-form", false, "Some description")
+ f.Bool("long-form2", false, "Some description\n with multiline")
+ f.BoolP("long-name", "s", false, "Some description")
+ f.BoolP("long-name2", "t", false, "Some description with\n multiline")
+ f.StringP("some-very-long-arg", "l", "test", "Some very long description having break the limit")
+ f.StringP("other-very-long-arg", "o", "long-default-value", "Some very long description having break the limit")
+ f.String("some-very-long-arg2", "very long default value", "Some very long description\nwith line break\nmultiple")
+ f.SetOutput(buf)
+ return f
+}
+
+const expectedOutput2 = ` --long-form Some description
+ --long-form2 Some description
+ with multiline
+ -s, --long-name Some description
+ -t, --long-name2 Some description with
+ multiline
+ -o, --other-very-long-arg string Some very long description having
+ break the limit (default
+ "long-default-value")
+ -l, --some-very-long-arg string Some very long description having
+ break the limit (default "test")
+ --some-very-long-arg2 string Some very long description
+ with line break
+ multiple (default "very long default
+ value")
+`
+
+func TestPrintUsage_2(t *testing.T) {
+ buf := bytes.Buffer{}
+ f := setUpPFlagSet2(&buf)
+ res := f.FlagUsagesWrapped(80)
+ if res != expectedOutput2 {
+ t.Errorf("Expected \n%q \nActual \n%q", expectedOutput2, res)
+ }
+}