Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature]: Improve clink startup speed #383

Closed
DarkRRb opened this issue Dec 22, 2024 · 18 comments · Fixed by #386
Closed

[Feature]: Improve clink startup speed #383

DarkRRb opened this issue Dec 22, 2024 · 18 comments · Fixed by #386
Labels
enhancement New feature or request

Comments

@DarkRRb
Copy link

DarkRRb commented Dec 22, 2024

1. Your usage scenarios?

PowerShell 启动太慢了, 我是直接使用的 CMD, 但目前没有支持 CMD

可以参考 fnm 配置 CMD 的方式操作

2. What is your expected outcome?

支持 CMD

@DarkRRb DarkRRb added the enhancement New feature or request label Dec 22, 2024
@DarkRRb
Copy link
Author

DarkRRb commented Dec 22, 2024

看了一下, 似乎是每次执行命令的时候都要执行一遍 env?

@jan-bar
Copy link
Contributor

jan-bar commented Dec 23, 2024

20241223_095849

用这个hook下cmd吧,纯cmd官方文档也说只支持全局环境。

@ViCrack
Copy link

ViCrack commented Dec 23, 2024

我自己用clink,加了clink_vfox.lua之后,明显感觉变慢了,性能比较差,不知道是不是个例现象

@jan-bar
Copy link
Contributor

jan-bar commented Dec 23, 2024

我自己用clink,加了clink_vfox.lua之后,明显感觉变慢了,性能比较差,不知道是不是个例现象

@ViCrack 是敲vfox xxx命令时慢了点,还是任何命令都慢啊?因为做了vfox命令自动补全,最新clink_vfox.lua会在首次执行vfox命令时执行vfox available从网络获取支持的编程语言列表,但后面再执行vfox命令时不会受影响。可以自己修改lua代码,手动添加常用编程语言到vfox_sdk_table变量里面,这样可以避免网络影响额。

