Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 61 additions & 8 deletions pkg/cmd/open/open.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,12 @@ const (
EditorCursor = "cursor"
EditorWindsurf = "windsurf"
EditorTmux = "tmux"
EditorVim = "vim"
)

var (
openLong = "[command in beta] This will open VS Code, Cursor, Windsurf, or tmux SSH-ed in to your instance. You must have the editor installed in your path."
openExample = "brev open instance_id_or_name\nbrev open instance\nbrev open instance code\nbrev open instance cursor\nbrev open instance windsurf\nbrev open instance tmux\nbrev open --set-default cursor\nbrev open --set-default windsurf\nbrev open --set-default tmux"
openLong = "[command in beta] This will open VS Code, Cursor, Windsurf, tmux, or vim SSH-ed in to your instance. You must have the editor installed in your path."
openExample = "brev open instance_id_or_name\nbrev open instance\nbrev open instance code\nbrev open instance cursor\nbrev open instance windsurf\nbrev open instance tmux\nbrev open instance vim\nbrev open --set-default cursor\nbrev open --set-default windsurf\nbrev open --set-default tmux\nbrev open --set-default vim"
)

type OpenStore interface {
Expand Down Expand Up @@ -100,14 +101,14 @@ func NewCmdOpen(t *terminal.Terminal, store OpenStore, noLoginStartStore OpenSto
cmd.Flags().BoolVarP(&host, "host", "", false, "ssh into the host machine instead of the container")
cmd.Flags().BoolVarP(&waitForSetupToFinish, "wait", "w", false, "wait for setup to finish")
cmd.Flags().StringVarP(&directory, "dir", "d", "", "directory to open")
cmd.Flags().StringVar(&setDefault, "set-default", "", "set default editor (code, cursor, windsurf, or tmux)")
cmd.Flags().StringVar(&setDefault, "set-default", "", "set default editor (code, cursor, windsurf, tmux, or vim)")

return cmd
}

func handleSetDefault(t *terminal.Terminal, editorType string) error {
if editorType != EditorVSCode && editorType != EditorCursor && editorType != EditorWindsurf && editorType != EditorTmux {
return fmt.Errorf("invalid editor type: %s. Must be 'code', 'cursor', 'windsurf', or 'tmux'", editorType)
if editorType != EditorVSCode && editorType != EditorCursor && editorType != EditorWindsurf && editorType != EditorTmux && editorType != EditorVim {
return fmt.Errorf("invalid editor type: %s. Must be 'code', 'cursor', 'windsurf', 'tmux', or 'vim'", editorType)
}

homeDir, err := os.UserHomeDir()
Expand All @@ -131,8 +132,8 @@ func handleSetDefault(t *terminal.Terminal, editorType string) error {
func determineEditorType(args []string) (string, error) {
if len(args) == 2 {
editorType := args[1]
if editorType != EditorVSCode && editorType != EditorCursor && editorType != EditorWindsurf && editorType != EditorTmux {
return "", fmt.Errorf("invalid editor type: %s. Must be 'code', 'cursor', 'windsurf', or 'tmux'", editorType)
if editorType != EditorVSCode && editorType != EditorCursor && editorType != EditorWindsurf && editorType != EditorTmux && editorType != EditorVim {
return "", fmt.Errorf("invalid editor type: %s. Must be 'code', 'cursor', 'windsurf', 'tmux', or 'vim'", editorType)
}
return editorType, nil
}
Expand All @@ -151,7 +152,7 @@ func determineEditorType(args []string) (string, error) {
}

// Fetch workspace info, then open code editor
func runOpenCommand(t *terminal.Terminal, tstore OpenStore, wsIDOrName string, setupDoneString string, directory string, host bool, editorType string) error { //nolint:funlen // define brev command
func runOpenCommand(t *terminal.Terminal, tstore OpenStore, wsIDOrName string, setupDoneString string, directory string, host bool, editorType string) error { //nolint:funlen,gocyclo // define brev command
// todo check if workspace is stopped and start if it if it is stopped
fmt.Println("finding your instance...")
res := refresh.RunRefreshAsync(tstore)
Expand Down Expand Up @@ -220,6 +221,10 @@ func runOpenCommand(t *terminal.Terminal, tstore OpenStore, wsIDOrName string, s
errMsg := "tmux not found on remote instance. This will be installed automatically."
return handlePathError(tstore, workspace, errMsg)
}
if strings.Contains(err.Error(), `vim: command not found`) {
errMsg := "vim not found on remote instance. This will be installed automatically."
return handlePathError(tstore, workspace, errMsg)
}
return breverrors.WrapAndTrace(err)
}
// Call analytics for open
Expand Down Expand Up @@ -353,12 +358,16 @@ func tryToInstallWindsurfExtensions(
// Opens code editor. Attempts to install code in path if not installed already
func getEditorName(editorType string) string {
switch editorType {
case EditorVSCode:
return "VSCode"
case EditorCursor:
return "Cursor"
case EditorWindsurf:
return "Windsurf"
case EditorTmux:
return "tmux"
case EditorVim:
return "vim"
default:
return "VSCode"
}
Expand Down Expand Up @@ -389,6 +398,8 @@ func openEditorByType(t *terminal.Terminal, editorType string, sshAlias string,
return openWindsurf(sshAlias, path, tstore)
case EditorTmux:
return openTmux(sshAlias, path, tstore)
case EditorVim:
return openVim(sshAlias, path, tstore)
default:
tryToInstallExtensions(t, extensions)
return openVsCode(sshAlias, path, tstore)
Expand Down Expand Up @@ -568,6 +579,28 @@ func openTmux(sshAlias string, path string, store OpenStore) error {
return nil
}

func openVim(sshAlias string, path string, store OpenStore) error {
_ = store

err := ensureVimInstalled(sshAlias)
if err != nil {
return breverrors.WrapAndTrace(err)
}

vimCmd := fmt.Sprintf("ssh -t %s 'cd %s && vim'", sshAlias, path)

sshCmd := exec.Command("bash", "-c", vimCmd) // #nosec G204
sshCmd.Stderr = os.Stderr
sshCmd.Stdout = os.Stdout
sshCmd.Stdin = os.Stdin

err = sshCmd.Run()
if err != nil {
return breverrors.WrapAndTrace(err)
}
return nil
}

func ensureTmuxInstalled(sshAlias string) error {
checkCmd := fmt.Sprintf("ssh %s 'which tmux >/dev/null 2>&1'", sshAlias)
checkExec := exec.Command("bash", "-c", checkCmd) // #nosec G204
Expand All @@ -587,3 +620,23 @@ func ensureTmuxInstalled(sshAlias string) error {
}
return nil
}

func ensureVimInstalled(sshAlias string) error {
checkCmd := fmt.Sprintf("ssh %s 'which vim >/dev/null 2>&1'", sshAlias)
checkExec := exec.Command("bash", "-c", checkCmd) // #nosec G204
err := checkExec.Run()
if err == nil {
return nil
}

installCmd := fmt.Sprintf("ssh %s 'sudo apt-get update && sudo apt-get install -y vim'", sshAlias)
installExec := exec.Command("bash", "-c", installCmd) // #nosec G204
installExec.Stderr = os.Stderr
installExec.Stdout = os.Stdout

err = installExec.Run()
if err != nil {
return breverrors.WrapAndTrace(err)
}
return nil
}
Loading