We can use dictionaries to help us complete keywords. To set a new dictionary you can use set dictionary+=path/to/dict. This way you will be able to complete from a dictionary by typing <C-x><C-k> in Insert mode; and then use <C-n> or <C-p> to browser the suggestions. Moreover, you can set complete+=k and now you can type <C-n> or <C-p> right away.

From :help 'dictionary'

Each file should contain a list of words. This can be one word per line, or several words per line, separated by non-keyword characters (white space is preferred).

But maybe I would like a term Monty Python in my dictionary, such that when I write Mon one of the suggestions would be Monty Python. The GNU Miscfiles web2a is an example of a dicionary in which each line is made up of two words that go together.

Is there a way to include dictionary terms which have spaces?

  • I looked at the source code yesterday, and I don't think this is possible, but I'm not 100% sure. Feb 21 '15 at 13:48
  • 1
    It would work with Mon..., but think about Py... or Monty Py.... How would Vim know how many words go backwards to find the beginning of the pattern to look for? I'm not sure, but this might be the reason why it's done this way.
    – xaizek
    Feb 21 '15 at 17:11
  • @xaizek, I see your point. But at least for completing several words (Monty Python) when you have just typed part of the first (e.g. Mon) there would be no problem. Feb 21 '15 at 20:28
  • I'm not sure if "at least for" is good enough for Bram. I read some discussions on features that are missing from Vim and they stopped after stating that implementation has limitations similar to this one.
    – xaizek
    Feb 22 '15 at 8:53

I looked at the source code last week, and I don't think this is possible. As xaizek pointed out in a comment, this would make completion ambiguous.

However, I've thought of a workaround :-) There's the CompleteDone autocmd, which is run when:

After Insert mode completion is done. Either when something was completed or abandoning completion.

What we can do is write a dictionary not with spaces, but with another character; and use the CompleteDone autocmd to replace this character afterwards.

In my example, I use the underscore (_). I originally tried to use a more "special" character (such as ·), but that doesn't seem to work.

An example dictionary file looks like:


And with this autocmd the underscores get replaced with spaces; it should be fairly obvious how it works, so I'll not explain that any further:

fun! CompleteSpace()
    " Save cursor position
    let l:save_cursor = getpos(".")

    " Get word we just completed ('borrowed' from: http://stackoverflow.com/a/23541748/660921)
    let l:word = matchstr(strpart(getline('.'), 0, col('.') - 1), '\k\+$')

    " Replace _ with space
    let l:new = substitute(l:word, "_", " ", "g")

    " Run :s
    exe "s/" . l:word . "/" . l:new . "/e"

    " Restore cursor
    call setpos(".", l:save_cursor)

if has("patch-7.3-598")
    au CompleteDone * call CompleteSpace()

This could perhaps be optimized a bit, but this seems to be 'good enough' for now ;-)


Unfortunately, this autocmd is not perfect, as documented in the todo.txt file:

The CompleteDone autocommand needs some info passed to it:
- The word that was selected (empty if abandoned complete)
- Type of completion: tag, omnifunc, user func.


Patch to add v:completed_item. (Shougo Matsu, 2013 Nov 29).

The problem is that it might cause side-effects when completing source code as well; for example my_variable_name() gets "fixed" to my variable name. The autocmd below is for all files, you can restrict the autocmd for certain files... There is actually a patch floating around which seems to fix this, but it's not applied yet for whatever reason. Perhaps it's simply forgotten, or maybe it needs some love to fix a minor issue; you could pursue it :-)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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