Skip to content

Commit df87b92

Browse files
authored
chore: use charm.land/fang/v2 for better tables, colors (#58)
- use `charm.land/fang/v2` for better tables, colors - replace `version` subcommand with `--version` flag
1 parent 2e28f62 commit df87b92

16 files changed

Lines changed: 208 additions & 161 deletions

README.md

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,14 +56,17 @@ Store a key with `loops auth login --name <name>`. Run this again with a differe
5656

5757
Use `--team <name>` on any command to pick a specific stored key.
5858

59-
### Environment variable
60-
61-
Set `LOOPS_API_KEY` to use a key directly — useful for CI or when keyring storage isn't available.
62-
6359
### Precedence
6460

6561
When multiple keys are available, the CLI resolves them in this order:
6662

6763
1. `LOOPS_API_KEY` env var
6864
1. `--team` flag
6965
1. The current default (set via `loops auth use`)
66+
67+
## Environment variables
68+
69+
| Variable | Description |
70+
| --- | --- |
71+
| `LOOPS_API_KEY` | API key to use directly — useful for CI or when keyring storage isn't available. |
72+
| `NO_COLOR` | Set to `1` to disable color output. `0` or unset leaves color on. |

cmd/auth_list.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,15 @@ var authListCmd = &cobra.Command{
3434
return nil
3535
}
3636

37-
w := newTableWriter(cmd.OutOrStdout())
38-
fmt.Fprintln(w, "NAME\tACTIVE\tAPI KEY\t")
37+
t := newStyledTable(cmd.OutOrStdout(), "NAME", "ACTIVE", "API KEY")
3938
for _, e := range entries {
4039
active := ""
4140
if e.Name == activeTeam {
4241
active = "*"
4342
}
44-
fmt.Fprintf(w, "%s\t%s\t%s\n", e.Name, active, maskKey(e.APIKey))
43+
t.Row(e.Name, active, maskKey(e.APIKey))
4544
}
46-
return w.Flush()
45+
return t.Render()
4746
},
4847
}
4948

cmd/auth_status.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,12 @@ var statusCmd = &cobra.Command{
3434
activeKey = "(none)"
3535
}
3636

37-
fmt.Fprintf(cmd.OutOrStdout(), "Active Key: %s\n", activeKey)
38-
fmt.Fprintf(cmd.OutOrStdout(), "API Key: %s\n", masked)
39-
fmt.Fprintf(cmd.OutOrStdout(), "Team: %s\n", keyResp.TeamName)
40-
fmt.Fprintf(cmd.OutOrStdout(), "Endpoint: %s\n", cfg.EndpointURL)
41-
return nil
37+
t := newStyledTable(cmd.OutOrStdout(), "FIELD", "VALUE")
38+
t.Row("activeKey", activeKey)
39+
t.Row("apiKey", masked)
40+
t.Row("teamName", keyResp.TeamName)
41+
t.Row("endpointUrl", cfg.EndpointURL)
42+
return t.Render()
4243
},
4344
}
4445

cmd/build_info.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package cmd
2+
3+
import (
4+
"runtime/debug"
5+
"strings"
6+
)
7+
8+
var (
9+
version = "dev"
10+
commit = "none"
11+
)
12+
13+
func init() {
14+
if info, ok := debug.ReadBuildInfo(); ok && version == "dev" {
15+
if info.Main.Version != "" && info.Main.Version != "(devel)" {
16+
version = strings.TrimPrefix(info.Main.Version, "v")
17+
}
18+
for _, s := range info.Settings {
19+
if s.Key == "vcs.revision" && len(s.Value) >= 7 {
20+
commit = s.Value[:7]
21+
break
22+
}
23+
}
24+
}
25+
}

cmd/contact_properties.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,11 @@ var contactPropertiesListCmd = &cobra.Command{
4949
return nil
5050
}
5151

52-
w := newTableWriter(cmd.OutOrStdout())
53-
fmt.Fprintln(w, "KEY\tLABEL\tTYPE")
52+
t := newStyledTable(cmd.OutOrStdout(), "KEY", "LABEL", "TYPE")
5453
for _, p := range props {
55-
fmt.Fprintf(w, "%s\t%s\t%s\n", p.Key, p.Label, p.Type)
54+
t.Row(p.Key, p.Label, p.Type)
5655
}
57-
w.Flush()
58-
59-
return nil
56+
return t.Render()
6057
},
6158
}
6259

cmd/contacts.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -131,14 +131,13 @@ var contactsFindCmd = &cobra.Command{
131131
}
132132

