fix(completion): offer unique hostnames without instance prefix

bash (and zsh without a matcher) only accept candidates that start with
the typed text, so "fsn1-bx1<Tab>" found nothing when every candidate
was qualified as "prod/…". Hostnames that exist in only one instance
are now offered bare; names present in several instances stay
qualified. Connecting to a bare name still checks every instance for
ambiguity, so the connection behavior is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sebastian UnterschützandClaude Opus 5.5 committed 2026-10-28 11:44:54 +01:00
1 parent 6243514def
commit 091f5cc518
5 files changed
+80 -4

No files matched your search

+37
View File
@@ -1,6 +1,10 @@
package main
import (
"sort"
"strings"
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/cache"
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/config"
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/netbox"
"git.zb-server.de/Sebi/ssh-netbox-wrapper/internal/shortcuts"
@@ -30,3 +34,36 @@ func normalizeTarget(cfg config.ShortcutsConfig, qualified bool) func(string) st
return name
}
}
// hostCompletions returns the cached hosts matching toComplete in a form that
// starts with the typed text, because bash and fish only accept such
// candidates. Without an instance prefix, a hostname that is unique across
// all instances is offered bare ("web01"), so it completes like with a single
// NetBox; connecting to it still checks every instance for ambiguity.
// Names present in several instances stay qualified ("prod/web01").
func hostCompletions(entries []cache.Entry, toComplete string) []string {
prefix := strings.ToLower(toComplete)
qualifiedInput := strings.Contains(prefix, "/")
instances := make(map[string]int)
for _, e := range entries {
_, name := netbox.SplitTarget(e.Name)
instances[strings.ToLower(name)]++
}
var out []string
for _, e := range entries {
source, name := netbox.SplitTarget(e.Name)
target := strings.ToLower(e.Name)
switch {
case source != "" && !qualifiedInput && strings.HasPrefix(strings.ToLower(name), prefix):
if instances[strings.ToLower(name)] == 1 {
out = append(out, name)
} else {
out = append(out, e.Name)
}
case strings.HasPrefix(target, prefix):
out = append(out, e.Name)
}
}
sort.Strings(out)
return out
}