commit ab81af8a2e2e05221038f5c0db2310027f6c1fcd
parent e586fd8024c1920f8f9cda76284747733aafde04
Author: Sean Enck <sean@ttypty.com>
Date: Wed, 6 Sep 2023 20:37:37 -0400
use an ansi module for better coloring outputs
Diffstat:
5 files changed, 36 insertions(+), 133 deletions(-)
diff --git a/go.mod b/go.mod
@@ -7,6 +7,7 @@ require (
github.com/hashicorp/go-envparse v0.1.0
github.com/pquerna/otp v1.4.0
github.com/tobischo/gokeepasslib/v3 v3.5.1
+ mpldr.codes/ansi v1.5.0
mvdan.cc/sh/v3 v3.7.0
)
diff --git a/go.sum b/go.sum
@@ -31,5 +31,7 @@ golang.org/x/exp v0.0.0-20230105202349-8879d0199aa3 h1:fJwx88sMf5RXwDwziL0/Mn9Wq
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+mpldr.codes/ansi v1.5.0 h1:jAAtDMwU/DC7OPxmrVFpmM3RrSQDcMeLhuk6BuEoWZc=
+mpldr.codes/ansi v1.5.0/go.mod h1:SYuKX0r6nxvySxMxzQX9frQaKLjEqKapjjg17euonMc=
mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=
diff --git a/internal/app/totp.go b/internal/app/totp.go
@@ -14,6 +14,7 @@ import (
"github.com/enckse/lockbox/internal/platform"
coreotp "github.com/pquerna/otp"
otp "github.com/pquerna/otp/totp"
+ "mpldr.codes/ansi"
)
var (
@@ -105,10 +106,6 @@ func (args *TOTPArguments) display(opts TOTPOptions) error {
if !interactive && clip {
return errors.New("clipboard not available in non-interactive mode")
}
- coloring, err := platform.NewTerminal(platform.Red)
- if err != nil {
- return err
- }
entity, err := opts.app.Transaction().Get(backend.NewPath(args.Entry, args.token), backend.SecretValue)
if err != nil {
return err
@@ -159,6 +156,10 @@ func (args *TOTPArguments) display(opts TOTPOptions) error {
if err != nil {
return err
}
+ allowColor, err := canColor()
+ if err != nil {
+ return err
+ }
for {
if !first {
time.Sleep(500 * time.Millisecond)
@@ -180,27 +181,30 @@ func (args *TOTPArguments) display(opts TOTPOptions) error {
if err != nil {
return err
}
- startColor := ""
- endColor := ""
- for _, when := range colorRules {
- if left < when.End && left >= when.Start {
- startColor = coloring.Start
- endColor = coloring.End
+ isColor := false
+ if allowColor {
+ for _, when := range colorRules {
+ if left < when.End && left >= when.Start {
+ isColor = true
+ }
}
}
leftString := fmt.Sprintf("%d", left)
if len(leftString) < 2 {
leftString = "0" + leftString
}
- expires := fmt.Sprintf("%s%s (%s)%s", startColor, now.Format("15:04:05"), leftString, endColor)
- outputs := []string{expires}
+ txt := fmt.Sprintf("%s (%s)", now.Format("15:04:05"), leftString)
+ if isColor {
+ txt = ansi.Red(txt)
+ }
+ outputs := []string{txt}
if !clip {
outputs = append(outputs, fmt.Sprintf("%s\n %s", args.Entry, code))
if !once {
outputs = append(outputs, "-> CTRL+C to exit")
}
} else {
- fmt.Fprintf(writer, "-> %s\n", expires)
+ fmt.Fprintf(writer, "-> %s\n", txt)
return clipboard.CopyTo(code)
}
if !once {
@@ -287,3 +291,19 @@ func NewTOTPArguments(args []string, tokenType string) (*TOTPArguments, error) {
}
return opts, nil
}
+
+func canColor() (bool, error) {
+ interactive, err := config.EnvInteractive.Get()
+ if err != nil {
+ return false, err
+ }
+ colors := interactive
+ if colors {
+ isColored, err := config.EnvNoColor.Get()
+ if err != nil {
+ return false, err
+ }
+ colors = !isColored
+ }
+ return colors, nil
+}
diff --git a/internal/platform/terminal.go b/internal/platform/terminal.go
@@ -1,54 +0,0 @@
-// Package platform handles platform-specific operations.
-package platform
-
-import (
- "errors"
-
- "github.com/enckse/lockbox/internal/config"
-)
-
-const (
- termBeginRed = "\033[1;31m"
- termEndRed = "\033[0m"
-)
-
-const (
- // Red will get red terminal coloring.
- Red = iota
-)
-
-type (
- // Color are terminal colors for dumb terminal coloring.
- Color int
-)
-
-type (
- // Terminal represents terminal coloring information.
- Terminal struct {
- Start string
- End string
- }
-)
-
-// NewTerminal will retrieve start/end terminal coloration indicators.
-func NewTerminal(color Color) (Terminal, error) {
- if color != Red {
- return Terminal{}, errors.New("bad color")
- }
- interactive, err := config.EnvInteractive.Get()
- if err != nil {
- return Terminal{}, err
- }
- colors := interactive
- if colors {
- isColored, err := config.EnvNoColor.Get()
- if err != nil {
- return Terminal{}, err
- }
- colors = !isColored
- }
- if colors {
- return Terminal{Start: termBeginRed, End: termEndRed}, nil
- }
- return Terminal{}, nil
-}
diff --git a/internal/platform/terminal_test.go b/internal/platform/terminal_test.go
@@ -1,66 +0,0 @@
-package platform_test
-
-import (
- "os"
- "testing"
-
- "github.com/enckse/lockbox/internal/platform"
-)
-
-func TestHasColoring(t *testing.T) {
- os.Setenv("LOCKBOX_INTERACTIVE", "yes")
- os.Setenv("LOCKBOX_NOCOLOR", "no")
- term, err := platform.NewTerminal(platform.Red)
- if err != nil {
- t.Errorf("color was valid: %v", err)
- }
- if term.Start != "\033[1;31m" || term.End != "\033[0m" {
- t.Error("bad resulting color")
- }
-}
-
-func TestBadColor(t *testing.T) {
- _, err := platform.NewTerminal(platform.Color(5))
- if err == nil || err.Error() != "bad color" {
- t.Errorf("invalid color error: %v", err)
- }
-}
-
-func TestNoColoring(t *testing.T) {
- os.Setenv("LOCKBOX_INTERACTIVE", "no")
- os.Setenv("LOCKBOX_NOCOLOR", "yes")
- term, err := platform.NewTerminal(platform.Red)
- if err != nil {
- t.Errorf("color was valid: %v", err)
- }
- if term.Start != "" || term.End != "" {
- t.Error("should have no color")
- }
- os.Setenv("LOCKBOX_INTERACTIVE", "yes")
- os.Setenv("LOCKBOX_NOCOLOR", "yes")
- term, err = platform.NewTerminal(platform.Red)
- if err != nil {
- t.Errorf("color was valid: %v", err)
- }
- if term.Start != "" || term.End != "" {
- t.Error("should have no color")
- }
- os.Setenv("LOCKBOX_INTERACTIVE", "no")
- os.Setenv("LOCKBOX_NOCOLOR", "no")
- term, err = platform.NewTerminal(platform.Red)
- if err != nil {
- t.Errorf("color was valid: %v", err)
- }
- if term.Start != "" || term.End != "" {
- t.Error("should have no color")
- }
- os.Setenv("LOCKBOX_INTERACTIVE", "yes")
- os.Setenv("LOCKBOX_NOCOLOR", "no")
- term, err = platform.NewTerminal(platform.Red)
- if err != nil {
- t.Errorf("color was valid: %v", err)
- }
- if term.Start == "" || term.End == "" {
- t.Error("should have color")
- }
-}