Improving Vim auto complete for CSS class names

Just a quick tip about Vim autocompletion.

I’ve been using the excellent SuperTab Vim Plugin for a couple years, it works reasonably well (autocompletes based on words from all buffers, file names, tags, context, etc…) but it doesn’t work really well for text that is split by dashes - CSS contains lots of these… - so I started to get frustrated with it.

You can change the auto complete behavior with set iskeyword which also changes the behavior of standard motion commands like w, e, b (it changes the word delimiters) – which a find a PITA since I got used to these motions. My quick and dirty solution to the problem was to keep iskeyword with the minimal value as possible and only change it during InsertEnter. That way I can still use cw, ve, db to edit each fragment, autocomplete will work properly for words like foo-bar__baz, and you can still use W, B and E if you want to quickly jump around. For me that’s the best of both worlds!

function! KeywordsAll()
    setl iskeyword=@,48-57,192-255,\@,\$,%,-,_

function! KeywordsBasic()
    setl iskeyword=@,48-57,192-255

" improve the 'search word under cursor' behavior
nnoremap * :silent call KeywordsAll() * :silent call KeywordsBasic()
nnoremap # :silent call KeywordsAll() # :silent call KeywordsBasic()

augroup is_keyword
  " clear commands before resetting
  " make sure `complete` works as expected for CSS class names whithout
  " messing with motions (eg. '.foo-bar__baz') and we make sure all
  " delimiters (_,-,$,%,.) are treated as word separators outside insert mode
  autocmd InsertEnter,BufLeave * :call KeywordsAll()
  autocmd InsertLeave,BufEnter * :call KeywordsBasic()
  " yes, we need to duplicate it on VimEnter for some weird reason
  autocmd VimEnter * nnoremap * :silent call KeywordsAll() * :silent call KeywordsBasic()
  autocmd VimEnter * nnoremap # :silent call KeywordsAll() # :silent call KeywordsBasic()
augroup END

And here are my other autocomplete settings:

set infercase
set completeopt=longest,menuone
set omnifunc=syntaxcomplete#Complete
set completefunc=syntaxcomplete#Complete
set complete=.,w,b,u,U,t,i,d

augroup omni_complete
  " clear commands before resetting
  " Enable omnicomplete for supported filetypes
  autocmd FileType css,scss setlocal omnifunc=csscomplete#CompleteCSS
  autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
  autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
  autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
  autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags
augroup END

I’m not using any plugin to generate JavaScript or CSS tags so my code completion is mostly based on all words contained on all the open buffers. Because of the way I structure my code nowadays, I hardly need more than that.

PS: I don’t recommend Vim to a new developer for the same reasons as described in this post, even tho I can’t see myself using another editor nowadays… – here is my complete .vimrc + some links in case you are interested.

Edit (2013/04/25): changed autocmd to be triggered on BufEnter and BufLeave to improve complete across all open buffers.
Edit (2013/05/01): improved * and # behavior.

Tags: , ,


[…] Artigo traduzido pela Redação iMasters, com autorização do autor. Publicado originalmente em http://blog.millermedeiros.com/vim-css-complete/ […]

Leave a Comment

Please post only comments that will add value to the content of this page. Please read the about page to understand the objective of this blog and the way I think about it. Thanks.

Comments are parsed as Markdown and you can use basic HTML tags (a, blockquote, cite, code, del, em, strong) but some code may be striped if not escaped (specially PHP and HTML tags that aren't on the list). Line and paragraph breaks automatic. Code blocks should be indented with 4 spaces.