Skip to content

Commit

Permalink
feat: run autocomplete on init (#1291)
Browse files Browse the repository at this point in the history
Signed-off-by: Ivan Dagelic <[email protected]>
  • Loading branch information
idagelic authored Oct 25, 2024
1 parent 1f146b3 commit 35da4d8
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 114 deletions.
4 changes: 4 additions & 0 deletions cmd/daytona/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"os/exec"
"path/filepath"

"github.com/daytonaio/daytona/pkg/cmd/autocomplete"
"github.com/google/uuid"
)

Expand Down Expand Up @@ -51,6 +52,9 @@ func GetConfig() (*Config, error) {

_, err = os.Stat(configFilePath)
if os.IsNotExist(err) {
// Setup autocompletion when adding initial config
_ = autocomplete.DetectShellAndSetupAutocompletion(autocomplete.AutoCompleteCmd.Root())

config := &Config{
Id: uuid.NewString(),
DefaultIdeId: getInitialDefaultIde(),
Expand Down
2 changes: 1 addition & 1 deletion docs/daytona.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ daytona [flags]
### SEE ALSO

* [daytona api-key](daytona_api-key.md) - Api Key commands
* [daytona autocomplete](daytona_autocomplete.md) - Adds completion script for your shell enviornment
* [daytona autocomplete](daytona_autocomplete.md) - Adds a completion script for your shell environment
* [daytona build](daytona_build.md) - Manage builds
* [daytona code](daytona_code.md) - Open a workspace in your preferred IDE
* [daytona config](daytona_config.md) - Output Daytona configuration
Expand Down
2 changes: 1 addition & 1 deletion docs/daytona_autocomplete.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## daytona autocomplete

Adds completion script for your shell enviornment
Adds a completion script for your shell environment

```
daytona autocomplete [bash|zsh|fish|powershell] [flags]
Expand Down
2 changes: 1 addition & 1 deletion docs/workspace_mode/daytona.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ daytona [flags]
### SEE ALSO

* [daytona agent](daytona_agent.md) - Start the agent process
* [daytona autocomplete](daytona_autocomplete.md) - Adds completion script for your shell enviornment
* [daytona autocomplete](daytona_autocomplete.md) - Adds a completion script for your shell environment
* [daytona docs](daytona_docs.md) - Opens the Daytona documentation in your default browser.
* [daytona expose](daytona_expose.md) - Expose a local port over stdout - Used by the Daytona CLI to make direct connections to the project
* [daytona forward](daytona_forward.md) - Forward a port publicly via an URL
Expand Down
2 changes: 1 addition & 1 deletion docs/workspace_mode/daytona_autocomplete.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
## daytona autocomplete

Adds completion script for your shell enviornment
Adds a completion script for your shell environment

```
daytona autocomplete [bash|zsh|fish|powershell] [flags]
Expand Down
2 changes: 1 addition & 1 deletion hack/docs/daytona.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ options:
usage: Display the version of Daytona
see_also:
- daytona api-key - Api Key commands
- daytona autocomplete - Adds completion script for your shell enviornment
- daytona autocomplete - Adds a completion script for your shell environment
- daytona build - Manage builds
- daytona code - Open a workspace in your preferred IDE
- daytona config - Output Daytona configuration
Expand Down
2 changes: 1 addition & 1 deletion hack/docs/daytona_autocomplete.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: daytona autocomplete
synopsis: Adds completion script for your shell enviornment
synopsis: Adds a completion script for your shell environment
usage: daytona autocomplete [bash|zsh|fish|powershell] [flags]
inherited_options:
- name: help
Expand Down
2 changes: 1 addition & 1 deletion hack/docs/workspace_mode/daytona.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ options:
usage: Display the version of Daytona
see_also:
- daytona agent - Start the agent process
- daytona autocomplete - Adds completion script for your shell enviornment
- daytona autocomplete - Adds a completion script for your shell environment
- daytona docs - Opens the Daytona documentation in your default browser.
- daytona expose - Expose a local port over stdout - Used by the Daytona CLI to make direct connections to the project
- daytona forward - Forward a port publicly via an URL
Expand Down
2 changes: 1 addition & 1 deletion hack/docs/workspace_mode/daytona_autocomplete.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: daytona autocomplete
synopsis: Adds completion script for your shell enviornment
synopsis: Adds a completion script for your shell environment
usage: daytona autocomplete [bash|zsh|fish|powershell] [flags]
inherited_options:
- name: help
Expand Down
106 changes: 0 additions & 106 deletions pkg/cmd/autocomplete.go

This file was deleted.

139 changes: 139 additions & 0 deletions pkg/cmd/autocomplete/autocomplete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
// Copyright 2024 Daytona Platforms Inc.
// SPDX-License-Identifier: Apache-2.0

package autocomplete

import (
"errors"
"fmt"
"os"
"path/filepath"
"strings"

"github.com/spf13/cobra"
)

var supportedShells = []string{"bash", "zsh", "fish", "powershell"}

var AutoCompleteCmd = &cobra.Command{
Use: fmt.Sprintf("autocomplete [%s]", strings.Join(supportedShells, "|")),
Short: "Adds a completion script for your shell environment",
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
shell := args[0]

profilePath, err := SetupAutocompletionForShell(cmd.Root(), shell)
if err != nil {
return err
}

fmt.Println("Autocomplete script generated and injected successfully.")
fmt.Printf("Please source your %s profile to apply the changes or restart your terminal.\n", shell)
fmt.Printf("For manual sourcing, use: source %s\n", profilePath)
if shell == "bash" {
fmt.Println("Please make sure that you have bash-completion installed in order to get full autocompletion functionality.")
fmt.Println("On how to install bash-completion, please refer to the following link: https://www.daytona.io/docs/tools/cli/#daytona-autocomplete")
}

return nil
},
}

func DetectShellAndSetupAutocompletion(rootCmd *cobra.Command) error {
shell := os.Getenv("SHELL")
if shell == "" {
return fmt.Errorf("unable to detect the shell, please use a supported one: %s", strings.Join(supportedShells, ", "))
}

for _, supportedShell := range supportedShells {
if strings.Contains(shell, supportedShell) {
shell = supportedShell
break
}
}

_, err := SetupAutocompletionForShell(rootCmd, shell)
if err != nil {
return err
}

return nil
}

func SetupAutocompletionForShell(rootCmd *cobra.Command, shell string) (string, error) {
homeDir, err := os.UserHomeDir()
if err != nil {
return "", fmt.Errorf("error finding user home directory: %s", err)
}

var filePath, profilePath string
switch shell {
case "bash":
filePath = filepath.Join(homeDir, ".daytona.completion_script.bash")
profilePath = filepath.Join(homeDir, ".bashrc")
case "zsh":
filePath = filepath.Join(homeDir, ".daytona.completion_script.zsh")
profilePath = filepath.Join(homeDir, ".zshrc")
case "fish":
filePath = filepath.Join(homeDir, ".config", "fish", "daytona.completion_script.fish")
profilePath = filepath.Join(homeDir, ".config", "fish", "config.fish")
case "powershell":
filePath = filepath.Join(homeDir, "daytona.completion_script.ps1")
profilePath = filepath.Join(homeDir, "Documents", "WindowsPowerShell", "Microsoft.PowerShell_profile.ps1")
default:
return "", errors.New("unsupported shell type. Please use bash, zsh, fish, or powershell")
}

file, err := os.Create(filePath)
if err != nil {
return "", fmt.Errorf("error creating completion script file: %s", err)
}
defer file.Close()

switch shell {
case "bash":
err = rootCmd.GenBashCompletion(file)
case "zsh":
err = rootCmd.GenZshCompletion(file)
case "fish":
err = rootCmd.GenFishCompletion(file, true)
case "powershell":
err = rootCmd.GenPowerShellCompletionWithDesc(file)
}

if err != nil {
return "", fmt.Errorf("error generating completion script: %s", err)
}

sourceCommand := fmt.Sprintf("\nsource %s\n", filePath)
if shell == "powershell" {
sourceCommand = fmt.Sprintf(". %s\n", filePath)
}

alreadyPresent := false
// Read existing content from the file
profile, err := os.ReadFile(profilePath)

if err != nil && !os.IsNotExist(err) {
return "", fmt.Errorf("error while reading profile (%s): %s", profilePath, err)
}

if strings.Contains(string(profile), strings.TrimSpace(sourceCommand)) {
alreadyPresent = true
}

if !alreadyPresent {
// Append the source command to the shell's profile file if not present
profile, err := os.OpenFile(profilePath, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return "", fmt.Errorf("error opening profile file (%s): %s", profilePath, err)
}
defer profile.Close()

if _, err := profile.WriteString(sourceCommand); err != nil {
return "", fmt.Errorf("error writing to profile file (%s): %s", profilePath, err)
}
}

return profilePath, nil
}
1 change: 1 addition & 0 deletions pkg/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/daytonaio/daytona/internal"
. "github.com/daytonaio/daytona/internal/util"
. "github.com/daytonaio/daytona/pkg/cmd/apikey"
. "github.com/daytonaio/daytona/pkg/cmd/autocomplete"
. "github.com/daytonaio/daytona/pkg/cmd/build"
. "github.com/daytonaio/daytona/pkg/cmd/containerregistry"
. "github.com/daytonaio/daytona/pkg/cmd/gitprovider"
Expand Down

0 comments on commit 35da4d8

Please sign in to comment.