neovimnushell

How to execute Nushell commands inside nvim command line?


I am using Neovim in Windows 11 26100.3476, with msys2 for gcc to run Zsh.

I used to use this Zsh command in Neovim:

# this is my config in ~/.zshrc
function ngr(){
  cd /c/SoftWare/Nginx && ./nginx -s reload
}
:! zsh -c "ngr"

With Nushell, I added a custom command in config.nu :

def ngr [] {
  cd c:/SoftWare/Nginx
  ./nginx.exe -s reload
}

It works when I run it in Nushell directly.

I added vim.opt.sh = "nu" to my nvim config, but when I try to use :!nu -c "ngr":

:!nu -c "ngr"
Error:
nu::shell::io::not_found
  x I/O error
  `->   x Cound not access file
  
  help: The error occurred at'/s'
shell returned 1

Neovim error

Is there a way to run my custom nushell command in Neovim?


Solution

  • I believe you are running into a combination of some misconceptions, missing information, and even a Nushell bug (or at least missing feature).

    Summary recommendation

    (Tested on Neovim on Windows with Nushell 0.102.1)

    Details and Background

    Startup config is not processed when running a commandstring (or script)

    First, you don't mention where you had defined your ngr command when you were doing this with Zsh. It doesn't appear that it is a function that was defined in a Zsh startup file like ~/.zshrc, because if it was, you should have the same issue with that Zsh commandline.

    Most shells (including Bash, Zsh, Fish, and Nushell) don't process your startup config when running with <shell> -c "<commandstring>". Startup config files (a) naturally make the startup take longer, (b) (shouldn't, but) often include interactive output (and sometimes even input) that you wouldn't want when running a one-off commandstring.

    So that leads me to believe your ngr command in Zsh might have been a script on the path ... But ...

    Windows vs. Linux/macOS differences

    In the custom command you provided, you are using a Windows path. This leads me to believe that you may have been using Zsh under Linux or macOS, but now you are running Nushell under Windows. If so, then scripts work differently. In Linux, a script can have a shebang line that tells the OS what program to use to execute it. As far as I know, Windows does not have this.

    So under Zsh in Linux, you could run an ngr script (assuming proper shebang) in Neovim using:

    :!zsh -c "ngr"
    

    But you could also just run it with :!ngr alone, if that were the case.

    If you were in Linux, Nushell should do the same.

    Windows vs. Linux/macOS Neovim differences

    I won't claim to be a Neovim expert, but as far as I can tell, Windows Neovim is configured with the assumption that it is using CMD as its shell. That means that it uses /s as the default command flag. On Linux, it uses -c since that's what most shells use. And Nushell uses -c. You'd have a similar issue if you tried to use Git Bash for Windows under Windows Nushell.

    So if switching from a *nix-based system to Windows, you'll need to update your Neovim config to handle the Nushell (and other non-CMD shells) flag. Courtesy of this thread in the Neovim repo.

    In init.lua:

    vim.opt.sh = 'nu'
    vim.opt.shellcmdflag = '-c'
    vim.opt.shellquote = ""
    vim.opt.shellxquote = ""
    

    Then :source init.lua and try :!ls. If you see a Nushell style directory listing, then you are one step closer.

    Nushell doesn't process startup config even when using -i

    That's probably a bug - It's at least a missing feature, IMHO. I'm surprised I didn't know this already, or I would have tried to fix it. There's an old issue on this - #7442.

    If this was in place, the solution could be:

    :!nu -ic "ngr"
    

    That would load your startup config where the custom command is defined and then run it. I'll work on getting this fixed/added (disclosure - I'm a Nushell contributor and (recent) core team member).

    Even so, this might not be the most efficient solution. I'd still probably recommend ...

    Alternatives

    Probably the easiest solution on Nushell Windows would be to simply define this in a file to be source'd and put it in your $NU_LIB_PATH. By default, Nushell will look for source files in a scripts directory under your config directory, so:

    # Check/confirm that scripts are in your libs path
    $NU_LIB_DIRS
    # => ╭───┬───────────────────────────────────────────────────────╮
    # => │ 0 │ C:\Users\user1234\.config\nushell\scripts             │
    # => │ 1 │ C:\Users\user1234\AppData\Roaming\nushell\completions │
    # => ╰───┴───────────────────────────────────────────────────────╯
    
    # If so, go to the config dir and create the scripts dir
    cd $nu.default-config-dir
    mkdir scripts
    cd scripts
    vi ngr
    

    In ngr, add just the following (no custom command def):

    c:/SoftWare/Nginx/nginx.exe -s reload
    

    Save the file, then :!source ngr should work to reload Ngnix.