DEV Community


Posted on

How to improve your vim/nvim coding experience with vim-easycomplete?


There are many excellent vim auto-completion plugins such as nvim-cmp, vim-lsp, YouCompleteMe and coc.nvim etc. I used coc.nvim for a long time. It’s experience is good. But there are a few things I don’t like. These plugins tend to have too much dependencies and do not have minimal configuration. For example, I don't want to install Node when programming c++ or golang. In my opinion vim is more lightweight than vscode so I don’t need the fully integrated features of it. Besides other completion plugins neither have good experiences enough nor compatible with vim and nvim at the same time. Therefor I created vim-easycomplete according to my personal habits.


Vim-easycomplete is a fast and minimalism style completion plugin for vim/nvim. The goal is to work everywhere out of the box with high-speed performance. It requires pure vim script. You don’t need to configure anything. Especially, You don’t have to install Node and a bunch of Node modules unless you’re a javascript/typescript programmer.

It is easy to install and use. It contains these features:

  • Buffer Keywords/Directory support
  • LSP(language-server-protocol) support
  • TabNine support. (Highly Recommend!)
  • Easy to install LSP Server with one command
  • Written in pure vim script for vim8 and neovim
  • Snippet support with ultisnips.
  • Fast performance

The reason I decided to use pure vim script instead of lua or python is that I want a wider range of compatibility. And I made a lot of async handling with vim script to avoid the block of vim.


Easycomplete requires Vim 8.2 and higher version with MacOS/Linux/FreeBSD. For neovim users, 0.4.4 and higher is required.

For vim-plug:

Plug 'jayli/vim-easycomplete'
Enter fullscreen mode Exit fullscreen mode

Run :PlugInstall.

For dein.vim

call dein#add('jayli/vim-easycomplete')
Enter fullscreen mode Exit fullscreen mode


The plugin is out of box and config noghting.


By default it use Tab to trigger the completion suggestions. Alse use Tab and Shift-Tab to select matched items. Use Ctrl-] for definition jumping, Ctrl-t for jumping back (Same as tags jumping). Or you can map :EasyCompleteGotoDefinition by yourself.

If you don't want use Tab to trigger completion suggestions. You can change this setting by:

let g:easycomplete_tab_trigger="<c-space>"
Enter fullscreen mode Exit fullscreen mode

Use :EasyCompleteNextDiagnostic and :EasyCompletePreviousDiagnostic for diagnostics jumping. The plugin has already map diagnostic jumping to <C-j> and <C-k>. You can change these mapping via:

nnoremap <silent> <C-n> :EasyCompleteNextDiagnostic<CR>
nnoremap <silent> <C-p> :EasyCompletePreviousDiagnostic<CR>
Enter fullscreen mode Exit fullscreen mode

You only have to set custom diagnostic HOTKEYs manually in case of there was a conflict. By default press <C-j> or <C-k> for diagnostics jumping like this:

  • Set let g:easycomplete_diagnostics_enable = 0 to disable lsp diagnostics.
  • Set let g:easycomplete_lsp_checking = 0 to disable lsp checking for installation.

Checking if LSP server is installed via :EasyCompleteCheck. If current LSP Server is not ready, Use :EasyCompleteInstallServer to install.

Typing ./ or ../ to trigger directory completion suggestion.

Dictionary suggestion support via set dictionary=${Your_Dictionary_File} if you need.

Vim-Easycomplete also support signature popup (Use let g:easycomplete_signature_enable = 0 to disable):

Typing :h easycomplete for help.

All commands:

Command Description
:EasyCompleteInstallServer Install LSP server for current fileytpe
:InstallLspServer Same as EasyCompleteInstallServer
:EasyCompleteDisable Disable EasyComplete
:EasyCompleteEnable Enable EasyComplete
:EasyCompleteGotoDefinition Goto definition position
:EasyCompleteCheck Checking LSP server
:EasyCompletePreviousDiagnostic Goto Previous diagnostic
:EasyCompleteNextDiagnostic Goto Next diagnostic
:EasyCompleteProfileStart Start record diagnostics message
:EasyCompleteProfileStop Stop record diagnostics message
:EasyCompleteLint Do diagnostic
:LintEasyComplete Do diagnostic
:DenoCache Do Deno Cache for downloading modules

Language Support

