system() with powershell in vim
Asked Answered
D

2

7

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?

Dealings answered 30/9, 2011 at 4:22 Comment(3)
Does the answer for this question help? https://mcmap.net/q/1625520/-vim-with-powershellTarantula
@Tarantula I did look through that question before posting, but I was unable to find anything in there that really helped. I did try the "hack" of running powershell through cmd as described in the answer by Nathan Hartley, but I run into the exact same problem. I think the root of the problem is that the > redirection operator in powershell writes to a file in utf-16. If I could find a way to get > to output ascii, instead, I think that would solve the problemDealings
I don't think it is returning unicode when running in your function. If it was, you would see a lot more ^@ characters. Instead, what I think you are seeing are representations of the carriage-return character (0x0d) that are included in the standard Windows line terminator (CR LF). As for when you are in powershell itself, the > redirector is actually shorthand for Out-File, which does default to unicode. Try replacing CR characters (\r) with an empty string before displaying the result.Rubi
D
4

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.

Dealings answered 20/10, 2011 at 3:1 Comment(0)
G
1

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().

Gamic answered 16/12, 2014 at 7:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.