mirror of
https://github.com/lukaszraczylo/kportal.git
synced 2026-07-11 07:22:15 +00:00
Optimisation & fixes
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/lukaszraczylo/kportal/internal/complete"
|
||||
)
|
||||
|
||||
// completionCmd handles shell completion generation and installation
|
||||
func completionCmd(args []string) int {
|
||||
fs := flag.NewFlagSet("completion", flag.ContinueOnError)
|
||||
fs.SetOutput(os.Stderr)
|
||||
|
||||
var (
|
||||
installFlag bool
|
||||
shellFlag string
|
||||
uninstall bool
|
||||
)
|
||||
|
||||
fs.BoolVar(&installFlag, "install", false, "Install completions for the shell")
|
||||
fs.BoolVar(&uninstall, "uninstall", false, "Uninstall completions")
|
||||
fs.StringVar(&shellFlag, "shell", "", "Shell type: bash, zsh, or fish (auto-detected if empty)")
|
||||
|
||||
if err := fs.Parse(args); err != nil {
|
||||
if err == flag.ErrHelp {
|
||||
printCompletionHelp()
|
||||
return 0
|
||||
}
|
||||
return 2
|
||||
}
|
||||
|
||||
// Determine shell type
|
||||
var shell complete.Shell
|
||||
if shellFlag != "" {
|
||||
switch shellFlag {
|
||||
case "bash":
|
||||
shell = complete.ShellBash
|
||||
case "zsh":
|
||||
shell = complete.ShellZsh
|
||||
case "fish":
|
||||
shell = complete.ShellFish
|
||||
default:
|
||||
fprintf(os.Stderr, "Error: unknown shell %q (use bash, zsh, or fish)\n", shellFlag)
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
shell = complete.AutoDetectShell()
|
||||
}
|
||||
|
||||
// Handle uninstall
|
||||
if uninstall {
|
||||
installer := complete.NewInstaller(shell)
|
||||
if err := installer.Uninstall(); err != nil {
|
||||
fprintf(os.Stderr, "Error uninstalling completions: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
fmt.Println("✅ Completions uninstalled")
|
||||
return 0
|
||||
}
|
||||
|
||||
// Handle install
|
||||
if installFlag {
|
||||
if err := complete.InstallCompletions(shell); err != nil {
|
||||
fprintf(os.Stderr, "Error installing completions: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Print completion script to stdout
|
||||
if err := complete.Print(shell); err != nil {
|
||||
fprintf(os.Stderr, "Error generating completions: %v\n", err)
|
||||
return 1
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
func printCompletionHelp() {
|
||||
fprintf(os.Stdout, `Generate shell completions for kportal.
|
||||
|
||||
Usage:
|
||||
kportal completion [flags]
|
||||
|
||||
Flags:
|
||||
--install Install completions for the current shell
|
||||
--uninstall Remove installed completions
|
||||
--shell <type> Shell type: bash, zsh, or fish (auto-detected)
|
||||
|
||||
Examples:
|
||||
# Generate and source completions (bash)
|
||||
source <(kportal completion)
|
||||
|
||||
# Install completions (requires shell restart)
|
||||
kportal completion --install
|
||||
|
||||
# Install for specific shell
|
||||
kportal completion --install --shell zsh
|
||||
|
||||
# Uninstall completions
|
||||
kportal completion --uninstall
|
||||
|
||||
Shell-specific setup:
|
||||
|
||||
Bash (~/.bashrc):
|
||||
source <(kportal completion)
|
||||
|
||||
Zsh (~/.zshrc):
|
||||
autoload -Uz compinit && compinit
|
||||
source <(kportal completion)
|
||||
|
||||
Fish (~/.config/fish/config.fish):
|
||||
kportal completion --install --shell fish
|
||||
# Or manually:
|
||||
kportal completion --shell fish > ~/.config/fish/completions/kportal.fish
|
||||
`)
|
||||
}
|
||||
+10
-5
@@ -117,9 +117,14 @@ func runMain() int {
|
||||
// of long-running modes (headless, verbose-loop, interactive).
|
||||
func run(ctx context.Context, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
|
||||
// Subcommand dispatch must run BEFORE the main flag set is parsed because
|
||||
// generate has its own FlagSet and must not see kportal's top-level flags.
|
||||
if len(args) >= 1 && args[0] == "generate" {
|
||||
return runGenerate(args[1:])
|
||||
// generate and completion have their own FlagSets and must not see kportal's top-level flags.
|
||||
if len(args) >= 1 {
|
||||
switch args[0] {
|
||||
case "generate":
|
||||
return runGenerate(args[1:])
|
||||
case "completion":
|
||||
return completionCmd(args[1:])
|
||||
}
|
||||
}
|
||||
|
||||
opts, code, handled := parseFlags(args, stderr)
|
||||
@@ -498,7 +503,7 @@ func runVerboseTable(ctx context.Context, opts runOptions, cfg *config.Config, d
|
||||
// Background update check (best effort).
|
||||
go func() {
|
||||
checker := version.NewChecker(githubOwner, githubRepo, appVersion)
|
||||
uctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
uctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
if update := checker.CheckForUpdate(uctx); update != nil {
|
||||
log.Printf("Update available: v%s (current: v%s) - %s",
|
||||
@@ -590,7 +595,7 @@ func runInteractive(ctx context.Context, opts runOptions, cfg *config.Config, de
|
||||
|
||||
go func() {
|
||||
checker := version.NewChecker(githubOwner, githubRepo, appVersion)
|
||||
uctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
uctx, cancel := context.WithTimeout(ctx, 10*time.Second)
|
||||
defer cancel()
|
||||
if update := checker.CheckForUpdate(uctx); update != nil {
|
||||
bubbleTeaUI.SetUpdateAvailable(update.LatestVersion, update.ReleaseURL)
|
||||
|
||||
Reference in New Issue
Block a user