EasyComplete support keywords/dictionary/directory completion by default.

Semantic Completion for Other Languages

Most Language require LSP Server. Install missing LSP Server with :InstallLspServer for current filetype (recommended). LSP Server will be installed in ~/.config/vim-easycomplete/servers.

Enter fullscreen mode Exit fullscreen mode

Or you can install a lsp server with specified plugin name (not recommended). Take typescript/javascript for example:

:InstallLspServer ts
Enter fullscreen mode Exit fullscreen mode

All supported languages:

Plugin Name Languages Language Server Installer Env requirements
directory directory suggestion No Need Integrated None
buf keywords & dictionary No Need Integrated None
snips Snippets Support ultisnips Manually python3
ts JavaScript/TypeScript tsserver Yes node/npm
deno JavaScript/TypeScript deno Yes deno
tn TabNine TabNine Yes None
vim Vim vim-language-server Yes node/npm
cpp C/C++ ccls Yes ruby/brew
css CSS css-languageserver Yes node/npm
html HTML html-languageserver Yes node/npm
yml YAML yaml-language-server Yes node/npm
xml Xml lemminx Yes java/jdk
sh Bash bash-language-server Yes node/npm
json JSON json-languageserver Yes node/npm
php php intelephense Yes node/npm
dart dart analysis-server-dart-snapshot Yes None
py Python pyls Yes python3/pip3
java Java eclipse-jdt-ls Yes java11/jdk
go Go gopls Yes go
r R r-languageserver Yes R
rb Ruby solargraph Yes ruby/bundle
lua Lua emmylua-ls Yes java/jdk
nim Nim nimlsp Yes nim/nimble
rust Rust rust-analyzer Yes None
kt Kotlin kotlin-language-server Yes java/jdk
grvy Groovy groovy-language-server Yes java/jdk
cmake cmake cmake-language-server Yes python3/pip3
cs C# omnisharp-lsp Yes None

More info about semantic completion for each supported language:

Snippet Support

Vim-EasyComplete does not support snippets by default. If you want snippet integration, you will first have to install ultisnips. UltiSnips is compatible with Vim-EasyComplete out of the box. UltiSnips required python3 installed. Install with vim-plug:

Plug 'SirVer/ultisnips'
Enter fullscreen mode Exit fullscreen mode

Solution of "E319: No python3 provider found" Error in neovim 0.4.4 with ultisnips

TabNine Support

Install TabNine: :InstallLspServer tabnine. Then restart your vim/nvim.

Set let g:easycomplete_tabnine_enable = 0 to disable TabNine. You can config TabNine by g:easycomplete_tabnine_config witch contains two properties:

  • line_limit: The number of lines before and after the cursor to send to TabNine. If the option is smaller, the performance may be improved. (default: 1000)
  • max_num_result: Max results from TabNine. (default: 10)
let g:easycomplete_tabnine_config = {
    \ 'line_limit': 1000,
    \ 'max_num_result' : 10,
    \ }
Enter fullscreen mode Exit fullscreen mode

By default, an API key is not required to use TabNine in vim-easycomplete. If you have a Tabnine's Pro API key or purchased a subscription license. To configure, you'll need to use the TabNine' magic string. Type Tabnine::config in insert mode to open the configuration panel.

Add custom completion plugin

Take snip as an example (source file) without lsp server.

au User easycomplete_custom_plugin call easycomplete#RegisterSource({
    \ 'name':        'snips',
    \ 'whitelist':   ['*'],
    \ 'completor':   'easycomplete#sources#snips#completor',
    \ 'constructor': 'easycomplete#sources#snips#constructor',
    \  })
Enter fullscreen mode Exit fullscreen mode

Another example with lsp server support is easier. source file. By the way, you don't have to writing an omnifunc for Vim's omnicomplete.

You can redefine a completion plugin via easycomplete_custom_plugin event with the same name of default lsp plugin. For example. We replace ts plugin's lsp server tsserver by typescript-language-server. Copy this code in your .vimrc:

au User easycomplete_custom_plugin call easycomplete#RegisterSource({
    \ 'name': 'ts',
    \ 'whitelist': ['javascript','typescript','javascript.jsx',
    \               'typescript.tsx', 'javascriptreact', 'typescriptreact'],
    \ 'completor': function('g:Tss_Completor'),
    \ 'constructor': function('g:Tss_Constructor'),
    \ 'gotodefinition': function('g:Tss_GotoDefinition'),
    \ 'command': 'typescript-language-server'
    \  })

