feat: netssh completion install — user-space shell completion setup
Adds `netssh completion install` subcommand: - Auto-detects shell from $SHELL, override with --shell bash|zsh|fish - bash → ~/.local/share/bash-completion/completions/netssh - zsh → ~/.zfunc/_netssh (prints fpath hint) - fish → ~/.config/fish/completions/netssh.fish - No sudo required Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+75
-1
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
@@ -207,11 +208,84 @@ func rootCmd() *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
// cobra automatically adds a "completion" subcommand
|
// cobra automatically adds a "completion" subcommand; we extend it with "install".
|
||||||
root.AddCommand(configureCmd(), searchCmd(), cacheCmd())
|
root.AddCommand(configureCmd(), searchCmd(), cacheCmd())
|
||||||
|
|
||||||
|
for _, cmd := range root.Commands() {
|
||||||
|
if cmd.Name() == "completion" {
|
||||||
|
cmd.AddCommand(completionInstallCmd(root))
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return root
|
return root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func completionInstallCmd(root *cobra.Command) *cobra.Command {
|
||||||
|
var shell string
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "install",
|
||||||
|
Short: "Install shell completion for the current user (no sudo required)",
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if shell == "" {
|
||||||
|
shell = filepath.Base(os.Getenv("SHELL"))
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
dir string
|
||||||
|
file string
|
||||||
|
gen func() ([]byte, error)
|
||||||
|
note string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch shell {
|
||||||
|
case "bash":
|
||||||
|
dir = filepath.Join(os.Getenv("HOME"), ".local", "share", "bash-completion", "completions")
|
||||||
|
file = filepath.Join(dir, "netssh")
|
||||||
|
gen = func() ([]byte, error) {
|
||||||
|
var buf strings.Builder
|
||||||
|
return []byte(buf.String()), root.GenBashCompletionV2(&buf, true)
|
||||||
|
}
|
||||||
|
note = "Reload your shell or run: source " + file
|
||||||
|
case "zsh":
|
||||||
|
dir = filepath.Join(os.Getenv("HOME"), ".zfunc")
|
||||||
|
file = filepath.Join(dir, "_netssh")
|
||||||
|
gen = func() ([]byte, error) {
|
||||||
|
var buf strings.Builder
|
||||||
|
return []byte(buf.String()), root.GenZshCompletion(&buf)
|
||||||
|
}
|
||||||
|
note = "Make sure ~/.zfunc is in your fpath:\n fpath=(~/.zfunc $fpath)\n autoload -Uz compinit && compinit"
|
||||||
|
case "fish":
|
||||||
|
configDir, _ := os.UserConfigDir()
|
||||||
|
dir = filepath.Join(configDir, "fish", "completions")
|
||||||
|
file = filepath.Join(dir, "netssh.fish")
|
||||||
|
gen = func() ([]byte, error) {
|
||||||
|
var buf strings.Builder
|
||||||
|
return []byte(buf.String()), root.GenFishCompletion(&buf, true)
|
||||||
|
}
|
||||||
|
note = "Reload your shell or start a new fish session."
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("unsupported shell %q — use --shell bash|zsh|fish", shell)
|
||||||
|
}
|
||||||
|
|
||||||
|
script, err := gen()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("generating completion: %w", err)
|
||||||
|
}
|
||||||
|
if err := os.MkdirAll(dir, 0o755); err != nil {
|
||||||
|
return fmt.Errorf("creating %s: %w", dir, err)
|
||||||
|
}
|
||||||
|
if err := os.WriteFile(file, script, 0o644); err != nil {
|
||||||
|
return fmt.Errorf("writing %s: %w", file, err)
|
||||||
|
}
|
||||||
|
fmt.Printf("Completion installed → %s\n%s\n", file, note)
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&shell, "shell", "", "Shell to install for (default: $SHELL). Supported: bash, zsh, fish")
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
func configureCmd() *cobra.Command {
|
func configureCmd() *cobra.Command {
|
||||||
return &cobra.Command{
|
return &cobra.Command{
|
||||||
Use: "configure",
|
Use: "configure",
|
||||||
|
|||||||
Reference in New Issue
Block a user