local vfox_sdk_table = {}
clink.argmatcher('vfox'):nofiles():setdelayinit(function(vfox)
if #vfox_sdk_table ~= 0 then
return
end
local vfox_available = io.popen('vfox available')
for line in vfox_available:lines() do
local sdk, yes = line:gsub('%c%[%d+m', ''):match('^(.+)%s(%u%u%u?)%s')
if (yes == 'YES' or yes == 'NO') and sdk then
sdk = sdk:gsub('%s*$', '')
table.insert(vfox_sdk_table, sdk)
end
end
vfox_available:close()

@DarkRRb
Copy link
Author

DarkRRb commented Dec 23, 2024 via email

@ViCrack
Copy link

ViCrack commented Dec 23, 2024

@jan-bar 是启动慢了,慢得能跟powershell比了。这里vfox available是否能实现做个时间缓存啥的,不需要每次都从网络获取吧。

另外如果只用cmd的话,执行vfox use -g java@8也会比较慢

如下图,Warning: The current shell lacks hook support or configuration. It has switched to global scope automatically. 显示完之后,隔了半分钟,这里有办法提速吗
image

@DarkRRb
Copy link
Author

DarkRRb commented Dec 23, 2024 via email

@DarkRRb
Copy link
Author

DarkRRb commented Dec 23, 2024

测试了一下, 似乎是 for line in vfox_activate:lines() do 非常慢, 不知道是不是我的原因?

@jan-bar
Copy link
Contributor

jan-bar commented Dec 23, 2024

@jan-bar 是启动慢了,慢得能跟powershell比了。这里vfox available是否能实现做个时间缓存啥的,不需要每次都从网络获取吧。

你可以写死你常用的编程语言到vfox_sdk_table变量,这样就不需要每次启动都从网络请求了,这部分逻辑确实要考虑网络不好的情况。

另外如果只用cmd的话,执行vfox use -g java@8也会比较慢

根据你图片提示的错误 Warning: The current shell lacks hook support or configuration. It has switched to global scope automatically. 来看,你用的cmd都没有被clink程序hook,所以这时候都没执行那个lua脚本额

@ViCrack
Copy link

ViCrack commented Dec 23, 2024

@jan-bar

图片提示的错误 Warning: The current shell lacks hook support or configuration. It has switched to global scope automatically.

这里我是去掉了那个clink_vfox.lua后的测试结果,我是故意没执行lua的,看看默认情况下cmd用 -g的速度

@jan-bar
Copy link
Contributor

jan-bar commented Dec 23, 2024

@DarkRRb

不知道这个 sdk 列表是不是只是为了补全,如果只补全的话可否移动到补全的时候执行?clink 的补全似乎是异步的,同时做好缓存?

clink.argmatcher('vfox'):nofiles():setdelayinit(function(vfox)

setdelayinit这个方法只会在第一次输入vfox + 空格时才会执行,所以不会拖慢启动速度。

测试了一下, 似乎是 for line in vfox_activate:lines() do 非常慢, 不知道是不是我的原因?

这个是按行读取vfox activate clink命令的标准输出,vfox启动所有类型终端都需要执行该hook,这段lua代码没法再优化了。或许你把vfox.exe放到PATH变量最前面的目录能提高执行时查找vfox.exe的速度吧。

@jan-bar
Copy link
Contributor

jan-bar commented Dec 23, 2024

@ViCrack

这里我是去掉了那个clink_vfox.lua后的测试结果,我是故意没执行lua的,看看默认情况下cmd用 -g的速度

vfox/internal/sdk.go

Lines 378 to 416 in ca4d9e6

pterm.Printf("Warning: The current shell lacks hook support or configuration. It has switched to global scope automatically.\n")
keys, err := b.EnvKeys(version, GlobalLocation)
if err != nil {
return err
}
toolVersion, err := toolset.NewToolVersion(b.sdkManager.PathMeta.HomePath)
if err != nil {
return fmt.Errorf("failed to read tool versions, err:%w", err)
}
bins, err := keys.Paths.ToBinPaths()
if err != nil {
return err
}
for _, bin := range bins.Slice() {
binShim := shim.NewShim(bin, b.sdkManager.PathMeta.GlobalShimsPath)
if err = binShim.Generate(); err != nil {
continue
}
}
// clear global env
if oldVersion, ok := toolVersion.Record[b.Plugin.SdkName]; ok {
b.clearGlobalEnv(Version(oldVersion))
}
if err = b.sdkManager.EnvManager.Load(keys); err != nil {
return err
}
err = b.sdkManager.EnvManager.Flush()
if err != nil {
return err
}
toolVersion.Record[b.Plugin.SdkName] = string(version)
if err = toolVersion.Save(); err != nil {
return fmt.Errorf("failed to save tool versions, err:%w", err)
}
return shell.GetProcess().Open(os.Getppid())

func (w windowsProcess) Open(pid int) error {
// On Windows, os.FindProcess does not actually find the process.
// So, we use this workaround to get the parent process name.
cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/NH", "/FO", "CSV")
output, err := cmd.Output()
if err != nil {
return err
}
cmd = exec.Command("wmic", "process", "where", fmt.Sprintf("ProcessId=%d", pid), "get", "ExecutablePath", "/format:list")
output, err = cmd.Output()
if err != nil {
return err
}
path := strings.TrimPrefix(strings.TrimSpace(string(output)), "ExecutablePath=")
command := exec.Command(path)
command.Env = os.Environ()
command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr
if err := command.Run(); err != nil {
return fmt.Errorf("open a new shell failed, err:%w", err)
}
return nil

我看了下源码,在打印那个提示时,会在window下启动新的进程,而且还执行了好几个window的可执行程序,估计是这几个地方消耗了时间吧,没执行那个lua脚本和执行后是两套不同的逻辑,所以你的这个测试不对。最好还是修改lua脚本看看哪里可以优化额。

@DarkRRb
Copy link
Author

DarkRRb commented Dec 23, 2024

测试了一下, 似乎是 for line in vfox_activate:lines() do 非常慢, 不知道是不是我的原因?

突然意识到, 并不是这里慢, 是 vfox activate clink 执行需要时间

@ViCrack
Copy link

ViCrack commented Dec 23, 2024

@jan-bar

  1. 打印那个提示时做的逻辑,启动tasklist、wmic等,可以用go原生winapi实现的吧,应该比起wmic遍历快多了,要不然用户只用cmd不用clink的话要花费半分钟确实很慢了

这里我是去掉了那个clink_vfox.lua后的测试结果,我是故意没执行lua的,看看默认情况下cmd用 -g的速度

vfox/internal/sdk.go

Lines 378 to 416 in ca4d9e6

pterm.Printf("Warning: The current shell lacks hook support or configuration. It has switched to global scope automatically.\n")
keys, err := b.EnvKeys(version, GlobalLocation)
if err != nil {
return err
}
toolVersion, err := toolset.NewToolVersion(b.sdkManager.PathMeta.HomePath)
if err != nil {
return fmt.Errorf("failed to read tool versions, err:%w", err)
}
bins, err := keys.Paths.ToBinPaths()
if err != nil {
return err
}
for _, bin := range bins.Slice() {
binShim := shim.NewShim(bin, b.sdkManager.PathMeta.GlobalShimsPath)
if err = binShim.Generate(); err != nil {
continue
}
}
// clear global env
if oldVersion, ok := toolVersion.Record[b.Plugin.SdkName]; ok {
b.clearGlobalEnv(Version(oldVersion))
}
if err = b.sdkManager.EnvManager.Load(keys); err != nil {
return err
}
err = b.sdkManager.EnvManager.Flush()
if err != nil {
return err
}
toolVersion.Record[b.Plugin.SdkName] = string(version)
if err = toolVersion.Save(); err != nil {
return fmt.Errorf("failed to save tool versions, err:%w", err)
}
return shell.GetProcess().Open(os.Getppid())

func (w windowsProcess) Open(pid int) error {
// On Windows, os.FindProcess does not actually find the process.
// So, we use this workaround to get the parent process name.
cmd := exec.Command("tasklist", "/FI", fmt.Sprintf("PID eq %d", pid), "/NH", "/FO", "CSV")
output, err := cmd.Output()
if err != nil {
return err
}
cmd = exec.Command("wmic", "process", "where", fmt.Sprintf("ProcessId=%d", pid), "get", "ExecutablePath", "/format:list")
output, err = cmd.Output()
if err != nil {
return err
}
path := strings.TrimPrefix(strings.TrimSpace(string(output)), "ExecutablePath=")
command := exec.Command(path)
command.Env = os.Environ()
command.Stdin = os.Stdin
command.Stdout = os.Stdout
command.Stderr = os.Stderr
if err := command.Run(); err != nil {
return fmt.Errorf("open a new shell failed, err:%w", err)
}
return nil

我看了下源码,在打印那个提示时,会在window下启动新的进程,而且还执行了好几个window的可执行程序,估计是这几个地方消耗了时间吧,没执行那个lua脚本和执行后是两套不同的逻辑,所以你的这个测试不对。最好还是修改lua脚本看看哪里可以优化额。

  1. 我用print调试了一下,应该主要是下面的代码导致慢,

local vfox_activate = io.popen('vfox activate clink')
for line in vfox_activate:lines() do
if not vfox_setenv(line) then
os.execute(line)
end
end
vfox_activate:close()

下面是我改进的代码,不知道可行不,lua可以用异步协程来执行命令,这样启动就不会有明显的卡顿了

-- 判断字符串是否不为空
local function is_not_empty(str)
    return str ~= nil and #str:gsub("%s", "") > 0
end

-- 异步执行 io.popen
local function async_activate_clink()
    return coroutine.create(function()
        local vfox_activate = io.popen('vfox activate clink')
        for line in vfox_activate:lines() do
            -- 排除返回的多余的空行,空行没必要执行os.execute
            if is_not_empty(line) then
                -- print(line)
                if string.sub(line, 1, 4) == "set " then
                    vfox_setenv(line)
                else
                    os.execute(line)
                end
            end
        end
        vfox_activate:close()
    end)
end

-- 创建一个异步任务
local task = async_activate_clink()

-- 执行异步任务
coroutine.resume(task)
  1. vfox available 慢的那部分,我已经手动添加常用编程语言到vfox_sdk_table变量里面了
    如下:
vfox_sdk_table = {
        "bun", "clang", "cmake", "crystal", "dart", "deno", "dotnet", "elixir",
        "erlang", "etcd", "flutter", "golang", "gradle", "groovy", "julia", "kotlin",
        "kubectl", "maven", "mongo", "ninja", "nodejs", "php", "protobuf", "python",
        "ruby", "scala", "terraform", "vlang", "zig"
    }

下面是整个lua文件的内容

clink_vfox.zip

@jan-bar
Copy link
Contributor

jan-bar commented Dec 24, 2024

@ViCrack

  1. 打印那个提示时做的逻辑,启动tasklist、wmic等,可以用go原生winapi实现的吧,应该比起wmic遍历快多了,要不然用户只用cmd不用clink的话要花费半分钟确实很慢了

你可以阅读源码,进入那个逻辑后,只能用全局环境,根本无法正常使用vfox的其他所有功能。所以我建议最好不要这样用,我感觉也没必要深入研究那块逻辑额。

下面是我的方案,主要修改3个地方

  1. 支持语言列表缓存在available.txt文件中,只要文件存在就不会执行vfox available从网络获取
  2. 和你一样将vfox activate clink放到协程中执行,空行可以不考虑,因为只会执行: os.execute('vfox env -c')
  3. 查了文档可以使用clink.promptcoroutine在协程中执行vfox env -s clink
-- https://chrisant996.github.io/clink/clink.html#extending-clink
local vfox_sdk_table = {}
clink.argmatcher('vfox'):nofiles():setdelayinit(function(vfox)
    if #vfox_sdk_table ~= 0 then
        return
    end

    local file_name = 'available.txt'
    local file_available = io.open(file_name, 'r')
    if file_available then
        for line in file_available:lines() do
            table.insert(vfox_sdk_table, line)
        end
    else
        file_available = io.open(file_name, 'w')
        local vfox_available = io.popen('vfox available')
        for line in vfox_available:lines() do
            local trim = line:gsub('%c%[%d+m', '')
            local name = trim:match('^(%S+)')
            if name and (trim:find('YES') or trim:find('NO')) then
                table.insert(vfox_sdk_table, name)
                file_available:write(name .. '\n')
            end
        end
        vfox_available:close()
    end
    file_available:close()

    local function vfox_ls_func()
        local pre, ls = '', {}
        local vfox_ls = io.popen('vfox ls')
        for line in vfox_ls:lines() do
            local txt = line:gsub('%c%[%d+m', ''):match('^%A+(%a.+)')
            if txt then
                if txt:find('v') == 1 then
                    ls[pre] = true
                    table.insert(ls, pre .. '@' .. txt:sub(2))
                else
                    pre = txt
                    ls[pre] = false
                end
            end
        end
        vfox_ls:close()
        return ls
    end
    local function vfox_sdk_func()
        local ls, res = vfox_ls_func(), {}
        for k, v in pairs(ls) do
            if type(v) == 'boolean' then
                table.insert(res, k)
            end
        end
        return res
    end

    local vfox_sdk = clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--help', '-h')
    local vfox_use = clink.argmatcher():nofiles():addarg(function()
        local ls, res = vfox_ls_func(), {}
        for k, v in pairs(ls) do
            if v then
                table.insert(res, v == true and k or v)
            end
        end
        return res
    end):addflags('--global', '-g', '--session', '-s', '--project', '-p', '--help', '-h')
    local vfox_help = clink.argmatcher():nofiles():addflags('--help', '-h')
    local vfox_shell = clink.argmatcher():nofiles():addarg('bash', 'zsh', 'pwsh', 'fish', 'clink')
    local vfox_uninstall = clink.argmatcher():nofiles():addarg(vfox_ls_func):addflags('--help', '-h')
    local vfox_install = clink.argmatcher():nofiles():addarg({
        onadvance = function() return 0 end,
        vfox_sdk_func,
    }):addflags('--all', '-a', '--help', '-h')

    vfox:addarg(
        'add' .. clink.argmatcher():nofiles():addarg({
            onadvance = function() return 0 end,
            function(word, word_index, line_state)
                local res, line = {}, line_state:getline()
                for _, v in ipairs(vfox_sdk_table) do
                    if not line:find(v) then
                        table.insert(res, v)
                    end
                end
                return res
            end
        }):addflags('--source', '-s', '--alias', '--help', '-h'),
        'use' .. vfox_use, 'u' .. vfox_use,
        'info' .. vfox_sdk,
        'remove' .. vfox_sdk,
        'search' .. vfox_sdk,
        'update' .. clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--all', '-a', '--help', '-h'),
        'available' .. vfox_help,
        'upgrade' .. vfox_help,
        'current' .. vfox_sdk, 'c' .. vfox_sdk,
        'list' .. vfox_sdk, 'ls' .. vfox_sdk,
        'uninstall' .. vfox_uninstall, 'un' .. vfox_uninstall,
        'install' .. vfox_install, 'i' .. vfox_install,
        'env' .. clink.argmatcher():nofiles():addflags(
            '--shell' .. vfox_shell, '-s' .. vfox_shell,
            '--cleanup', '-c',
            '--json', '-j',
            '--help', '-h'
        ),
        'activate' .. vfox_shell,
        'config' .. clink.argmatcher():nofiles():addarg(function()
            local res, vfox_config = {}, io.popen('vfox config -l')
            for line in vfox_config:lines() do
                local txt = line:gsub('%c%[%d+m', ''):match('^(%S+)')
                if txt then
                    table.insert(res, txt)
                end
            end
            vfox_config:close()
            return res
        end):addflags('--list', '-l', '--unset', '-un', '--help', '-h'),
        'cd' .. clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--plugin', '-p', '--help', '-h'),
        'help', 'h'
    ):addflags('--debug', '--help', '-h', '--version', '-v', '-V')
end)

local vfox_setenv = function(str)
    local key, val = str:match('^set "(.+)=(.*)"')
    if key and val then
        return os.setenv(key, val ~= '' and val or nil)
    end
end

local task = coroutine.create(function()
    local vfox_activate = io.popen('vfox activate clink')
    for line in vfox_activate:lines() do
        vfox_setenv(line)
    end
    vfox_activate:close()
    os.setenv('__VFOX_PID', os.getpid())
    os.execute('vfox env -c')
end)
coroutine.resume(task)

local vfox_prompt = clink.promptfilter(30)
function vfox_prompt:filter(prompt)
    clink.promptcoroutine(function()
        local env = io.popen('vfox env -s clink')
        for line in env:lines() do
            vfox_setenv(line)
        end
        env:close()
    end)
end

@DarkRRb 你可以用上面脚本测试看看额

@ViCrack
Copy link

ViCrack commented Dec 24, 2024

我自己试了上面的脚本,启动耗时已经几乎无感了。

另外vfox available这样应该也没必要缓存了,除非加上时间过期,不然以后内容可能不会及时更新。

@DarkRRb
Copy link
Author

DarkRRb commented Dec 24, 2024

  1. 支持语言列表缓存在available.txt文件中,只要文件存在就不会执行vfox available从网络获取

是否需要考虑更新的问题? 异步跑一个更新检测?

@jan-bar
Copy link
Contributor

jan-bar commented Dec 24, 2024

-- https://chrisant996.github.io/clink/clink.html#extending-clink
local vfox_sdk_table = {}
clink.argmatcher('vfox'):nofiles():setdelayinit(function(vfox)
    if #vfox_sdk_table ~= 0 then
        return
    end

    local use_cmd = true
    local current_timestamp = os.time()
    local file_name = os.getenv("USERPROFILE") .. '\\available.txt'
    local file_available = io.open(file_name, 'r')
    if file_available then
        local file_timestamp = tonumber(file_available:read('*l'))
        if current_timestamp - file_timestamp <= 24 * 60 * 60 then
            for line in file_available:lines() do
                table.insert(vfox_sdk_table, line)
            end
            use_cmd = false
        end
        file_available:close()
    end

    if use_cmd then
        file_available = io.open(file_name, 'w')
        file_available:write(current_timestamp .. '\n')
        local vfox_available = io.popen('vfox available')
        for line in vfox_available:lines() do
            local trim = line:gsub('%c%[%d+m', '')
            local name = trim:match('^(%S+)')
            if name and (trim:find('YES') or trim:find('NO')) then
                table.insert(vfox_sdk_table, name)
                file_available:write(name .. '\n')
            end
        end
        vfox_available:close()
        file_available:close()
    end

    local function vfox_ls_func()
        local pre, ls = '', {}
        local vfox_ls = io.popen('vfox ls')
        for line in vfox_ls:lines() do
            local txt = line:gsub('%c%[%d+m', ''):match('^%A+(%a.+)')
            if txt then
                if txt:find('v') == 1 then
                    ls[pre] = true
                    table.insert(ls, pre .. '@' .. txt:sub(2))
                else
                    pre = txt
                    ls[pre] = false
                end
            end
        end
        vfox_ls:close()
        return ls
    end
    local function vfox_sdk_func()
        local ls, res = vfox_ls_func(), {}
        for k, v in pairs(ls) do
            if type(v) == 'boolean' then
                table.insert(res, k)
            end
        end
        return res
    end

    local vfox_sdk = clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--help', '-h')
    local vfox_use = clink.argmatcher():nofiles():addarg(function()
        local ls, res = vfox_ls_func(), {}
        for k, v in pairs(ls) do
            if v then
                table.insert(res, v == true and k or v)
            end
        end
        return res
    end):addflags('--global', '-g', '--session', '-s', '--project', '-p', '--help', '-h')
    local vfox_help = clink.argmatcher():nofiles():addflags('--help', '-h')
    local vfox_shell = clink.argmatcher():nofiles():addarg('bash', 'zsh', 'pwsh', 'fish', 'clink')
    local vfox_uninstall = clink.argmatcher():nofiles():addarg(vfox_ls_func):addflags('--help', '-h')
    local vfox_install = clink.argmatcher():nofiles():addarg({
        onadvance = function() return 0 end,
        vfox_sdk_func,
    }):addflags('--all', '-a', '--help', '-h')

    vfox:addarg(
        'add' .. clink.argmatcher():nofiles():addarg({
            onadvance = function() return 0 end,
            function(word, word_index, line_state)
                local res, line = {}, line_state:getline()
                for _, v in ipairs(vfox_sdk_table) do
                    if not line:find(v) then
                        table.insert(res, v)
                    end
                end
                return res
            end
        }):addflags('--source', '-s', '--alias', '--help', '-h'),
        'use' .. vfox_use, 'u' .. vfox_use,
        'info' .. vfox_sdk,
        'remove' .. vfox_sdk,
        'search' .. vfox_sdk,
        'update' .. clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--all', '-a', '--help', '-h'),
        'available' .. vfox_help,
        'upgrade' .. vfox_help,
        'current' .. vfox_sdk, 'c' .. vfox_sdk,
        'list' .. vfox_sdk, 'ls' .. vfox_sdk,
        'uninstall' .. vfox_uninstall, 'un' .. vfox_uninstall,
        'install' .. vfox_install, 'i' .. vfox_install,
        'env' .. clink.argmatcher():nofiles():addflags(
            '--shell' .. vfox_shell, '-s' .. vfox_shell,
            '--cleanup', '-c',
            '--json', '-j',
            '--help', '-h'
        ),
        'activate' .. vfox_shell,
        'config' .. clink.argmatcher():nofiles():addarg(function()
            local res, vfox_config = {}, io.popen('vfox config -l')
            for line in vfox_config:lines() do
                local txt = line:gsub('%c%[%d+m', ''):match('^(%S+)')
                if txt then
                    table.insert(res, txt)
                end
            end
            vfox_config:close()
            return res
        end):addflags('--list', '-l', '--unset', '-un', '--help', '-h'),
        'cd' .. clink.argmatcher():nofiles():addarg(vfox_sdk_func):addflags('--plugin', '-p', '--help', '-h'),
        'help', 'h'
    ):addflags('--debug', '--help', '-h', '--version', '-v', '-V')
end)

local vfox_setenv = function(str)
    local key, val = str:match('^set "(.+)=(.*)"')
    if key and val then
        return os.setenv(key, val ~= '' and val or nil)
    end
end

local task = coroutine.create(function()
    local vfox_activate = io.popen('vfox activate clink')
    for line in vfox_activate:lines() do
        vfox_setenv(line)
    end
    vfox_activate:close()
    os.setenv('__VFOX_PID', os.getpid())
    os.execute('vfox env -c')
end)
coroutine.resume(task)

local vfox_prompt = clink.promptfilter(30)
function vfox_prompt:filter(prompt)
    clink.promptcoroutine(function()
        local env = io.popen('vfox env -s clink')
        for line in env:lines() do
            vfox_setenv(line)
        end
        env:close()
    end)
end

@ViCrack @DarkRRb 添加代码,文件不存在或文件时间戳和当前时间相差超过24小时,这两种情况会使用命令获取最新列表,过期时间可自行修改源码进行指定。

@jan-bar jan-bar changed the title [Feature]: Support cmd on Windows [Feature]: Improve clink startup speed Dec 25, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants