I use several different programming languages every day, and I'd like to have different tab widths (in spaces) for each. For example: I use the "standard" 2 spaces for Ruby, but all our existing Matlab code uses 4 spaces.
I have this from my personal ~/.vimrc:
augroup lang_perl
au!
set tabstop=4 " tabstop length N in spaces
set shiftwidth=4 " make >> and friends (<<, ^T, ^D) shift N, not the default 8
set expandtab " Use spaces instead of tabs
augroup END
augroup lang_ruby
au!
set tabstop=2 " tabstop length N in spaces
set shiftwidth=2 " make >> and friends (<<, ^T, ^D) shift N, not the default 8
set expandtab " Use spaces instead of tabs
augroup END
Those work, but the following doesn't:
augroup lang_matlab
au!
set tabstop=4 " tabstop length N in spaces
set shiftwidth=4 " make >> and friends (<<, ^T, ^D) shift N, not the default 8
set expandtab " Use spaces instead of tabs
augroup END
I really don't understand how augroup lang_ruby figures out that I'm editing a Ruby file. (My searches brought up ftdetect, but the solution wasn't obvious.) It doesn't seem like vim knows that I'm editing Matlab using augroup lang_matlab. What do I change to make this work?
If you want to have a large number of settings for {filetype}, you should put them into ~/.vim/ftplugin/{filetype}.vim or into file that matches ~/.vim/ftplugin/{filetype}/**/*.vim (examples: ~/.vim/ftplugin/ruby/foo.vim, ~/.vim/ftplugin/ruby/foo/bar.vim). In this case you don't need any autocommands at all. If you still want to use autocommands, use the following:
augroup lang_matlab
autocmd!
autocmd FileType matlab setlocal ts=4 sw=4 et
augroup END
. Note two things: FileType event (it is there and it is not BufRead,BufNewFile) and setlocal instead of plain set. First is intended to be used for filetype settings, second is how buffer-specific options must be set.
About why perl and ruby settings work and why matlab settings does not: your example code is just the same as
augroup lang_perl
autocmd!
augroup END
augroup lang_ruby
autocmd!
augroup END
set tabstop=4 " tabstop length N in spaces
set shiftwidth=4 " make >> and friends (<<, ^T, ^D) shift N, not the default 8
set expandtab " Use spaces instead of tabs
set tabstop=2 " tabstop length N in spaces
set shiftwidth=2 " make >> and friends (<<, ^T, ^D) shift N, not the default 8
set expandtab " Use spaces instead of tabs
So, you effectively set ts=2 sw=2 et. But the $VIMRUNTIME/ftplugin/perl.vim contains the following code:
setlocal tabstop=4
setlocal shiftwidth=4
so, ts=4 sw=4 for perl is set into ftplugin/perl.vim, not in your vimrc (if you have installed perl-support plugin). You can check it by replacing tabstop=4 with tabstop=8 in vimrc.
I cannot tell you how it's determined that lang_perl or lang_ruby shall be read. But looking at the autocommand documentation brings up an example for gzipped files (:he gzip-example):
augroup gzip
autocmd!
autocmd BufReadPre,FileReadPre *.gz set bin
autocmd BufReadPost,FileReadPost *.gz '[,']!gunzip
autocmd BufReadPost,FileReadPost *.gz set nobin
autocmd BufReadPost,FileReadPost *.gz execute ":doautocmd BufReadPost " . expand("%:r")
autocmd BufWritePost,FileWritePost *.gz !mv <afile> <afile>:r
autocmd BufWritePost,FileWritePost *.gz !gzip <afile>:r
autocmd FileAppendPre *.gz !gunzip <afile>
autocmd FileAppendPre *.gz !mv <afile>:r <afile>
autocmd FileAppendPost *.gz !mv <afile> <afile>:r
autocmd FileAppendPost *.gz !gzip <afile>:r
augroup END
See it? Every autocmd that gets specified carries an Event (BufReadPre, FileReadPre) and the extension for which it shall be executed (*.gz). This is backing up my hitherto opinion that you can use any name for your augroup but have to specify an extension that the augroup shall be responsible for in order to get it working correctly.
Another quote of :he autocmd-groups:
Normally, when executing autocommands automatically, Vim uses the autocommands
for all groups. The group only matters when executing autocommands with
":doautocmd" or ":doautoall", or when defining or deleting autocommands.
So, in order to make an augroup for matlab files, this one should do the trick:
augroup lang_matlab
autocmd!
autocmd BufRead *.m set ts=4 sw=4 expandtab
augroup END
And make sure that these settings don't get overwritten by any augroups that do something unconditional (i.e. modify the other augroup definitions too).
Use ftplugins, configuring vim will be much more easier to achieve.
See gVim and multiple programming languages
Related
I am using the nerdtree with some other plugins.
When I edit files with different indent settings (e.g. Makefile which requires tabs and *.js which should have spaces) then vim mixes up both and applies tabs to *.js.
The file type stuff is defined in these lines:
" use real tabs for these languages
autocmd FileType go,make
\ set noexpandtab
" use two spaces for these languages
autocmd FileType ruby,html,json,jade,javascript
\ set tabstop=2 |
\ set shiftwidth=2
" use four spaces for these languages
autocmd FileType css
\ set tabstop=4 |
\ set shiftwidth=4
Any idea how to make vim to reapply autocmd Filetype when opening another tab in nerdtree?
Bodo
You should use setlocal instead of set to prevent your settings from leaking to other buffers.
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
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
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.
I am experiencing some very painful lag when accessing directories/files over UNC paths using gVim 7.3 on Windows Vista.
It is slow reading/writing files, as well as tab completiong of directory/file names when opening new buffers. I don't notice this lag when using WordPad though.
Things I've tried:
Cream (apparently they had a fix for directory naming schemes)
Mapping the network drive to z: or something else
Various settings
set ffs=dos
set complete=.,w,b,u,t
set noshellslash
I've tried cygwin, but the same noticeable lag appears there as well. I already have all swap/backup files turned off. Any help greatly appreciated... I've dumped my vimrc for reference
if v:progname =~? "evim"
finish
endif
set nocompatible
:runtime! ftplugin/man.vim
set backspace=indent,eol,start
colorscheme torte " murphy
syn on
set ffs=unix,dos
" portable friendly
set nobackup
set nowritebackup
set noswapfile
set viminfo=
" gui options (http://steveno.wordpress.com/2007/10/08/vim-for-windows/)
set guioptions-=T " No toolbar
set gfn=Consolas:h9:cANSI
set history=50
set ruler
set showcmd
set incsearch
set number
set tabstop=4
set softtabstop=4
set shiftwidth=4
set wrap
set wildmode=longest,list,full " Complete longest string, list alternatives
" then completed next full match, cycling back
function! ToggleHLSearch()
if &hls
set nohls
else
set hls
endif
endfunction
function! InsertTabWrapper()
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-p>"
endif
endfunction
inoremap <tab> <c-r>=InsertTabWrapper()<CR>
nmap <silent> <C-n> <Esc>:call ToggleHLSearch()<CR>
nmap ,s :source ~/.vimrc<Return>
" change current directory to that of open buffer
nmap ,c :cd %:p:h<Return>
nmap <c-h> <c-w>h<c-w><bar>
nmap <c-l> <c-w>l<c-w><bar>
map <C-J> <C-W>j<C-W>_
map <C-K> <C-W>k<C-W>_
map Q gq
" Commenting blocks of text
" ,< <!-- --> html style comments
map ,< :s/^\(.*\)$/<!-- \1 -->/<CR><Esc>:nohlsearch<CR>
" ,/ // comments
map ,/ :s/^/\/\//<CR>
" ,# # comments
map ,# :s/^/#/<CR>
" uncommenting all of the above
"map ,- :s/^\(\/\/|<!-- |#\)\(.*\)\(-->\)*/\1/<CR>
if &t_Co > 2 || has("gui_running")
syntax on
set hlsearch
endif
if has("autocmd")
"&& !exists("autocommands_loaded")
let autocommands_loaded = 1
filetype plugin indent on
augroup vimrcEx
au!
" Remove ALL autocommands for the current group.
autocmd!
autocmd FileType text setlocal textwidth=78
autocmd BufReadPost *
\ if line("'\"") > 0 && line("'\"") <= line("$") |
\ exe "normal g`\"" |
\ endif
au BufRead *.html set filetype=html4
augroup END
" allow editing Word Docs sanely
autocmd BufReadPre *.doc set ro
autocmd BufReadPre *.doc set hlsearch!
autocmd BufReadPost *.doc %!antiword "%"
" uncomment the following to remember the view of the file edited between
" sessions
" au BufWinLeave * mkview
" au BufWinEnter * silent loadview
" run file with PHP CLI (CTRL-M)
autocmd FileType php noremap <C-M> :w!<CR>:!/usr/bin/php %<CR>
" parser check (CTRL-L)
autocmd FileType php noremap <C-L> :!/usr/bin/php -l %<CR>
" highlight current line only for current buffer
"autocmd BufLeave * setlocal nocursorline
"autocmd BufEnter * setlocal cursorline
au BufRead,BufNewFile *.tea set filetype=tea
"au! Syntax newlang source $VIM/newlanguage.vim
else
set autoindent
endif
the same thing was driving me insane, but there is a fix I just found.
I really do not know why yet, but the problem goes away when you disable plugin/matchparen.vim plugin (changing vim extension would do the trick).
I will definitely look into it as I use parentheses matching a lot.
See
:he swap-file
You can disable swapfiles with :se noswapfile (caution!) or use the `directory` setting to keep the swapfile on a local disk.
Starting vim with the -n option also disables swapfiles; you might want to combine that with -R for readonly mode
Another solution I found is that mounting a UNC path as a local drive letter and let Vim use the drive-letter based paths only.
e.g., \\some-server\path\to\workdir => Z:\path\to\workdir
This eliminates the lag completely unless you have connection problems.