5

I am having trouble getting vimdiff to work on a Windows 10 machine. I am running vim from Powershell. Powershell is also declared in $myvimrc as my shell of choice:

set shell=C:\WINDOWS\system32\WindowsPowershell\v1.0\powershell.exe

The documents I am attempting to compare are not saved as files. I open two vertical splits, enter text into each, and run :windo diffthis. The output is E97: Cannot create diffs.

This article says I may need to download and use a different diff.exe than the one installed with gvim. I have downloaded the recommended "GnuWin32 diff" package and added the install directory to my Windows Path ($env:path). Continuing to follow these directions, I've commented out the default diffexpr declaration, but still get E97.

I have also tried calling my own function to no avail. In this attempt, I've made sure to escape backslashes, and have also copied the downloaded diff.exe to a directory I am confident I have full permissions to. To help with troubleshooting, I've temporarily saved the two files I wish to compare, and specified their full paths explicitly rather than using vim's v:fname_in and v:fname_new (and v:fname_out).

set diffexpr=TestDiff()
function TestDiff()
       silent execute "!& " . "C:\\diff.exe" . " -a --binary " "C:\\a.edi" . " " . "C:\\b.edi" . " > " . "C:\\tmp.txt"
endfunction

I've researched this error by running :h E97, which returns the following information:

Vim will do a test if the diff output looks alright. If it doesn't, you will get an error message. Possible causes:

  • The "diff" program cannot be executed.
  • The "diff" program doesn't produce normal "ed" style diffs (see above).
  • The 'shell' and associated options are not set correctly. Try if filtering works with a command like ":!sort".
  • You are using 'diffexpr' and it doesn't work. If it's not clear what the problem is set the 'verbose' option to one or more to see more messages.

The self-installing Vim for MS-Windows includes a diff program. If you don't have it you might want to download a diff.exe. For example from http://gnuwin32.sourceforge.net/packages/diffutils.htm.

I believe that I pass the first two of these requirements, as tmp.txt is generated and follows the example "ed" style diff that is provided in the help file. I have not set other shell-related parameters (shelltype, shellpipe, etc) in $myvimrc, but executing other commands with :! complete without issue.

There is no additional information in :messages, only the E97 error.

Edit: If I remove set shell=C:\WINDOWS\system32\WindowsPowershell\v1.0\powershell.exe from $myvimrc, defaulting the shell back to cmd.exe, diffthis works as expected. It seems that others have also had this problem when using Powershell.

Below are captures of the command windows that pop up when running diffthis with both shells. The commands used are nearly identical.

cmd

powershell

I had speculated that the forward slashes apparent in the Powershell version of this attempt were problematic, but I am able to run this command exactly (with dummy files in place of the .tmp files) and it outputs what seems to be an adequate file for use with diff. I've also tried adding a substitute of forward slashes to back slashes to no avail.

root
  • 325
  • 2
  • 11
  • For what it's worth, I have gvim installed on my Windows 10 machine, using the Windows installer for gvim, and the `:diffthis` command worked fine for me when I started gvim from the clickable icons. It also worked fine when I ran it from PowerShell. I didn't have to set any variables or anything. Do you have any custom configuration that might conflict with vim? – joanis Jun 11 '19 at 19:09
  • current vim comes with the diff functionality included, you don't need an external diff command anymore. Just make sure your `diffopt` setting includes `internal` – Christian Brabandt Jun 12 '19 at 06:25
  • I have updated the original post with additional information. The problem is stemming from defining my `shell` as Powershell. – root Jun 13 '19 at 14:20

1 Answers1

3

The problem boils down to how vim/Powershell are A) encapsulating the command in quotes and B) handling white space in path names.

I am able to bypass this problem with the following changes to $myvimrc:

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

Also a change in the default MyDiff() function within the if that sets the path to diff in the cmd variable:

  " below is the default
  " let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
  let cmd = "C:/diff"

This approach is dependent upon copying the diff.exe that ships with vim to a directory that doesn't contain spaces in the path for simplicity (C:\diff.exe).

The resulting command that is executed is:

powershell -c C:/diff -a --binary C:/<redacted>/a.tmp C:/<redacted>/b.tmp > C:/<redacted>/c.tmp
root
  • 325
  • 2
  • 11