diff --git a/.github/workflows/semantic-pr.yml b/.github/workflows/semantic-pr.yml index fda8238d..40db6a85 100644 --- a/.github/workflows/semantic-pr.yml +++ b/.github/workflows/semantic-pr.yml @@ -28,3 +28,4 @@ jobs: website plugin completions + deps diff --git a/cmd/asdf/main.go b/cmd/asdf/main.go index 85c958e5..997b062f 100644 --- a/cmd/asdf/main.go +++ b/cmd/asdf/main.go @@ -1,7 +1,7 @@ // Main entrypoint for the CLI app package main -import "github.com/asdf-vm/asdf/cli" +import "github.com/asdf-vm/asdf/internal/cli" // Replaced with the real version during a typical build var version = "v-dev" diff --git a/cli/cli.go b/internal/cli/cli.go similarity index 97% rename from cli/cli.go rename to internal/cli/cli.go index 0a2ccb91..afb9d976 100644 --- a/cli/cli.go +++ b/internal/cli/cli.go @@ -2,7 +2,6 @@ package cli import ( - _ "embed" "errors" "fmt" "io" @@ -14,6 +13,7 @@ import ( "strings" "text/tabwriter" + "github.com/asdf-vm/asdf/internal/completions" "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/exec" "github.com/asdf-vm/asdf/internal/execenv" @@ -52,7 +52,7 @@ func Execute(version string) { app := &cli.App{ Name: "asdf", - Version: "0.1.0", + Version: version, // Not really sure what I should put here, but all the new Golang code will // likely be written by me. Copyright: "(c) 2024 Trevor Brown", @@ -315,45 +315,18 @@ func Execute(version string) { } } -//go:embed completions/asdf.bash -var bashCompletions string - -//go:embed completions/asdf.zsh -var zshCompletions string - -//go:embed completions/asdf.fish -var fishCompletions string - -//go:embed completions/asdf.nu -var nuCompletions string - -//go:embed completions/asdf.elv -var elvishCompletions string - func completionCommand(l *log.Logger, shell string) error { - switch shell { - case "bash": - fmt.Print(bashCompletions) - return nil - case "zsh": - fmt.Print(zshCompletions) - return nil - case "fish": - fmt.Print(fishCompletions) - return nil - case "nushell": - fmt.Print(nuCompletions) - return nil - case "elvish": - fmt.Print(elvishCompletions) - return nil - default: - fmtString := `No completions available for shell with name %s -Completions are available for: bash, zsh, fish, nushell, elvish` - msg := fmt.Sprintf(fmtString, shell) - l.Print(msg) - return errors.New(msg) + file, ok := completions.Get(shell) + if !ok { + l.Printf(`No completions available for shell with name %q +Completions are available for: %v`, shell, strings.Join(completions.Names(), ", ")) + return errors.New("bad shell name") } + defer file.Close() + + io.Copy(os.Stdout, file) + + return nil } // This function is a whole mess and needs to be refactored diff --git a/cli/completions/asdf.bash b/internal/completions/asdf.bash similarity index 100% rename from cli/completions/asdf.bash rename to internal/completions/asdf.bash diff --git a/cli/completions/asdf.elv b/internal/completions/asdf.elvish similarity index 100% rename from cli/completions/asdf.elv rename to internal/completions/asdf.elvish diff --git a/cli/completions/asdf.fish b/internal/completions/asdf.fish similarity index 100% rename from cli/completions/asdf.fish rename to internal/completions/asdf.fish diff --git a/cli/completions/asdf.nu b/internal/completions/asdf.nushell similarity index 100% rename from cli/completions/asdf.nu rename to internal/completions/asdf.nushell diff --git a/cli/completions/asdf.zsh b/internal/completions/asdf.zsh similarity index 100% rename from cli/completions/asdf.zsh rename to internal/completions/asdf.zsh diff --git a/internal/completions/completions.go b/internal/completions/completions.go new file mode 100644 index 00000000..37338550 --- /dev/null +++ b/internal/completions/completions.go @@ -0,0 +1,40 @@ +// Package completions handles shell completion files. +// +// To add completion support for a shell, simply add a file named +// "asdf." to this directory, replacing "" with the name +// of the shell. +package completions + +import ( + "embed" + "errors" + "io/fs" + "slices" + "strings" +) + +//go:embed asdf.* +var completions embed.FS + +// Get returns a file containing completion code for the given shell if it is +// found. +func Get(name string) (fs.File, bool) { + file, err := completions.Open("asdf." + name) + if err != nil { + if errors.Is(err, fs.ErrNotExist) { + return nil, false + } + panic(err) // This should never happen. + } + return file, true +} + +// Names returns a slice of shell names that completion is available for. +func Names() []string { + files, _ := fs.Glob(completions, "asdf.*") + for i, file := range files { + files[i] = strings.TrimPrefix(file, "asdf.") + } + slices.Sort(files) + return files +} diff --git a/internal/completions/completions_test.go b/internal/completions/completions_test.go new file mode 100644 index 00000000..a001fd5c --- /dev/null +++ b/internal/completions/completions_test.go @@ -0,0 +1,30 @@ +package completions + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGet(t *testing.T) { + t.Run("returns file when completion file found with matching name", func(t *testing.T) { + file, found := Get("bash") + + info, err := file.Stat() + assert.Nil(t, err) + assert.Equal(t, "asdf.bash", info.Name()) + + assert.True(t, found) + }) + + t.Run("returns false when completion file not found", func(t *testing.T) { + _, found := Get("non-existent") + assert.False(t, found) + }) +} + +func TestNames(t *testing.T) { + t.Run("returns slice of shell names for which completion is available", func(t *testing.T) { + assert.Equal(t, []string{"bash", "elvish", "fish", "nushell", "zsh"}, Names()) + }) +} diff --git a/internal/execenv/execenv_test.go b/internal/execenv/execenv_test.go index 28c6f7b1..b340a25c 100644 --- a/internal/execenv/execenv_test.go +++ b/internal/execenv/execenv_test.go @@ -5,7 +5,7 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/plugins" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/stretchr/testify/assert" ) diff --git a/internal/git/git_test.go b/internal/git/git_test.go index 11b21bea..0db56b5f 100644 --- a/internal/git/git_test.go +++ b/internal/git/git_test.go @@ -5,7 +5,7 @@ import ( "path/filepath" "testing" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5/plumbing" "github.com/stretchr/testify/assert" diff --git a/internal/help/help_test.go b/internal/help/help_test.go index 9a8874b1..c8ae86bb 100644 --- a/internal/help/help_test.go +++ b/internal/help/help_test.go @@ -9,7 +9,7 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/plugins" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/stretchr/testify/assert" ) diff --git a/internal/installs/installs_test.go b/internal/installs/installs_test.go index 8f093955..f8e7f22c 100644 --- a/internal/installs/installs_test.go +++ b/internal/installs/installs_test.go @@ -8,8 +8,8 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/installtest" "github.com/asdf-vm/asdf/internal/plugins" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/asdf-vm/asdf/internal/toolversions" - "github.com/asdf-vm/asdf/repotest" "github.com/stretchr/testify/assert" ) diff --git a/internal/pluginindex/pluginindex_test.go b/internal/pluginindex/pluginindex_test.go index 6a766f98..e618d594 100644 --- a/internal/pluginindex/pluginindex_test.go +++ b/internal/pluginindex/pluginindex_test.go @@ -9,7 +9,7 @@ import ( "time" "github.com/asdf-vm/asdf/internal/git" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/stretchr/testify/assert" ) diff --git a/internal/plugins/plugins_test.go b/internal/plugins/plugins_test.go index beb80911..af2372a9 100644 --- a/internal/plugins/plugins_test.go +++ b/internal/plugins/plugins_test.go @@ -9,7 +9,7 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/data" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/stretchr/testify/assert" ) diff --git a/repotest/repotest.go b/internal/repotest/repotest.go similarity index 100% rename from repotest/repotest.go rename to internal/repotest/repotest.go diff --git a/internal/resolve/resolve_test.go b/internal/resolve/resolve_test.go index 76aa0aca..92536526 100644 --- a/internal/resolve/resolve_test.go +++ b/internal/resolve/resolve_test.go @@ -8,7 +8,7 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/plugins" - "github.com/asdf-vm/asdf/repotest" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/stretchr/testify/assert" ) diff --git a/internal/shims/shims_test.go b/internal/shims/shims_test.go index 8e38bb09..dfd84e51 100644 --- a/internal/shims/shims_test.go +++ b/internal/shims/shims_test.go @@ -12,8 +12,8 @@ import ( "github.com/asdf-vm/asdf/internal/installs" "github.com/asdf-vm/asdf/internal/installtest" "github.com/asdf-vm/asdf/internal/plugins" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/asdf-vm/asdf/internal/toolversions" - "github.com/asdf-vm/asdf/repotest" "github.com/stretchr/testify/assert" "golang.org/x/sys/unix" ) diff --git a/internal/versions/versions_test.go b/internal/versions/versions_test.go index f955b2cd..6250f57b 100644 --- a/internal/versions/versions_test.go +++ b/internal/versions/versions_test.go @@ -9,8 +9,8 @@ import ( "github.com/asdf-vm/asdf/internal/config" "github.com/asdf-vm/asdf/internal/plugins" + "github.com/asdf-vm/asdf/internal/repotest" "github.com/asdf-vm/asdf/internal/toolversions" - "github.com/asdf-vm/asdf/repotest" "github.com/stretchr/testify/assert" ) diff --git a/scripts/lint.bash b/scripts/lint.bash index 904fbcda..3553d60e 100755 --- a/scripts/lint.bash +++ b/scripts/lint.bash @@ -31,7 +31,7 @@ run_shfmt_stylecheck() { print.info "Checking .bash with shfmt" shfmt --language-dialect bash --indent 2 "${shfmt_flag}" \ - cli/completions/*.bash \ + internal/completions/*.bash \ bin/asdf \ bin/private/asdf-exec \ lib/utils.bash \ @@ -55,7 +55,7 @@ run_shellcheck_linter() { print.info "Checking .bash files with Shellcheck" shellcheck --shell bash --external-sources \ - cli/completions/*.bash \ + internal/completions/*.bash \ bin/asdf \ bin/private/asdf-exec \ lib/utils.bash \ @@ -123,7 +123,7 @@ run_fish_linter() { printf "%s\n" "[WARNING] fish_indent not found. Skipping .fish files." else print.info "Checking .fish files with fish_indent" - fish_indent "${flag}" ./cli/completions/asdf.fish + fish_indent "${flag}" ./internal/completions/asdf.fish fi }