Single quotes acting like double quotes (_vimrc: MyDiff())

68 views
Skip to first unread message

star...@gmail.com

unread,
Oct 11, 2013, 3:40:36 AM10/11/13
to vim...@googlegroups.com
What steps will reproduce the problem?
1. Open file1.txt in gvim
2. :diffsplit file2.txt

What is the expected output? What do you see instead?
I expect the diffsplit command to show the differences between file1.txt and file2.txt in two windows. I get two errors instead and the two windows show no differences.

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

What version of the product are you using? On what operating system?
I recently (yesterday) installed gvim74.exe on Windows XP SP3. This problem did not happen with vim 7.3. It started happening immediately after replacing it by installing vim 7.4.

Please provide any additional information below.
In the MyDiff() function of the _vimrc that is distributed with the gvim74.exe installer, I changed single quotes to double quotes on line 13 of the function, and the problem was fixed. This allowed the pattern in the IF test to match.

So change original: (single quotes)
if &sh =~ '\<cmd' (fails)

To: (double quotes)
if &sh =~ "\<cmd" (works)

Or keep single quotes but escape the backslash:
if &sh =~ '\\<cmd' (also works)

Oddly, from what I understand of literal strings from vim:help, the original line is technically correct. It seems like there is a bug in vim 7.4 that is swapping the meaning of single and double quotes, at least in this context.

1 function MyDiff()
2 let opt = '-a --binary '
3 if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
4 if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
5 let arg1 = v:fname_in
6 if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
7 let arg2 = v:fname_new
8 if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
9 let arg3 = v:fname_out
10 if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
11 let eq = ''
12 if $VIMRUNTIME =~ ' '
13>>> if &sh =~ '\<cmd' <<< CHANGE TO DOUBLE QUOTES
14 let cmd = '""' . $VIMRUNTIME . '\diff"'
15 let eq = '"'
16 else
17 let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'
18 endif
19 else
20 let cmd = $VIMRUNTIME . '\diff'
21 endif
22 silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq
23 endfunction

