How do I tidy up my vimrc file? - vim

My Vim configuration file is getting bigger (15KB+). And I try not to make my vim launch slower by sourcing more (larger) files at startup. For the same purpose I use only essential plugins and I try to keep the number of plugin as less as possible.
So, somewhere in my .vimrc file, I have these lines:
autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=4 softtabstop=4
autocmd FileType python setlocal textwidth=78
autocmd FileType python match ErrorMsg '\%>80v.\+'
autocmd FileType python inoremap <F5> <esc>:upd\|!python %<cr>
autocmd FileType python nnoremap <F5> :upd\|!python %<cr>
autocmd FileType python nnoremap <leader>8 :w\|call Flake8()<cr>
autocmd FileType python setlocal formatoptions-=t
autocmd BufWritePost *.py call Flake8()
Now I see in first 7 lines, all lines have autocmd FileType python in common. So my thinking is, if we manage to replace all those word with something less then Vim will fire up faster. But I don't know how to do that.
Can we group them? How? Anything else?

Just put
setlocal expandtab shiftwidth=4 tabstop=4 softtabstop=4 textwidth=78 formatoptions-=t
match ErrorMsg '\%>80v.\+'
inoremap <F5> <esc>:upd\|!python %<cr>
nnoremap <F5> :upd\|!python %<cr>
nnoremap <leader>8 :w\|call Flake8()<cr>
in ~/.vim/after/ftplugin/python.vim.
Vim will read this file only when you open a Python file.
I've been meaning to do this for some time, actually. And for the same reasons.

Filetype-specific stuff should be moved to ~/.vim/after/ftplugin/{filetype}.vim, as romainl has already pointed out.
I moved all my custom mappings and commands into ~/.vim/plugin/my{mappings,commands}.vim, and mostly only put real settings (the :set commands) and plugin customizations into .vimrc. Any mappings / commands that aren't simple one-liners and delegate to functions then use the autoload mechanism. This keeps the amount of stuff read at startup small.
TL,DR: Autoload is great; all plugins should use it.

