lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 1143e815f0c0e19effa74e0e600dd2d9acac7ed4
parent d200f190114506275d6681eac33e3f8a855dfb1b
Author: Sean Enck <sean@ttypty.com>
Date:   Thu, 21 Mar 2024 21:35:10 -0400

initial work on fish completion

Diffstat:
MREADME.md | 2+-
Minternal/app/completions.go | 14++++----------
Minternal/app/completions_test.go | 19++++++++++---------
Minternal/app/core.go | 4++++
Minternal/app/core_test.go | 4++--
Minternal/app/info.go | 4++--
Minternal/app/info_test.go | 26++++++++++++++++++++++++++
7 files changed, 49 insertions(+), 24 deletions(-)

diff --git a/README.md b/README.md @@ -34,7 +34,7 @@ Use `lb help verbose` for additional information about options and environment v `lb` should work on combinations of the following: - linux/macOS/WSL -- zsh/bash (for completions) +- zsh/bash/fish (for completions) - amd64/arm64 ## usage diff --git a/internal/app/completions.go b/internal/app/completions.go @@ -119,14 +119,14 @@ func loadProfiles(exe string, canFilter bool) []Profile { } // GenerateCompletions handles creating shell completion outputs -func GenerateCompletions(isBash, isHelp bool, exe string) ([]string, error) { +func GenerateCompletions(completionType string, isHelp bool, exe string) ([]string, error) { if isHelp { var h []string for _, p := range loadProfiles(exe, false) { if p.IsDefault { continue } - text := fmt.Sprintf("export %s\n - filtered completions\n - useful when:\n", p.Env()) + text := fmt.Sprintf("when %s\n - filtered completions\n - useful when:\n", p.Env()) for idx, e := range p.env { if idx > 0 { text = fmt.Sprintf("%s and\n", text) @@ -138,7 +138,7 @@ func GenerateCompletions(isBash, isHelp bool, exe string) ([]string, error) { h = append(h, strings.TrimSpace(fmt.Sprintf(` %s is not set unset %s -export %s=<unknown> +when %s=<unknown> - default completions `, config.EnvironmentCompletionKey, config.EnvironmentCompletionKey, config.EnvironmentCompletionKey))) return h, nil @@ -161,16 +161,10 @@ export %s=<unknown> CompletionEnv: fmt.Sprintf("$%s", config.EnvironmentCompletionKey), } - using, err := readDoc("zsh.sh") + using, err := readDoc(fmt.Sprintf("%s.sh", completionType)) if err != nil { return nil, err } - if isBash { - using, err = readDoc("bash.sh") - if err != nil { - return nil, err - } - } shellScript, err := readDoc("shell.sh") if err != nil { return nil, err diff --git a/internal/app/completions_test.go b/internal/app/completions_test.go @@ -9,12 +9,13 @@ import ( ) func TestCompletions(t *testing.T) { - testCompletion(t, true) - testCompletion(t, false) + testCompletion(t, "bash") + testCompletion(t, "zsh") + testCompletion(t, "fish") } -func testCompletion(t *testing.T, bash bool) { - v, err := app.GenerateCompletions(bash, true, "lb") +func testCompletion(t *testing.T, completionMode string) { + v, err := app.GenerateCompletions(completionMode, true, "lb") if err != nil { t.Errorf("invalid error: %v", err) } @@ -23,7 +24,7 @@ func testCompletion(t *testing.T, bash bool) { } defer os.Clearenv() os.Setenv("LOCKBOX_COMPLETION_FUNCTION", "A") - o, err := app.GenerateCompletions(bash, true, "lb") + o, err := app.GenerateCompletions(completionMode, true, "lb") if err != nil { t.Errorf("invalid error: %v", err) } @@ -31,7 +32,7 @@ func testCompletion(t *testing.T, bash bool) { t.Errorf("invalid result") } os.Setenv("LOCKBOX_COMPLETION_FUNCTION", "") - v, err = app.GenerateCompletions(bash, false, "lb") + v, err = app.GenerateCompletions(completionMode, false, "lb") if err != nil { t.Errorf("invalid error: %v", err) } @@ -39,12 +40,12 @@ func testCompletion(t *testing.T, bash bool) { t.Errorf("invalid result") } os.Setenv("LOCKBOX_COMPLETION_FUNCTION", "ZZZ") - _, err = app.GenerateCompletions(bash, false, "lb") + _, err = app.GenerateCompletions(completionMode, false, "lb") if err == nil || err.Error() != "no profiles loaded, invalid environment setting?" { t.Errorf("invalid error: %v", err) } os.Setenv("LOCKBOX_COMPLETION_FUNCTION", "NOCLIP-READONLY") - n, err := app.GenerateCompletions(bash, false, "lb") + n, err := app.GenerateCompletions(completionMode, false, "lb") if err != nil { t.Errorf("invalid error: %v", err) } @@ -52,7 +53,7 @@ func testCompletion(t *testing.T, bash bool) { t.Errorf("invalid result, should filter") } os.Setenv("LOCKBOX_COMPLETION_FUNCTION", "DEFAULT") - d, err := app.GenerateCompletions(bash, false, "lb") + d, err := app.GenerateCompletions(completionMode, false, "lb") if err != nil { t.Errorf("invalid error: %v", err) } diff --git a/internal/app/core.go b/internal/app/core.go @@ -72,6 +72,8 @@ const ( JSONCommand = "json" // ZshCommand is the command to generate zsh completions ZshCommand = "zsh" + // FishCommand is the command to generate fish completions + FishCommand = "fish" docDir = "doc" textFile = ".txt" ) @@ -206,6 +208,8 @@ func Usage(verbose bool, exe string) ([]string, error) { results = append(results, command(VersionCommand, "", "display version information")) results = append(results, command(ZshCommand, "", "generate user environment zsh completion")) results = append(results, subCommand(ZshCommand, CompletionHelpCommand, "", completionHelpDesc)) + results = append(results, command(FishCommand, "", "generate user environment fish completion")) + results = append(results, subCommand(FishCommand, CompletionHelpCommand, "", completionHelpDesc)) sort.Strings(results) usage := []string{fmt.Sprintf("%s usage:", exe)} if verbose { diff --git a/internal/app/core_test.go b/internal/app/core_test.go @@ -9,11 +9,11 @@ import ( func TestUsage(t *testing.T) { u, _ := app.Usage(false, "lb") - if len(u) != 25 { + if len(u) != 27 { t.Errorf("invalid usage, out of date? %d", len(u)) } u, _ = app.Usage(true, "lb") - if len(u) != 108 { + if len(u) != 110 { t.Errorf("invalid verbose usage, out of date? %d", len(u)) } for _, usage := range u { diff --git a/internal/app/info.go b/internal/app/info.go @@ -61,7 +61,7 @@ func info(command string, args []string) ([]string, error) { return nil, errors.New("invalid env command") } return config.Environ(), nil - case BashCommand, ZshCommand: + case BashCommand, ZshCommand, FishCommand: if len(args) > 1 { return nil, fmt.Errorf("invalid %s command", command) } @@ -77,7 +77,7 @@ func info(command string, args []string) ([]string, error) { if err != nil { return nil, err } - return GenerateCompletions(command == BashCommand, isHelp, exe) + return GenerateCompletions(command, isHelp, exe) } return nil, nil } diff --git a/internal/app/info_test.go b/internal/app/info_test.go @@ -123,3 +123,29 @@ func TestZshInfo(t *testing.T) { t.Errorf("invalid error: %v", err) } } + +func TestFishInfo(t *testing.T) { + os.Clearenv() + var buf bytes.Buffer + ok, err := app.Info(&buf, "fish", []string{}) + if !ok || err != nil { + t.Errorf("invalid error: %v", err) + } + if buf.String() == "" { + t.Error("nothing written") + } + buf = bytes.Buffer{} + ok, err = app.Info(&buf, "fish", []string{"help"}) + if !ok || err != nil { + t.Errorf("invalid error: %v", err) + } + if buf.String() == "" { + t.Error("nothing written") + } + if _, err = app.Info(&buf, "fish", []string{"defaults"}); err.Error() != "invalid fish subcommand" { + t.Errorf("invalid error: %v", err) + } + if _, err = app.Info(&buf, "fish", []string{"test", "default"}); err.Error() != "invalid fish command" { + t.Errorf("invalid error: %v", err) + } +}