{"id":2124,"date":"2022-06-20T02:35:44","date_gmt":"2022-06-19T21:05:44","guid":{"rendered":"https:\/\/smarttech101.com\/?p=2124"},"modified":"2023-09-01T08:30:33","modified_gmt":"2023-09-01T03:00:33","slug":"nvim-lsp-autocompletion-mapping-snippets-fuzzy-search","status":"publish","type":"post","link":"https:\/\/smarttech101.com\/nvim-lsp-autocompletion-mapping-snippets-fuzzy-search\/","title":{"rendered":"Nvim lsp autocompletion: mapping, snippets, fuzzy search"},"content":{"rendered":"\n
Nvim lsp autocompletion helps you in completing any variable-name\/file-path\/function\/spelling and thus preventing typing mistakes. It also prevents you from memorizing too much programming jargon. Nowadays AI-based completions (ex – Tabnine) are also being developed. More on this in my next article.<\/p>\n\n\n\n
If have not set up basic configuration in Neovim, do that over here<\/a>. This article is part of my series on setting up Nvim Lsp (Neovim Language Server Protocol):<\/p>\n\n\n\n I recommend you to follow all three articles in the above order.<\/p>\n\n\n\n Please install the following plug-ins if you have not installed them. I will be showing the power of neovim-lsp autocompletion using these plug-ins.<\/p>\n\n\n\n Please note that there are other snippet plug-ins that have been covered in this article at appropriate places. However, I have not tested them as extensively as Ultisnips.<\/p>\n\n\n\n When it comes to snippets’ expansion, most of the snippet plug-ins such as Ultisnips set up a shortcut. For example, in bash language, when you type For the above configuration, create a file Now, put the following lines in the file Now, to move from one “tabstop” to another, use the tab key (“tabstops” are special stops within which you can move using the tab key). And when there is no tabstops type a tab i.e. ‘\\t’.<\/p>\n\n\n\n Similarly, to go to the previous tabstop, use Shift+Tab.<\/p>\n\n\n\n In the above code, you can change the shortcut keys other than “Tab” and “Shift+Tab” (called For more about snippets, please keep reading.<\/p>\n\n\n\n To see the icons in the autocompletion menu as shown in figure 1, put the following code in the file \ud83d\udcd3 Note<\/strong>: You might not see the above icons in your browser. To see them, just enable a nerd font<\/a> in your terminal and then copy and paste these lines into a text file.<\/p>\n\n\n\n Now, kindly follow the heading Formatting in nvim-lsp autocompletion<\/a>.<\/p>\n\n\n\n Put the following codes in the file Where all the capitalized words will be replaced by your main configuration. And it is covered in the next headings (subheadings).<\/p>\n\n\n\n Replace the “SNIPPET_CONFIGURATION_GOES_HERE” with the following:<\/p>\n\n\n\n If you want to use a snippet engine other than Ultisnips, uncomment (delete the Formatting decides how autocompletion menu is shown – what is the order of icons, icon kinds, etc.<\/p>\n\n\n\n To configure the formatting, replace the FORMATTING_GOES_HERE with the following code:<\/p>\n\n\n\n \ud83d\udcd3 Note 1<\/strong>: If you don’t mention any source in the \ud83d\udcd3 Note 2<\/strong>: Change the Replace the MAPPING_GOES_HERE with the following:<\/p>\n\n\n\n \ud83e\udde0 Explanation 1<\/strong>: \ud83e\udde0 Explanation 2<\/strong>: I am using “Control + n” ( \ud83e\udde0 Explanation 3<\/strong>: You need to use Increase the numbers shown in \ud83e\udde0 Explanation 4<\/strong>: \ud83d\udcd3 Note<\/strong>: Many other keys are already set up as default by the nvim-lsp. For example, I do a lot of incorrect spellings. Therefore I have enabled the fuzzy matching. So, for example, if I just type To enable the fuzzy matching, replace the FUZZY_MATCHING_GOES_HERE with the following:<\/p>\n\n\n\n But if you like to disable this nice feature due to some reason, use SOURCES_RELATED_CONFIGURATION decides items (sources), their orders, terms, and conditions, etc. in the autocompletion menu.<\/p>\n\n\n\n To set this, replace the SOURCES_RELATED_CONFIGURATION with the following code:<\/p>\n\n\n\n \ud83d\udcd3 Note 1<\/strong>: The above settings make sure that \ud83d\udcd3 Note 2<\/strong>: Having \ud83d\udcd3 Note 3<\/strong>: I have tried to optimize the above order as much as possible so that you get maximum recommendations in the right order in the autocompletion menu. You can rearrange the above sources or install new source plug-ins and use them here according to your own preference. But at the same time, you can also set these orders depending upon your filetypes. That is shown in the upcoming headings.<\/p>\n\n\n\n You can use the nvim-lsp autocompletion in the neovim’s command line as well. To see it in action, see figure 4.<\/p>\n\n\n\n To use sources Here \ud83d\udcd3 Note<\/strong>: if you have enabled Similarly, you can also use the autocompletion menu in the neovim’s search (\/) as shown in the following figure.<\/p>\n\n\n\n To use That\u2019s all folks for nvim-LSP configuration. And don\u2019t forget to source the file In order to completely set up your Nvim-lsp, please go through all articles in the nvim-lsp series<\/a>.<\/p>\n\n\n\n\n
Table of Contents<\/h2>\n\n\n\n
\n
\n
Install useful plug-ins<\/h2>\n\n\n\n
\n
neovim\/nvim-lspconfig<\/code><\/li>\n\n\n\n
SirVer\/ultisnips<\/code> for snippets.<\/span> There are other snippet plug-ins. But this is one of the most famous plug-ins. So, I will be using it.<\/li>\n\n\n\n
honza\/vim-snippets<\/code> – it has the pre-built snippets for bash, python, etc. it integrates with ultisnips.<\/li>\n\n\n\n
hrsh7th\/nvim-cmp<\/code><\/li>\n\n\n\n
\n
hrsh7th\/cmp-nvim-lsp<\/code> provides
nvim_lsp<\/code> source for language servers’ completion service. It is a very important plug-in. <\/li>\n\n\n\n
hrsh7th\/cmp-cmdline<\/code> provides
cmdline<\/code> source for vim’s commands (figure 4)<\/li>\n\n\n\n
hrsh7th\/cmp-path<\/code> provides
path<\/code> source for the completion of filepaths<\/li>\n\n\n\n
hrsh7th\/cmp-buffer<\/code> provides
buffer<\/code> source for completion from the opened buffer<\/li>\n\n\n\n
hrsh7th\/cmp-calc<\/code> provides
calc<\/code> source for completion from vim’s built-in mathematical expression calculation facility (for example, suppose I have typed
2+3=<\/code> in a text file. Now,
5<\/code> will be suggested in the autocompletion menu.<\/li>\n\n\n\n
f3fora\/cmp-spell<\/code> provides a
spell<\/code> source based on vim’s
spellsuggest<\/code>. It is good for typing difficult words such as
flibbertigibbet<\/code> in English.<\/li>\n\n\n\n
tamago324\/cmp-zsh<\/code> provides
zsh<\/code> source. It gives completion like your zsh. A similar plugin is
Valodim\/vim-zsh-completion<\/code>.<\/li>\n\n\n\n
quangnguyen30192\/cmp-nvim-ultisnips<\/code> provides
ultisnips<\/code> source to put the list of available snippets into the autocompletion menu (figure 1)<\/li>\n\n\n\n
hrsh7th\/cmp-nvim-lsp-signature-help<\/code> provides
nvim_lsp_signature_help<\/code> source. Signature help shows information about the parameters of your function\/method in a floating window. For more, see the Signature Help section in nvim-lsp<\/a>.<\/li>\n\n\n\n
Snippets setup using Ultisnips<\/h2>\n\n\n\n
for<\/code> and press the shortcut for the
for<\/code> snippet expansion, an “empty”
for<\/code> loop will be created. But here, we will use an auto-completion engine for this purpose. The engine will suggest to you if there are any snippets. Now, you don’t have to use any shortcuts. As soon as you type the
for<\/code> keyword, a snippet, if any, will be shown. Just select that and the snippet will be expanded.<\/p>\n\n\n\n
for<\/code> snippet<\/figcaption><\/figure>\n\n\n\n
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>. Until this file is “sourced”, you will not see any result. I will show you how to source this file at the very end of this article.<\/p>\n\n\n\n
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>:<\/p>\n\n\n\n
vim.cmd [[\nlet g:UltiSnipsJumpForwardTrigger='<Tab>'\nlet g:UltiSnipsJumpBackwardTrigger='<S-Tab>'\n]]<\/code><\/pre>\n\n\n\n
<S-Tab><\/code> in neovim).<\/p>\n\n\n\n
Create icons in nvim-lsp autocompletion<\/h2>\n\n\n\n
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>:<\/p>\n\n\n\n
local kind_icons = {\n Class = \"\ufd2f\",\n Color = \"\uf8d7\",\n Constant = \"\uf8fe\",\n Constructor = \"\uf423\",\n Enum = \"\uf15d\",\n EnumMember = \"\uf15d\",\n Event = \"\uf0e7\",\n Field = \"\uf6fc\",\n File = \"\uf718\",\n Folder = \"\uf74a\",\n Function = \"\uf794\",\n Interface = \"\uf0e8\",\n Keyword = \"\uf80a\",\n Method = \"\uf6a6\",\n Module = \"\uf487\",\n Operator = \"\uf694\",\n Property = \"\ufc20\",\n Reference = \"\uf481\",\n Snippet = \"\uf44f\",\n Struct = \"\uf1b3\",\n Text = \"\ue612\",\n TypeParameter = \"\uf671\",\n Unit = \"\ue21f\",\n Value = \"\uf89f\",\n Variable = \"\uf5a0\",\n}<\/code><\/pre>\n\n\n\n
Configure mapping, fuzzy matching, sources, and formatting in the autocompletion menu<\/h2>\n\n\n\n
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>:<\/p>\n\n\n\n
local cmp = require 'cmp'\ncmp.setup({\n snippet = {\n SNIPPET_CONFIGURATION_GOES_HERE\n },\n formatting = {\n FORMATTING_GOES_HERE\n },\n mapping = {\n MAPPING_GOES_HERE\n },\n completion = {\n COMPLETION_RELATED_CONFIGURATION_GOES_HERE\n },\n matching = {\n FUZZY_MATCHING_GOES_HERE\n },\n sources = cmp.config.sources(SOURCES_RELATED_CONFIGURATION)\n})<\/code><\/pre>\n\n\n\n
Snippet configuration in nvim-lsp autocompletion<\/h3>\n\n\n\n
expand = function(args)\n -- For `vsnip`, uncomment the following.\n -- vim.fn[\"vsnip#anonymous\"](args.body)\n -- For `luasnip`, uncomment the following.\n -- require('luasnip').lsp_expand(args.body)\n -- For snippy, uncomment the following.\n -- require('snippy').expand_snippet(args.body)\n -- For `ultisnips`\n vim.fn[\"UltiSnips#Anon\"](args.body)\n end,<\/code><\/pre>\n\n\n\n
--<\/code> in front of that) that from the above code instead.<\/p>\n\n\n\n
Formatting in nvim-lsp autocompletion<\/h3>\n\n\n\n
format = function(entry, vim_item)\n -- Kind icons\n vim_item.kind = string.format(\"%s %s\", kind_icons[vim_item.kind], vim_item.kind) --Concatonate the icons with name of the item-kind\n vim_item.menu = ({\n nvim_lsp = \"[LSP]\",\n spell = \"[Spellings]\",\n zsh = \"[Zsh]\",\n buffer = \"[Buffer]\",\n ultisnips = \"[Snip]\",\n treesitter = \"[Treesitter]\",\n calc = \"[Calculator]\",\n nvim_lua = \"[Lua]\",\n path = \"[Path]\",\n nvim_lsp_signature_help = \"[Signature]\",\n cmdline = \"[Vim Command]\"\n })[entry.source.name]\n return vim_item\n end,<\/code><\/pre>\n\n\n\n
vim_item.menu()<\/code>, the right part of the completion menu will have unsightly empty space.<\/p>\n\n\n\n
nvim_lsp = \"[LSP]\"<\/code><\/figcaption><\/figure>\n\n\n\n
vim_item.kind<\/code> line to have the desired format of the autocompletion menu. The
format()<\/code> function shown above is almost like the
format()<\/code> function in any other language. So it should not be very difficult.<\/p>\n\n\n\n
Mapping in nvim-lsp autocompletion<\/h3>\n\n\n\n
['<C-n>'] = cmp.mapping(cmp.mapping.select_next_item(), { 'i', 'c' }),\n ['<C-p>'] = cmp.mapping(cmp.mapping.select_prev_item(), { 'i', 'c' }),\n ['<C-M-k>'] = cmp.mapping(cmp.mapping.scroll_docs(-4), { 'i', 'c' }),\n ['<C-M-j>'] = cmp.mapping(cmp.mapping.scroll_docs(4), { 'i', 'c' }),\n ['<C-Space>'] = cmp.mapping(cmp.mapping.complete(), { 'i', 'c' }),\n ['<C-y>'] = cmp.config.disable,\n ['<C-e>'] = cmp.mapping({\n i = cmp.mapping.abort(),\n c = cmp.mapping.close(),\n }),\n ['<CR>'] = cmp.mapping.confirm({ select = false }),<\/code><\/pre>\n\n\n\n
i<\/code>, and
c<\/code> shown above are for “insert” and “command” modes. Having them means the key bindings work in the autocompletion menu shown in both the insert as well as in command mode.<\/p>\n\n\n\n
<C-n><\/code>) and “Control + p” (
<C-p><\/code>) to move to the Next and Previous items shown in the auto-completion menu. This is similar to many other applications like Dmenu<\/a>, Ranger’s command line, Interactive Bash and Zsh Shells, Emacs, Fzf, and many more. Most of the shortcuts have been set up in this fashion. This is what I love above Linux (or Unix in general) based operating systems. You can configure all of your apps, their color schemes, shortcut keys, etc. in a similar fashion and thus reducing confusion.<\/p>\n\n\n\n
<C-M-k><\/code> (Control+Alt+k) and
<C-M-j><\/code> (Control+Alt+j) to scroll up and down in the scroll documents. Alternatively, you can also use your mouse scroll wheel. But that will require a vim command
:set mouse=a<\/code><\/p>\n\n\n\n
scroll_docs()<\/code> (in the above code it is
4)<\/code>), to increase the scroll sensitivity.<\/p>\n\n\n\n
<C-e><\/code> to escape i.e. close\/abort the completion menu. In insert mode, this shortcut, using
cmp.mapping.abort()<\/code> will close the completion menu and restore the initial state. But in the console mode, it, using
cmp.mapping.abort()<\/code> only closes the completion menu.<\/p>\n\n\n\n
<C-m><\/code> (Control+m) chooses your item from the completion menu.<\/p>\n\n\n\n
Keyword length in nvim-lsp autocompletion<\/h3>\n\n\n\n
keyword_length<\/code> sets the number of keywords you need to type before the autocompletion menu pops up. By default, it is 1. If you want to change it to a higher value, for example to 3, replace the COMPLETION_RELATED_CONFIGURATION_GOES_HERE with the following line:<\/p>\n\n\n\n
keyword_length = 1,<\/code><\/pre>\n\n\n\n
Fuzzy matching in nvim-lsp autocompletion<\/h3>\n\n\n\n
fr<\/code> instead of
for<\/code>, and there is a snippet for the loop, it will be shown in the autocompletion menu.<\/p>\n\n\n\n
disallow_fuzzy_matching = false,<\/code><\/pre>\n\n\n\n
true<\/code> instead of
false<\/code>.<\/p>\n\n\n\n
Configure sources to be used in the autocompletion menu<\/h3>\n\n\n\n
{\n { name = 'nvim_lsp' },\n -- For ultisnips users\n { name = 'ultisnips' },\n -- For vsnip users, uncomment the following.\n -- { name = 'vsnip' },\n -- For luasnip users, uncomment the following.\n -- { name = 'luasnip' },\n -- For snippy users, uncomment the following.\n -- { name = 'snippy' },\n }, {\n { name = 'buffer' },\n }, {\n { name = 'nvim_lsp_signature_help' },\n }, {\n { name = 'path' },\n }<\/code><\/pre>\n\n\n\n
buffer<\/code> source is visible in the completion menu only when the
nvim_lsp<\/code> and
ultisnips<\/code> sources are not available. Similarly,
nvim_lsp_signature_help<\/code> will be visible only when the
nvim_lsp<\/code>,
ultisnips<\/code>, and
buffer<\/code> are not available. The same goes for source
path<\/code>.<\/p>\n\n\n\n
nvim_lsp<\/code> and
ultisnips<\/code> in a single bracket will allow them to be mixed in the listing otherwise, all the autocompletion menu’s place is taken over by
nvim_lsp<\/code>.<\/p>\n\n\n\n
Configure nvim-lsp autocompletion for command line (console)<\/h2>\n\n\n\n
cmdline<\/code> and
path<\/code> source, append the following code in your file
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>:<\/p>\n\n\n\n
cmp.setup.cmdline(':', {\n sources = cmp.config.sources({\n { name = 'path' },\n { name = 'cmdline' },\n })\n})<\/code><\/pre>\n\n\n\n
cmdline<\/code> source will suggest you vim\/neovim commands and
path<\/code> source will complete file-path (ex – \/usr\/share, etc. in Linux).<\/p>\n\n\n\n
native_menu<\/code>, the above code will not work.<\/p>\n\n\n\n
Configure nvim-lsp autocompletion for search (\/)<\/h2>\n\n\n\n
buffer<\/code> source for
\/<\/code>, append the following code in the file
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code>:<\/p>\n\n\n\n
cmp.setup.cmdline('\/', {\n sources = {\n { name = 'buffer' },\n }\n})<\/code><\/pre>\n\n\n\n
Conclusion<\/h2>\n\n\n\n
~\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code> in your file
init.vim<\/code>:<\/p>\n\n\n\n
source $HOME\/.config\/nvim\/plug-config\/auto-cmp.lua<\/code><\/pre>\n\n\n\n