Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

system() with powershell in vim

Tags:

vim

powershell

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?

like image 855
actf Avatar asked Sep 30 '11 04:09

actf


People also ask

Can I use Vim in PowerShell?

Now, the vim command works in terminal and PowerShell windows.

How do I make a PowerShell executable?

To convert a single PowerShell script to EXE via the command-line requires a single line providing the main PS2EXE command ( Invoke-PS2EXE ) followed by the script's path to convert and the path to the EXE you'd like to create. You can now run target.exe, and it will invoke the code defined in the source.

How do you break a line in PowerShell?

Using PowerShell newline in Command To add newline in the PowerShell script command, use the` (backtick) character at the end of each line to break the command into multiple lines.


2 Answers

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.

like image 94
actf Avatar answered Oct 07 '22 00:10

actf


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

like image 24
Enno Avatar answered Oct 06 '22 23:10

Enno