I am using a scheme where a group of options is set in a function that is called by an auto command.
function! s:C_options()
setlocal cinoptions={0,:1s,g1s,t0,(0,=.5s
setlocal noautoindent
setlocal nosmartindent
setlocal cindent
call s:PROG_options()
endfunction
autocmd BufRead,BufNewFile *.c call s:C_options()
It is quite similar to using a filetype but you can use nested call, like having general programming options in s:PROG_options(), so you should be able to reduce further the size of your .vimrc.
The after\filetypesolution might be more efficient regarding initial load time, but I would rather have most of my customization in a single .vimrc than scattered in the .vimdirectory.

At least you can merge the first two lines with the 7th
autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=4 softtabstop=4 textwidth=78 formatoptions-=t
autocmd FileType python match ErrorMsg '\%>80v.\+'
autocmd FileType python inoremap <F5> <esc>:upd\|!python %<cr>
autocmd FileType python nnoremap <F5> :upd\|!python %<cr>
autocmd FileType python nnoremap <leader>8 :w\|call Flake8()<cr>
autocmd BufWritePost *.py call Flake8()
But I can't imagine how you can get rid of the others. On the other hand I don't think that these autocmd commands are taking so long to execute.

Related

Vim autocmd for FileType not working indirectly

I have a custom ~/.vimrc I made with this augroup:
augroup filetype_vim
autocmd!
autocmd! BufWritePost .vimrc* source %
autocmd FileType vim |
setlocal foldlevel=0 foldmethod=marker foldmarker={{{,}}}
augroup END
When I open vim directly to edit the ~/.vimrc like this: vim ~/.vimrc, the folding works as expected, I can fold {{{ marker:
:set foldmethod?
> foldmethod=marker
When I open vim without specifying a file: vim, and then trying to edit: :e ~/.vimrc, the foldmethod is different!
:set foldmethod?
> foldmethod=syntax
Which obviously comes from a different part of my vimrc.
Why doesn't it recognizes the file type when I open the file indirectly?
You've failed with VimScript syntax. Must be
autocmd FileType vim
\ setlocal foldlevel=0 foldmethod=marker foldmarker={{{,}}}
What you did instead is
autocmd FileType vim <nothing> | <nothing>
setlocal foo bar
Therefore setlocal applies to the current buffer only (i.e. command-line argument), not to anything else.

unset a filetype option when switching to any other filetype?

I have this line in my .vimrc:
au filetype python set colorcolumn=80
I would prefer if the colorcolumn disappeared when I switched to a non-python buffer. Is there a way to accomplish this?
Use setlocal to set that to just the buffer you want.
au filetype python setlocal colorcolumn=80
You can also abbreviate it to setl
au filetype python setl colorcolumn=80

Is it possible to include multiple file types when using the `FileType` event?

For example, I'd like to map a key when in a tex-like file, which includes many different flavor of tex files. Do I have to use multiple commands like this?
au FileType tex nm <C-H> <Plug>IMAP_JumpForward
au FileType latex nm <C-H> <Plug>IMAP_JumpForward
au FileType context nm <C-H> <Plug>IMAP_JumpForward
au FileType plaintex nm <C-H> <Plug>IMAP_JumpForward
...
Absolutely:
au FileType tex,latex,context,plaintex nm <C-H> <Plug>IMAP_JumpForward
Some thoughts:
Should be using a buffer local mapping instead of a global mapping
Using short names has only cons and zero pros. Don't.
This autocmd should be in a group
Autocmd's should be cleared (inside a group) so that re-sourcing is not a problem
Maybe use a after ftplugin script. e.g. ~/.vim/after/ftplugin/tex.vim instead of an :autocmd as they are easier to manage
look into romainl's idiomatic vimrc for more vimrc do's/don't's
Cleaned up version:
augroup tex_mappings
autocmd!
autocmd FileType tex,latex,context,plaintex nmap <buffer> <c-h> <Plug>IMAP_JumpForward
augroup END
Alternatively add the following to ~/.vim/after/ftplugin/txt.vim:
nmap <buffer> <c-h> <Plug>IMAP_JumpForward
Note: with the ftplugin approach you will need to add this line for each FileType (or use :source)
For more help see:
:h :au
:h :aug
:h :map-local
:h after-directory

How to prevent global defaults from overriding 'filetype=vim' specific settings in .vimrc when automatically sourcing .vimrc?

Context
I have my .vimrc automatically being sourced with:
autocmd! BufWritePost ~/.vimrc source ~/.vimrc
I also set defaults for spacing:
set tabstop=2 softtabstop=2 shiftwidth=2 expandtab
Later on, I use the FileType event to override the spacing default above with filetype-specific spacing:
" Syntax of these languages is fussy over tabs & spaces¬
autocmd FileType make setlocal ts=8 sts=8 sw=8 noexpandtab¬
autocmd FileType yaml setlocal ts=2 sts=2 sw=2 expandtab¬
" Customisations based on house-style (arbitrary)
autocmd FileType sh setlocal ts=4 sts=4 sw=4 expandtab
autocmd FileType vim setlocal ts=4 sts=4 sw=4 expandtab
Problem
The problem I am having is that sourcing my .vimrc will set the default values, but will not trigger the FileType event. This means that when I do a :write to my .vimrc while editting a file with filetype-specific spacing, the filetype-specific spacings get overridden by the defaults!
UPDATE: As pointed out by Ingo, the issue only arises in .vimrc and does not occur in any other files.
Example
As an example, when I am working on my .vimrc, initially the file-specific spacing (ts=4 sts=4 sw=4 expandtab) is enabled, but after I make some arbitrary change in my .vimrc, the default spacing (tabstop=2 softtabstop=2 shiftwidth=2 expandtab) is loaded but my file-specific spacing is NOT loaded (since the FileType event was not triggered by a write to my .vimrc) leaving me with the default spacing!
My question(s)
How can I override the default spacing with filetype specific spacings and preserve these even when auto-sourcing .vimrc?
If possible, I would like to accomplish this without getting rid of the autocmd's. Is that possible?
My hunch is that I should somehow manually trigger the FileType event when sourcing .vimrc Can this be done and is this the recommended approach?
Though you've very clearly described the problem, I doubt that this is happening.
As you're correctly using :setlocal for the filetype-specific settings, and :set in your ~/.vimrc, the sourcing of the latter will only affect the global defaults (and the current buffer, which is your .vimrc during the BufWritePost event). To affect other buffers, there would need to be a :bufdo command in your .vimrc.
You can check this with
:verbose set ts? sts? sw? et?
To avoid that your .vimrc settings are overridden with the global settings, you can append this:
if expand('%:t') ==# '.vimrc'
setlocal filetype=vim
endif
I ended up solving this issue by grouping the sourcing autocmd with another autocmd with the same event
" Reload changes to .vimrc automatically
autocmd BufWritePost ~/.vimrc source ~/.vimrc | setlocal filetype=vim
I had tried this earlier, but I was also using the AirlineRefresh command for vim-airline as such:
autocmd BufWritePost ~/.vimrc source ~/.vimrc | AirlineRefresh | setlocal filetype=vim
which was giving me this error:
E488: Trailing characters: AirlineRefresh | setlocal filetype=vim
Switching the order of AirlineRefresh and set local filetype=vim fixed the error and results in the desired behavior:
autocmd BufWritePost ~/.vimrc source ~/.vimrc | setlocal filetype=vim | AirlineRefresh
:bufdo e will do it but I couldn't just add it to my .vimrc. It will also remove syntax highlighting which is not so good.
:h bufdo execute the command in each buffer in the buffer list
:h :e re-edit the current file

How can I get MacVim to properly indent my .vimrc

I'm going through the VimCasts.org archive of videos and number 5 covers using Vim's auto-indentation to format source code. I see it working properly in my Objective-C file but not my .vimrc.
My tab settings are as follows:
set tabstop=2
set shiftwidth=2
set softtabstop=2
set expandtab
My .vimrc file has the following if block:
if has("autocmd")
filetype on
autocmd BufNewFile,BufRead *.rss,*.atom setfiletype xml
autocmd BufWritePre *.py,*.js :call <SID>StripTrailingWhitespaces()
endif
I would think that if I placed the cursor on the first line above and pressed Vjjjj= I would get the second, third and fourth line indented by two spaces, but what I get instead is:
if has("autocmd")
filetype on
autocmd BufNewFile,BufRead *.rss,*.atom setfiletype xml
autocmd BufWritePre *.py,*.js :call <SID>StripTrailingWhitespaces()
endif
Are my expectations incorrect or is this correct for some reason given the Vimscript language?
You need to add filetype plugin indent on to your vimrc to get vim to do indentation properly. (The plugin part isn't really necessary but is nice to have)
I would recommend replacing the filetype on line with filetype plugin indent on

Resources