version-fox / vfox

A cross-platform and extendable version manager with support for Java, Node.js, Flutter, .Net & more
https://vfox.lhan.me
Apache License 2.0
2.85k stars 102 forks source link

[Feature]: Support nushell for Windows #207

Open yanecc opened 6 months ago

yanecc commented 6 months ago

Well, nushell is also a common choice on Windows. Thanks a lot.

aooohan commented 6 months ago

If you are interested, you can provide a PR. ;)

RanolP commented 6 months ago

btw it seems duplicated with #46

I'm interested in implementing this. What could I do? I've checked other shells' implementation and there's a little magic inside what the implementors should know.

My questions:

[1]: it's not complete yet. just sharing purpose.

# config.nu
export-env {
    $env.__VFOX_SHELL = 'pwsh'; # use dummy shell for not-editing vfox code yet
    $env.__VFOX_PID = $nu.pid;
    vfox env --cleanup | null

    # like mise, we should support edge cases
    # seealso(mise's impl): https://github.com/jdx/mise/blob/e6448b335cf99db6fb2bdfd4c3f49ba255c2d8de/src/shell/nushell.rs#L38-L42)
    $env.config = (
        $env.config |
        update hooks.pre_prompt { |old_hooks| old_hooks ++ {
            # I parsed pwsh output for a temporal workaround, it could be better.
            for entry in (
                vfox env -s pwsh | split row "';" | str replace "='" "=" | parse '{name}={value}'
            ) {
                match $entry.name {
                    '$env:PATH' => {
                        load-env { Path: ($entry.value | split row ';') };
                    }
                    '$env:__VFOX_PREVIOUS_PATHS' => {
                        load-env { __VFOX_PREVIOUS_PATHS: $entry.value };
                    }
                }
            }
        }}
    )
}
alenros commented 5 months ago

@RanolP I've got this for Nushell: `function PLUGIN:Available(ctx) local versions = {} local resp, err = http.get({ url = util.RELEASES_URL })

if err ~= nil or resp.status_code ~= 200 then
    error("Getting releases failed: " .. err)
end

local type = util:getOsTypeAndArch()

local releases = json.decode(resp.body)
for _, release in ipairs(releases) do
    local version = release.tag_name
    local url = ""
    for _, asset in ipairs(release.assets) do
        if asset.name:find(type.osType) and asset.name:find(type.archType) then
            url = asset.browser_download_url
            break
        end
    end
    if url ~= "" then
        table.insert(versions, {
            version = version,
            url = url
        })
    end
end
return versions

