How to determine whether a set command failed to run in _vimrc? - vim

I added some set commands to my _vimrc file, how can I check whether the set command is executed successfully or not? I care about its status because there may be some different handling based on the status of previous set command.

You could try to raise the value of the verbose option until you find a value that allows you to catch every error thrown by every option (and set verbosefile=somefile as well because your life will be miserable if you don't) but I suspect what you want can't really be done in a manageable manner and probably not worth the hassle.
Here are a couple of idioms that could help you, though:
try something and catch errors
try
set option=value
catch /^Vim\%((\a\+)\)\=:EXXX/
set option=othervalue
endtry
See :help :try and :help :catch.
Note that raising verbose to its maximum value didn't allow me to catch the E596 error supposed to be thrown for invalid font so my point remains valid: it will be hard to find a silver bullet solution.
Also, guifont can take a coma-separated string as value so you can give it n fonts and let Vim use the first one that works.
do something only if a feature is present
if has('mouse_sgr')
set ttymouse=sgr
endif
See :help has().
If you gave us a concrete example of what you have in mind we could probably help you further.

You can actually handle exception in Vim.
In your case, this is an example:
for font in ['fonta:h10', 'fontb:h10', 'fontc:h10']
if !get(s:, 'font_set')
try
execute 'set guifont='.font
let s:font_set = 1
catch
endtry
else
break
endif
endfor
For more details, refer help :try.

Related

Describe vim replacements

In almost every copy of vim that I have used, the program will give a description of changes after replacing text. (For example, something like "92 substitutions on 20 lines" would be displayed.)
I'm now working with a copy of vim that does not do that by default.
Is there a simple command (or addition I can make to my vimrc file) that will enable this behavior?
It's governed by option report.
You can see you current setting with
set report?
To report even the minimal change
set report=0
I think you experience the effects of the 'report' option. If the (substitution, or any other command's) changes cover more than those (default 2), you'll see the message, else nothing.
So, you can put the following into your ~/.vimrc to always see those messages:
set report=0
Although not exactly your question,
in vim's substitutions, you can use the "n" flag to count the number of
matches and lines (without real substitutions).
Example
:%s/a//gn
55311 matches on 17459 lines

Vim: report error on a single line

When an error is raised inside a Vimscript function, Vim reports an error in the following format:
Error detected while processing function <SNR>My_Function:
line X:
EXXX: Error Message Here
This is very distracting. Ideally, I would like this to be formatted in some way to fit on a single line, but if that's not possible, then I just want the last EXXX line with the actual error. Is it possible to change this?
I don't like that behavior neither, but it is how it is, and cannot be changed.
Your functions need to :catch any errors, and convert this into the desired one-line error message:
function! s:My_Function()
try
" commands here
catch /^Vim\%((\a\+)\)\=:/
echohl ErrorMsg
echomsg substitute(v:exception, '^\CVim\%((\a\+)\)\=:', '', '')
echohl None
endtry
endfunction
This is how most plugins handle it. The behavior isn't completely like that of built-in commands, though: The error is effectively "swallowed", and subsequent commands (e.g. in a sequence cmd1 | call <SID>My_Function() | cmd3) will be executed despite the error. For most uses this is okay, and most users probably are even unaware of this.
better alternative
To make the custom command behave like a built-in one, the error message needs to be returned to the custom command or mapping, and :echoerr'd there. In my ingo-library plugin, I have corresponding helper functions:
function! s:My_Function()
try
" commands here
return 1 " Success
catch /^Vim\%((\a\+)\)\=:/
call ingo#err#SetVimException()
return 0 " Failure, use stored error message.
endif
endfunction
if ! <SID>My_Function() | echoerr ingo#err#Get() | endif
There is another approach to the problem: error messages can be decoded.
In my lh-vim-lib, I've defined a function that decodes the last error message and displays the result in the qf-window.
Given lh-vim-lib is installed, you've to add something like
command! WTF call lh#exception#say_what()
to your .vimrc.
The feature by itself has been inspired from https://github.com/tweekmonster/exception.vim, the difference is that I've used stuff I've already implemented in my library plugin in order to:
support localized messages
support autoloaded functions, even when # isn't in &isk (which is possible depending on the settings associated to the current filetype/buffer)
have as few loops as possible
factorize code with my logging, and unit testing, and DbC frameworks.
Near the end of the screencast I've recorded to demonstrate my Dbc framework, I've used :WTF to display the last error in a human friendly manner.

Why can't vim process .vimrc when winheight option isn't set twice?

I'm using the following options to make the split I'm focussing on the biggest on the screen. When bouncing between splits, window sizes get updated accordingly:
set winwidth=84
set winheight=5
set winminheight=5
set winheight=999
That works fine, however, you see that there are two definitions of winheight, which is kind of odd. I removed the first winheight declaration to see if things would work the same. Unfortunately, vim throws the error that it can't process my .vimrc file.
So, to clarify things, I stole this configuration from somebody's .vimrc. There must be a reason, why this options has to be set twice but I couldn't find something useful in the help.
Do you know, why vim throws the error in that case?
If the error you’re getting is E591:
E591: 'winheight' cannot be smaller than 'winminheight': winminheight=5
the problem may be simply one of ordering. By default, winheight is 1. Without the first winheight setting, you’re attempting to set a winminheight larger than the current winheight, which obviously causes problems (and results in the error).
I think that the duplicate declaration is also simply a matter of ordering. Attempting to start Vim up with the winheight=999 moved up before the winminheight setting gives me the alternate error
E36: Not enough room
Thus, if you want both to set the winheight to its maximum (999) and to set the winminheight to something more reasonable than its default (1), this may be the only workable approach.

Can an error text in Vim be replaced by personalized text?

For example, say you have
E385: search hit BOTTOM without match for: set
Can this error text be replaced with let's say,
Reached end of file. Sorry ol'chap, nothing found.
For a complete solution, you have to modify the Vim sources, either by modifying the (default, English) error messages or by creating your own localization (and setting your language to it), and then compile your own Vim binary.
Without modifying Vim itself, you have to wrap the commands that can issue the error. You can then intercept and translate the error message in Vimscript, like this:
try
" The original, wrapped command.
normal! n
catch /^Vim\%((\a\+)\)\=:E385/
echoerr "Reached end of file. Sorry ol'chap, nothing found."
endtry
For searches, that would be at least the n / N commands, as well as /, ?, *, #, ... Unless you have a really good reason, not worth it if you ask me.

Indenting Fortran code in Vim

I have a fortran code which looks like this:
open(2,file=filenm(i),status='unknown')
do j=1,num_lines
do k=1,dime
read(2,*) z(k)
enddo
if( j .ge. 1000 ) then
do k=1,dime
sumz(k)=sumz(k)+z(k)
enddo
nsteps=nsteps+1.0
endif
enddo
close(2)
as you can see the indentation is not even, I would like to have something
like this:
open(2,file=filenm(i),status='unknown')
do j=1,num_lines
do k=1,dime
read(2,*) z(k)
enddo
if( j .ge. 1000 ) then
do k=1,dime
sumz(k)=sumz(k)+z(k)
enddo
nsteps=nsteps+1.0
endif
enddo
close(2)
I can go line by line fixing the indentation but the code is kind of big.
I appreciate any comment.
I've gone through a very similar process of trying to get Fortran indenting to work in vim. I still don't have it great, but I've made some progress. The script that arutaku posted (http://www.vim.org/scripts/script.php?script_id=2299) is where I started, but you need to make sure that filetype plugin indent on is in your vimrc.
I also needed a script for determining if I was using fixed-form or free-form syntax, since in my environment I use both. This is recommended in the documentation (http://vimdoc.sourceforge.net/htmldoc/syntax.html#ft-fortran-syntax). As it specifies, I put this script in ~/.vim/ftplugin/fortran.vim:
let s:extfname = expand("%:e")
if s:extfname ==? "f90"
let fortran_free_source=1
unlet! fortran_fixed_source
else
let fortran_fixed_source=1
unlet! fortran_free_source
endif
I also use a script so that I can press F7 to automatically complete certain constructs: http://www.vim.org/scripts/script.php?script_id=2487. I also put that in ~/.vim/ftplugin/.
I also have these in my vimrc to try to improve things further:
let fortran_do_enddo=1
let fortran_more_precise=1
let fortran_have_tabs=1
I believe those are supposed to interact with the first script to control its behavior, but I'm not convinced that they all work for me. I know the first is supposed to properly indent do/enddo blocks. The issue there is that since old-style Fortran allows a do without a matching enddo, the script can't indent them properly unless you can guarantee that you won't use unmatched 'do' statements. The let fortran_do_enddo=1 is supposed to be that guarantee, but it doesn't seem to work for me. The last one is supposed to allow usage of the tab character, which old Fortran considered bad, so it prevents them from being marked as errors. That one appears to work for me. And to be honest, I don't remember what the middle one is supposed to do nor if it works for me.
Edit:
I discovered that there was an older version of the the first script in my vim installation directory (/usr/share/vim/vim70/indent/ in my case) to which I do not have access rights. You might have those rights, and if it's causing you problems, overwrite or delete it. If, like me, you can't edit it, you can get the version in your $HOME to overwrite the functions from the first. I did this by doing two things. First I had to remove the checks to see if the functions already exist (the statements like if exists("*FortranGetFixedIndent")) and then I had to change all the function declarations to force overwriting by using the ! character, i.e. function! SebuFortranGetFreeIndent(). As far as I can tell, everything now works roughly as I would expect!
Does gg=G work?
gg: go to top
=: indent...
G: ... until the end
Try: https://sourceforge.net/projects/findent/files/
From the README:
findent: indents/beautifies/converts Fortran sources
findent supports Fortran-2008
findent can convert from fixed form to free form
binaries for Unix and Windows (findent and findent.exe respectively)
wrapper for processing one or more files in one call available for Unix and Windows (wfindent and wfindent.bat respectively)
(g)vim users: findent can act as a plug-in to format your edit file with the '=' command
gui frontent available in a separate package: jfindent
You can use auto-indentation writing <x>== (in command mode) where x is the number of lines to be indented.
If vim does not have fortran indentation you can load the following plugin and try the == combination: http://www.vim.org/scripts/script.php?script_id=2299

Resources