Can't run Vimdiff (7.4) on Windows 7

16,398

This issue can be caused by the default _vimrc file created by the installer on Windows. If you're still using that default file, or if you copied it at some point, then check the function you've assigned to the diffexpr option. One of the patches between Vim 7.3 and 7.4 introduced new default quoting rules for the cmd.exe shell on Windows. This patch broke the workaround in the MyDiff() function designed to fix the same issue solved by the patch.

The MyDiff() function was fixed by version 7.4.103 by fixing the installer. Here is the MyDiff() function which the latest installer will create for you if you just want to copy it to your _vimrc:

 function MyDiff()
   let opt = '-a --binary '
   if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
   if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
   let arg1 = v:fname_in
   if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
   let arg2 = v:fname_new
   if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
   let arg3 = v:fname_out
   if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
   if $VIMRUNTIME =~ ' '
     if &sh =~ '\<cmd'
       if empty(&shellxquote)
         let l:shxq_sav = ''
         set shellxquote&
       endif
       let cmd = '"' . $VIMRUNTIME . '\diff"'
     else
       let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
     endif
   else
     let cmd = $VIMRUNTIME . '\diff'
   endif
   silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3
   if exists('l:shxq_sav')
     let &shellxquote=l:shxq_sav
   endif
 endfunction

You can see your full version in Vim using the :version or :intro commands, or at the splash screen at startup.

Unfortunately if you want an official installer, you will either need to wait until 8.0, or install a nightly build. Nevertheless, you can install Vim from other places or build your own Vim.


Duplicated on Stack Overflow (unusually, on-topic on both sites), if this answer is updated so should the other.

Share:
16,398

Related videos on Youtube

ysap
Author by

ysap

Updated on September 18, 2022

