commit 7b51021d42ca1555e8508d10392f21c88fb5781b
parent 437f861fa25cbf1b389bfdfc4f48c6b6f277115d
Author: Sean Enck <sean@ttypty.com>
Date: Tue, 25 Jul 2023 20:17:38 -0400
split core -> completion for cleanup
Diffstat:
4 files changed, 171 insertions(+), 153 deletions(-)
diff --git a/internal/app/completions.go b/internal/app/completions.go
@@ -0,0 +1,118 @@
+// Package app common objects
+package app
+
+import (
+ "bytes"
+ "fmt"
+ "text/template"
+
+ "github.com/enckse/lockbox/internal/inputs"
+)
+
+type (
+ // Completions handles the inputs to completions for templating
+ Completions struct {
+ Options []string
+ CanClip bool
+ CanTOTP bool
+ ReadOnly bool
+ InsertCommand string
+ TOTPSubCommands []string
+ TOTPListCommand string
+ RemoveCommand string
+ ClipCommand string
+ ShowCommand string
+ MultiLineCommand string
+ MoveCommand string
+ TOTPCommand string
+ DoTOTPList string
+ DoList string
+ Executable string
+ JSONCommand string
+ HelpCommand string
+ HelpAdvancedCommand string
+ }
+)
+
+// GenerateCompletions handles creating shell completion outputs
+func GenerateCompletions(isBash, defaults bool) ([]string, error) {
+ name, err := exeName()
+ if err != nil {
+ return nil, err
+ }
+ c := Completions{
+ Executable: name,
+ InsertCommand: InsertCommand,
+ RemoveCommand: RemoveCommand,
+ TOTPSubCommands: []string{TOTPMinimalCommand, TOTPOnceCommand, TOTPShowCommand},
+ TOTPListCommand: TOTPListCommand,
+ ClipCommand: ClipCommand,
+ ShowCommand: ShowCommand,
+ MultiLineCommand: MultiLineCommand,
+ JSONCommand: JSONCommand,
+ HelpCommand: HelpCommand,
+ HelpAdvancedCommand: HelpAdvancedCommand,
+ TOTPCommand: TOTPCommand,
+ MoveCommand: MoveCommand,
+ DoList: fmt.Sprintf("%s %s", name, ListCommand),
+ DoTOTPList: fmt.Sprintf("%s %s %s", name, TOTPCommand, TOTPListCommand),
+ Options: []string{MultiLineCommand, EnvCommand, HelpCommand, ListCommand, ShowCommand, VersionCommand, JSONCommand},
+ }
+ isReadOnly := false
+ isClip := true
+ isTOTP := true
+ if !defaults {
+ ro, err := inputs.IsReadOnly()
+ if err != nil {
+ return nil, err
+ }
+ isReadOnly = ro
+ noClip, err := inputs.IsNoClipEnabled()
+ if err != nil {
+ return nil, err
+ }
+ if noClip {
+ isClip = false
+ }
+ noTOTP, err := inputs.IsNoTOTP()
+ if err != nil {
+ return nil, err
+ }
+ if noTOTP {
+ isTOTP = false
+ }
+ }
+ c.CanClip = isClip
+ c.ReadOnly = isReadOnly
+ c.CanTOTP = isTOTP
+ if c.CanClip {
+ c.Options = append(c.Options, ClipCommand)
+ c.TOTPSubCommands = append(c.TOTPSubCommands, TOTPClipCommand)
+ }
+ if !c.ReadOnly {
+ c.Options = append(c.Options, MoveCommand, RemoveCommand, InsertCommand)
+ c.TOTPSubCommands = append(c.TOTPSubCommands, TOTPInsertCommand)
+ }
+ if c.CanTOTP {
+ c.Options = append(c.Options, TOTPCommand)
+ }
+ using, err := readDoc("zsh")
+ if err != nil {
+ return nil, err
+ }
+ if isBash {
+ using, err = readDoc("bash")
+ if err != nil {
+ return nil, err
+ }
+ }
+ t, err := template.New("t").Parse(using)
+ if err != nil {
+ return nil, err
+ }
+ var buf bytes.Buffer
+ if err := t.Execute(&buf, c); err != nil {
+ return nil, err
+ }
+ return []string{buf.String()}, nil
+}
diff --git a/internal/app/completions_test.go b/internal/app/completions_test.go
@@ -0,0 +1,53 @@
+package app_test
+
+import (
+ "os"
+ "testing"
+
+ "github.com/enckse/lockbox/internal/app"
+)
+
+func TestGenerateCompletions(t *testing.T) {
+ testCompletions(t, true)
+ testCompletions(t, false)
+}
+
+func testCompletions(t *testing.T, bash bool) {
+ os.Setenv("LOCKBOX_NOTOTP", "yes")
+ os.Setenv("LOCKBOX_READONLY", "yes")
+ os.Setenv("LOCKBOX_NOCLIP", "yes")
+ defaults, _ := app.GenerateCompletions(bash, true)
+ roNoTOTPClip, _ := app.GenerateCompletions(bash, false)
+ if roNoTOTPClip[0] == defaults[0] {
+ t.Error("should not match defaults")
+ }
+ os.Setenv("LOCKBOX_NOTOTP", "")
+ roNoClip, _ := app.GenerateCompletions(bash, false)
+ if roNoClip[0] == defaults[0] || roNoClip[0] == roNoTOTPClip[0] {
+ t.Error("should not equal defaults nor no totp/clip")
+ }
+ os.Setenv("LOCKBOX_READONLY", "")
+ os.Setenv("LOCKBOX_NOCLIP", "yes")
+ noClip, _ := app.GenerateCompletions(bash, false)
+ if roNoClip[0] == noClip[0] || noClip[0] == defaults[0] || noClip[0] == roNoTOTPClip[0] {
+ t.Error("readonly/noclip != noclip (nor defaults, nor ro/no totp/clip)")
+ }
+ os.Setenv("LOCKBOX_READONLY", "yes")
+ os.Setenv("LOCKBOX_NOCLIP", "")
+ ro, _ := app.GenerateCompletions(bash, false)
+ if roNoClip[0] == ro[0] || noClip[0] == ro[0] || ro[0] == defaults[0] || ro[0] == roNoTOTPClip[0] {
+ t.Error("readonly/noclip != ro (nor ro == noclip, nor ro == defaults)")
+ }
+ os.Setenv("LOCKBOX_READONLY", "")
+ os.Setenv("LOCKBOX_NOCLIP", "")
+ os.Setenv("LOCKBOX_NOTOTP", "")
+ isDefaultsToo, _ := app.GenerateCompletions(bash, false)
+ if isDefaultsToo[0] != defaults[0] {
+ t.Error("defaults should match env defaults")
+ }
+ for _, confirm := range [][]string{defaults, roNoClip, noClip, ro, isDefaultsToo} {
+ if len(confirm) != 1 {
+ t.Error("completions returned an invalid array")
+ }
+ }
+}
diff --git a/internal/app/core.go b/internal/app/core.go
@@ -2,7 +2,6 @@
package app
import (
- "bytes"
"embed"
"fmt"
"io"
@@ -10,7 +9,6 @@ import (
"path/filepath"
"sort"
"strings"
- "text/template"
"github.com/enckse/lockbox/internal/backend"
"github.com/enckse/lockbox/internal/inputs"
@@ -93,28 +91,6 @@ type (
args []string
tx *backend.Transaction
}
- // Completions handles the inputs to completions for templating
- Completions struct {
- Options []string
- CanClip bool
- CanTOTP bool
- ReadOnly bool
- InsertCommand string
- TOTPSubCommands []string
- TOTPListCommand string
- RemoveCommand string
- ClipCommand string
- ShowCommand string
- MultiLineCommand string
- MoveCommand string
- TOTPCommand string
- DoTOTPList string
- DoList string
- Executable string
- JSONCommand string
- HelpCommand string
- HelpAdvancedCommand string
- }
)
// NewDefaultCommand creates a new app command
@@ -195,89 +171,6 @@ func exeName() (string, error) {
return filepath.Base(n), nil
}
-// GenerateCompletions handles creating shell completion outputs
-func GenerateCompletions(isBash, defaults bool) ([]string, error) {
- name, err := exeName()
- if err != nil {
- return nil, err
- }
- c := Completions{
- Executable: name,
- InsertCommand: InsertCommand,
- RemoveCommand: RemoveCommand,
- TOTPSubCommands: []string{TOTPMinimalCommand, TOTPOnceCommand, TOTPShowCommand},
- TOTPListCommand: TOTPListCommand,
- ClipCommand: ClipCommand,
- ShowCommand: ShowCommand,
- MultiLineCommand: MultiLineCommand,
- JSONCommand: JSONCommand,
- HelpCommand: HelpCommand,
- HelpAdvancedCommand: HelpAdvancedCommand,
- TOTPCommand: TOTPCommand,
- MoveCommand: MoveCommand,
- DoList: fmt.Sprintf("%s %s", name, ListCommand),
- DoTOTPList: fmt.Sprintf("%s %s %s", name, TOTPCommand, TOTPListCommand),
- Options: []string{MultiLineCommand, EnvCommand, HelpCommand, ListCommand, ShowCommand, VersionCommand, JSONCommand},
- }
- isReadOnly := false
- isClip := true
- isTOTP := true
- if !defaults {
- ro, err := inputs.IsReadOnly()
- if err != nil {
- return nil, err
- }
- isReadOnly = ro
- noClip, err := inputs.IsNoClipEnabled()
- if err != nil {
- return nil, err
- }
- if noClip {
- isClip = false
- }
- noTOTP, err := inputs.IsNoTOTP()
- if err != nil {
- return nil, err
- }
- if noTOTP {
- isTOTP = false
- }
- }
- c.CanClip = isClip
- c.ReadOnly = isReadOnly
- c.CanTOTP = isTOTP
- if c.CanClip {
- c.Options = append(c.Options, ClipCommand)
- c.TOTPSubCommands = append(c.TOTPSubCommands, TOTPClipCommand)
- }
- if !c.ReadOnly {
- c.Options = append(c.Options, MoveCommand, RemoveCommand, InsertCommand)
- c.TOTPSubCommands = append(c.TOTPSubCommands, TOTPInsertCommand)
- }
- if c.CanTOTP {
- c.Options = append(c.Options, TOTPCommand)
- }
- using, err := readDoc("zsh")
- if err != nil {
- return nil, err
- }
- if isBash {
- using, err = readDoc("bash")
- if err != nil {
- return nil, err
- }
- }
- t, err := template.New("t").Parse(using)
- if err != nil {
- return nil, err
- }
- var buf bytes.Buffer
- if err := t.Execute(&buf, c); err != nil {
- return nil, err
- }
- return []string{buf.String()}, nil
-}
-
// Usage return usage information
func Usage(verbose bool) ([]string, error) {
name, err := exeName()
diff --git a/internal/app/core_test.go b/internal/app/core_test.go
@@ -1,7 +1,6 @@
package app_test
import (
- "os"
"strings"
"testing"
@@ -25,48 +24,3 @@ func TestUsage(t *testing.T) {
}
}
}
-
-func TestGenerateCompletions(t *testing.T) {
- testCompletions(t, true)
- testCompletions(t, false)
-}
-
-func testCompletions(t *testing.T, bash bool) {
- os.Setenv("LOCKBOX_NOTOTP", "yes")
- os.Setenv("LOCKBOX_READONLY", "yes")
- os.Setenv("LOCKBOX_NOCLIP", "yes")
- defaults, _ := app.GenerateCompletions(bash, true)
- roNoTOTPClip, _ := app.GenerateCompletions(bash, false)
- if roNoTOTPClip[0] == defaults[0] {
- t.Error("should not match defaults")
- }
- os.Setenv("LOCKBOX_NOTOTP", "")
- roNoClip, _ := app.GenerateCompletions(bash, false)
- if roNoClip[0] == defaults[0] || roNoClip[0] == roNoTOTPClip[0] {
- t.Error("should not equal defaults nor no totp/clip")
- }
- os.Setenv("LOCKBOX_READONLY", "")
- os.Setenv("LOCKBOX_NOCLIP", "yes")
- noClip, _ := app.GenerateCompletions(bash, false)
- if roNoClip[0] == noClip[0] || noClip[0] == defaults[0] || noClip[0] == roNoTOTPClip[0] {
- t.Error("readonly/noclip != noclip (nor defaults, nor ro/no totp/clip)")
- }
- os.Setenv("LOCKBOX_READONLY", "yes")
- os.Setenv("LOCKBOX_NOCLIP", "")
- ro, _ := app.GenerateCompletions(bash, false)
- if roNoClip[0] == ro[0] || noClip[0] == ro[0] || ro[0] == defaults[0] || ro[0] == roNoTOTPClip[0] {
- t.Error("readonly/noclip != ro (nor ro == noclip, nor ro == defaults)")
- }
- os.Setenv("LOCKBOX_READONLY", "")
- os.Setenv("LOCKBOX_NOCLIP", "")
- os.Setenv("LOCKBOX_NOTOTP", "")
- isDefaultsToo, _ := app.GenerateCompletions(bash, false)
- if isDefaultsToo[0] != defaults[0] {
- t.Error("defaults should match env defaults")
- }
- for _, confirm := range [][]string{defaults, roNoClip, noClip, ro, isDefaultsToo} {
- if len(confirm) != 1 {
- t.Error("completions returned an invalid array")
- }
- }
-}