fix: Standardize and wrap example descriptions at 80 chars (#2894)

This commit is contained in:
Mathias Fredriksson
2022-07-11 19:08:09 +03:00
committed by GitHub
parent 50e8a27d04
commit 749694b7de
12 changed files with 223 additions and 103 deletions

View File

@ -141,15 +141,16 @@ func configSSH() *cobra.Command {
Annotations: workspaceCommand,
Use: "config-ssh",
Short: "Populate your SSH config with Host entries for all of your workspaces",
Example: `
- You can use -o (or --ssh-option) so set SSH options to be used for all your
workspaces.
` + cliui.Styles.Code.Render("$ coder config-ssh -o ForwardAgent=yes") + `
- You can use --dry-run (or -n) to see the changes that would be made.
` + cliui.Styles.Code.Render("$ coder config-ssh --dry-run"),
Example: formatExamples(
example{
Description: "You can use -o (or --ssh-option) so set SSH options to be used for all your workspaces",
Command: "coder config-ssh -o ForwardAgent=yes",
},
example{
Description: "You can use --dry-run (or -n) to see the changes that would be made",
Command: "coder config-ssh --dry-run",
},
),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := createClient(cmd)
if err != nil {

View File

@ -18,14 +18,17 @@ import (
)
func dotfiles() *cobra.Command {
var (
symlinkDir string
)
var symlinkDir string
cmd := &cobra.Command{
Use: "dotfiles [git_repo_url]",
Args: cobra.ExactArgs(1),
Short: "Check out and install a dotfiles repository.",
Example: "coder dotfiles [-y] git@github.com:example/dotfiles.git",
Example: formatExamples(
example{
Description: "Check out and install a dotfiles repository without prompts",
Command: "coder dotfiles --yes git@github.com:example/dotfiles.git",
},
),
RunE: func(cmd *cobra.Command, args []string) error {
var (
dotfilesRepoDir = "dotfiles"

View File

@ -11,7 +11,11 @@ import (
func parameters() *cobra.Command {
cmd := &cobra.Command{
Short: "List parameters for a given scope",
Example: "coder parameters list workspace my-workspace",
Example: formatExamples(
example{
Command: "coder parameters list workspace my-workspace",
},
),
Use: "parameters",
// Currently hidden as this shows parameter values, not parameter
// schemes. Until we have a good way to distinguish the two, it's better

View File

@ -32,28 +32,28 @@ func portForward() *cobra.Command {
Short: "Forward one or more ports from the local machine to the remote workspace",
Aliases: []string{"tunnel"},
Args: cobra.ExactArgs(1),
Example: `
- Port forward a single TCP port from 1234 in the workspace to port 5678 on
your local machine
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 5678:1234") + `
- Port forward a single UDP port from port 9000 to port 9000 on your local
machine
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --udp 9000") + `
- Forward a Unix socket in the workspace to a local Unix socket
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --unix ./local.sock:~/remote.sock") + `
- Forward a Unix socket in the workspace to a local TCP port
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --unix 8080:~/remote.sock") + `
- Port forward multiple TCP ports and a UDP port
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53"),
Example: formatExamples(
example{
Description: "Port forward a single TCP port from 1234 in the workspace to port 5678 on your local machine",
Command: "coder port-forward <workspace> --tcp 5678:1234",
},
example{
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
Command: "coder port-forward <workspace> --udp 9000",
},
example{
Description: "Forward a Unix socket in the workspace to a local Unix socket",
Command: "coder port-forward <workspace> --unix ./local.sock:~/remote.sock",
},
example{
Description: "Forward a Unix socket in the workspace to a local TCP port",
Command: "coder port-forward <workspace> --unix 8080:~/remote.sock",
},
example{
Description: "Port forward multiple TCP ports and a UDP port",
Command: "coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
},
),
RunE: func(cmd *cobra.Command, args []string) error {
specs, err := parsePortForwards(tcpForwards, udpForwards, unixForwards)
if err != nil {

View File

@ -101,12 +101,16 @@ func Root() *cobra.Command {
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
}
},
Example: ` Start a Coder server.
` + cliui.Styles.Code.Render("$ coder server") + `
Get started by creating a template from an example.
` + cliui.Styles.Code.Render("$ coder templates init"),
Example: formatExamples(
example{
Description: "Start a Coder server",
Command: "coder server",
},
example{
Description: "Get started by creating a template from an example",
Command: "coder templates init",
},
),
}
cmd.AddCommand(
@ -160,7 +164,6 @@ func versionCmd() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Show coder version",
Example: "coder version",
RunE: func(cmd *cobra.Command, args []string) error {
var str strings.Builder
_, _ = str.WriteString(fmt.Sprintf("Coder %s", buildinfo.Version()))
@ -370,6 +373,34 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.
{{end}}`
}
// example represents a standard example for command usage, to be used
// with formatExamples.
type example struct {
Description string
Command string
}
// formatExamples formats the exampels as width wrapped bulletpoint
// descriptions with the command underneath.
func formatExamples(examples ...example) string {
wrap := cliui.Styles.Wrap.Copy()
wrap.PaddingLeft(4)
var sb strings.Builder
for i, e := range examples {
if len(e.Description) > 0 {
_, _ = sb.WriteString(" - " + wrap.Render(e.Description + ":")[4:] + "\n\n ")
}
// We add 1 space here because `cliui.Styles.Code` adds an extra
// space. This makes the code block align at an even 2 or 6
// spaces for symmetry.
_, _ = sb.WriteString(" " + cliui.Styles.Code.Render(fmt.Sprintf("$ %s", e.Command)))
if i < len(examples)-1 {
_, _ = sb.WriteString("\n\n")
}
}
return sb.String()
}
// FormatCobraError colorizes and adds "--help" docs to cobra commands.
func FormatCobraError(err error, cmd *cobra.Command) string {
helpErrMsg := fmt.Sprintf("Run '%s --help' for usage.", cmd.CommandPath())

66
cli/root_internal_test.go Normal file
View File

@ -0,0 +1,66 @@
package cli
import (
"testing"
"github.com/stretchr/testify/require"
)
func Test_formatExamples(t *testing.T) {
t.Parallel()
tests := []struct {
name string
examples []example
wantMatches []string
}{
{
name: "No examples",
examples: nil,
wantMatches: nil,
},
{
name: "Output examples",
examples: []example{
{
Description: "Hello world",
Command: "echo hello",
},
{
Description: "Bye bye",
Command: "echo bye",
},
},
wantMatches: []string{
"Hello world", "echo hello",
"Bye bye", "echo bye",
},
},
{
name: "No description outputs commands",
examples: []example{
{
Command: "echo hello",
},
},
wantMatches: []string{
"echo hello",
},
},
}
for _, tt := range tests {
tt := tt
t.Run(tt.name, func(t *testing.T) {
t.Parallel()
got := formatExamples(tt.examples...)
if len(tt.wantMatches) == 0 {
require.Empty(t, got)
} else {
for _, want := range tt.wantMatches {
require.Contains(t, got, want)
}
}
})
}
}

View File

@ -4,10 +4,9 @@ import (
"bytes"
"testing"
"github.com/coder/coder/buildinfo"
"github.com/stretchr/testify/require"
"github.com/coder/coder/buildinfo"
"github.com/coder/coder/cli"
"github.com/coder/coder/cli/clitest"
)

View File

@ -103,7 +103,12 @@ func scheduleStart() *cobra.Command {
cmd := &cobra.Command{
Annotations: workspaceCommand,
Use: "start <workspace-name> { <start-time> [day-of-week] [location] | manual }",
Example: `start my-workspace 9:30AM Mon-Fri Europe/Dublin`,
Example: formatExamples(
example{
Description: "Set the workspace to start at 9:30am (in Dublin) from Monday to Friday",
Command: "coder schedule start my-workspace 9:30AM Mon-Fri Europe/Dublin",
},
),
Short: "Edit workspace start schedule",
Long: scheduleStartDescriptionLong,
Args: cobra.RangeArgs(2, 4),
@ -151,7 +156,11 @@ func scheduleStop() *cobra.Command {
Annotations: workspaceCommand,
Args: cobra.ExactArgs(2),
Use: "stop <workspace-name> { <duration> | manual }",
Example: `stop my-workspace 2h30m`,
Example: formatExamples(
example{
Command: "coder schedule stop my-workspace 2h30m",
},
),
Short: "Edit workspace stop schedule",
Long: scheduleStopDescriptionLong,
RunE: func(cmd *cobra.Command, args []string) error {
@ -194,7 +203,11 @@ func scheduleOverride() *cobra.Command {
Args: cobra.ExactArgs(2),
Annotations: workspaceCommand,
Use: "override-stop <workspace-name> <duration from now>",
Example: "override-stop my-workspace 90m",
Example: formatExamples(
example{
Command: "coder schedule override-stop my-workspace 90m",
},
),
Short: "Edit stop time of active workspace",
Long: scheduleOverrideDescriptionLong,
RunE: func(cmd *cobra.Command, args []string) error {

View File

@ -16,18 +16,20 @@ func templates() *cobra.Command {
Use: "templates",
Short: "Create, manage, and deploy templates",
Aliases: []string{"template"},
Example: `
- Create a template for developers to create workspaces
` + cliui.Styles.Code.Render("$ coder templates create") + `
- Make changes to your template, and plan the changes
` + cliui.Styles.Code.Render("$ coder templates plan <name>") + `
- Update the template. Your developers can update their workspaces
` + cliui.Styles.Code.Render("$ coder templates update <name>"),
Example: formatExamples(
example{
Description: "Create a template for developers to create workspaces",
Command: "coder templates create",
},
example{
Description: "Make changes to your template, and plan the changes",
Command: "coder templates plan my-template",
},
example{
Description: "Update the template. Your developers can update their workspaces",
Command: "coder templates update my-template",
},
),
}
cmd.AddCommand(
templateCreate(),

View File

@ -9,9 +9,7 @@ import (
)
func userList() *cobra.Command {
var (
columns []string
)
var columns []string
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
@ -35,13 +33,15 @@ func userList() *cobra.Command {
}
func userSingle() *cobra.Command {
var (
columns []string
)
var columns []string
cmd := &cobra.Command{
Use: "show <username|user_id|'me'>",
Short: "Show a single user. Use 'me' to indicate the currently authenticated user.",
Example: "coder users show me",
Example: formatExamples(
example{
Command: "coder users show me",
},
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := createClient(cmd)

View File

@ -31,15 +31,17 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command {
panic(fmt.Sprintf("%s is not supported", sdkStatus))
}
var (
columns []string
)
var columns []string
cmd := &cobra.Command{
Use: fmt.Sprintf("%s <username|user_id>", verb),
Short: short,
Args: cobra.ExactArgs(1),
Aliases: aliases,
Example: fmt.Sprintf("coder users %s example_user", verb),
Example: formatExamples(
example{
Command: fmt.Sprintf("coder users %s example_user", verb),
},
),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := createClient(cmd)
if err != nil {

View File

@ -37,21 +37,20 @@ func wireguardPortForward() *cobra.Command {
Args: cobra.ExactArgs(1),
// Hide all wireguard commands for now while we test!
Hidden: true,
Example: `
- Port forward a single TCP port from 1234 in the workspace to port 5678 on
your local machine
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 5678:1234") + `
- Port forward a single UDP port from port 9000 to port 9000 on your local
machine
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --udp 9000") + `
- Port forward multiple TCP ports and a UDP port
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53") + `
`,
Example: formatExamples(
example{
Description: "Port forward a single TCP port from 1234 in the workspace to port 5678 on your local machine",
Command: "coder wireguard-port-forward <workspace> --tcp 5678:1234",
},
example{
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
Command: "coder wireguard-port-forward <workspace> --udp 9000",
},
example{
Description: "Port forward multiple TCP ports and a UDP port",
Command: "coder wireguard-port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
},
),
RunE: func(cmd *cobra.Command, args []string) error {
specs, err := parsePortForwards(tcpForwards, nil, nil)
if err != nil {