function! g:Tss_Constructor(opt, ctx)
  if executable('typescript-language-server')
    call easycomplete#lsp#register_server({
          \ 'name': 'typescript-language-server',
          \ 'cmd': {server_info->['typescript-language-server', '--stdio']},
          \ 'root_uri':{server_info-> "file://". fnamemodify(expand('%'), ':p:h')},
          \ 'initialization_options': {'diagnostics': 'true'},
          \ 'whitelist': ['javascript','typescript','javascript.jsx','typescript.tsx'],
          \ 'workspace_config': {},
          \ 'semantic_highlight': {},
          \ })
    call easycomplete#util#log(printf("'typescript-language-server'".
          \ "is not avilable, Please install: '%s'",
          \ 'npm -g install typescript-language-server'))

function! g:Tss_Completor(opt, ctx) abort
  return easycomplete#DoLspComplete(a:opt, a:ctx)

function! g:Tss_GotoDefinition(...)
  return easycomplete#DoLspDefinition(["js","ts","jsx","tsx"])
Enter fullscreen mode Exit fullscreen mode

So you should redefine at least three functions completor/constructor/gotodefinition.

Beautify the vim completion menu

There are four build-in popup menu themes in cterm: blue,light,rider and sharp. (let g:easycomplete_scheme="sharp"). Customise vim completion menu via these configurations:

  • Set let g:easycomplete_menuflag_buf = '[B]' for keywords menu flag.
  • Set let g:easycomplete_kindflag_buf = '' for keywords kind flag.
  • Set let g:easycomplete_menuflag_dict = '[D]' for dictionary menu flag.
  • Set let g:easycomplete_kindflag_dict = '' for dictionary kind flag.
  • Set let g:easycomplete_menuflag_snip = '[S]' for snippets menu flag.
  • Set let g:easycomplete_kindflag_snip = 's' for snippets kind flag.
  • Set let g:easycomplete_kindflag_tabnine = '' for TabNine kind flag.
  • Set let g:easycomplete_lsp_type_font = {...} for custom fonts.

Example configuration with

let g:easycomplete_menuflag_buf = ""
let g:easycomplete_kindflag_buf = "⚯"
let g:easycomplete_menuflag_snip = ""
let g:easycomplete_kindflag_snip = "ട"
let g:easycomplete_kindflag_dict = "≡"
let g:easycomplete_menuflag_dict = ""
let g:easycomplete_kindflag_tabnine = ""
let g:easycomplete_lsp_type_font = {
      \ 'text' : '⚯',         'method':'m',    'function': 'f',
      \ 'constructor' : '≡',  'field': 'f',    'default':'d',
      \ 'variable' : '𝘤',     'class':'c',     'interface': 'i',
      \ 'module' : 'm',       'property': 'p', 'unit':'u',
      \ 'value' : '𝘧',        'enum': 'e',     'keyword': 'k',
      \ 'snippet': '𝘧',       'color': 'c',    'file':'f',
      \ 'reference': 'r',     'folder': 'f',   'enummember': 'e',
      \ 'constant':'c',       'struct': 's',   'event':'e',
      \ 'typeparameter': 't', 'var': 'v',      'const': 'c',
      \ 'operator':'o',
      \ 't':'𝘵',   'f':'𝘧',   'c':'𝘤',   'm':'𝘮',   'u':'𝘶',   'e':'𝘦',
      \ 's':'𝘴',   'v':'𝘷',   'i':'𝘪',   'p':'𝘱',   'k':'𝘬',   'r':'𝘳',
      \ 'o':"𝘰",   'l':"𝘭",   'a':"𝘢",   'd':'𝘥',
      \ }
Enter fullscreen mode Exit fullscreen mode

You can define icon alias via giving fullnames and shortname.



[WIP] If you have bug reports or feature suggestions, please use the issue tracker. In the meantime feel free to read some of my thoughts at,,

More Examples:

Update Deno Cache via :DenoCache

Directory selecting:

Handle backsapce typing

TabNine supporting:

Top comments (1)

tabnine profile image

Thank you for this informative article! We are happy to help you code 💙