vimdiff E97 in Powershell - windows

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

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

Related

Add Path to OSX to El Capitan

I am trying to learn UNIX.
I am using a book called “Wicked Cool Shell Scripts”.
I am told that .bash_profile contains my login for bash and that I can add paths to it so that commands I enter in Terminal will find the scripts I am writing.
The contents of my current bash_profile is:
export PATH=~/bin:$PATH
When I type echo $PATH I get:
/usr/local/opt/php#7.0/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.3/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/opt/X11/bin
I would like to add a path so that - as the book suggests - I can write scripts and refer to them directly from the command line, instead of having to constantly navigate to that directory to run them.
I have a file with a shebang. It runs fine when I type its name and am in the same directory. I have moved that file to the folder scripts, which is located under crg/Users/ (ie: Users/crg/scripts)
According to this book, I can now alter my $PATH to include that directory, so that when I type that filename, the program will run.
I cannot do this successfully.
I don’t know why.
After every edit, I quit terminal and reopen it, to ensure it is using the newly edited bash_profile.
As per the books instructions on page 5, I have tried entering this in my bash_profile:
export PATH=”/Users/crg/scripts/:$PATH”
I save my bash_profile, quit Terminal, reopen it and type echo $Path
This is the result:
”/Users/crg/scripts/:??
This is not right. In fact, it's wildly wrong. And it does not allow me to run scripts from the folder indicated. It also seems to completely overwrite whatever was in the bash_profile before this, so I cannot - after doing this 'simple edit' suggested by a 'professional' - run a php -version command from the Terminal.
I am at a complete loss as to why this is happening.
Why is there a quotation mark at the beginning of this line (but not at the end)?
What's with the colon and the 2 question marks at the end of this line?
How do I add/append a path to my bash_profile?
More questions:
When I try and solve this on my own using “the Internet”, I discover many interesting versions of this ‘simple’ process: Here’s one suggested by a ‘professional’:
export PATH="${PATH}:/path/to/program/inside/package"
This is very different from what the book says...
Here’s another version of ‘how to do it’ by ‘a professional’:
export PATH=$PATH:/usr/local/sbin/modemZapp
Notice that this one doesn’t even have quotes. In both, the PATH variable comes before the actual path.
Why are there so many 'versions' of how to perform this simple task?
Can someone please tell me how to add a path to my .bash_profile?
UPDATE: I have followed the advice here, (add it to etc/paths) but this does not work either.
I get the exact same thing when I type echo $PATH in a new Terminal:
/usr/local/opt/php#7.0/bin:/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.5/bin:/Library/Frameworks/Python.framework/Versions/3.3/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/usr:/usr/local/share/npm/bin:/Users/fhb/scripts:/opt/X11/bin
I can't help but note a comment on that last page: "I have been through at least a dozen different methods for adding directories to $PATH. Why are there so many and why do so few of them work?"
To answer your first question if you look closely your quotes are ” instead of ". I'm guessing you edited either your bash_profile or this post in a rich text editor instead of a plain text one. I would recommend notepad for Windows or nano for *nix if you are writing code. To fix this issue, replace the ” with ".
To answer your second question, bash is quite forgiving and will allow you to set a string variable in multiple different ways, even without quotes. However you can run into issues when a string contains whitespace, for example: /Users/lilHenry/my scripts.
The "${PATH}" syntax is just another way to declare a string. It has the benefit that it allows you to interpolate variables into a string like so:
prefix="foo"
echo "${prefix}bar"
This will output foobar, whereas echo "$prefixbar" will not output anything as the variable prefixbar has not been set. I would suggest sticking with the export PATH="/Users/me/bin:$PATH" syntax.

How can I add a vertical space in 'Terminal' after each command?

