I have been using Vim as a research database, and I use tags in the form of @tag for each note, written in the second line after the title. I might have more than one tag.

How can I make dictionary completion (C-x C-k in insert mode) look in a 'tags' when triggered after an @ sign in insert mode?

  • 1
    Vim doesn't have autocomplete. Are you using a plugin or are you referring to one of the ins-completion commands?
    – jamessan
    Feb 26, 2015 at 20:42
  • When in insert mode I press CTRL-X CTRL-K I get a drop down list of all the possible words that could complete the fragment typed so far. Perhaps the function has a different name, but the function is there, and pulls the words from the current dictionary. I would like to pull the words from a list, if the first character is the @ sign. Any help would be appreciated.
    – Amaru
    Feb 27, 2015 at 6:59
  • If you never normally use CTRL-X CTRL-K, you could change the 'dictionary' option to point to a different file. Alternatively you could turn your tags into vim tags and use CTRL-X CTRL-T or write a user-defined completion function and use CTRL-X CTRL-U. Both of these would be harder to do, though.
    – Matt Boehm
    Feb 27, 2015 at 15:01

4 Answers 4


Does it have to be dictionary completion, triggered via i_CTRL-X_CTRL-K? If another trigger key is fine (e.g. i_CTRL-X_CTRL-@), you can do this:

  1. Save the 'dictionary' option value
  2. Change it to point to your tags file
  3. Install an :autocmd CompleteDone handler that resets the option value
  4. Trigger dictionary completion


If you don't actually need dictionary completion, just some values from a particular file, you can alternatively look at my EntryComplete plugin; it provides configuable sources.


Thank you jamessa, Matt and Ingo. I followed Ingo's suggestion and, after digging a bit around Internet, wrote a small function to toggle the dictionaries I use (English and Spanish) and the tags file (actually .tags). Now I can press F6 to switch from English to Spanish, and from Spanish to tags, and from tags to no dictionary. Now, on each setting, I can press to trigger the dictionary completion, and it works great.


In case someone is interested, here is the function:

"  myspell.vim
"  This fuction allows switching spellchecking in two languages, and
"  to have a local spell file and/or a local tags file for each 
"  project. The local spell files is called 'local.utf-8.add' and the
"  tags file is '.tags'.
"  Using tags:
"  The 'tags' file is a text file that lists one tag per line, organized
"  alphabetically. A tag is a keyword preceded by the '@' sign. For
"  instance @novel. This tag file is used to autocomplete tags in
"  reference files. Autocomplete is triggered by C-X.
"  Note: To create a '.local.utf-8.add' file, open it in Vim, save it,
"  and run: mkspell to generate the local spell file.
"  Note: To create a 'tags' file, go to the root folder of a given
"  project and issue ':maketags.sh'. This will create a 'tags' file.
"  Make sure that the '.local.vimrc' in the root file for the project
"  includes the line 'let g:localroot=<project's root>'
"  Inspired by:
"  http://vim.wikia.com/wiki/Toggle_spellcheck_with_function_keys
if exists("loaded_myspell")
let loaded_myspell = 1

let g:myLangList  = [ "nospell",     "en_us",      "es",      ""     ]
let g:myLangName  = [ "No spelling", "US English", "Spanish", "Tags" ]
let g:myLangShort = [ "", "EN", "SP", "T" ]

function! MySpellLang()
    " Check if 'g:myLang' exists for the buffer in question, and if it
    " doesn't check if spell is set and adjust 'g:myLang' accordingly.
    if !exists( "g:myLang")
        if &spell
            let g:myLang=index(g:myLangList, &spelllang)
            let g:myLang = 0
    " Spellfile
    " g:localroot can be configured in '.local.vimrc' at the root
    " level of any project. This configuration is read by the plugin
    " 'vim-localrc' (which also reads any other configuration settings).
    if !exists("g:localroot")
        let g:localroot=expand('%:p:h')
    let g:localspell=fnameescape(g:localroot).'/.local.utf-8.add'
    " Loop through languages
    let g:myLang += 1
    if  g:myLang >= len(g:myLangList) | let g:myLang = 0 | endif
    if  g:myLang == 0
        set nospell
        set spellfile=
        set dictionary=
    elseif g:myLang == 1
        set spell spelllang=en_us
        " 'set' needst to be use for '~' to be resolved here
        set spellfile=~/.vim/spell/en.utf-8.add
        set dictionary=
    elseif g:myLang == 2
        set spell spelllang=es
        set spellfile=~/.vim/spell/es.utf-8.add
        set dictionary=
    elseif g:myLang == 3
        set nospell spellfile=
        let b:localtag=fnameescape(g:localroot).'/.tags'
        if !filereadable(b:localtag) 
            " Save current directory, removing new-line and escaping spaces
            let b:savedir = fnameescape(substitute(system('pwd'),'\n','','g'))
            " Go to the local root 
            :execute "cd ".fnameescape(g:localroot)
            " Call the tag maker script
            :execute "silent !maketags.sh ".b:localtag
            " Change directory back
            :execute "cd ".b:savedir
        exec ":set dictionary+=".b:localtag
    if g:myLang>0 && g:myLang<3 && filereadable(g:localspell) 
        exec "set spellfile+=".g:localspell
    echo "language: " g:myLangName[g:myLang]

map <F6> :call MySpellLang()<CR>
imap <F6> <C-o>:call MySpellLang()<CR>
"================================================================ EOF

And this is the shell script that creates the .tags file:

#! /bin/bash
# maketags
# This program generates tags for all of the md files in and under the
# folder from which it is called as long as the tags are of the form 
# '@tag' and separated by spaces. If an arument is give, it is used
# as the name of the tag file.

if [ -z "$1" ]

touch temp.text

find "$PWD" -name '*.md' -type f -exec awk '{
        if (index($0,"@") > 0) {
            line = $0
            do { 
                tag  = ""
                iB   = index(line,"@")
                if ( iB > 0 ) {
                    line = substr(line,iB)
                    iE   = index(line," ")
                    if (iE == 0) iE = length(line) + 1
                    tag  = substr(line,1,iE-1)
                    line = substr(line,2)
                    printf("%s\n", tag) >> "temp.text"
            } while ( tag != "")
     }' "{}" \;

sort temp.text > tags.txt
rm temp.text
uniq tags.txt > "$TAGFILE"
rm tags.txt

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.