Comments

  • ysap
    ysap over 1 year

    I recently installed the 7.4 version of gVim on a Windows 7 machine. Trying to diff two files from the context-sensitive menu on Windows Explorer, I keep getting the error messages:

    E810: Cannot read or write temp files
    E97: Cannot create diffs

    The two selected files are opened in the two-pane gVim view, and the editor seems to be in diff mode, but the actual differences are not highlighted.

    The %TEMP% and %TMP% environment variables are populated with a valid directory name.

    I get the same response when opening the files in a regular gVim session and typing :diffthis in the command prompt.

    This used to work properly with Vim 7.3, but it looked like something was changed in v7.4.

    How can I diff the two files?

  • ysap
    ysap over 10 years
    Found a few solutions on then net, but this is the only one that worked for me!
  • ysap
    ysap over 10 years
    BTW - how can you tell the # of the sub-version (e.g. 7.4.103)?
  • Ben
    Ben over 10 years
    Three ways: startup on an empty buffer shows version information including patch level, the :intro command shows the same text, and the :version command gives the information on an "included patches" line. :version also gives a very detailed list of included or excluded features as well.
  • Ben
    Ben over 10 years
    Also, Bram doesn't usually release any official installers after the initial minor version, e.g. 7.4.0. But there are plenty of places to get an installer for a more recent Vim if you don't feel like compiling, the most often cited probably being here: sourceforge.net/projects/cream/files/Vim
  • ysap
    ysap over 10 years
    Well, the startup screen and :intro show me the same info (that is, just "7.4"). :version shows "7.4" and elaborates on the compilation time. No patch version number. Your 2nd comment may explain why it is so. It is compiled by mool(at)tororo, which I assume refers to Mr. Moolner.
  • Ben
    Ben over 10 years
    Yes, if no patch level is listed, you have 7.4.0.
  • Captain Man
    Captain Man over 8 years
    I put the MyDiff() and set diffexpr=MyDiff() in my .vimrc, and I still get the error. I am using Git for Windows' vim/vimdif (:version gives 7.4, patches: 1-872). Am I missing a step?
  • Ben
    Ben over 8 years
    Another cause for diff errors is a TMP or TEMP directory that does not exist. Echo the value of $TMP and $TEMP in Vim, do they point to writeable, existing locations?
  • Captain Man
    Captain Man over 8 years
    @Ben that is where things got a little odd. :echo $TMP and :echo $TEMP were both /tmp. After doing cd /tmp in git bash and doing ls to investigate, it turns out it's mapped to C:\Windows\Temp, I right-clicked and made the folder not read-only but I still seem to get this issue. I looked at the folder again and it seems Windows made it read-only again, why, I don't know, but it seems to set it back everytime. I need to figure out a way to have it always not be read-only or to map this /tmp to a different folder.
  • Captain Man
    Captain Man over 8 years
    @Ben setting them to /c/temp and running cacls C:\temp /E /G everyone:F (which as I understand should give everyone full access) still results in the same errors. (I also tried it on C:\Windows\Temp as suggested here).
  • Ben
    Ben over 8 years
    Does C:\Temp exist on your system? It doesn't by default in windows these days. I don't expect anything in C:\Windows to ever work; those folders always need admin rights to access for good reasons, I can't imagine who thought that was a good TMP location. What is your shell set to? The diffexpr here is really designed for a standard cmd.exe setup.
  • Captain Man
    Captain Man over 8 years
    @Ben I've fixed the issue, it was something else causing this, and I misunderstood this MyDiff() to be something to use when using vim on windows, but it's for something for using vim through cmd, I am using vim through git bash. Thank you.
  • Ben
    Ben over 8 years
    If it's likely to hit others, feel free to add another answer. There is a spot in the MyDiff function for other shells, but I'm not sure how well it works.
  • ysap
    ysap almost 8 years
    Just found out that the suggested fix (which works great for a couple of years now, being migrated between systems) fails when trying to vimdiff from Cygwin terminal. Apparently, the block if takes a wrong branch b/c it misidentifies the command shell.
  • ysap
    ysap almost 8 years
    The reported &sh is /bin/bash rather than cmd.exe, but the actual shell is, of course, cmd.exe, so the quoting scheme fails.
  • Ben
    Ben almost 8 years
    I don't think I follow you correctly. If you are running Vim in cygwin, with the shell set to cygwin bash, why do you expect to use cmd.exe quoting rules?
  • ysap
    ysap almost 8 years
    Ben, I am not expecting anything... just reporting what I see. Since posting that comment I figured out that there are actually two problematic cases - one is using Git's difftool to view file diffs (in which case it uses the bash shell from the Git installation) and the second is when running gvim -d from the Cygwin bash command line.
  • ysap
    ysap almost 8 years
    In the MyDiff() function you posted, I removed the silent so I get to see the actual command line. The Git command generates: C:/Program Files (x86)/Git/bin/bash -c "c:\Program" Files (x86)\Vim\vim74\diff" -a --binary C:/cygwin64/tmp/VIoEA21.tmp C:/cygwin64/tmp/VInEA22.tmp > C:/cygwin64/tmp/VIdEA23.tmp".
  • ysap
    ysap almost 8 years
    The Cygwin command gave: /bin/bash -c ""C:\Program Files (x86)\Vim\vim74\diff" -a --binary C:/cygwin64/tmp/VIo6893.tmp C:/cygwin64/tmp/VIn6894.tmp > C:/cygwin64/tmp/VId6895.tmp". You can see that the generated commands are different, and the quotes are set in the wrong place.
  • ysap
    ysap almost 8 years
    Anyway, I played a little (not so little actually...) with the function, but could not make it to work. I got it to generate the following command: /bin/bash -c "C:/Program\ Files\ \(x86\)/Vim/vim74/diff -a --binary C:/cygwin64/tmp/VIo6C5B.tmp C:/cygwin64/tmp/VIn6C5C.tmp > C:/cygwin64/tmp/VId6C5D.tmp" but from some unidentified reason, it still does not open the editor as expected. However, when using the same line manually from the bash command line - it actually works. So, the problem lies in the gvim -d step.
  • Ben
    Ben almost 8 years
    I don't know enough about Vim in cygwin to address that very well. I do know that cygwin has a Vim package available that will natively understand cygdrive paths and such. I also am pretty sure the normal Windows Vim can probably work with the cygwin shell and tools, but you will need to carefully configure all the shell-related options, in particular shellquote and shellxquote. Getting that configuration figured out is probably worth another answer in its own right.
  • mosh
    mosh almost 7 years
    cygwin/vim has very FEW features compiled in, so it is best to take the official build of gvim for windows will all the features turned on and tested. If you are using cygwin64, set shell=c:/cygwin64/bin/bash to address the above problem, it affects all plugins that launch shell commands like fugitive.vim also.