I've just started using Terminal (the CLI for Mac OS X).
When I run a command, get some information back, run another command, get more info etc., it is hard (on the eyes) to find a certain point on the screen (e.g. the output for the command before last).
Is there a way of adding a vertical empty space to the end of each output/ after each command is run that has no output?
Each new command that you enter is preceded by a "prompt", and these can be customized (though the exact way to customize depends on the shell). Since you mention Mac OS X I'm assuming you are using the default bash shell, in which case the absolute simplest way to add a blank line is like this: PROMPT_COMMAND=echo. You can run that command to try it out, or add it to a startup file (like .profile in your home folder) to have it done automatically each time.
If you use Bash 4.4 and you want a blank line after your prompt, you could set the PS0 prompt to a newline:
PS0="\n"
Now, this will be inserted every time you run a command:
$ echo "Hello"
Hello
Wondering this too, I've looked at the menu options in Terminal & most of the control characters one can type in and nothing does this on a keystroke. You can however enter an echo command, it alone to leave a single blank line below it before the next prompt. echo \n will add an extra blank line to that, echo \n\n to do 2 extra, ie. 3 blank lines, etc. (you can also do echo;echo;echo getting the same effect)
You can create a shell alias like alias b='echo;echo' (i couldn't seem to get the \n notation to work in a alias), then entering b on a prompt will leave a double-blank line, not bad. Then you gotta figure out how to save aliases in your .profile script.
I tried making an alias for the command ' ' ie. space character, which I though you could type like \ (hmm, stack overflow not formatting this well, that's backslash followed by a space, then return to execute it), but the bash shell doesn't seem to allow an alias with that name. It probably wouldn't allow a function named that either (similar to alias), though I didn't check.
I often use the fish shell, and I found that it does allow a function with that name! Created with function ' '; echo \n; end and indeed it works; at the shell prompt, typing the command \ (again backslash space) leaves a double blank line.
Cool, but.. I tried saving this function using funcsave ' ' (how you save functions in fish, no messing with startup scripts!) and afterwards the function no longer works :^( This is probably a bug in the fish shell. It's in active development right now though, I think I'll report this as a bug since I would kind of like this to work myself.
One could also send Apple a feature request through their bug reporter for an Insert Blank Line menu/keyboard command in Terminal. If someone pays attention to your request it might be implemented in a year maybe.
I wanted to solve exactly the same, and for anyone interested in doing the same, I used what tripleee said in his comment here - I created a .bash_profile (see details here) with the line export PS1="\n\n$ ".
Hopefully that helps someone else too!

vim temporary files with native vim on windows

When running a native compilation of gVim under Win7 I have the following in my vimrc:
if has ("win32")
let $TMP="C:/tmp"
setlocal equalprg=tidy\ --output-xhtml\ y\ -utf8\ --wrap-attributes\ 1\ --vertical-space\ 1\ --indent\ auto\ --wrap\ 0\ --show-body-only\ auto\ --preserve-entities\ 1\ -q\ -f\ shellpipe=2>
endif
This should create a temp file. However, after running the command, I see:
shell returned 1
E485: Can't read file C:\tmp\VIoC935.tmp
The common recommendation for native windows E485 errors is to set the tmp variable, which I have, as you can see from my vimrc snippet. If I remove the let statement, I get a similar result:
shell returned 1
E485: Can't read file C:\Users\ksk\AppData\Local\Temp\VIfFA01.tmp
In both cases; both directories exist and gVim can write a file to those locations, i.e.,
:w C:\Users\ksk\AppData\Local\Temp\VIfFA01.tmp
in the current buffer will write this file without error.
Interestingly, while writing this, I found that if I create a new buffer, and delete the original buffer, the equalprg function runs without error (with and without the "let" statement in vimrc)
This doesn't apply to the original question, but I ran into the same symptoms because of the setting of my SHELL variable within gvim. I was launching gvim from a Cygwin window, and it picked up the SHELL setting from within cygwin: /bin/bash. I had to do a ":set SHELL=C:/cygwin/bin/bash" from within gvim, and then the temporary file problem went away. So check the setting of your SHELL variable within gVim (via ":set shell") when trying to troubleshoot this kind of problem.
Interestingly, while writing this, I found that if I create a new buffer, and delete the original buffer, the equalprg function runs without error (with and without the "let" statement in vimrc)
That's probably because you use setlocal in your vimrc
E485: Can't read file C:\tmp\VIoC935.tmp
I know the reason, but I don't know how to fix it without changing indentation options. The issue is caused by the '>' symbol of your indent command, it should work after removing the last part of it or even only the '>' symbol. It's so because '>' has a special meaning in shell commands. In *nix one can probably just escape it, but this doesn't work for me in Windows.
P.S. I know this is not a full answer, but maybe it will help you solve the issue.
Update. Small discussion in the comments discovered that the correct way of escaping is to enclose the last argument in double quotes (the variant 2) below). So the working command is:
setlocal equalprg=tidy\ --output-xhtml\ y\ -utf8\ --wrap-attributes\ 1\ --vertical-space\ 1\ --indent\ auto\ --wrap\ 0\ --show-body-only\ auto\ --preserve-entities\ 1\ -q\ -f\ "shellpipe=2>"

Save file In a different folder in vim

I'm working with several files in gvim in Windows 7. I need to test the files (Python scripts) in linux. So apart from their original location I want to also save the files in a folder called linux. I want to do this with new files that I will be creating/modifying. That's why I want to use a mapping with the % sign to get the name of the current file Into the new path.
The problem I'm having is that the % sign is escaped with a backslash, so this doesn't work :
:w C:\projects\linux\%:t
Being the original location:
C:\projects\foo\
Is there a simple way to just save the current file in a different folder? (I have read that the % sign is a filename character, so I could erase it from the string isfname and it should work but I think I am making it more complicated than what it really is.)
Sorry, late to the party, but you could also use the workaround
:exe 'w C:\projects\linux\' . expand('%:t')
My recollection is that you can escape the backslash by doubling it (but I'm not on Windows at present so I can't confirm it immediately). You don't need to escape them all, just the one which is causing trouble:
:w C:\projects\linux\\%:t
You might be able to do this sort of thing fairly automatically using the autocmd feature.
The following (untested) line in your platform's equivalent of ~/.vimrc will update a copy of a file when gvim makes modifications:
" clear commands
autocmd!
" when writing buffers, save a copy -- see :help filename-modifiers
autocmd BufWritePost c:/path/to/source/directory w %:t
The :t will take just the tail of the pathname; if you're working with multi-level directories, perhaps :p:. would be better. See the documentation for more details.
If you change the last backslash to a forward slash it will work:
:w C:\projects\linux/%:t

Problem with input filter using doxygen 1.6.3 on windows XP

I am trying to use doxygen to generate documentation for some matlab classes I have written. I am using the doxygen-matlab package, which includes a perl script to kludge matlab .m files into c++ style commented files, so that doxygen can read them.
In my doxyfile, I have set (according to the instructions)
FILTER_PATTERNS = *m=C:/doxygenMatlab/m2cpp.pl
However, when the code runs, rather than running the script on the input files, it appears to just open the script using whatever the default windows setting for .pl is.
IE, if I associate .pl with notepad, the script is opened by notepad once for each input file doxygen is trying to parse. If I associate .pl with perl.exe, the script runs and throws the no argument error
Argument must contain filename -1 at C:\doxygenMatlab\m2cpp.pl line 4.
The doxygen documentation says
Doxygen will invoke the filter program by executing (via popen()) the command <filter> <input-file>
So I am wondering if there is some problem with popen() and windows that I could fix.
Could you try the workarounds I posted on the Matlab File Exchange regarding the doxygen package ?
Set the following variables in the Doxyfile :
INPUT_FILTER=perl m2cpp.pl
FILE_PATTERNS=*.m
If it doesn't work you should try to install ActivePerl : with this version of perl, everything is working fine.
I tried to reproduce the error using the Windows command prompt ("cmd") and noticed the following:
If you call "perl m2cpp.pl" you get error -1 because you did not specify a m-file to be translated into a cpp-file.
If you call "perl m2cpp.pl mfile" and the path of mfile contains spaces, you get error 1.
After I moved the mfile into a location which does not contain spaces, I got the desired output.
Now back to Doxygen. I tried what you suggested, Fabrice, without any luck. I read the doxygen help and found out that the INPUT_FILTER variable is only read and used if FILTER_PATTERNS is empty.
Therefore, I now use INPUT_FILTER = "C:\Programme\MATLAB\R2009a\sys\perl\win32\bin\perl U:\doxygen_matlab\m2cpp.pl" and an empty FILTER_PATTERNS variable. With this configuration, you can even leave the PERL_PATH variable empty. Moreover, there seems to be no issues with file names that contain spaces.
Unfortunately, all files are parsed with the above configuration, not only m-files. However, setting FILTER_PATTERNS to something like *.m=C:\Programme\MATLAB\R2009a\sys\perl\win32\bin\perl U:\doxygen_matlab\m2cpp.pl does not work because doxygen automatically adds the name of the filtered mfile and interprets the command as perl "m2cpp.pl mfile". Of course, the file "m2cpp.pl mfile" does not exist, because these are two files.
Maybe you can find a solution to this problem. In the meantime, I suggest the workaround above and that you keep your C-files away from the folder that contains the m-files.
write a simple batch file, e.g. mfilter.bat, which takes one argument from command line:
C:\Programme\MATLAB\R2009a\sys\perl\win32\bin\perl U:\doxygen_matlab\m2cpp.pl %1
Change setting in Doxyfile:
FILTER_PATTERNS = *.m=mfile.bat
This did it for me (on a Windows platform)
I think I solved this problem : it came from a bad association between .pl and the program to execute (maybe due to a bad installation of the perl shipped whith Matlab ?).
To correct this, you should change the association for the .pl files : in a Windows command prompt ("cmd"), just type de 2 following lines :
assoc .pl=PerlScript
ftype PerlScript=C:\Program Files\MATLAB\R20xx\sys\perl\win32\bin\perl.exe %1 %*
(the old installation forgot the %* at the end, the arguments were not passed to the m2cpp.pl script).
And then everything should be fine with the FILTER_PATTERNS set the usual way, for example FILTER_PATTERN=*m=C:\DoxygenMatlbab\m2cpp.pl
Could you tell me if this fixed your problem ?
According to the Doxygen forums, there is a difference in behavior between using INPUT_FILTER and FILTER_PATTERNS.
I found that if I do some extra (escaped) quoting, I can get FILTER_PATTERNS to work. For example, instead of:
FILTER_PATTERNS = "*.m=sed -e 's|%%|//!|'"
Try:
FILTER_PATTERNS = "*.m=\"sed -e 's|%%|//!|'\""
(All of my experimentation was done with doxygen version 1.8.6)

Resources