I have used vim for C++ development for quite a while now where, for auto completion, i would either use YCM or, lately, the combination of LanguageClient-neovim and clangd. Lately, however, having been influenced by a few articles from vimways.org, i would like to explore a more ascetic auto-completion setup. Among several auto-completion flavours that vim offers, one can find "omni-completion", a context specific auto completion style with support for multiple languages. :h compl-omni-filetypes lists C as supported language and this is already a good start.

When looking further for omni-complete for C++, I find projects like OmniCppComplete but the last available version is quite dated: 2007. Given we get a new standard every 3 years since 2011, it feels that any C++ related tool should get a facelift every now and then.

I realize that i can always get back to the comfort of modern LSP in combination with a LSP client plugin, but what be the hard-core vim way to continue? The fewer plugins the better, right? Do vim ninjas among you say C style omni-complete is good for 80% of the cases? Or do you toss auto complete all together, claiming it hinders your learning progress of the code base?

  • 1
    LSP is great and a vast improvement over anything that came before it IMO (ctags, jedi, etc.) Don't let some pedantic random internet Vim purist dictate you that "this is the one and true only blessed Vim Way™" and distract you from getting stuff done. If LSP makes you productive and happy: use it. Jun 5, 2020 at 16:44
  • 1
    @MartinTournoij true, i agree that LSP is probably superior to most decade old solution (or older). What i am trying to find out is how much of the core Vim am I really overlooking.. Name it pure academic interest. For instance, i was surprise how far setting path to relevant folders and combining it with find and wildmenu could get you in terms of navigating through files in the project. I still would prefer my fzf integration, but what if i am using someone elses vim setup...
    – ambushed
    Jun 5, 2020 at 17:43
  • 1
    Completion is much harder because it requires parsing the code to know 1) what symbols there are and 2) which one make sense in the current context. ctags mostly solves the first problem (although results vary per-language) but not the second. You can solve that in VimScript, but it's often inperfect. Using an external tool as omnicomplete solves both, but that's essentially what LSP is. For example for Go there was gocode which could be used like this, but for all intents and purposes it was basically just an ad-hoc LSP. I never managed to get good completion before LSP in Vim myself. Jun 6, 2020 at 5:05

1 Answer 1


I believe the reason OmniCppComplete hasn't been updated in so many years is because it relies on ctags files. Therefore, as long as your own ctags file is up-to-date, it should provide good and accurate suggestions. For what it is worth, I just installed that plugin, created the required ctags file and it seems to be working correctly.

Having said that, the built-in support for C and C++ in vim is already really good even without plugins. If your path is pointing to the directory in which your C, C++ libraries can be found (usually, within /usr/include/, /usr/local/include and /user/local/share), it will traverse recursively all the files based on your :h include command. However, this must be used carefully as it can be a slow process (see :h file-searching).

A faster alternative, as you have found, is the use of tags. For example, ctags -R -n --sort=yes --c++-kinds=+p --fields=+iaS --extras=+q -f tags /usr/include/c++/ will create a ctags file from your c++ libraries. It needs to be stored in one of the locations described in :h tags and it will provide suggestions (i_CTRL-X_CTRL-]) and jump to definitions (CTRL-]) without any additional configuration. You can even customize ctag's output to use it as a tokenizer (via --regex-LANG=) if you need a more granular control over the resulting tags.

On your last questions comparing LSP vs built-in features, the best option is largely a matter of personal requirements. LSP is a much smarter and complex tool. As there is no free lunch, complex tools tend to be finicky, more difficult to configure properly, more resource-hungry and more likely to break. In terms of capabilities, LSP doesn't cover edge cases that ctags is able to handle easily, but on the other hand, using LSP only for definitions and references seems like overkill as it can do a lot more. In my opinion, most developers will never have an actual need to use LSP for their work because either their codebases are not sufficiently complex or because refactoring is not common enough to justify its use. That's not to say you should stop using LSP, however, if you are regularly having to fix your setup when LSP misbehaves (which is not an uncommon occurrence with LSP) without taking full advantage of what LSP has to offer, a lightweight environment with ctags and the commands described in :h include-search is a very good alternative.

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.