133133
c := contacts[0]
134-
w := newTableWriter(cmd.OutOrStdout())
135-
fmt.Fprintln(w, "FIELD\tVALUE\tCUSTOM")
134+
t := newStyledTable(cmd.OutOrStdout(), "FIELD", "VALUE", "CUSTOM")
136135
row := func(field, value string, custom bool) {
137136
marker := ""
138137
if custom {
139138
marker = "*"
140139
}
141-
fmt.Fprintf(w, "%s\t%s\t%s\n", field, value, marker)
140+
t.Row(field, value, marker)
142141
}
143142
row("id", c.ID, false)
144143
row("email", c.Email, false)
@@ -153,9 +152,7 @@ var contactsFindCmd = &cobra.Command{
153152
for _, k := range sortedKeys(c.Custom) {
154153
row(k, formatCustomValue(c.Custom[k]), true)
155154
}
156-
w.Flush()
157-
158-
return nil
155+
return t.Render()
159156
},
160157
}
161158

cmd/contacts_suppression.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,10 @@ var contactsSuppressionCheckCmd = &cobra.Command{
4848
if result.IsSuppressed {
4949
suppressed = "yes"
5050
}
51-
fmt.Fprintf(cmd.OutOrStdout(), "Suppressed: %s\n", suppressed)
52-
fmt.Fprintf(cmd.OutOrStdout(), "Removal quota: %d/%d remaining\n", result.RemovalQuota.Remaining, result.RemovalQuota.Limit)
53-
return nil
51+
t := newStyledTable(cmd.OutOrStdout(), "FIELD", "VALUE")
52+
t.Row("isSuppressed", suppressed)
53+
t.Row("removalQuota", fmt.Sprintf("%d/%d remaining", result.RemovalQuota.Remaining, result.RemovalQuota.Limit))
54+
return t.Render()
5455
},
5556
}
5657

cmd/lists.go

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,14 +43,11 @@ var listsListCmd = &cobra.Command{
4343
return nil
4444
}
4545

46-
w := newTableWriter(cmd.OutOrStdout())
47-
fmt.Fprintln(w, "ID\tNAME\tDESCRIPTION\tPUBLIC")
46+
t := newStyledTable(cmd.OutOrStdout(), "ID", "NAME", "DESCRIPTION", "PUBLIC")
4847
for _, l := range lists {
49-
fmt.Fprintf(w, "%s\t%s\t%s\t%v\n", l.ID, l.Name, l.Description, l.IsPublic)
48+
t.Row(l.ID, l.Name, l.Description, fmt.Sprintf("%v", l.IsPublic))
5049
}
51-
w.Flush()
52-
53-
return nil
50+
return t.Render()
5451
},
5552
}
5653

cmd/output.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"encoding/json"
55
"fmt"
66
"io"
7-
"text/tabwriter"
87
)
98

109
type outputFlag string
@@ -31,10 +30,6 @@ func isJSONOutput() bool {
3130
return outputFormat == "json"
3231
}
3332

34-
func newTableWriter(w io.Writer) *tabwriter.Writer {
35-
return tabwriter.NewWriter(w, 0, 0, 2, ' ', 0)
36-
}
37-
3833
func printJSON(w io.Writer, v any) error {
3934
enc := json.NewEncoder(w)
4035
enc.SetIndent("", " ")

cmd/root.go

Lines changed: 15 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
package cmd
22

33
import (
4-
"fmt"
4+
"context"
5+
"io"
56
"os"
67
"time"
78

9+
"charm.land/fang/v2"
810
"github.com/loops-so/cli/internal/api"
911
"github.com/loops-so/cli/internal/config"
1012
"github.com/spf13/cobra"
@@ -36,18 +38,12 @@ var rootCmd = &cobra.Command{
3638
SilenceUsage: true,
3739
}
3840

39-
func fixHelpFlags(cmd *cobra.Command) {
40-
cmd.InitDefaultHelpFlag()
41-
if f := cmd.Flags().Lookup("help"); f != nil {
42-
name := cmd.Name()
43-
if name == "" {
44-
name = "this command"
45-
}
46-
f.Usage = "Help for " + name
47-
}
48-
for _, sub := range cmd.Commands() {
49-
fixHelpFlags(sub)
41+
func jsonAwareErrorHandler(w io.Writer, styles fang.Styles, err error) {
42+
if isJSONOutput() {
43+
_ = printJSON(w, Result{Success: false, Message: err.Error()})
44+
return
5045
}
46+
fang.DefaultErrorHandler(w, styles, err)
5147
}
5248

5349
func Execute() {
@@ -63,17 +59,17 @@ func Execute() {
6359
}
6460
}()
6561

66-
fixHelpFlags(rootCmd)
67-
err := rootCmd.Execute()
62+
err := fang.Execute(
63+
context.Background(),
64+
rootCmd,
65+
fang.WithVersion(version),
66+
fang.WithCommit(commit),
67+
fang.WithErrorHandler(jsonAwareErrorHandler),
68+
)
6869

6970
checkForUpdate(os.Stderr)
7071

7172
if err != nil {
72-
if isJSONOutput() {
73-
printJSON(os.Stderr, Result{Success: false, Message: err.Error()})
74-
} else {
75-
fmt.Fprintln(os.Stderr, "Error:", err)
76-
}
7773
os.Exit(1)
7874
}
7975
}

0 commit comments

Comments
 (0)