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,
|
Annotations: workspaceCommand,
|
||||||
Use: "config-ssh",
|
Use: "config-ssh",
|
||||||
Short: "Populate your SSH config with Host entries for all of your workspaces",
|
Short: "Populate your SSH config with Host entries for all of your workspaces",
|
||||||
Example: `
|
Example: formatExamples(
|
||||||
- You can use -o (or --ssh-option) so set SSH options to be used for all your
|
example{
|
||||||
workspaces.
|
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",
|
||||||
` + cliui.Styles.Code.Render("$ coder config-ssh -o ForwardAgent=yes") + `
|
},
|
||||||
|
example{
|
||||||
- You can use --dry-run (or -n) to see the changes that would be made.
|
Description: "You can use --dry-run (or -n) to see the changes that would be made",
|
||||||
|
Command: "coder config-ssh --dry-run",
|
||||||
` + cliui.Styles.Code.Render("$ coder config-ssh --dry-run"),
|
},
|
||||||
|
),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
client, err := createClient(cmd)
|
client, err := createClient(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -18,14 +18,17 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func dotfiles() *cobra.Command {
|
func dotfiles() *cobra.Command {
|
||||||
var (
|
var symlinkDir string
|
||||||
symlinkDir string
|
|
||||||
)
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "dotfiles [git_repo_url]",
|
Use: "dotfiles [git_repo_url]",
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Short: "Check out and install a dotfiles repository.",
|
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 {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
var (
|
var (
|
||||||
dotfilesRepoDir = "dotfiles"
|
dotfilesRepoDir = "dotfiles"
|
||||||
|
@ -11,7 +11,11 @@ import (
|
|||||||
func parameters() *cobra.Command {
|
func parameters() *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Short: "List parameters for a given scope",
|
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",
|
Use: "parameters",
|
||||||
// Currently hidden as this shows parameter values, not parameter
|
// Currently hidden as this shows parameter values, not parameter
|
||||||
// schemes. Until we have a good way to distinguish the two, it's better
|
// 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",
|
Short: "Forward one or more ports from the local machine to the remote workspace",
|
||||||
Aliases: []string{"tunnel"},
|
Aliases: []string{"tunnel"},
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Example: `
|
Example: formatExamples(
|
||||||
- Port forward a single TCP port from 1234 in the workspace to port 5678 on
|
example{
|
||||||
your local machine
|
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",
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 5678:1234") + `
|
},
|
||||||
|
example{
|
||||||
- Port forward a single UDP port from port 9000 to port 9000 on your local
|
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
|
||||||
machine
|
Command: "coder port-forward <workspace> --udp 9000",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --udp 9000") + `
|
example{
|
||||||
|
Description: "Forward a Unix socket in the workspace to a local Unix socket",
|
||||||
- Forward a Unix socket in the workspace to a local Unix socket
|
Command: "coder port-forward <workspace> --unix ./local.sock:~/remote.sock",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --unix ./local.sock:~/remote.sock") + `
|
example{
|
||||||
|
Description: "Forward a Unix socket in the workspace to a local TCP port",
|
||||||
- Forward a Unix socket in the workspace to a local TCP port
|
Command: "coder port-forward <workspace> --unix 8080:~/remote.sock",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --unix 8080:~/remote.sock") + `
|
example{
|
||||||
|
Description: "Port forward multiple TCP ports and a UDP port",
|
||||||
- Port forward multiple TCP ports and a UDP port
|
Command: "coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53"),
|
),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
specs, err := parsePortForwards(tcpForwards, udpForwards, unixForwards)
|
specs, err := parsePortForwards(tcpForwards, udpForwards, unixForwards)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
45
cli/root.go
45
cli/root.go
@ -101,12 +101,16 @@ func Root() *cobra.Command {
|
|||||||
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
|
_, _ = fmt.Fprintln(cmd.ErrOrStderr())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
Example: formatExamples(
|
||||||
Example: ` Start a Coder server.
|
example{
|
||||||
` + cliui.Styles.Code.Render("$ coder server") + `
|
Description: "Start a Coder server",
|
||||||
|
Command: "coder server",
|
||||||
Get started by creating a template from an example.
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder templates init"),
|
example{
|
||||||
|
Description: "Get started by creating a template from an example",
|
||||||
|
Command: "coder templates init",
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
@ -160,7 +164,6 @@ func versionCmd() *cobra.Command {
|
|||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Show coder version",
|
Short: "Show coder version",
|
||||||
Example: "coder version",
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
var str strings.Builder
|
var str strings.Builder
|
||||||
_, _ = str.WriteString(fmt.Sprintf("Coder %s", buildinfo.Version()))
|
_, _ = str.WriteString(fmt.Sprintf("Coder %s", buildinfo.Version()))
|
||||||
@ -370,6 +373,34 @@ Use "{{.CommandPath}} [command] --help" for more information about a command.
|
|||||||
{{end}}`
|
{{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.
|
// FormatCobraError colorizes and adds "--help" docs to cobra commands.
|
||||||
func FormatCobraError(err error, cmd *cobra.Command) string {
|
func FormatCobraError(err error, cmd *cobra.Command) string {
|
||||||
helpErrMsg := fmt.Sprintf("Run '%s --help' for usage.", cmd.CommandPath())
|
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"
|
"bytes"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coder/coder/buildinfo"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"github.com/coder/coder/buildinfo"
|
||||||
"github.com/coder/coder/cli"
|
"github.com/coder/coder/cli"
|
||||||
"github.com/coder/coder/cli/clitest"
|
"github.com/coder/coder/cli/clitest"
|
||||||
)
|
)
|
||||||
|
@ -103,7 +103,12 @@ func scheduleStart() *cobra.Command {
|
|||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Annotations: workspaceCommand,
|
Annotations: workspaceCommand,
|
||||||
Use: "start <workspace-name> { <start-time> [day-of-week] [location] | manual }",
|
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",
|
Short: "Edit workspace start schedule",
|
||||||
Long: scheduleStartDescriptionLong,
|
Long: scheduleStartDescriptionLong,
|
||||||
Args: cobra.RangeArgs(2, 4),
|
Args: cobra.RangeArgs(2, 4),
|
||||||
@ -151,7 +156,11 @@ func scheduleStop() *cobra.Command {
|
|||||||
Annotations: workspaceCommand,
|
Annotations: workspaceCommand,
|
||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
Use: "stop <workspace-name> { <duration> | manual }",
|
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",
|
Short: "Edit workspace stop schedule",
|
||||||
Long: scheduleStopDescriptionLong,
|
Long: scheduleStopDescriptionLong,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@ -194,7 +203,11 @@ func scheduleOverride() *cobra.Command {
|
|||||||
Args: cobra.ExactArgs(2),
|
Args: cobra.ExactArgs(2),
|
||||||
Annotations: workspaceCommand,
|
Annotations: workspaceCommand,
|
||||||
Use: "override-stop <workspace-name> <duration from now>",
|
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",
|
Short: "Edit stop time of active workspace",
|
||||||
Long: scheduleOverrideDescriptionLong,
|
Long: scheduleOverrideDescriptionLong,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
@ -16,18 +16,20 @@ func templates() *cobra.Command {
|
|||||||
Use: "templates",
|
Use: "templates",
|
||||||
Short: "Create, manage, and deploy templates",
|
Short: "Create, manage, and deploy templates",
|
||||||
Aliases: []string{"template"},
|
Aliases: []string{"template"},
|
||||||
Example: `
|
Example: formatExamples(
|
||||||
- Create a template for developers to create workspaces
|
example{
|
||||||
|
Description: "Create a template for developers to create workspaces",
|
||||||
` + cliui.Styles.Code.Render("$ coder templates create") + `
|
Command: "coder templates create",
|
||||||
|
},
|
||||||
- Make changes to your template, and plan the changes
|
example{
|
||||||
|
Description: "Make changes to your template, and plan the changes",
|
||||||
` + cliui.Styles.Code.Render("$ coder templates plan <name>") + `
|
Command: "coder templates plan my-template",
|
||||||
|
},
|
||||||
- Update the template. Your developers can update their workspaces
|
example{
|
||||||
|
Description: "Update the template. Your developers can update their workspaces",
|
||||||
` + cliui.Styles.Code.Render("$ coder templates update <name>"),
|
Command: "coder templates update my-template",
|
||||||
|
},
|
||||||
|
),
|
||||||
}
|
}
|
||||||
cmd.AddCommand(
|
cmd.AddCommand(
|
||||||
templateCreate(),
|
templateCreate(),
|
||||||
|
@ -9,9 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func userList() *cobra.Command {
|
func userList() *cobra.Command {
|
||||||
var (
|
var columns []string
|
||||||
columns []string
|
|
||||||
)
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Aliases: []string{"ls"},
|
Aliases: []string{"ls"},
|
||||||
@ -35,13 +33,15 @@ func userList() *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func userSingle() *cobra.Command {
|
func userSingle() *cobra.Command {
|
||||||
var (
|
var columns []string
|
||||||
columns []string
|
|
||||||
)
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "show <username|user_id|'me'>",
|
Use: "show <username|user_id|'me'>",
|
||||||
Short: "Show a single user. Use 'me' to indicate the currently authenticated user.",
|
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),
|
Args: cobra.ExactArgs(1),
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
client, err := createClient(cmd)
|
client, err := createClient(cmd)
|
||||||
|
@ -31,15 +31,17 @@ func createUserStatusCommand(sdkStatus codersdk.UserStatus) *cobra.Command {
|
|||||||
panic(fmt.Sprintf("%s is not supported", sdkStatus))
|
panic(fmt.Sprintf("%s is not supported", sdkStatus))
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var columns []string
|
||||||
columns []string
|
|
||||||
)
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: fmt.Sprintf("%s <username|user_id>", verb),
|
Use: fmt.Sprintf("%s <username|user_id>", verb),
|
||||||
Short: short,
|
Short: short,
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Aliases: aliases,
|
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 {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
client, err := createClient(cmd)
|
client, err := createClient(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,21 +37,20 @@ func wireguardPortForward() *cobra.Command {
|
|||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
// Hide all wireguard commands for now while we test!
|
// Hide all wireguard commands for now while we test!
|
||||||
Hidden: true,
|
Hidden: true,
|
||||||
Example: `
|
Example: formatExamples(
|
||||||
- Port forward a single TCP port from 1234 in the workspace to port 5678 on
|
example{
|
||||||
your local machine
|
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",
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 5678:1234") + `
|
},
|
||||||
|
example{
|
||||||
- Port forward a single UDP port from port 9000 to port 9000 on your local
|
Description: "Port forward a single UDP port from port 9000 to port 9000 on your local machine",
|
||||||
machine
|
Command: "coder wireguard-port-forward <workspace> --udp 9000",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --udp 9000") + `
|
example{
|
||||||
|
Description: "Port forward multiple TCP ports and a UDP port",
|
||||||
- Port forward multiple TCP ports and a UDP port
|
Command: "coder wireguard-port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53",
|
||||||
|
},
|
||||||
` + cliui.Styles.Code.Render("$ coder port-forward <workspace> --tcp 8080:8080 --tcp 9000:3000 --udp 5353:53") + `
|
),
|
||||||
`,
|
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
specs, err := parsePortForwards(tcpForwards, nil, nil)
|
specs, err := parsePortForwards(tcpForwards, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
Reference in New Issue
Block a user