(Credit to fvelasqu...@gmail.com, http://code.google.com/p/vim/issues/detail?id=28#c6)

bugreport.txt

Ben Fritz

unread,
Oct 11, 2013, 7:27:20 AM10/11/13
to vim...@googlegroups.com
On Friday, October 11, 2013 2:40:36 AM UTC-5, star...@gmail.com wrote:
> What steps will reproduce the problem?
> 1. Open file1.txt in gvim
> 2. :diffsplit file2.txt
>
> What is the expected output? What do you see instead?
> I expect the diffsplit command to show the differences between file1.txt and file2.txt in two windows. I get two errors instead and the two windows show no differences.
>
> E810: Cannot read or write temp files
> E97: Cannot create diffs
>
> What version of the product are you using? On what operating system?
> I recently (yesterday) installed gvim74.exe on Windows XP SP3. This problem did not happen with vim 7.3. It started happening immediately after replacing it by installing vim 7.4.
>
> Please provide any additional information below.
> In the MyDiff() function of the _vimrc that is distributed with the gvim74.exe installer, I changed single quotes to double quotes on line 13 of the function, and the problem was fixed. This allowed the pattern in the IF test to match.
>
> So change original: (single quotes)
> if &sh =~ '\<cmd' (fails)
>
> To: (double quotes)
> if &sh =~ "\<cmd" (works)
>
> Or keep single quotes but escape the backslash:
> if &sh =~ '\\<cmd' (also works)
>
> Oddly, from what I understand of literal strings from vim:help, the original line is technically correct. It seems like there is a bug in vim 7.4 that is swapping the meaning of single and double quotes, at least in this context.
>

Your "fix" and root cause are wrong as I explained in your vim_use post.

Vim does NOT confuse single and double quotes. You're confusing which code is running.

I confirm the following is present in dosinst.c which apparently creates the default _vimrc:


> 1 function MyDiff()
> 2 let opt = '-a --binary '
> 3 if &diffopt =~ 'icase' | let opt = opt . '-i ' | endif
> 4 if &diffopt =~ 'iwhite' | let opt = opt . '-b ' | endif
> 5 let arg1 = v:fname_in
> 6 if arg1 =~ ' ' | let arg1 = '"' . arg1 . '"' | endif
> 7 let arg2 = v:fname_new
> 8 if arg2 =~ ' ' | let arg2 = '"' . arg2 . '"' | endif
> 9 let arg3 = v:fname_out
> 10 if arg3 =~ ' ' | let arg3 = '"' . arg3 . '"' | endif
> 11 let eq = ''
> 12 if $VIMRUNTIME =~ ' '
> 13>>> if &sh =~ '\<cmd' <<< CHANGE TO DOUBLE QUOTES
> 14 let cmd = '""' . $VIMRUNTIME . '\diff"'
> 15 let eq = '"'

These two lines are WRONG with current default settings. They are a workaround for the issue fixed with external windows commands by the new shellxquote default value. Bram, these lines need to get removed.

> 16 else
> 17 let cmd = substitute($VIMRUNTIME, ' ', '" ', '') . '\diff"'

This is the line that is now actually running. I guess this method works fine in Windows XP with current defaults?

> 18 endif
> 19 else
> 20 let cmd = $VIMRUNTIME . '\diff'
> 21 endif
> 22 silent execute '!' . cmd . ' ' . opt . arg1 . ' ' . arg2 . ' > ' . arg3 . eq
> 23 endfunction
>
> (Credit to fvelasqu...@gmail.com, http://code.google.com/p/vim/issues/detail?id=28#c6)

fvelasqu posted that to a thread on a completely unrelated problem. THAT problem report deals with adding text in a new Vim with the default empty buffer shown. His post has to do with creating diffs. And as mentioned the "fix" is a garbage workaround that effectively forces the first if condition to never execute.

Ben Fritz

unread,
Oct 11, 2013, 7:29:12 AM10/11/13
to vim...@googlegroups.com
On Friday, October 11, 2013 6:27:20 AM UTC-5, Ben Fritz wrote:
> On Friday, October 11, 2013 2:40:36 AM UTC-5, star...@gmail.com wrote:
> > 14 let cmd = '""' . $VIMRUNTIME . '\diff"'
> > 15 let eq = '"'
>
> These two lines are WRONG with current default settings. They are a workaround for the issue fixed with external windows commands by the new shellxquote default value. Bram, these lines need to get removed.
>

If it wasn't clear, I mean the last two lines quoted above, i.e. the ones surrounding the command in an extra pair of quote characters. NOT the two lines I quoted directly below.

star...@gmail.com

unread,
Oct 11, 2013, 12:12:43 PM10/11/13
to vim...@googlegroups.com
Thanks Ben, you were right. I need to triple check my work sometimes when it's late. I think I was convinced that the ELSE block was wrong (and therefore causing the problem), but it actually seems to be working somehow. Sorry for posting twice.

By the way, I am running vim with default settings and files (including _vimrc). I don't have "diff.exe" anywhere else except the one that comes with vim.

FYI
&sh = C:\WINDOWS\system32\cmd.exe (so "if &sh =~ '\<cmd'" should match, which it does)

cmd (IF) = ""C:\Program Files\Vim\vim74\diff" (apparently causing the problem)

cmd (ELSE) = C:\Program" Files\Vim\vim74\diff" (this -looks- like it should fail with that quote in the middle after Program, but works somehow).

Ben Fritz

unread,
Oct 11, 2013, 1:21:19 PM10/11/13
to vim...@googlegroups.com

That's because cmd.exe quoting is "special".

With the new default settings in Vim 7.4, the correct command should be simply and intuitively:

Reply all
Reply to author
Forward
0 new messages