lockbox

password manager
Log | Files | Refs | README | LICENSE

commit 404b9c15998d0872510ffbdaed81d2466a8c0cd6
parent f9c91bb1561e6b9becc6e391867e360fdd570ccd
Author: Sean Enck <sean@ttypty.com>
Date:   Mon,  9 Jun 2025 15:13:35 -0400

remove conditionals in completions

Diffstat:
Minternal/app/completions/core.go | 63++++++---------------------------------------------------------
Minternal/app/completions/core_test.go | 27---------------------------
Minternal/app/completions/shell/bash.sh | 21++++++---------------
Minternal/app/completions/shell/zsh.sh | 25++++++++-----------------
Minternal/app/info.go | 7+------
Minternal/app/info_test.go | 8--------
6 files changed, 21 insertions(+), 130 deletions(-)

diff --git a/internal/app/completions/core.go b/internal/app/completions/core.go @@ -11,7 +11,6 @@ import ( "text/template" "git.sr.ht/~enckse/lockbox/internal/app/commands" - "git.sr.ht/~enckse/lockbox/internal/config" ) type ( @@ -35,59 +34,14 @@ type ( HelpAdvancedCommand string HelpConfigCommand string ExportCommand string - Options []CompletionOption - TOTPSubCommands []CompletionOption - Conditionals Conditionals - } - // Conditionals help control completion flow - Conditionals struct { - Not struct { - ReadOnly string - Ever string - } - Exported []string - } - // CompletionOption are conditional wrapped logic for options that may be disabled - CompletionOption struct { - Conditional string - Key string + Options []string + TOTPSubCommands []string } ) //go:embed shell/* var shell embed.FS -func (c Template) newGenOptions(defaults []string, kv map[string]string) []CompletionOption { - opt := []CompletionOption{} - for _, a := range defaults { - opt = append(opt, CompletionOption{c.Conditionals.Not.Ever, a}) - } - var keys []string - for k := range kv { - keys = append(keys, k) - } - sort.Strings(keys) - for _, key := range keys { - check := kv[key] - opt = append(opt, CompletionOption{check, key}) - } - return opt -} - -// NewConditionals creates the conditional components of completions -func NewConditionals() Conditionals { - const shellIsNotText = `[ "%s" != "%s" ]` - c := Conditionals{} - registerIsNotEqual := func(key interface{ Key() string }, right string) string { - k := key.Key() - c.Exported = append(c.Exported, k) - return fmt.Sprintf(shellIsNotText, fmt.Sprintf("$%s", k), right) - } - c.Not.ReadOnly = registerIsNotEqual(config.EnvReadOnly, config.YesValue) - c.Not.Ever = fmt.Sprintf(shellIsNotText, "1", "0") - return c -} - // Generate handles creating shell completion outputs func Generate(completionType, exe string) ([]string, error) { if !slices.Contains(commands.CompletionTypes, completionType) { @@ -112,16 +66,11 @@ func Generate(completionType, exe string) ([]string, error) { DoTOTPList: fmt.Sprintf("%s %s %s", exe, commands.TOTP, commands.TOTPList), ExportCommand: fmt.Sprintf("%s %s %s", exe, commands.Env, commands.Completions), } - c.Conditionals = NewConditionals() - c.Options = c.newGenOptions([]string{commands.Help, commands.List, commands.Show, commands.Version, commands.JSON, commands.Groups, commands.Clip, commands.TOTP}, - map[string]string{ - commands.Move: c.Conditionals.Not.ReadOnly, - commands.Remove: c.Conditionals.Not.ReadOnly, - commands.Insert: c.Conditionals.Not.ReadOnly, - commands.Unset: c.Conditionals.Not.ReadOnly, - }) - c.TOTPSubCommands = c.newGenOptions([]string{commands.TOTPMinimal, commands.TOTPOnce, commands.TOTPShow, commands.TOTPURL, commands.TOTPSeed, commands.TOTPClip}, nil) + c.Options = []string{commands.Help, commands.List, commands.Show, commands.Version, commands.JSON, commands.Groups, commands.Clip, commands.TOTP, commands.Move, commands.Remove, commands.Insert, commands.Unset} + c.TOTPSubCommands = []string{commands.TOTPMinimal, commands.TOTPOnce, commands.TOTPShow, commands.TOTPURL, commands.TOTPSeed, commands.TOTPClip} + sort.Strings(c.Options) + sort.Strings(c.TOTPSubCommands) using, err := shell.ReadFile(filepath.Join("shell", fmt.Sprintf("%s.sh", completionType))) if err != nil { diff --git a/internal/app/completions/core_test.go b/internal/app/completions/core_test.go @@ -1,14 +1,10 @@ package completions_test import ( - "fmt" - "slices" - "sort" "strings" "testing" "git.sr.ht/~enckse/lockbox/internal/app/completions" - "git.sr.ht/~enckse/lockbox/internal/reflect" ) func TestCompletions(t *testing.T) { @@ -20,29 +16,6 @@ func TestCompletions(t *testing.T) { } } -func TestConditionals(t *testing.T) { - c := completions.NewConditionals() - sort.Strings(c.Exported) - need := []string{"LOCKBOX_READONLY"} - if len(c.Exported) != len(need) || fmt.Sprintf("%v", c.Exported) != fmt.Sprintf("%v", need) { - t.Errorf("invalid exports: %v", c.Exported) - } - fields := reflect.ListFields(c.Not) - if len(fields) != len(need)+1 { - t.Errorf("invalid fields: %v", fields) - } - for _, n := range need { - value := "false" - switch n { - case "LOCKBOX_READONLY": - value = "true" - } - if !slices.Contains(fields, fmt.Sprintf(`[ "$%s" != "%s" ]`, n, value)) { - t.Errorf("needed conditional %s not found: %v", n, fields) - } - } -} - func testCompletion(t *testing.T, completionMode, need string) { v, err := completions.Generate(completionMode, "lb") if err != nil { diff --git a/internal/app/completions/shell/bash.sh b/internal/app/completions/shell/bash.sh @@ -2,13 +2,10 @@ _{{ $.Executable }}() { local cur opts chosen found - source <({{ $.ExportCommand }}) cur=${COMP_WORDS[COMP_CWORD]} if [ "$COMP_CWORD" -eq 1 ]; then {{- range $idx, $value := $.Options }} - if {{ $value.Conditional }}; then - opts="${opts}{{ $value.Key }} " - fi + opts="${opts}{{ $value }} " {{- end}} # shellcheck disable=SC2207 COMPREPLY=( $(compgen -W "$opts" -- "$cur") ) @@ -19,10 +16,8 @@ _{{ $.Executable }}() { chosen=${COMP_WORDS[1]} found=0 {{- range $idx, $value := $.Options }} - if {{ $value.Conditional }}; then - if [ "$chosen" == "{{ $value.Key }}" ]; then - found=1 - fi + if [ "$chosen" == "{{ $value }}" ]; then + found=1 fi {{- end}} if [ "$found" -eq 0 ]; then @@ -42,9 +37,7 @@ _{{ $.Executable }}() { "{{ $.TOTPCommand }}") opts="{{ $.TOTPListCommand }} " {{- range $key, $value := .TOTPSubCommands }} - if {{ $value.Conditional }}; then - opts="$opts {{ $value.Key }}" - fi + opts="$opts {{ $value }}" {{- end}} ;; "{{ $.ShowCommand }}" | "{{ $.JSONCommand }}" | "{{ $.ClipCommand }}") @@ -60,10 +53,8 @@ _{{ $.Executable }}() { "{{ $.TOTPCommand }}") case "${COMP_WORDS[2]}" in {{- range $key, $value := $.TOTPSubCommands }} - "{{ $value.Key }}") - if {{ $value.Conditional }}; then - opts=$({{ $.DoTOTPList }}) - fi + "{{ $value }}") + opts=$({{ $.DoTOTPList }}) ;; {{- end}} esac diff --git a/internal/app/completions/shell/zsh.sh b/internal/app/completions/shell/zsh.sh @@ -3,7 +3,6 @@ _{{ $.Executable }}() { local curcontext="$curcontext" state len chosen found args typeset -A opt_args - source <({{ $.ExportCommand }}) _arguments \ '1: :->main'\ '*: :->args' @@ -13,12 +12,10 @@ _{{ $.Executable }}() { main) args="" {{- range $idx, $value := $.Options }} - if {{ $value.Conditional }}; then - if [ -n "$args" ]; then - args="$args " - fi - args="${args}{{ $value.Key }}" + if [ -n "$args" ]; then + args="$args " fi + args="${args}{{ $value }}" {{- end }} _arguments "1:main:($args)" ;; @@ -29,10 +26,8 @@ _{{ $.Executable }}() { chosen=$words[2] found=0 {{- range $idx, $value := $.Options }} - if {{ $value.Conditional }}; then - if [[ "$chosen" == "{{ $value.Key }}" ]]; then - found=1 - fi + if [[ "$chosen" == "{{ $value }}" ]]; then + found=1 fi {{- end }} if [ "$found" -eq 0 ]; then @@ -67,18 +62,14 @@ _{{ $.Executable }}() { 3) compadd "$@" {{ $.TOTPListCommand }} {{- range $key, $value := .TOTPSubCommands }} - if {{ $value.Conditional }}; then - compadd "$@" {{ $value.Key }} - fi + compadd "$@" {{ $value }} {{ end }} ;; 4) case $words[3] in {{- range $key, $value := .TOTPSubCommands }} - "{{ $value.Key }}") - if {{ $value.Conditional }}; then - compadd "$@" $({{ $.DoTOTPList }}) - fi + "{{ $value }}") + compadd "$@" $({{ $.DoTOTPList }}) ;; {{- end}} esac diff --git a/internal/app/info.go b/internal/app/info.go @@ -61,12 +61,7 @@ func info(command string, args []string) ([]string, error) { switch len(args) { case 0: case 1: - sub := args[0] - if sub == commands.Completions { - set = completions.NewConditionals().Exported - } else { - set = []string{sub} - } + set = []string{args[0]} default: return nil, errors.New("invalid env command, too many arguments") } diff --git a/internal/app/info_test.go b/internal/app/info_test.go @@ -83,14 +83,6 @@ func TestEnvInfo(t *testing.T) { } store.SetString("LOCKBOX_READONLY", "true") buf = bytes.Buffer{} - ok, err = app.Info(&buf, "vars", []string{"completions"}) - if !ok || err != nil { - t.Errorf("invalid error: %v", err) - } - if strings.TrimSpace(buf.String()) != "LOCKBOX_READONLY=true" { - t.Error("nothing written") - } - buf = bytes.Buffer{} ok, err = app.Info(&buf, "vars", []string{"LOCKBOX_READONLY"}) if !ok || err != nil { t.Errorf("invalid error: %v", err)