feat(shortcuts): regex rewrite rules for host shortcuts
shortcuts.rewrites applies regex replacements after the domain suffix is stripped, e.g. ^([a-z]+)[0-9]+- -> $1 turns fsn1-bx1.hoster.de into fsnbx1. The shortcut works for connecting (cached hosts), shell aliases, and Tab completion, where it is offered when the full name does not match the typed text. Rules are editable in netssh configure, and netssh alias --test HOSTNAME shows a name's shortcut and the cached hosts it matches. The shortcut lookup only ran when domains or strip_hyphens were set; it now also runs for rewrite-only configurations. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
d51c040d9f
commit
878701aba7
12 files changed
+408
-21
No files matched your search
+37
-4
@@ -132,7 +132,7 @@ func runSSHWrapper(args []string) {
|
||||
// Shortcut cache lookup: scan entries whose normalized name matches the input.
|
||||
// If a stale match is found, use the canonical name for the NetBox re-fetch below.
|
||||
lookupHost := parsed.Host
|
||||
shortcutsEnabled := len(cfg.Shortcuts.Domains) > 0 || cfg.Shortcuts.StripHyphens
|
||||
shortcutsEnabled := cfg.Shortcuts.Enabled()
|
||||
if cached, _ := c.Get(lookupHost); shortcutsEnabled && cached.Name == "" && useCache {
|
||||
normalize := normalizeTarget(cfg.Shortcuts, source != "")
|
||||
entry, found, fresh, err := c.GetByShortcut(lookupHost, normalize)
|
||||
@@ -339,7 +339,7 @@ func rootCmd() *cobra.Command {
|
||||
c := cache.New(cfg.CachePath(), cfg.Cache.TTL)
|
||||
_ = c.Load()
|
||||
|
||||
hosts := hostCompletions(c.All(), toComplete)
|
||||
hosts := hostCompletions(c.All(), toComplete, cfg.Shortcuts)
|
||||
if limit := cfg.Completion.MaxResults; limit > 0 && len(hosts) > limit {
|
||||
hosts = hosts[:limit]
|
||||
}
|
||||
@@ -645,13 +645,15 @@ func buildAliasEntries(c *cache.Cache, cfg config.Config) []hook.AliasEntry {
|
||||
}
|
||||
|
||||
func aliasCmd() *cobra.Command {
|
||||
var shell string
|
||||
var shell, test string
|
||||
cmd := &cobra.Command{
|
||||
Use: "alias",
|
||||
Short: "Print shell aliases for all cached hosts",
|
||||
Long: `Print shell alias definitions for all cached hosts.
|
||||
The alias name is the shortened form derived from the configured shortcuts
|
||||
(domain suffixes stripped, hyphens optionally stripped).
|
||||
(domain suffixes stripped, rewrite rules applied, hyphens optionally stripped).
|
||||
|
||||
Check a rule with: netssh alias --test fsn1-bx1.example.com
|
||||
|
||||
Source the output in your shell profile:
|
||||
bash/zsh: eval "$(netssh alias)"
|
||||
@@ -668,6 +670,10 @@ Or use in a script:
|
||||
if err := c.Load(); err != nil {
|
||||
return err
|
||||
}
|
||||
if test != "" {
|
||||
printShortcutTest(os.Stdout, test, c.All(), cfg.Shortcuts)
|
||||
return nil
|
||||
}
|
||||
if shell == "" {
|
||||
shell = filepath.Base(os.Getenv("SHELL"))
|
||||
}
|
||||
@@ -694,9 +700,36 @@ Or use in a script:
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringVar(&shell, "shell", "", "Output format: bash, zsh, fish (default: $SHELL)")
|
||||
cmd.Flags().StringVar(&test, "test", "", "Show the shortcut for a hostname and the cached hosts it matches")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// printShortcutTest helps writing shortcut rules: it shows what a name is
|
||||
// shortened to and which cached hosts share that shortcut.
|
||||
func printShortcutTest(w io.Writer, name string, entries []cache.Entry, sc config.ShortcutsConfig) {
|
||||
normalize := normalizeTarget(sc, strings.Contains(name, "/"))
|
||||
short := normalize(name)
|
||||
fmt.Fprintf(w, "%s → %s\n", name, short)
|
||||
var matches []string
|
||||
for _, e := range entries {
|
||||
if normalize(e.Name) == short {
|
||||
matches = append(matches, e.Name)
|
||||
}
|
||||
}
|
||||
sort.Strings(matches)
|
||||
switch len(matches) {
|
||||
case 0:
|
||||
fmt.Fprintln(w, "no cached host has this shortcut")
|
||||
case 1:
|
||||
fmt.Fprintf(w, "matches %s\n", matches[0])
|
||||
default:
|
||||
fmt.Fprintf(w, "ambiguous, matches %d hosts:\n", len(matches))
|
||||
for _, m := range matches {
|
||||
fmt.Fprintf(w, " %s\n", m)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// shellInitCmd is called at shell startup to update alias files and trigger a
|
||||
// background cache refresh when stale. Intentionally silent — never disrupts the prompt.
|
||||
func shellInitCmd() *cobra.Command {
|
||||
|
||||
Reference in new issue
Block a user