Vim: tab autocomplete in insert mode + and fuzzy search for opening files
Today I set up my Vim to do tab autocompletion in insert mode (meaning that while typing you can use tab to autocomplete), and to do fuzzy search file opening (meaning that you can type a few characters from a filename and it will fuzzy search all files in the directory to find a match). Both of these are some small workflow optimisations to help me get coding faster.
Both of these come from Gary Bernhardt’s .vimrc file and to get them working you just need to copy the code snippets from their GitHub into your own .vimrc file. Please copy them from the above link rather than from this page as I have edited them to remove the comments!
For remapping the tab key to do autocompletion:
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
" MULTIPURPOSE TAB KEY
" Indent if we're at the beginning of a line. Else, do completion.
""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
function! InsertTabWrapper()
let col = col('.') - 1
if !col || getline('.')[col - 1] !~ '\k'
return "\<tab>"
else
return "\<c-p>"
endif
endfunction
inoremap <expr> <tab> InsertTabWrapper()
inoremap <s-tab> <c-n>This looks very simple for something that’s doing autocompletion, but I think what it’s actually doing is hooking in to Vim’s inbuilt autocompletion and just mapping tab to the correct behaviour depending on context.
To set up fuzzy search file opening:
First you need to actually install the selecta program using brew install selecta . This is because Vim is actually just going to call this program in your shell.
Then you need to put the following code snippets into your .vimrc (I’ve broken them up so I can explain them a bit, but you can just put them in all together).
SelectaCommand function:
This is the function which hooks into the selecta program, it pipes the result of the choice_command argument into the selecta program with the selecta_args argument, and then calls the result with the vim_command argument.
function! SelectaCommand(choice_command, selecta_args, vim_command)
try
let selection = system(a:choice_command . " | selecta " . a:selecta_args)
let selection = substitute(selection, ' ', '\\ ', "g")
catch /Vim:Interrupt/
redraw!
return
endtry
redraw!
exec a:vim_command . " " . selection
endfunctionSelectaFile function:
This is a wrapper on the SelectaCommand function above which calls find on the path argument to get all the files in that path and then calls glob in vim to open the files. It also excludes certain files (in the example below .pyc files, you can add more exclusions by adding more -and -not -iname 'PATTERN'.
function! SelectaFile(path, glob)
call SelectaCommand("find " . a:path . "/* -type f -and -iname '" . a:glob . "' -and -not -iname '*.pyc'", "", ":e")
endfunctionRemapping:
This is the part where we map the SelectaFile function onto actual key commands, so here we’ve mapped our leader key followed by f to search the current directory, and as I’m working with Java at the moment I’ve mapped my leader key followed by gm to search the src/main directory.
nnoremap <leader>f :call SelectaFile(".", "*")<cr>
nnoremap <leader>gm :call SelectaFile("src/main", "*")<cr>
nnoremap <leader>gt :call SelectaFile("src/test", "*")<cr>Bonus function:
This is a little extra function which is mapped to Ctrl+g and has exactly the same behaviour in calling find with selecta, but this time it calls it using the word you’re cursor in vim is on — useful for quickly opening the file where a function/class is defined!
function! SelectaIdentifier()
normal
call SelectaCommand("find * -type f", "-s " . @z, ":e")
endfunctionnnoremap <c-g> :call SelectaIdentifier()<cr>
See Gary Bernhardt’s .vimrc (linked below) for commented versions of the code.
sources:
https://github.com/garybernhardt/selecta
https://github.com/garybernhardt/dotfiles/blob/master/.vimrc
