Skip to content

Commit

Permalink
Align example lines with rest of usage output
Browse files Browse the repository at this point in the history
Now that multi-line Example values do not need explicit indent to have
them shown left-aligned in usage, update usage to ensure there is at
least a designated amount of indent for each non-empty line, so as to
match up with the rest of the usage sections.

Also correct for some specific situations where the explicit indent of
subsequent lines is still present in the Example value by making the
output for such value left aligned as well.

Signed-off-by: Vui Lam <[email protected]>
  • Loading branch information
vuil committed May 7, 2024
1 parent 4ee5878 commit 4ee88d1
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 14 deletions.
52 changes: 47 additions & 5 deletions plugin/usage.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,52 @@ func aliasesWithMappedName(cmd *cobra.Command) string {
return strings.Join(append([]string{cmdName}, cmd.Aliases...), ", ")
}

// ensure that the example string is left indented by the designated amount
func alignExampleForUsage(exampleString string) string {
var result string

// always indent single line by designated amount
if !strings.Contains(strings.TrimSpace(exampleString), "\n") {
result = indentStr + strings.TrimLeft(exampleString, " ")
return result
}

var hasUnexpectedIndent bool
lines := strings.Split(exampleString, "\n")
numLines := len(lines)

for i := 1; i < numLines; i++ {
if lines[i] == "" {
continue
}
if strings.HasPrefix(lines[i], indentStr) && !strings.HasPrefix(lines[i], indentStr+" ") {
continue
}
hasUnexpectedIndent = true
break
}

if !hasUnexpectedIndent {
// A special case identified where all or all-but-first lines are
// indented exactly by 2 spaces. Opinionatedly, we treat this as
// attempts to address past indentation quirks, and hence will ensure
// all lines are uniformly indented instead.
result = indentStr + strings.TrimLeft(exampleString, " ")
} else {
// Otherwise we just indent all non-empty lines (include lines with
// leading spaces) by the same extra amount.
for _, l := range lines {
if l != "" {
l = indentStr + l
}
result = result + l + "\n"
}
result = strings.TrimSuffix(result, "\n")
}

return result
}

func printHelp(cmd *cobra.Command) string {
var output strings.Builder
target := types.StringToTarget(cmd.Annotations["target"])
Expand All @@ -289,11 +335,7 @@ func printHelp(cmd *cobra.Command) string {

if cmd.HasExample() {
output.WriteString("\n" + component.Bold(examplesStr) + "\n")

// matches cobra default help template's behavior of not indenting the
// Example value, which has the added benefit of ensuring multiline
// .Example values are aligned
output.WriteString(cmd.Example + "\n")
output.WriteString(alignExampleForUsage(cmd.Example) + "\n")
}

if cmd.HasAvailableSubCommands() {
Expand Down
129 changes: 120 additions & 9 deletions plugin/usage_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ Aliases:
test, t
Examples:
sample example usage of the test command
sample example usage of the test command
Available Commands:
fetch Fetch the plugin tests
Expand Down Expand Up @@ -240,7 +240,7 @@ Aliases:
test, t
Examples:
sample example usage of the test command
sample example usage of the test command
Available Commands:
fetch Fetch the plugin tests
Expand Down Expand Up @@ -301,7 +301,7 @@ Aliases:
test, t
Examples:
sample example usage of the test command
sample example usage of the test command
Available Commands:
fetch Fetch the plugin tests
Expand Down Expand Up @@ -357,7 +357,7 @@ Usage:
tanzu test fetch [flags]
Examples:
sample example usage of the fetch command
sample example usage of the fetch command
Flags:
-h, --help help for fetch
Expand Down Expand Up @@ -415,7 +415,7 @@ Usage:
tanzu fetch [flags]
Examples:
sample example usage of the fetch command
sample example usage of the fetch command
Flags:
-h, --help help for fetch
Expand Down Expand Up @@ -469,7 +469,7 @@ Usage:
tanzu kubernetes test fetch [flags]
Examples:
sample example usage of the fetch command
sample example usage of the fetch command
Flags:
-h, --help help for fetch
Expand Down Expand Up @@ -521,7 +521,7 @@ Usage:
tanzu mission-control test fetch [flags]
Examples:
sample example usage of the fetch command
sample example usage of the fetch command
Flags:
-h, --help help for fetch
Expand Down Expand Up @@ -584,8 +584,8 @@ Aliases:
pu, psh
Examples:
sample example usage of the push command
more sample example usage of the push command
sample example usage of the push command
more sample example usage of the push command
Available Commands:
more Push more
Expand Down Expand Up @@ -658,3 +658,114 @@ Global Flags:

assert.Equal(t, expected, got)
}

func TestExampleIndent(t *testing.T) {
tests := []struct {
test string
input string
// add leading newline to align expected output for improved readability
expectedOutputWithLeadingNewline string
}{
{
test: "single line - no indent",
input: "first line",
expectedOutputWithLeadingNewline: `
first line`,
},
{
test: "single line - with indent",
input: " first line",
expectedOutputWithLeadingNewline: `
first line`,
},
{
test: "single line - with irregular indent",
input: " first line",
expectedOutputWithLeadingNewline: `
first line`,
},
{
test: "single line - with newline",
input: "first line\n",
expectedOutputWithLeadingNewline: `
first line
`,
},
{
test: "single line - with newlines",
input: "first line\n\n\n",
expectedOutputWithLeadingNewline: `
first line
`,
},
{
test: "multi line - no pre-indents",
input: "first line\nsecond line\nthird line",
expectedOutputWithLeadingNewline: `
first line
second line
third line`,
},
{
test: "multi line - with pre-indents of all lines",
input: " first line\n second line\n third line",
expectedOutputWithLeadingNewline: `
first line
second line
third line`,
},
{
test: "multi line - with pre-indents of subsequent lines and newlines",
input: "first line\n\n second line\n third line\n\n\n",
expectedOutputWithLeadingNewline: `
first line
second line
third line
`,
},

// when example lines have unrecognized indentation amounts
// no special handling other than shift all lines by same indent
{
test: "multi line - lines having unexpected indent amounts - a",
input: "first line\n second line\n third line",
expectedOutputWithLeadingNewline: `
first line
second line
third line`,
},
{
test: "multi line - lines having unexpected indent amounts - b",
input: "first line\n para one\n next\n more indent\n another",
expectedOutputWithLeadingNewline: `
first line
para one
next
more indent
another`,
},
{
test: "multi line - lines having unexpected indent amounts and newlines",
input: "first line\n\n second line\n third line\n\n",
expectedOutputWithLeadingNewline: `
first line
second line
third line
`,
},
}
for _, spec := range tests {
t.Run(spec.test, func(t *testing.T) {
assert := assert.New(t)
result := alignExampleForUsage(spec.input)
assert.Equal(spec.expectedOutputWithLeadingNewline, "\n"+result)
})
}
}

0 comments on commit 4ee88d1

Please sign in to comment.