Skip to content

Commit

Permalink
fix: resolve nushell support issue
Browse files Browse the repository at this point in the history
  • Loading branch information
bytemain committed Jan 25, 2025
1 parent acc4836 commit 584b0e9
Show file tree
Hide file tree
Showing 13 changed files with 178 additions and 192 deletions.
14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@
[![GitHub Release](https://img.shields.io/github/v/release/version-fox/vfox?display_name=tag&style=for-the-badge)](https://github.com/version-fox/vfox/releases)
[![Discord](https://img.shields.io/discord/1191981003204477019?style=for-the-badge&logo=discord)](https://discord.gg/85c8ptYgb7)

[[English]](./README.md) [[中文文档]](./README_CN.md)
[[English]](./README.md) [[中文文档]](./README_CN.md)

If you **switch between development projects which expect different environments**, specifically different runtime versions or ambient libraries,
or **you are tired of all kinds of cumbersome environment configurations**, `vfox` is the ideal choice for you.

## Introduction

**`vfox` is a cross-platform version manager(similar to `nvm`, `fvm`, `sdkman`, `asdf-vm`, etc.), extendable via plugins**. It allows you to quickly install
Expand Down Expand Up @@ -57,13 +58,14 @@ if (-not (Test-Path -Path $PROFILE)) { New-Item -Type File -Path $PROFILE -Force
# 3. copy internal/shell/clink_vfox.lua to script path

# For Nushell:
vfox activate nushell | save --append $nu.config-path
vfox activate nushell $nu.default-config-dir | save --append $nu.config-path
```
> Remember to restart your shell to apply the changes.
#### 3. Add an SDK plugin
```bash
```bash
$ vfox add nodejs
```
Expand Down Expand Up @@ -93,8 +95,8 @@ Our future plans and high priority features and enhancements are:
- Introducing plugin templates to facilitate multi-file plugin development.
- Establishing a global registry (similar to `NPM Registry` or `Scoop Main Bucket`) to provide a unified entry point for plugin distribution.
- Decomposing the existing plugin repository into individual repositories, one for each plugin.
- [X] Allowing the switching of registry addresses.
- [X] Plugin capabilities: Parsing legacy configuration files, such as `.nvmrc`, `.node-version`, `.sdkmanrc`, etc.
- [x] Allowing the switching of registry addresses.
- [x] Plugin capabilities: Parsing legacy configuration files, such as `.nvmrc`, `.node-version`, `.sdkmanrc`, etc.
- [ ] Plugin capabilities: Allowing plugins to load installed runtimes and provide information about the runtime.
## Available Plugins
Expand Down Expand Up @@ -126,7 +128,6 @@ Plugin Contributions, please go to [Public Registry](https://github.com/version-
## Thanks
> Thanks JetBrains for the free open source license. :)
<a href="https://www.jetbrains.com/?from=gev" target="_blank">
Expand All @@ -139,4 +140,3 @@ Plugin Contributions, please go to [Public Registry](https://github.com/version-
[Apache 2.0 license](./LICENSE) - Copyright (C) 2024 Han Li
and [contributors](https://github.com/version-fox/vfox/graphs/contributors)
30 changes: 7 additions & 23 deletions cmd/commands/activate.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"strings"
"text/template"

"github.com/version-fox/vfox/internal/toolset"

"github.com/version-fox/vfox/internal"

"github.com/urfave/cli/v2"
Expand All @@ -46,26 +44,7 @@ func activateCmd(ctx *cli.Context) error {
manager := internal.NewSdkManager()
defer manager.Close()

workToolVersion, err := toolset.NewToolVersion(manager.PathMeta.WorkingDirectory)
if err != nil {
return err
}

if err = manager.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return err
}
homeToolVersion, err := toolset.NewToolVersion(manager.PathMeta.HomePath)
if err != nil {
return err
}
sdkEnvs, err := manager.EnvKeys(toolset.MultiToolVersions{
workToolVersion,
homeToolVersion,
}, internal.ShellLocation)
sdkEnvs, err := manager.FullEnvKeys()
if err != nil {
return err
}
Expand All @@ -91,7 +70,12 @@ func activateCmd(ctx *cli.Context) error {
return fmt.Errorf("unknown target shell %s", name)
}
exportStr := s.Export(exportEnvs)
str, err := s.Activate()
str, err := s.Activate(
shell.ActivateConfig{
SelfPath: path,
Args: ctx.Args().Tail(),
},
)
if err != nil {
return err
}
Expand Down
84 changes: 17 additions & 67 deletions cmd/commands/env.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,12 @@ package commands
import (
"encoding/json"
"fmt"

"github.com/urfave/cli/v2"
"github.com/version-fox/vfox/internal"
"github.com/version-fox/vfox/internal/cache"
"github.com/version-fox/vfox/internal/env"
"github.com/version-fox/vfox/internal/logger"
"github.com/version-fox/vfox/internal/shell"
"github.com/version-fox/vfox/internal/toolset"
"path/filepath"
)

var Env = &cli.Command{
Expand All @@ -47,6 +45,10 @@ var Env = &cli.Command{
Aliases: []string{"j"},
Usage: "output json format",
},
&cli.BoolFlag{
Name: "full",
Usage: "output full env",
},
},
Action: envCmd,
Category: CategorySDK,
Expand All @@ -57,8 +59,10 @@ func envCmd(ctx *cli.Context) error {
return outputJSON()
} else if ctx.IsSet("cleanup") {
return cleanTmp()
} else if ctx.IsSet("full") {
return envFlag(ctx, "full")
} else {
return envFlag(ctx)
return envFlag(ctx, "cwd")
}
}

Expand Down Expand Up @@ -109,7 +113,7 @@ func cleanTmp() error {
return nil
}

func envFlag(ctx *cli.Context) error {
func envFlag(ctx *cli.Context, mode string) error {
shellName := ctx.String("shell")
if shellName == "" {
return cli.Exit("shell name is required", 1)
Expand All @@ -120,13 +124,19 @@ func envFlag(ctx *cli.Context) error {
}
manager := internal.NewSdkManager()
defer manager.Close()
var sdkEnvs internal.SdkEnvs
var err error
if mode == "full" {
sdkEnvs, err = manager.FullEnvKeys()
} else {
sdkEnvs, err = manager.AggregateEnvKeys()
}

sdkEnvs, err := aggregateEnvKeys(manager)
if err != nil {
return err
}

if len(sdkEnvs) == 0 && shellName != "nushell" {
if len(sdkEnvs) == 0 {
return nil
}

Expand All @@ -145,63 +155,3 @@ func envFlag(ctx *cli.Context) error {
fmt.Println(exportStr)
return nil
}

func aggregateEnvKeys(manager *internal.Manager) (internal.SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(manager.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = manager.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}

curToolVersion, err := toolset.NewToolVersion(manager.PathMeta.CurTmpPath)
if err != nil {
return nil, err
}
defer curToolVersion.Save()

// Add the working directory to the first
tvs := toolset.MultiToolVersions{workToolVersion, curToolVersion}

flushCache, err := cache.NewFileCache(filepath.Join(manager.PathMeta.CurTmpPath, "flush_env.cache"))
if err != nil {
return nil, err
}
defer flushCache.Close()

var sdkEnvs []*internal.SdkEnv

tvs.FilterTools(func(name, version string) bool {
if lookupSdk, err := manager.LookupSdk(name); err == nil {
vv, ok := flushCache.Get(name)
if ok && string(vv) == version {
logger.Debugf("Hit cache, skip flush environment, %s@%s\n", name, version)
return true
} else {
logger.Debugf("No hit cache, name: %s cache: %s, expected: %s \n", name, string(vv), version)
}
v := internal.Version(version)
if keys, err := lookupSdk.EnvKeys(v, internal.ShellLocation); err == nil {
flushCache.Set(name, cache.Value(version), cache.NeverExpired)

sdkEnvs = append(sdkEnvs, &internal.SdkEnv{
Sdk: lookupSdk, Env: keys,
})

// If we encounter a .tool-versions file, it is valid for the entire shell session,
// unless we encounter the next .tool-versions file or manually switch to the use command.
curToolVersion.Record[name] = version
return true
}
}
return false
})

return sdkEnvs, nil
}
2 changes: 1 addition & 1 deletion docs/guides/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ y
::: details Nushell

```shell
vfox activate nushell | save --append $nu.config-path
vfox activate nushell $nu.default-config-dir | save --append $nu.config-path
```

:::
Expand Down
84 changes: 84 additions & 0 deletions internal/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"github.com/mitchellh/go-ps"
"github.com/pterm/pterm"
"github.com/urfave/cli/v2"
"github.com/version-fox/vfox/internal/cache"
"github.com/version-fox/vfox/internal/config"
"github.com/version-fox/vfox/internal/env"
"github.com/version-fox/vfox/internal/logger"
Expand Down Expand Up @@ -69,6 +70,89 @@ type Manager struct {
Config *config.Config
}

func (m *Manager) FullEnvKeys() (SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(m.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = m.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}
homeToolVersion, err := toolset.NewToolVersion(m.PathMeta.HomePath)
if err != nil {
return nil, err
}
return m.EnvKeys(toolset.MultiToolVersions{
workToolVersion,
homeToolVersion,
}, ShellLocation)
}

func (m *Manager) AggregateEnvKeys() (SdkEnvs, error) {
workToolVersion, err := toolset.NewToolVersion(m.PathMeta.WorkingDirectory)
if err != nil {
return nil, err
}

if err = m.ParseLegacyFile(func(sdkname, version string) {
if _, ok := workToolVersion.Record[sdkname]; !ok {
workToolVersion.Record[sdkname] = version
}
}); err != nil {
return nil, err
}

curToolVersion, err := toolset.NewToolVersion(m.PathMeta.CurTmpPath)
if err != nil {
return nil, err
}
defer curToolVersion.Save()

// Add the working directory to the first
tvs := toolset.MultiToolVersions{workToolVersion, curToolVersion}

flushCache, err := cache.NewFileCache(filepath.Join(m.PathMeta.CurTmpPath, "flush_env.cache"))
if err != nil {
return nil, err
}
defer flushCache.Close()

var sdkEnvs []*SdkEnv

tvs.FilterTools(func(name, version string) bool {
if lookupSdk, err := m.LookupSdk(name); err == nil {
vv, ok := flushCache.Get(name)
if ok && string(vv) == version {
logger.Debugf("Hit cache, skip flush environment, %s@%s\n", name, version)
return true
} else {
logger.Debugf("No hit cache, name: %s cache: %s, expected: %s \n", name, string(vv), version)
}
v := Version(version)
if keys, err := lookupSdk.EnvKeys(v, ShellLocation); err == nil {
flushCache.Set(name, cache.Value(version), cache.NeverExpired)

sdkEnvs = append(sdkEnvs, &SdkEnv{
Sdk: lookupSdk, Env: keys,
})

// If we encounter a .tool-versions file, it is valid for the entire shell session,
// unless we encounter the next .tool-versions file or manually switch to the use command.
curToolVersion.Record[name] = version
return true
}
}
return false
})

return sdkEnvs, nil
}

func (m *Manager) EnvKeys(tvs toolset.MultiToolVersions, location Location) (SdkEnvs, error) {
var sdkEnvs SdkEnvs
tools := make(map[string]struct{})
Expand Down
2 changes: 1 addition & 1 deletion internal/shell/bash.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ type bash struct{}

var Bash = bash{}

func (b bash) Activate() (string, error) {
func (b bash) Activate(config ActivateConfig) (string, error) {
return bashHook, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/shell/clink.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type clink struct{}

var Clink = clink{}

func (b clink) Activate() (string, error) {
func (b clink) Activate(config ActivateConfig) (string, error) {
return clinkHook, nil
}

Expand Down
2 changes: 1 addition & 1 deletion internal/shell/fish.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ function cleanup_on_exit --on-process-exit %self
end;
`

func (sh fish) Activate() (string, error) {
func (sh fish) Activate(config ActivateConfig) (string, error) {
return fishHook, nil
}

Expand Down
Loading

0 comments on commit 584b0e9

Please sign in to comment.