kassio / neoterm

Wrapper of some vim/neovim's :terminal functions.
Other
1.32k stars 117 forks source link

Neoterm error when default shell is changed to pwsh/powershell #332

Open daephx opened 3 years ago

daephx commented 3 years ago

I am uncertain as to if this could be related to #246 but it was the only issue I saw within the same vein. Thanks in advanced for any information! 🎉

Describe the bug Upfront, it's important to know: I'm running Windows 10. Following the help documentation :h shell-powershell. I changed the default shell for Neovim to pwsh/powershell. This allows me to use PowerShell aliases in command mode such as !ls or !mv % ~/Desktop and have a fairly consistent command structure to bash. While commands in cmd.exe are slightly diffrent: !dir and !move % ~/Desktop <- doesn't seem to work.

Unfortunately, regardless of if I use powershell or pwsh as the new default, and regardless of how I set my g:neoterm_shell. This breaks Neoterm, resulting in an error when running :Tnew or :T ls.

To Reproduce Steps to reproduce the behavior:

  1. Be on Windows 10
  2. Change default shell to powershell :h shell-powershell
  3. Create new Neoterm :Tnew || :T ls
  4. See error

Expected behavior Neoterm should still function under these conditions. But cannot handle this modification.

Screenshots/gifs Windows PowerShell: I struggled to copy the text before the term window closed powershell.exe image

PowerShell Core: The error output is slightly different from powershell.exe pwsh.exe

Id     Name            PSJobTypeName   State         HasMoreData     Location             Command
--     ----            -------------   -----         -----------     --------             -------
1      Job1            BackgroundJob   Running       True            localhost            Microsoft.PowerShell.Man…
::neoterm-1: The term '::neoterm-1' is not recognized as a name of a cmdlet, function, script file, or executable program.
Check the spelling of the name, or if a path was included, verify that the path is correct and try again.

Versions Information:

" File: neoterm.vim
" Desc: Configs for neoterm plugin

" --- Initialization ---

" Prevent this file from loading without plugin
if empty('g:neoterm_loaded') | finish | endif

" Windows - Powershell
if has("win32")
  " Use pwsh if available, else use windows PowerShell
  let g:neoterm_shell = executable('pwsh') ? 'pwsh' : 'powershell'
  let g:neoterm_eof = "\r"
else " Use whatever shell you prefer, default to bash
  let g:neoterm_shell = executable('zsh') ? 'zsh' : 'bash'
endif

" Neoterm Options

let g:neoterm_default_mod = "botright"
let g:neoterm_size = 25
let g:neoterm_autoscroll = 1
let g:neoterm_keep_term_open = 1
let g:neoterm_autoinsert = 1
let g:neoterm_fixedsize = 1

" Mappings

" Escape terminal buffer via <ESC>
" tnoremap <silent> <Esc> <C-\><C-n>

" Spawn/Toggle Terminal
noremap <silent> <leader>` :Ttoggle<CR>
tnoremap <silent> <leader>` <C-\><C-n>:Ttoggle<CR>
noremap <silent> <F12> :Ttoggle<CR>
tnoremap <silent> <F12> <C-\><C-n>:Ttoggle<CR>

" Allow Ctrl+W to switch window in terminal
tnoremap <silent> <C-w> <C-\><C-n><C-w>

" Press enter for insert mode in terminal
" nnoremap <Enter> :if &buftype = 'terminal' | startinsert | endif

" Automatic insert mode on terminal buf/win enter
" Prevent terminal buffer for holding <Esc> hostage
" Provides compatibility with fzf terminal window
augroup TerminalBuffers
  autocmd!
  if has("nvim")
    " Hide terminal from buffer list
    autocmd TermOpen,TermEnter * setlocal nobuflisted
    " Auto enter insert mode for terminal buffers
    " autocmd BufWinEnter,WinEnter term://* startinsert
    autocmd BufEnter term://* startinsert
    autocmd BufLeave term://* stopinsert
    " Allow escape from terminal and fzfterm
    autocmd TermOpen * tnoremap <buffer> <Esc> <c-\><c-n>
    autocmd FileType fzf tunmap <buffer> <Esc>
  endif
augroup END

Additional context For clarity sake: I have a preference for PowerShell Core and have slightly modified the shell replacement command. However, I do not believe this is important to the issue seeing as: both result the same errors already presented.

Original: Windows PowerShell Provided by `:h shell-powershell` ```viml let &shell = has('win32') ? 'powershell' : 'pwsh' ```
Modified: PowerShell Core Wrapped within an `if has('win32')` for safety ```viml let &shell = executable('pwsh') ? 'pwsh' : 'powershell' ```
eyalk11 commented 2 years ago

I tried, and it works for me (windows 10, nvim 6.0) . I didn't know neoterm_shell var... nice.

function! TermOV(use_file_dir)
    let t=&shell
    let g:neoterm_shell = executable('pwsh') ? 'pwsh' : 'powershell'
    set shell=cmd.exe
    set splitright
    let k=g:neoterm.last_id+1
    vertical Tnew "~/"
    "exe k."T . /etc/bashrc"
    "exe k."T . ~/.bash_profile"
    if a:use_file_dir
        exe k."T cd " . expand('%:p:h')
    "else
        "exe k."T hookvim" 
    endif  
        "exe k."T set -o emacs"
    "if g:on_ek_computer
        "exe k."T bind '\"\\C-r\": \"\\C-ahstr -- \\C-j\"'"
    "endif
    exe k."Tclear"
    set shell=t
endfunction

It is important that shell would be cmd.exe

cheinigk commented 2 years ago

Just stumbeled upon a similar error using MSYS bash instead of cmd. Found out, that neoterm uses an heuristic to find the opened terminal. Essentially it goes like this:

  1. When you open a terminal in neovim, the buffer is named according to the shell and the command you have provided while opening the terminal.
  2. neoterm uses a comment instead of a command and therefore, you can, e.g. do :b neoterm-3 to jump to the third terminal

Now to the actual error you are getting: on Windows, this marker is set to &::neoterm which I believe is a comment string in cmd.exe. You will have to change it to a proper PowerShell comment string with

let g:neoterm_marker = ';#neoterm'

And just as a reference, this is my working config to use MSYS bash with neoterm on windows:

if vim.loop.os_uname().sysname == "Windows_NT" then
  vim.o.shell=vim.env.HOME:gsub('\\', '/') .. [[/AppData/Local/Programs/msys64/usr/bin/bash.exe]]
  vim.o.shellpipe="| tee"
  vim.o.shellslash=true
  vim.o.shellredir=">"
  vim.o.shellquote=""
  vim.o.shellxquote=""
  vim.o.shellcmdflag="-c"
  vim.g.neoterm_marker=";#neoterm"
end