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]: Support nushell for Windows #207

Open
yanecc opened this issue Apr 16, 2024 · 11 comments
Open

[Feature]: Support nushell for Windows #207

yanecc opened this issue Apr 16, 2024 · 11 comments
Labels
enhancement New feature or request

Comments

@yanecc
Copy link
Contributor

yanecc commented Apr 16, 2024

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

@yanecc yanecc added the enhancement New feature or request label Apr 16, 2024
@aooohan aooohan added the duplicate This issue or pull request already exists label Apr 17, 2024
@aooohan
Copy link
Member

aooohan commented Apr 17, 2024

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

@RanolP
Copy link

RanolP commented May 1, 2024

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 };
                    }
                }
            }
        }}
    )
}

@alenros
Copy link

alenros commented May 13, 2024

@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
Copy link
Member

aooohan commented May 13, 2024

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:

Due to a bug in PowerShell, we have to cleanup first when the shell open.
#>
& '{{.SelfPath}}' env --cleanup 2>$null | Out-Null;

  • 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.

os.setenv('__VFOX_PID', os.getpid())

export __VFOX_PID=$$;

_ = os.Setenv(env.HookFlag, name)
exportEnvs[env.HookFlag] = &name

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 };
                    }
                }
            }
        }}
    )
}

@aooohan aooohan removed the duplicate This issue or pull request already exists label May 13, 2024
@apple-phi
Copy link

@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
Copy link

RanolP commented Jul 11, 2024

Recently I had no times to implement this sry

@endoarato
Copy link

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.

@colececil
Copy link
Contributor

I'm currently working on a code change to integrate this into vfox, and I hope to get a pull request created within the next several days.

I do have one question at the moment, if anyone can answer... In what kinds of scenarios should I expect vfox env -s <shell> to produce output? I want to be able to reproduce a scenario like that to make sure I can get everything tested before I create my pull request, but I haven't been able to figure it out.

@jan-bar
Copy link
Contributor

jan-bar commented Dec 29, 2024

@colececil

  1. In fact, the terminal adaptation only needs code similar to the following. When starting the terminal, set the __VFOX_PID environment variable and the environment variable generated by vfox activate xxx, and execute vfox env -c once.
  2. Then set the environment variables generated by vfox env -s xxx in the terminal callback every time you enter the return key

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 vfox_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(vfox_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

@colececil
Copy link
Contributor

Thanks, @jan-bar. I think I have it figured out now.

Specifically, I was trying to figure out how to get vfox env -s <shell> to produce an output so I can properly test my implementation of the hook in Nushell. I initially wasn't able to figure that out, but now I've learned that:

  1. It only seems to produce an output in a directory where a .tool-versions file specifies an SDK version to use.
  2. It only seems to produce an output when the current environment variables don't match the desired environment variables. (Because of this, I never see any output when directly running vfox env -s bash inside Bash, because the environment variables have already been set by the hook at that point.)

To illustrate, see this example running vfox env -s bash in Bash:

image

Compared with this example running vfox env -s bash in Nushell:

image

Anyway, now that I have a better understanding of the purpose and functionality of vfox env -s <shell>, I should be able to do my testing.

@colececil
Copy link
Contributor

@jan-bar, @aooohan, @RanolP, would any of you be able to review and help with my pull request? ☝️ I haven't heard anything from anyone on it yet. Thanks!

bytemain pushed a commit that referenced this issue Jan 24, 2025
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

No branches or pull requests

8 participants