lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 73356a540fba4fce6062e4944747cac67a8ec0e6
parent e9247b213d948a41586e1a6063fe0030caec312c
Author: Sean Enck <sean@ttypty.com>
Date:   Sun,  6 Oct 2024 18:02:52 -0400

fish rewritten

Diffstat:
Minternal/app/completions.go | 9++++++++-
Minternal/app/completions_test.go | 1+
Minternal/app/core.go | 8+++++---
Minternal/app/core_test.go | 4++--
Minternal/app/info.go | 2+-
Minternal/app/info_test.go | 1+
Ainternal/app/shell/fish.sh | 39+++++++++++++++++++++++++++++++++++++++
7 files changed, 57 insertions(+), 7 deletions(-)

diff --git a/internal/app/completions.go b/internal/app/completions.go @@ -31,6 +31,11 @@ type ( HelpAdvancedCommand string Options []CompletionOption TOTPSubCommands []CompletionOption + Conditionals struct { + ReadOnly string + NoClip string + NoTOTP string + } } // CompletionOption are conditional wrapped logic for options that may be disabled CompletionOption struct { @@ -87,8 +92,10 @@ func GenerateCompletions(completionType, exe string) ([]string, error) { DoList: fmt.Sprintf("%s %s", exe, ListCommand), DoTOTPList: fmt.Sprintf("%s %s %s", exe, TOTPCommand, TOTPListCommand), } + c.Conditionals.ReadOnly = newConditional(config.EnvReadOnly.Key(), config.YesValue) + c.Conditionals.NoClip = newConditional(config.EnvNoClip.Key(), config.YesValue) + c.Conditionals.NoTOTP = newConditional(config.EnvNoTOTP.Key(), config.YesValue) - // TOTPSubCommands: []string{TOTPMinimalCommand, TOTPOnceCommand, TOTPShowCommand, TOTPClipCommand, TOTPInsertCommand}, cmds := newGenOptions( EnvCommand, HelpCommand, diff --git a/internal/app/completions_test.go b/internal/app/completions_test.go @@ -10,6 +10,7 @@ import ( func TestCompletions(t *testing.T) { for k, v := range map[string]string{ "zsh": "typeset -A opt_args", + "fish": "set -f commands", "bash": "local cur opts", } { testCompletion(t, k, v) diff --git a/internal/app/core.go b/internal/app/core.go @@ -71,8 +71,10 @@ const ( JSONCommand = "json" // CompletionsZshCommand is the command to generate zsh completions CompletionsZshCommand = "zsh" - docDir = "doc" - textFile = ".txt" + // CompletionsFishCommand is the command to generate fish completions + CompletionsFishCommand = "fish" + docDir = "doc" + textFile = ".txt" // PasswordGenerateCommand is the command to do password generation PasswordGenerateCommand = "pwgen" ) @@ -80,7 +82,7 @@ const ( var ( //go:embed doc/* docs embed.FS - completionTypes = []string{CompletionsBashCommand, CompletionsZshCommand} + completionTypes = []string{CompletionsBashCommand, CompletionsFishCommand, CompletionsZshCommand} ) type ( 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) != 26 { t.Errorf("invalid usage, out of date? %d", len(u)) } u, _ = app.Usage(true, "lb") - if len(u) != 114 { + if len(u) != 115 { 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 @@ -77,7 +77,7 @@ func info(command string, args []string) ([]string, error) { return nil, errors.New("invalid completions subcommand") } switch shell { - case CompletionsZshCommand, CompletionsBashCommand: + case CompletionsZshCommand, CompletionsBashCommand, CompletionsFishCommand: break default: return nil, fmt.Errorf("unknown completion type: %s", shell) diff --git a/internal/app/info_test.go b/internal/app/info_test.go @@ -74,6 +74,7 @@ func TestCompletionInfo(t *testing.T) { defer os.Clearenv() for k, v := range map[string]string{ "zsh": "typeset -A opt_args", + "fish": "set -f commands", "bash": "local cur opts", } { for _, b := range []bool{true, false} { diff --git a/internal/app/shell/fish.sh b/internal/app/shell/fish.sh @@ -0,0 +1,39 @@ +complete -c {{ $.Executable }} -f + + +function {{ $.Executable }}-completion + set -f commands "" +{{- range $idx, $value := $.Options }} + {{- if gt $idx 0 }} + set -f commands " $commands" + {{ end }} + if {{ $value.Conditional }} + set -f commands "{{ $value.Key }}$commands" + end +{{- end }} + complete -c {{ $.Executable }} -n "not __fish_seen_subcommand_from $commands" -a "$commands" + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.HelpCommand }}; and test (count (commandline -opc)) -lt 3" -a "{{ $.HelpAdvancedCommand }}" + if {{ $.Conditionals.ReadOnly }} + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.InsertCommand }} {{ $.MultiLineCommand }} {{ $.RemoveCommand }}; and test (count (commandline -opc)) -lt 3" -a "({{ $.DoList }})" + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.MoveCommand }}; and test (count (commandline -opc)) -lt 4" -a "({{ $.DoList }})" + end + if {{ $.Conditionals.NoTOTP }} + set -f totps "" +{{- range $idx, $value := $.TOTPSubCommands }} + {{- if gt $idx 0 }} + set -f totps " $totps" + {{ end }} + if {{ $value.Conditional }} + set -f totps "{{ $value.Key }}$totps" + end +{{- end }} + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.TOTPCommand }}; and not __fish_seen_subcommand_from $totps" -a "$totps" + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.TOTPCommand }}; and __fish_seen_subcommand_from $totps; and test (count (commandline -opc)) -lt 4" -a "({{ $.DoTOTPList }})" + end + if {{ $.Conditionals.NoClip }} + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.ClipCommand }}; and test (count (commandline -opc)) -lt 3" -a "({{ $.DoList}})" + end + complete -c {{ $.Executable }} -n "__fish_seen_subcommand_from {{ $.ShowCommand }} {{ $.JSONCommand }}; and test (count (commandline -opc)) -lt 3" -a "({{ $.DoList}})" +end + +{{ $.Executable }}-completion