Skip to content
This repository was archived by the owner on Aug 30, 2024. It is now read-only.

Commit 6ef3b24

Browse files
committed
Add new RichCLIMessage error type
1 parent c9043b7 commit 6ef3b24

File tree

3 files changed

+84
-5
lines changed

3 files changed

+84
-5
lines changed

cmd/coder/main.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import (
99
"os"
1010
"runtime"
1111

12+
"cdr.dev/coder-cli/internal/clog"
1213
"cdr.dev/coder-cli/internal/cmd"
1314
"cdr.dev/coder-cli/internal/x/xterminal"
15+
"golang.org/x/xerrors"
1416

1517
"go.coder.com/flog"
1618
)
@@ -42,6 +44,11 @@ func main() {
4244
app.Version = fmt.Sprintf("%s %s %s/%s", version, runtime.Version(), runtime.GOOS, runtime.GOARCH)
4345

4446
if err := app.ExecuteContext(ctx); err != nil {
45-
flog.Fatal("%v", err)
47+
var cliErr clog.RichCLIMessage
48+
if xerrors.As(err, &cliErr) {
49+
fmt.Println(cliErr.Error())
50+
} else {
51+
flog.Fatal("%v", err)
52+
}
4653
}
4754
}

internal/clog/error.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package clog
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/fatih/color"
8+
)
9+
10+
// RichCLIMessage provides a human-readable message for CLI errors and messages.
11+
type RichCLIMessage struct {
12+
Level string
13+
Color color.Attribute
14+
Header string
15+
Lines []string
16+
}
17+
18+
// Error formats the CLI message for consumption by a human as an error.
19+
func (r RichCLIMessage) Error() string {
20+
var str strings.Builder
21+
str.WriteString(fmt.Sprintf("%s: %s\n",
22+
color.New(r.Color).Sprint(r.Level),
23+
color.New(color.Bold).Sprint(r.Header)),
24+
)
25+
for _, line := range r.Lines {
26+
str.WriteString(fmt.Sprintf(" %s %s\n", color.New(r.Color).Sprint("|"), line))
27+
}
28+
return str.String()
29+
}
30+
31+
// String gives the same formatting as Error.
32+
func (r RichCLIMessage) String() string {
33+
return r.Error()
34+
}
35+
36+
// Warn creates an error with the level "warning".
37+
func Warn(header string, lines ...string) error {
38+
return RichCLIMessage{
39+
Color: color.FgYellow,
40+
Level: "warning",
41+
Header: header,
42+
Lines: lines,
43+
}
44+
}
45+
46+
// Error creates an error with the level "error".
47+
func Error(header string, lines ...string) error {
48+
return RichCLIMessage{
49+
Color: color.FgRed,
50+
Level: "error",
51+
Header: header,
52+
Lines: lines,
53+
}
54+
}
55+
56+
// Fatal creates an error with the level "fatal".
57+
func Fatal(header string, lines ...string) error {
58+
return RichCLIMessage{
59+
Color: color.FgRed,
60+
Level: "fatal",
61+
Header: header,
62+
Lines: lines,
63+
}
64+
}
65+
66+
// Bold provides a convenience wrapper around color.New for brevity when logging.
67+
func Bold(a string) string {
68+
return color.New(color.Bold).Sprint(a)
69+
}

internal/cmd/ceapi.go

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66

77
"cdr.dev/coder-cli/coder-sdk"
8+
"cdr.dev/coder-cli/internal/clog"
89
"golang.org/x/xerrors"
910
)
1011

@@ -73,10 +74,12 @@ func findEnv(ctx context.Context, client *coder.Client, envName, userEmail strin
7374
found = append(found, env.Name)
7475
}
7576

76-
return nil, notFoundButDidFind{
77-
needle: envName,
78-
haystack: found,
79-
}
77+
return nil, clog.Fatal(
78+
"failed to execute command in environment",
79+
fmt.Sprintf("environment %q not found in %q", envName, found),
80+
"",
81+
clog.Bold("tip: ")+"view your environments with \"coder envs ls\"",
82+
)
8083
}
8184

8285
type notFoundButDidFind struct {

0 commit comments

Comments
 (0)