Using bash completion with ctags and Vim
Talk0this wiki
created 2008 · complexity basic · author Seanhodges · version 7.0
Add the following to your ~/.bash_completion file (create it if it does not exist):
_vim_ctags() {
local cur prev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case "${prev}" in
-t)
# Avoid the complaint message when no tags file exists
if [ ! -r ./tags ]
then
return
fi
# Escape slashes to avoid confusing awk
cur=${cur////\\/}
COMPREPLY=( $(compgen -W "`awk -v ORS=" " "/^${cur}/ { print \\$1 }" tags`" ) )
;;
*)
# Perform usual completion mode
;;
esac
}
# Files matching this pattern are excluded
excludelist='*.@(o|O|so|SO|so.!(conf)|SO.!(CONF)|a|A|rpm|RPM|deb|DEB|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MP?(E)G|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)'
complete -F _vim_ctags -f -X "${excludelist}" vi vim gvim rvim view rview rgvim rgview gview
Once you restart your bash session (or create a new one) you can type:
~$ vim -t MyC<tab key>
and it will auto-complete the tag the same way it does for files and directories:
MyClass MyClassFactory ~$ vim -t MyC
I find this really useful when I'm jumping into a quick bug fix.
Comments
I've added a similar tip for ZSH.
I was very excited to see this, but I was very annoyed that it expected a tags file in the current directory. I keep a tags file at the root of each project, and vim -t is smart enough to find the correct tags file, so I wanted bash completion to be just as smart.
So, I modified the file a bit. It will now look for a tags file in the current directory, and then keep looking in parent directories until it finds one.
(note: changed `pwd` to $PWD)
_vim_ctags() {
local cur prev
COMPREPLY=()
cur="${COMP_WORDS[COMP_CWORD]}"
prev="${COMP_WORDS[COMP_CWORD-1]}"
case "${prev}" in
-t)
while [ "${PWD}" != "/" ]; do
if [ -r ./tags ]; then
# Escape slashes to avoid confusing awk
cur=${cur////\\/}
COMPREPLY=( $(compgen -W "`awk -v ORS=" " "/^${cur}/ { print \\$1 }" tags`" ) )
return
fi
cd ..
done
return
;;
*)
# Perform usual completion mode
;;
esac
}
# Files matching this pattern are excluded
excludelist='*.@(o|O|so|SO|so.!(conf)|SO.!(CONF)|a|A|rpm|RPM|deb|DEB|gif|GIF|jp?(e)g|JP?(E)G|mp3|MP3|mp?(e)g|MP?(E)G|avi|AVI|asf|ASF|ogg|OGG|class|CLASS)'
complete -F _vim_ctags -f -X "${excludelist}" vi vim gvim rvim view rview rgvim rgview gview
Here is how I modified the completion function with tags-file search for my own .bashrc. I basically rewrote most of it, partly just for stylistic preference, but also to make some improvements:
- the upward directory search doesn't change the current directory, which is typically not a good idea in a shell function
- it uses grep instead of awk. grep is most likely faster, and the invocation is simpler
_vim_ctags() {
local cur prev
cur=${COMP_WORDS[COMP_CWORD]} prev=${COMP_WORDS[COMP_CWORD-1]}
$prev = -t || return
local tagsdir=$PWD while "$tagsdir" && ! -f "$tagsdir/tags" ; do tagsdir=${tagsdir%/*} done -f "$tagsdir/tags" || return
COMPREPLY=( $(grep -o "^$cur[^ ]*" "$tagsdir/tags" ) ) }
I haven't done extensive testing on it, but it works for me so far.
Note that there is an invisible tab character inside the grep pattern.