end`

and util.getOsTypeAndArch: util.RELEASES_URL = "https://api.github.com/repos/nushell/nushell/releases"

function util:getOsTypeAndArch() local osType = RUNTIME.osType local archType = RUNTIME.archType if RUNTIME.osType == "darwin" then osType = "macoS" elseif RUNTIME.osType == "linux" then osType = "linux" elseif RUNTIME.osType == "windows" then osType = "windows" end if RUNTIME.archType == "amd64" then archType = "x86_64" elseif RUNTIME.archType == "arm64" then archType = "-armv" -- TODO: Find out exact version for 386 elseif RUNTIME.archType == "386" then archType = "x86" end return { osType = osType, archType = archType } end

aooohan commented 5 months ago

I'm interested in implementing this. What could I do? I've checked other shells' implementation and there's a little magic inside what the implementors should know.

My questions:

  • What should I hook for?

    • afaik, nushell doesn't provide an exit hook. Is it ok? (I think it's ok because Clink implementation seems to have missed this)

We can execute cleanup task when shell activate vfox first time. Like pwsh:

https://github.com/version-fox/vfox/blob/9fcc3fbfd35a80b3f6f3d84614b46ef415e3d973/internal/shell/powershell.go#L36-L38

  • nushell provides pre_prompt, pre_execution hook. I made PoC with pre_prompt only[1] and it seems to work correctly (not much-tested yet). Fish seems to utilize preexec hook but why? I don't know much about fish so cannot understand why is it required. Should I implement this for nushell?

pre_prompt enough.

  • What env vars should I update?

    • I found __VFOX_SHELL, __VFOX_PID, and __VFOX_PREVIOUS_PATHS. When are they updated?

__VFOX_PID and __VFOX_SHELL will be set when activate vfox first time, but __VFOX_PID needs to be set in a nushell script.

https://github.com/version-fox/vfox/blob/9fcc3fbfd35a80b3f6f3d84614b46ef415e3d973/internal/shell/clink_vfox.lua#L118

https://github.com/version-fox/vfox/blob/9fcc3fbfd35a80b3f6f3d84614b46ef415e3d973/internal/shell/bash.go#L29

https://github.com/version-fox/vfox/blob/9fcc3fbfd35a80b3f6f3d84614b46ef415e3d973/cmd/commands/activate.go#L82-L83

In 0.5.0, __VFOX_PREVIOUS_PATHS is no longer required.

[1]: it's not complete yet. just sharing purpose.

# config.nu
export-env {
    $env.__VFOX_SHELL = 'pwsh'; # use dummy shell for not-editing vfox code yet
    $env.__VFOX_PID = $nu.pid;
    vfox env --cleanup | null

    # like mise, we should support edge cases
    # seealso(mise's impl): https://github.com/jdx/mise/blob/e6448b335cf99db6fb2bdfd4c3f49ba255c2d8de/src/shell/nushell.rs#L38-L42)
    $env.config = (
        $env.config |
        update hooks.pre_prompt { |old_hooks| old_hooks ++ {
            # I parsed pwsh output for a temporal workaround, it could be better.
            for entry in (
                vfox env -s pwsh | split row "';" | str replace "='" "=" | parse '{name}={value}'
            ) {
                match $entry.name {
                    '$env:PATH' => {
                        load-env { Path: ($entry.value | split row ';') };
                    }
                    '$env:__VFOX_PREVIOUS_PATHS' => {
                        load-env { __VFOX_PREVIOUS_PATHS: $entry.value };
                    }
                }
            }
        }}
    )
}
apple-phi commented 3 months ago

@RanolP Just wondering if you've made any headway on this? Would be helpful to me if you have a working version but no worries if not

RanolP commented 3 months ago

Recently I had no times to implement this sry

endoarato commented 1 month ago

btw it seems duplicated with #46

I'm interested in implementing this. What could I do? I've checked other shells' implementation and there's a little magic inside what the implementors should know.

My questions:

  • What should I hook for?

    • afaik, nushell doesn't provide an exit hook. Is it ok? (I think it's ok because Clink implementation seems to have missed this)
    • nushell provides pre_prompt, pre_execution hook. I made PoC with pre_prompt only[1] and it seems to work correctly (not much-tested yet). Fish seems to utilize preexec hook but why? I don't know much about fish so cannot understand why is it required. Should I implement this for nushell?
  • What env vars should I update?

    • I found __VFOX_SHELL, __VFOX_PID, and __VFOX_PREVIOUS_PATHS. When are they updated?

[1]: it's not complete yet. just sharing purpose.

# config.nu
export-env {
    $env.__VFOX_SHELL = 'pwsh'; # use dummy shell for not-editing vfox code yet
    $env.__VFOX_PID = $nu.pid;
    vfox env --cleanup | null

    # like mise, we should support edge cases
    # seealso(mise's impl): https://github.com/jdx/mise/blob/e6448b335cf99db6fb2bdfd4c3f49ba255c2d8de/src/shell/nushell.rs#L38-L42)
    $env.config = (
        $env.config |
        update hooks.pre_prompt { |old_hooks| old_hooks ++ {
            # I parsed pwsh output for a temporal workaround, it could be better.
            for entry in (
                vfox env -s pwsh | split row "';" | str replace "='" "=" | parse '{name}={value}'
            ) {
                match $entry.name {
                    '$env:PATH' => {
                        load-env { Path: ($entry.value | split row ';') };
                    }
                    '$env:__VFOX_PREVIOUS_PATHS' => {
                        load-env { __VFOX_PREVIOUS_PATHS: $entry.value };
                    }
                }
            }
        }}
    )
}

This worked for me. the only change I had to do was put it directly in the pre_prompt hook in config.nu instead of appending it.