diff --git a/cmd/ide/ide.go b/cmd/ide/ide.go index 8e932444f..bcfb39150 100644 --- a/cmd/ide/ide.go +++ b/cmd/ide/ide.go @@ -2,6 +2,7 @@ package ide import ( "github.com/devsy-org/devsy/cmd/flags" + "github.com/devsy-org/devsy/pkg/ide/ideparse" "github.com/spf13/cobra" ) @@ -18,3 +19,18 @@ func NewIDECmd(flags *flags.GlobalFlags) *cobra.Command { ideCmd.AddCommand(NewListCmd(flags)) return ideCmd } + +func ideNameCompletion( + _ *cobra.Command, + args []string, + _ string, +) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + names := make([]string, 0, len(ideparse.AllowedIDEs)) + for _, entry := range ideparse.AllowedIDEs { + names = append(names, string(entry.Name)) + } + return names, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/ide/list.go b/cmd/ide/list.go index 5d57e47a7..8ec435195 100644 --- a/cmd/ide/list.go +++ b/cmd/ide/list.go @@ -4,8 +4,8 @@ import ( "context" "encoding/json" "fmt" + "os" "sort" - "strconv" "github.com/devsy-org/devsy/cmd/flags" "github.com/devsy-org/devsy/pkg/config" @@ -59,9 +59,13 @@ func (cmd *ListCmd) Run(ctx context.Context) error { case output.ModePlain: tableEntries := [][]string{} for _, entry := range ideparse.AllowedIDEs { + marker := "" + if devsyConfig.Current().DefaultIDE == string(entry.Name) { + marker = "*" + } tableEntries = append(tableEntries, []string{ string(entry.Name), - strconv.FormatBool(devsyConfig.Current().DefaultIDE == string(entry.Name)), + marker, }) } sort.SliceStable(tableEntries, func(i, j int) bool { @@ -85,7 +89,7 @@ func (cmd *ListCmd) Run(ctx context.Context) error { if err != nil { return err } - fmt.Print(string(out)) + _, _ = fmt.Fprintln(os.Stdout, string(out)) } return nil diff --git a/cmd/ide/options.go b/cmd/ide/options.go index f4a094ac5..62ee9225a 100644 --- a/cmd/ide/options.go +++ b/cmd/ide/options.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "fmt" + "os" "sort" "github.com/devsy-org/devsy/cmd/flags" @@ -26,13 +27,11 @@ func NewOptionsCmd(flags *flags.GlobalFlags) *cobra.Command { GlobalFlags: flags, } optionsCmd := &cobra.Command{ - Use: "get", - Short: "Get IDE options", + Use: "get ", + Short: "Get IDE options (list available IDEs with 'devsy ide list')", + Args: cobra.ExactArgs(1), + ValidArgsFunction: ideNameCompletion, RunE: func(cobraCmd *cobra.Command, args []string) error { - if len(args) != 1 { - return fmt.Errorf("specify the ide") - } - return cmd.Run(cobraCmd.Context(), args[0]) }, } @@ -94,11 +93,11 @@ func (cmd *OptionsCmd) Run(ctx context.Context, ide string) error { } } - out, err := json.Marshal(options) + out, err := json.MarshalIndent(options, "", " ") if err != nil { return err } - fmt.Print(string(out)) + _, _ = fmt.Fprintln(os.Stdout, string(out)) } return nil diff --git a/cmd/ide/set.go b/cmd/ide/set.go index 85581aedd..062a2a146 100644 --- a/cmd/ide/set.go +++ b/cmd/ide/set.go @@ -8,8 +8,6 @@ import ( "github.com/devsy-org/devsy/cmd/flags" "github.com/devsy-org/devsy/pkg/config" "github.com/devsy-org/devsy/pkg/ide/ideparse" - "github.com/devsy-org/devsy/pkg/log" - "github.com/devsy-org/devsy/pkg/provider" "github.com/spf13/cobra" ) @@ -17,28 +15,29 @@ import ( type SetCmd struct { *flags.GlobalFlags - Options []string - Workspace string + Options []string } -// NewSetCmd creates the 'devsy ide set' command. Without --workspace it sets -// global options for the named IDE; with --workspace it assigns the IDE to an -// existing workspace without starting it. +// NewSetCmd creates the 'devsy ide set' command. It sets global options for +// the named IDE. To assign an IDE to a specific workspace, use +// 'devsy workspace set-ide '. func NewSetCmd(flags *flags.GlobalFlags) *cobra.Command { cmd := &SetCmd{ GlobalFlags: flags, } setCmd := &cobra.Command{ Use: "set ", - Short: "Set IDE options, or assign an IDE to a workspace with --workspace", - Long: `Set IDE options for the named IDE. - -With --workspace , assigns the IDE to an existing workspace without -starting it. The change is persisted to the workspace config and used on the -next 'devsy workspace up'. Available IDEs can be listed with 'devsy ide list'.`, + Short: "Set global IDE options", + Long: `Set global options for the named IDE. + +To assign an IDE to a specific workspace, use +'devsy workspace set-ide '. Available IDEs can be listed +with 'devsy ide list'.`, + Args: cobra.ExactArgs(1), + ValidArgsFunction: ideNameCompletion, RunE: func(cobraCmd *cobra.Command, args []string) error { - if len(args) != 1 { - return fmt.Errorf("specify the ide") + if len(cmd.Options) == 0 { + return fmt.Errorf("nothing to do: pass --option KEY=VALUE") } return cmd.Run(cobraCmd.Context(), args[0]) }, @@ -46,8 +45,6 @@ next 'devsy workspace up'. Available IDEs can be listed with 'devsy ide list'.`, setCmd.Flags(). StringArrayVarP(&cmd.Options, "option", "o", []string{}, "IDE option in the form KEY=VALUE") - setCmd.Flags(). - StringVar(&cmd.Workspace, "workspace", "", "Assign the IDE to this workspace instead of setting global options") return setCmd } @@ -64,14 +61,8 @@ func (cmd *SetCmd) Run(_ context.Context, ideName string) error { return err } - if cmd.Workspace != "" { - return cmd.runWorkspace(devsyConfig, ideName) - } - - if len(cmd.Options) > 0 { - if err := setOptions(devsyConfig, ideName, cmd.Options, ideOptions); err != nil { - return err - } + if err := setOptions(devsyConfig, ideName, cmd.Options, ideOptions); err != nil { + return err } if err := config.SaveConfig(devsyConfig); err != nil { @@ -79,23 +70,3 @@ func (cmd *SetCmd) Run(_ context.Context, ideName string) error { } return nil } - -func (cmd *SetCmd) runWorkspace(devsyConfig *config.Config, ideName string) error { - contextName := devsyConfig.DefaultContext - if !provider.WorkspaceExists(contextName, cmd.Workspace) { - return fmt.Errorf("workspace %q not found in context %q", cmd.Workspace, contextName) - } - - workspace, err := provider.LoadWorkspaceConfig(contextName, cmd.Workspace) - if err != nil { - return fmt.Errorf("load workspace config: %w", err) - } - - workspace, err = ideparse.RefreshIDEOptions(devsyConfig, workspace, ideName, cmd.Options) - if err != nil { - return fmt.Errorf("refresh ide options: %w", err) - } - - log.Infof("set IDE for workspace %q to %q", workspace.ID, workspace.IDE.Name) - return nil -} diff --git a/cmd/ide/use.go b/cmd/ide/use.go index 034b9e488..db10b8403 100644 --- a/cmd/ide/use.go +++ b/cmd/ide/use.go @@ -10,6 +10,7 @@ import ( "github.com/devsy-org/devsy/pkg/config" "github.com/devsy-org/devsy/pkg/ide" "github.com/devsy-org/devsy/pkg/ide/ideparse" + "github.com/devsy-org/devsy/pkg/log" options2 "github.com/devsy-org/devsy/pkg/options" "github.com/spf13/cobra" ) @@ -27,18 +28,14 @@ func NewUseCmd(flags *flags.GlobalFlags) *cobra.Command { GlobalFlags: flags, } useCmd := &cobra.Command{ - Use: "use", + Use: "use ", Short: "Configure the default IDE to use (list available IDEs with 'devsy ide list')", Long: `Configure the default IDE to use Available IDEs can be listed with 'devsy ide list'`, + Args: cobra.ExactArgs(1), + ValidArgsFunction: ideNameCompletion, RunE: func(cobraCmd *cobra.Command, args []string) error { - if len(args) != 1 { - return fmt.Errorf( - "specify the ide to use, list available IDEs with 'devsy ide list'", - ) - } - return cmd.Run(cobraCmd.Context(), args[0]) }, } @@ -75,6 +72,7 @@ func (cmd *UseCmd) Run(ctx context.Context, ide string) error { return fmt.Errorf("save config: %w", err) } + log.Infof("default IDE set to %q", ide) return nil } diff --git a/cmd/workspace/set_ide.go b/cmd/workspace/set_ide.go new file mode 100644 index 000000000..ff5f4fa88 --- /dev/null +++ b/cmd/workspace/set_ide.go @@ -0,0 +1,95 @@ +package workspace + +import ( + "context" + "fmt" + "strings" + + "github.com/devsy-org/devsy/cmd/completion" + "github.com/devsy-org/devsy/cmd/flags" + "github.com/devsy-org/devsy/pkg/config" + "github.com/devsy-org/devsy/pkg/ide/ideparse" + "github.com/devsy-org/devsy/pkg/log" + "github.com/devsy-org/devsy/pkg/provider" + "github.com/spf13/cobra" +) + +// SetIDECmd holds the set-ide cmd flags. +type SetIDECmd struct { + *flags.GlobalFlags + + Options []string +} + +// NewSetIDECmd creates the 'devsy workspace set-ide' command. It assigns an +// IDE to an existing workspace without starting it. The change is persisted +// to the workspace config and used on the next 'devsy workspace up'. +func NewSetIDECmd(globalFlags *flags.GlobalFlags) *cobra.Command { + cmd := &SetIDECmd{ + GlobalFlags: globalFlags, + } + + setIDECmd := &cobra.Command{ + Use: "set-ide ", + Short: "Assign an IDE to an existing workspace", + Long: `Assign an IDE to an existing workspace without starting it. + +The change is persisted to the workspace config and used on the next +'devsy workspace up'. Available IDEs can be listed with 'devsy ide list'.`, + Args: cobra.ExactArgs(2), + RunE: func(cobraCmd *cobra.Command, args []string) error { + return cmd.Run(cobraCmd.Context(), args[0], args[1]) + }, + ValidArgsFunction: func( + rootCmd *cobra.Command, args []string, toComplete string, + ) ([]string, cobra.ShellCompDirective) { + if len(args) == 0 { + return completion.GetWorkspaceSuggestions( + rootCmd, + cmd.Context, + cmd.Provider, + args, + toComplete, + cmd.Owner, + ) + } + return nil, cobra.ShellCompDirectiveNoFileComp + }, + } + + setIDECmd.Flags(). + StringArrayVarP(&cmd.Options, "option", "o", []string{}, "IDE option in the form KEY=VALUE") + return setIDECmd +} + +// Run validates inputs and applies the IDE assignment to the workspace config. +func (cmd *SetIDECmd) Run(_ context.Context, workspaceName, ideName string) error { + ideName = strings.ToLower(ideName) + + devsyConfig, err := config.LoadConfig(cmd.Context, cmd.Provider) + if err != nil { + return err + } + + if _, err := ideparse.GetIDEOptions(ideName); err != nil { + return err + } + + contextName := devsyConfig.DefaultContext + if !provider.WorkspaceExists(contextName, workspaceName) { + return fmt.Errorf("workspace %q not found in context %q", workspaceName, contextName) + } + + workspace, err := provider.LoadWorkspaceConfig(contextName, workspaceName) + if err != nil { + return fmt.Errorf("load workspace config: %w", err) + } + + workspace, err = ideparse.RefreshIDEOptions(devsyConfig, workspace, ideName, cmd.Options) + if err != nil { + return fmt.Errorf("refresh ide options: %w", err) + } + + log.Infof("set IDE for workspace %q to %q", workspace.ID, workspace.IDE.Name) + return nil +} diff --git a/cmd/workspace/workspace.go b/cmd/workspace/workspace.go index 8bebc7d58..7949971c3 100644 --- a/cmd/workspace/workspace.go +++ b/cmd/workspace/workspace.go @@ -22,6 +22,7 @@ func NewWorkspaceCmd(globalFlags *flags.GlobalFlags) *cobra.Command { cmd.AddCommand(NewLogsCmd(globalFlags)) cmd.AddCommand(NewBuildCmd(globalFlags)) cmd.AddCommand(NewRenameCmd(globalFlags)) + cmd.AddCommand(NewSetIDECmd(globalFlags)) cmd.AddCommand(NewExportCmd(globalFlags)) cmd.AddCommand(NewImportCmd(globalFlags)) cmd.AddCommand(NewPingCmd(globalFlags)) diff --git a/desktop/src/main/ipc.ts b/desktop/src/main/ipc.ts index 3b0f0b208..4bb9ff61e 100644 --- a/desktop/src/main/ipc.ts +++ b/desktop/src/main/ipc.ts @@ -149,7 +149,7 @@ export function registerIpcHandlers(deps: IpcDependencies): { "workspace_set_ide", async (_event, args: { workspaceId: string; ide: string }) => { trackEvent("workspace_set_ide", { ide: args.ide }) - await cli.runRaw(["ide", "set", args.ide, "--workspace", args.workspaceId]) + await cli.runRaw(["workspace", "set-ide", args.workspaceId, args.ide]) }, )