package context import ( "fmt" "maps" "slices" "charm.land/huh/v2" "github.com/psviderski/uncloud/internal/cli" "github.com/psviderski/uncloud/internal/cli/completion" "github.com/psviderski/uncloud/internal/cli/tui" "github.com/spf13/cobra" ) func NewUseCommand() *cobra.Command { cmd := &cobra.Command{ Use: "use [CONTEXT]", Short: "Switch to a different cluster context.", Long: "Switch to a different cluster context. If no context is provided, " + "a list of available contexts will be displayed for selection.", Args: cobra.MaximumNArgs(1), RunE: func(cmd *cobra.Command, args []string) error { uncli := cmd.Context().Value("cli").(*cli.CLI) if len(args) == 1 { if err := uncli.SetCurrentContext(args[0]); err != nil { return fmt.Errorf("failed to set the current cluster context to '%s': %w", args[0], err) } fmt.Printf("Current cluster context is now '%s'.\n", args[0]) return nil } return selectContext(uncli) }, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]cobra.Completion, cobra.ShellCompDirective) { if len(args) > 0 { return nil, cobra.ShellCompDirectiveNoFileComp } uncli := cmd.Context().Value("cli").(*cli.CLI) return completion.Contexts(cmd.Context(), uncli, args, toComplete) }, } return cmd } func selectContext(uncli *cli.CLI) error { if uncli.Config == nil { return fmt.Errorf("context management is not available: Uncloud configuration file is not being used") } if len(uncli.Config.Contexts) == 0 { return fmt.Errorf("no contexts found in Uncloud config (%s)", uncli.Config.Path()) } if !tui.IsTerminalAvailable() { return fmt.Errorf("cannot select a context interactively without a terminal. " + "Pass the context name explicitly: uc ctx use CONTEXT") } contextNames := slices.Sorted(maps.Keys(uncli.Config.Contexts)) var selected string form := huh.NewForm( huh.NewGroup( huh.NewSelect[string](). Title("Select a cluster context"). Options(buildContextOptions(contextNames, uncli.Config.CurrentContext)...). Value(&selected), ), ) if err := form.Run(); err != nil { return fmt.Errorf("select cluster context: %w", err) } if err := uncli.SetCurrentContext(selected); err != nil { return fmt.Errorf("set current cluster context: %w", err) } fmt.Printf("Current cluster context is now '%s'.\n", selected) return nil } func buildContextOptions(contexts []string, current string) []huh.Option[string] { options := make([]huh.Option[string], len(contexts)) for i, ctx := range contexts { opt := huh.NewOption(ctx, ctx) if ctx == current { opt.Key += " (current)" opt = opt.Selected(true) } options[i] = opt } return options }