mirror of
https://github.com/coder/coder.git
synced 2025-07-09 11:45:56 +00:00
fix: Standardize and wrap example descriptions at 80 chars (#2894)
This commit is contained in:
committed by
GitHub
parent
50e8a27d04
commit
749694b7de
@ -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 {
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
45
cli/root.go
45
cli/root.go
@ -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
66
cli/root_internal_test.go
Normal 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)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -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"
|
||||
)
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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)
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
Reference in New Issue
Block a user