From dedb6c2c35329486b7e3cd87fdb3647c565df02d Mon Sep 17 00:00:00 2001 From: Chance Date: Thu, 18 Apr 2024 14:08:15 +0800 Subject: [PATCH] feat: add `config` command to manipulate configuration (#211) Only string and boolean type are supported. --------- Co-authored-by: Han Li --- cmd/cmd.go | 1 + cmd/commands/config.go | 123 +++++++++++++++++++++++++++ docs/guides/configuration.md | 27 +++++- docs/usage/all-commands.md | 1 + docs/zh-hans/guides/configuration.md | 38 +++++++-- docs/zh-hans/usage/all-commands.md | 1 + internal/config/config.go | 9 ++ 7 files changed, 190 insertions(+), 10 deletions(-) create mode 100644 cmd/commands/config.go diff --git a/cmd/cmd.go b/cmd/cmd.go index 7b25372d..869448d3 100644 --- a/cmd/cmd.go +++ b/cmd/cmd.go @@ -95,6 +95,7 @@ func newCmd() *cmd { commands.Add, commands.Activate, commands.Env, + commands.Config, commands.Cd, } diff --git a/cmd/commands/config.go b/cmd/commands/config.go new file mode 100644 index 00000000..7fa61f4c --- /dev/null +++ b/cmd/commands/config.go @@ -0,0 +1,123 @@ +package commands + +import ( + "fmt" + "github.com/urfave/cli/v2" + "github.com/version-fox/vfox/internal" + "reflect" + "strconv" + "strings" +) + +var Config = &cli.Command{ + Name: "config", + Usage: "Setup, view config", + Flags: []cli.Flag{ + &cli.BoolFlag{ + Name: "list", + Aliases: []string{"l"}, + Usage: "list all config", + }, + &cli.BoolFlag{ + Name: "unset", + Aliases: []string{"un"}, + Usage: "remove a config", + }, + }, + Action: configCmd, +} + +func configCmd(ctx *cli.Context) error { + manager := internal.NewSdkManager() + defer manager.Close() + config := reflect.ValueOf(manager.Config) + + if ctx.Bool("list") { + configList("", config) + return nil + } + + args := ctx.Args() + if args.Len() == 0 { + return ctx.App.Run([]string{"CMD", "config", "-h"}) + } + + keys := strings.Split(args.First(), ".") + unset := ctx.Bool("unset") + if !unset && args.Len() == 1 { + configGet(config, keys) + return nil + } + + value := args.Get(1) + if unset { + value = "" + } + configSet(config, keys, value) + return manager.Config.SaveConfig(manager.PathMeta.HomePath) +} + +func configList(prefix string, v reflect.Value) { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + + for i := 0; i < v.NumField(); i++ { + key := v.Type().Field(i).Tag.Get("yaml") + value := v.Field(i) + if (value.Kind() == reflect.Ptr && value.Elem().Kind() == reflect.Struct) || value.Kind() == reflect.Struct { + configList(prefix+key+".", value) + } else { + if value.Kind() == reflect.String && value.IsZero() { + continue + } + fmt.Printf(prefix+key+" = %v\n", value.Interface()) + } + } +} + +func configGet(v reflect.Value, keys []string) { + var foundCount int + for _, key := range keys { + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + for i := 0; i < v.NumField(); i++ { + if v.Type().Field(i).Tag.Get("yaml") == key { + v = v.Field(i) + foundCount = foundCount + 1 + break + } + } + } + if foundCount == len(keys) { + if (v.Kind() == reflect.Ptr && v.Elem().Kind() == reflect.Struct) || v.Kind() == reflect.Struct { + configList(strings.Join(keys, ".")+".", v) + } else { + fmt.Printf("%v\n", v.Interface()) + } + } +} + +func configSet(v reflect.Value, keys []string, value string) { + key := keys[0] + if v.Kind() == reflect.Ptr { + v = v.Elem() + } + for i := 0; i < v.NumField(); i++ { + if v.Type().Field(i).Tag.Get("yaml") == key { + if len(keys) > 1 { + configSet(v.Field(i), keys[1:], value) + } else { + switch v.Field(i).Kind() { + case reflect.Bool: + parseBool, _ := strconv.ParseBool(value) + v.Field(i).SetBool(parseBool) + default: + v.Field(i).SetString(value) + } + } + break + } + } +} diff --git a/docs/guides/configuration.md b/docs/guides/configuration.md index c78139ce..0617a3f9 100644 --- a/docs/guides/configuration.md +++ b/docs/guides/configuration.md @@ -20,11 +20,12 @@ legacyVersionFile: ``` ::: warning + 1. If both `.tool-versions` and other version manager's configuration files (`.nvmrc`, `.sdkmanrc`, etc.) exist in the directory, `vfox` **priority read** the `.tool-versions` file. 2. Enabling this feature may cause `vfox` to refresh environment variables slightly slower, **please enable it according to your needs**. -::: + ::: ## Proxy Settings @@ -61,7 +62,7 @@ If you want to use **your own registry or third-party mirror registry**, please ```yaml registry: - address: 'https://vfox-plugins.lhan.me' + address: "https://vfox-plugins.lhan.me" ``` ::: tip Available Mirrors @@ -69,3 +70,25 @@ registry: - https://cdn.jsdelivr.net/gh/version-fox/vfox-plugins/plugins - https://rawcdn.githack.com/version-fox/vfox-plugins/plugins ::: + +## Config Command + +Setup, view config + +**Usage** + +```shell +vfox config [] [] + +vfox config proxy.enable true +vfox config proxy.url http://localhost:7890 +vfox config storage.sdkPath /tmp +``` + +`key`: Configuration item, separated by `. `. +`value`: If not passed, look at the value of the configuration item. + +**Options** + +- `-l, --list`: list all config. +- `-un, --unset`: remove a config. diff --git a/docs/usage/all-commands.md b/docs/usage/all-commands.md index 0976f011..be42a0ff 100644 --- a/docs/usage/all-commands.md +++ b/docs/usage/all-commands.md @@ -13,6 +13,7 @@ vfox uninstall @ Uninstall the specified version of SDK vfox use [--global --project --session] [@] Use the specified version of SDK for different scope vfox list [] List all installed versions of SDK vfox current [] Show the current version of SDK +vfox config [] [] Setup, view config vfox cd [--plugin] [] Launch a shell in the VFOX_HOME, SDK directory, or plugin directory vfox help Show this help message ``` diff --git a/docs/zh-hans/guides/configuration.md b/docs/zh-hans/guides/configuration.md index d941f22c..b1d621a1 100644 --- a/docs/zh-hans/guides/configuration.md +++ b/docs/zh-hans/guides/configuration.md @@ -3,13 +3,12 @@ `vfox` 允许你修改一些配置, 所有配置信息都存放在`$HOME/.version-fox/config.yaml`文件中。 ::: tip 注意 -如果你是首次运行`vfox`, 则会自动创建一个空的config.yaml文件。 +如果你是首次运行`vfox`, 则会自动创建一个空的 config.yaml 文件。 ::: ## 兼容版本文件 - -插件 **支持** 读取其他版本管理器的配置文件, 例如: Nodejs的`nvm`的`.nvmrc`文件, Java的`SDKMAN`的`.sdkmanrc`文件等。 +插件 **支持** 读取其他版本管理器的配置文件, 例如: Nodejs 的`nvm`的`.nvmrc`文件, Java 的`SDKMAN`的`.sdkmanrc`文件等。 此能力**默认是关闭的**, 如果你想开启, 请按照以下方式配置: @@ -19,15 +18,16 @@ legacyVersionFile: ``` ::: warning + 1. 如果目录里同时存在`.tool-versions`和其他版本管理器的配置文件(`.nvmrc`, `.sdkmanrc`等), -`vfox` **优先加载**`.tool-versions`文件. + `vfox` **优先加载**`.tool-versions`文件. 2. 开启此功能可能会导致`vfox`刷新环境变量时略微变慢, **请根据自己的需求开启**。 -::: + ::: ## 代理设置 ::: tip 注意 -当前仅支持http(s)代理协议 +当前仅支持 http(s)代理协议 ::: **格式**: `http[s]://[username:password@]host:port` @@ -40,7 +40,7 @@ proxy: ## 存储路径 -`vfox`默认将SDK缓存文件存储在`$HOME/.version-fox/cache`目录下。 +`vfox`默认将 SDK 缓存文件存储在`$HOME/.version-fox/cache`目录下。 ::: danger !!! 在配置之前, 请确保`vfox`有文件夹的写权限。⚠⚠⚠ @@ -59,7 +59,7 @@ storage: ```yaml registry: - address: 'https://vfox-plugins.lhan.me' + address: "https://vfox-plugins.lhan.me" ``` ::: tip 可用镜像 @@ -68,3 +68,25 @@ registry: - https://cdn.jsdelivr.net/gh/version-fox/vfox-plugins/plugins - https://rawcdn.githack.com/version-fox/vfox-plugins/plugins ::: + +## Config 命令 + +设置,查看配置 + +**用法** + +```shell +vfox config [] [] + +vfox config proxy.enable true +vfox config proxy.url http://localhost:7890 +vfox config storage.sdkPath /tmp +``` + +`key`:配置项,以`.`分割。 +`value`:不传为查看配置项的值。 + +**选项** + +- `-l, --list`:列出所有配置。 +- `-un, --unset`:删除一个配置。 diff --git a/docs/zh-hans/usage/all-commands.md b/docs/zh-hans/usage/all-commands.md index 1eeb4a31..64b1af9c 100644 --- a/docs/zh-hans/usage/all-commands.md +++ b/docs/zh-hans/usage/all-commands.md @@ -13,6 +13,7 @@ vfox uninstall @ Uninstall the specified version of SDK vfox use [--global --project --session] [@] Use the specified version of SDK for different scope vfox list [] List all installed versions of SDK vfox current [] Show the current version of SDK +vfox config [] [] Setup, view config vfox cd [--plugin] [] Launch a shell in the VFOX_HOME, SDK directory, or plugin directory vfox help Show this help message ``` diff --git a/internal/config/config.go b/internal/config/config.go index 23fa9aa7..d401d443 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -78,3 +78,12 @@ func NewConfig(path string) (*Config, error) { p := filepath.Join(path, filename) return NewConfigWithPath(p) } + +func (c *Config) SaveConfig(path string) error { + p := filepath.Join(path, filename) + content, err := yaml.Marshal(c) + if err != nil { + return err + } + return os.WriteFile(p, content, 0644) +}