Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 11, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions cli/configssh.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
17 changes: 10 additions & 7 deletions cli/dotfiles.go
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Use: "dotfiles [git_repo_url]",
Args: cobra.ExactArgs(1),
Short: "Check out and install a dotfiles repository.",
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"
Expand Down
10 changes: 7 additions & 3 deletions cli/parameters.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@ import (

func parameters() *cobra.Command {
cmd := &cobra.Command{
Short: "List parameters for a given scope",
Example: "coder parameters list workspace my-workspace",
Use: "parameters",
Short: "List parameters for a given scope",
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
// not to add confusion or lock ourselves into a certain api.
Expand Down
44 changes: 22 additions & 22 deletions cli/portforward.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
49 changes: 40 additions & 9 deletions cli/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -158,9 +162,8 @@ func Root() *cobra.Command {
// versionCmd prints the coder version
func versionCmd() *cobra.Command {
return &cobra.Command{
Use: "version",
Short: "Show coder version",
Example: "coder version",
Use: "version",
Short: "Show coder version",
RunE: func(cmd *cobra.Command, args []string) error {
var str strings.Builder
_, _ = str.WriteString(fmt.Sprintf("Coder %s", buildinfo.Version()))
Expand Down Expand Up @@ -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 {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neat way to do this. Much better than hoping the visual display is correct!

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())
Expand Down
66 changes: 66 additions & 0 deletions cli/root_internal_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
})
}
}
3 changes: 1 addition & 2 deletions cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down
33 changes: 23 additions & 10 deletions cli/schedule.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,15 @@ 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`,
Short: "Edit workspace start schedule",
Long: scheduleStartDescriptionLong,
Args: cobra.RangeArgs(2, 4),
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),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := createClient(cmd)
if err != nil {
Expand Down Expand Up @@ -151,9 +156,13 @@ func scheduleStop() *cobra.Command {
Annotations: workspaceCommand,
Args: cobra.ExactArgs(2),
Use: "stop <workspace-name> { <duration> | manual }",
Example: `stop my-workspace 2h30m`,
Short: "Edit workspace stop schedule",
Long: scheduleStopDescriptionLong,
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 {
client, err := createClient(cmd)
if err != nil {
Expand Down Expand Up @@ -194,9 +203,13 @@ func scheduleOverride() *cobra.Command {
Args: cobra.ExactArgs(2),
Annotations: workspaceCommand,
Use: "override-stop <workspace-name> <duration from now>",
Example: "override-stop my-workspace 90m",
Short: "Edit stop time of active workspace",
Long: scheduleOverrideDescriptionLong,
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 {
overrideDuration, err := parseDuration(args[1])
if err != nil {
Expand Down
26 changes: 14 additions & 12 deletions cli/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
20 changes: 10 additions & 10 deletions cli/userlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,7 @@ import (
)

func userList() *cobra.Command {
var (
columns []string
)
var columns []string
cmd := &cobra.Command{
Use: "list",
Aliases: []string{"ls"},
Expand All @@ -35,14 +33,16 @@ 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",
Args: cobra.ExactArgs(1),
Use: "show <username|user_id|'me'>",
Short: "Show a single user. Use 'me' to indicate the currently authenticated user.",
Example: formatExamples(
example{
Command: "coder users show me",
},
),
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
client, err := createClient(cmd)
if err != nil {
Expand Down
Loading