system() with powershell in vim
I'm trying to write a simple function in Vim to return the results of a powershell command. I keep getting gibberish in the results though.
I think this may be an encoding problem, but as you'll see the problem is strange since it "sort of works". I don't have any solution to the problem though.
With the following non-default shell options set in vim:
set shell=powershell
set shellcmdflag=-c
Given the following function:
function! Test()
let result = system("ls")
call setline(1, result)
endfunction
When I run (from C:\Windows):
:call Test()
The following is written to my buffer:
^@^@ Directory: C:\Windows^@^@^@ Mode LastWriteTime Length Name ^@-------
....continues
开发者_运维问答
However when I run the following command:
:r!ls
I get back exactly what I would expect (i.e. the powershell results of ls) Even more interesting is when I run the command:
:echo system("ls")
The results look correct
I've tried modifying my original function as follows:
function! Test()
let result = system("ls")
echo result
call setline(1, result)
endfunction
and the value echo'ed out is exactly what I would expect - yet I still see gibberish
I've also tried the following modification to my function:
function! Test()
let result = system("ls")
let conv = iconv(result, "utf-8", &enc)
call setline(1, conv)
endfunction
But the results are exactly the same (i.e. they include the ^@^@ symbols and other gibberish)
My guess as to what's happening is that powershell cmds which are redirected using > produce utf-16 output, and vim is unable to deal with this. I get the following from powershell (file in this case is the gnu32 program):
PS> ls > test
PS> file test
test; Little-endian UTF-16 Unicode text, with CRLF, CR line terminator
I've also tried playing around with $OutputEncoding, without any success, as described here: http://blogs.msdn.com/b/powershell/archive/2006/12/11/outputencoding-to-the-rescue.aspx
Anyone have any ideas what I'm doing wrong here?
I've finally figured this out.
The following modification to my function does pretty much exactly what I want:
function! Test()
let @r = system("ls")
put! r
endfunction
I think Artomegus is correct, the problem is really the carriage return, and not an encoding problem.
As a side note, I ran into problems when I had only the following in my .vimrc file:
set shell=powershell
set shellcmdflag=-c
With just these settings when I ran :call Test() I would get an error about Vim being unable to read the temp file.
The fix for this problem is to add the following to your .vimrc file:
set shell=powershell
set shellcmdflag=-c
set shellquote=\"
set shellxquote=
You must set the shellquote to be \" and shellxquote to be a blank space (i.e. empty) because by default on windows, shellxquote is set to \" which overrides the value of shellquote. This is problematic when using the system function, which runs the vimrun.exe program behind the scenes.
Hopefully this helps someone else. I've been stuck on this for a long time, but now powershell works perfectly for me with 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().
精彩评论