Vim with Powershell

VimPowershell

Vim Problem Overview


I'm using gvim on Windows.

In my _vimrc I've added:

set shell=powershell.exe
set shellcmdflag=-c
set shellpipe=>
set shellredir=>

function! Test()
  echo system("dir -name")
endfunction

command! -nargs=0 Test :call Test()

If I execute this function (:Test) I see nonsense characters (non number/letter ASCII characters).

If I use cmd as the shell, it works (without the -name), so the problem seems to be with getting output from powershell into vim.

Interestingly, this works great:

:!dir -name

As does this:

:r !dir -name

UPDATE: confirming behavior mentioned by David

If you execute the set commands mentioned above in the _vimrc, :Test outputs nonsense. However, if you execute them directly in vim instead of in the _vimrc, :Test works as expected.

Also, I've tried using iconv in case it was an encoding problem:

:echo iconv( system("dir -name"), "unicode", &enc )

But this didn't make any difference. I could be using the wrong encoding types though.

Anyone know how to make this work?

Vim Solutions


Solution 1 - Vim

It is a bit of a hack, but the following works in Vim 7.2. Notice, I am running Powershell within a CMD session.

if has("win32")
	set shell=cmd.exe
	set shellcmdflag=/c\ powershell.exe\ -NoLogo\ -NoProfile\ -NonInteractive\ -ExecutionPolicy\ RemoteSigned
	set shellpipe=|
	set shellredir=>
endif

function! Test()
  echo system("dir -name")
endfunction

Tested with the following...

  • :!dir -name
  • :call Test()

Solution 2 - Vim

I ran into a similar problem described by many here.

Specifically, calling

:set shell=powershell

manually from within vim would cause powershell to work fine, but as soon as I added:

set shell=powershell

to my vimrc file I would get the error "Unable to open temp file .... "

The problem is that by default when shell is modified, vim automatically sets shellxquote to " which means that shell commands will look like the following:

 powershell -c "cmd > tmpfile"

Where as this command needs to look like this, in order for vim to read the temp file:

 powershell -c "cmd" > tmpfile

Setting shellquote to " in my vimrc file and unsetting shellxquote (i.e. setting it to a blank space) seem to fix all my problems:

set shell=powershell
set shellcmdflag=-c
set shellquote=\"
set shellxquote=

I've also tried taking this further and scripting vim a bit using the system() call: https://stackoverflow.com/questions/7605917/system-with-powershell-in-vim

Solution 3 - Vim

I suspect that the problem is that Powershell uses the native String encoding for .NET, which is UTF-16 plus a byte-order-mark.

When it's piping objects between commands it's not a problem. It's a total PITA for external programs though.

You can pipe the output through out-file, which does support changing the encoding, but still formats the output for the terminal that it's in by default (arrgh!), so things like "Get-Process" will truncate with ellipses, etc. You can specify the width of the virtual terminal that Out-File uses though.

Not sure how useful this information is, but it does illuminate the problem a bit more.

Solution 4 - Vim

Try replacing

"dir \*vim\*"

with

 " -command { dir \*vim\* }"

EDIT: Try using cmd.exe as the shell and put "powershell.exe" before "-command"

Solution 5 - Vim

Interesting question - here is something else to add to the confusion. Without making any changes to my .vimrc file, if I then run the following commands in gvim:

:set shell=powershell.exe
:set shellcmdflag=-noprofile
:echo system("dir -name")

It behaves as expected!

If I make the same changes to my .vimrc file, though (the shell and shellcmdflag options), running :echo system("dir -name") returns the nonsense characters!

Solution 6 - Vim

The initial example code works fine for me when I plop it in vimrc.

So now I'm trying to figure out what in my vimrc is making it function. Possibly:

set encoding=utf8

Edit: Yep, that appears to do it. You probably want to have VIM defaulting to unicode anyway, these days...

Solution 7 - Vim

None of the answers on this page were working for me until I found this hint from https://github.com/dougireton/mirror_pond/blob/master/vimrc - set shellxquote= [space character] was the missing piece.

if has("win32") || has("gui_win32") 
     if executable("PowerShell") 
        " Set PowerShell as the shell for running external ! commands 
        " http://stackoverflow.com/questions/7605917/system-with-powershell-in-vim      
        set shell=PowerShell 
        set shellcmdflag=-ExecutionPolicy\ RemoteSigned\ -Command 
        set shellquote=\" 
        " shellxquote must be a literal space character. 
        set shellxquote=  
   endif 
endif 

Solution 8 - Vim

Combining the answers in this and the related thread, add the following to your $profile assuming you installed diffutils from chocolatey:

Remove-Item Alias:diff -force

And add the following to your ~/.vimrc:

if (has('win32') || has('gui_win32')) && executable('pwsh')
    set shell=pwsh
    set shellcmdflag=\ -ExecutionPolicy\ RemoteSigned\ -NoProfile\ -Nologo\ -NonInteractive\ -Command
endif

make sure shellcmdflag is exactly as shown

All credit for these solutions to their respective contributors, this is merely an aggregation post.

Solution 9 - Vim

I propose an hackish solution. It doesn't really solve the problem, but it get the job done somehow.

This Vim plugin automate the creation of a temporary script file, powershell call through cmd.exe and paste of the result. It's not as nice as a proper powershell handling by vim, but it works.

Solution 10 - Vim

Try instead

set shellcmdflag=\ -c

Explanation:

Vim uses tempname() to generate a temp file path that system() reads.

If &shell contains 'sh' and &shellcmdflag starts with '-' then tempname() generates a temp file path with forward slashes.

Thus, if

set shell=powershell
set shellcmdflag=-c

then Vim will try to read a temp file with forward slashes that cannot be found.

A remedy is to set instead

set shellcmdflag=\ -c

that is, add a whitespace to &shellcmdflag so that the first character is no longer '-' and tempname() produces a temp file path with backward slashes that can be found by system().


I remarked on the vim_dev mailing list ( https://groups.google.com/forum/#!topic/vim_dev/vTR05EZyfE0 ) that this deserves better documentation.

Solution 11 - Vim

actf answer works for me, but because of Powershell built in DIFF (which is different from the Linux one) you must add this line to your Powershell profile to have diff working again in VIM:

Remove-Item Alias:diff -force

Solution 12 - Vim

I'm running GVim v8.2 (Windows).

Using the fullpath to the executable works for me:

set shell=C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe

Solution 13 - Vim

I don't use VIM but Powershell's default output is Unicode. Notepad can read unicode, you could use it to see if you are getting the output you expect.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKevin BerridgeView Question on Stackoverflow
Solution 1 - VimNathan HartleyView Answer on Stackoverflow
Solution 2 - VimactfView Answer on Stackoverflow
Solution 3 - VimAdrianView Answer on Stackoverflow
Solution 4 - VimMark SchillView Answer on Stackoverflow
Solution 5 - VimDavid MohundroView Answer on Stackoverflow
Solution 6 - VimDan FitchView Answer on Stackoverflow
Solution 7 - VimMark StanfillView Answer on Stackoverflow
Solution 8 - VimRafael KitoverView Answer on Stackoverflow
Solution 9 - VimRaoul SupercopterView Answer on Stackoverflow
Solution 10 - VimEnnoView Answer on Stackoverflow
Solution 11 - VimLoboView Answer on Stackoverflow
Solution 12 - VimCRTejaswiView Answer on Stackoverflow
Solution 13 - VimDan KingView Answer on Stackoverflow