Neovim

Neovim setup and general info

Updated: 08 November 2024

Installation

The following need to be installed to use Neovim with Plugins

I had an issue installing vim-plug that ended up putting the config into the wrong folder, just ensure that ~/.vim/autoload contents are copied to ~/.config/nvim/autoload if nvim can’t find the plug function - create the .config/nvim directory if it doesn’t exist

Setup

Vim Plug

Vim Plug GitHub

First, create a ~/.config/nvim/init.vim file if it doesn’t already exist, and add the following to setup vim-plug

init.vim

1
call plug#begin(stdpath('data') . '/plugged')
2
3
" Plugins will be defined in this block
4
5
call plug#end()

After adding a plugin and saving (:w), you will need to reload the nvim config:

1
:source path/to/nvim.init

And then install the plugins again with:

1
:PlugInstall

CoC

CoC GitHub

CoC is a Vim plugin for code completion, it can be installed using Plug like so:

1
call plug#begin(stdpath('data') . '/plugged')
2
3
" Plugins will be defined in this block
4
Plug 'neoclide/coc.nvim', {'branch': 'release'}
5
6
call plug#end()

Next, run nvim and install the relevant language servers, for example we can install ts, eslint, prettier, and json support like so:

1
:CocInstall coc-json coc-tsserver

Alternatively, you can add the CoC extensions into the init.vim file like so:

1
let g:coc_global_extensions = [ 'coc-tsserver', 'coc-eslint', 'coc-prettier', 'coc-json' ]

The relevant CoC extensions will be automatically installed the next time you open an editor if they aren’t already

Key Bindings/Mappings

We can add keybindings for CoC by copying the base keybindings from their documentation, you can also see them below:

1
" Set internal encoding of vim, not needed on neovim, since coc.nvim using some
2
" unicode characters in the file autoload/float.vim
3
set encoding=utf-8
4
5
" TextEdit might fail if hidden is not set.
6
set hidden
7
8
" Some servers have issues with backup files, see #649.
9
set nobackup
10
set nowritebackup
11
12
" Give more space for displaying messages.
13
set cmdheight=2
14
15
" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
16
" delays and poor user experience.
17
set updatetime=300
18
19
" Don't pass messages to |ins-completion-menu|.
20
set shortmess+=c
21
22
" Always show the signcolumn, otherwise it would shift the text each time
23
" diagnostics appear/become resolved.
24
if has("nvim-0.5.0") || has("patch-8.1.1564")
25
" Recently vim can merge signcolumn and number column into one
26
set signcolumn=number
27
else
28
set signcolumn=yes
29
endif
30
31
" Use tab for trigger completion with characters ahead and navigate.
32
" NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
33
" other plugin before putting this into your config.
34
inoremap <silent><expr> <TAB>
35
\ pumvisible() ? "\<C-n>" :
36
\ CheckBackspace() ? "\<TAB>" :
37
\ coc#refresh()
38
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"
39
40
function! CheckBackspace() abort
41
let col = col('.') - 1
42
return !col || getline('.')[col - 1] =~# '\s'
43
endfunction
44
45
" Use <c-space> to trigger completion.
46
if has('nvim')
47
inoremap <silent><expr> <c-space> coc#refresh()
48
else
49
inoremap <silent><expr> <c-@> coc#refresh()
50
endif
51
52
" Make <CR> auto-select the first completion item and notify coc.nvim to
53
" format on enter, <cr> could be remapped by other vim plugin
54
inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
55
\: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"
56
57
" Use `[g` and `]g` to navigate diagnostics
58
" Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
59
nmap <silent> [g <Plug>(coc-diagnostic-prev)
60
nmap <silent> ]g <Plug>(coc-diagnostic-next)
61
62
" GoTo code navigation.
63
nmap <silent> gd <Plug>(coc-definition)
64
nmap <silent> gy <Plug>(coc-type-definition)
65
nmap <silent> gi <Plug>(coc-implementation)
66
nmap <silent> gr <Plug>(coc-references)
67
68
" Use K to show documentation in preview window.
69
nnoremap <silent> K :call ShowDocumentation()<CR>
70
71
function! ShowDocumentation()
72
if CocAction('hasProvider', 'hover')
73
call CocActionAsync('doHover')
74
else
75
call feedkeys('K', 'in')
76
endif
77
endfunction
78
79
" Highlight the symbol and its references when holding the cursor.
80
autocmd CursorHold * silent call CocActionAsync('highlight')
81
82
" Symbol renaming.
83
nmap <leader>rn <Plug>(coc-rename)
84
85
" Formatting selected code.
86
xmap <leader>f <Plug>(coc-format-selected)
87
nmap <leader>f <Plug>(coc-format-selected)
88
89
augroup mygroup
90
autocmd!
91
" Setup formatexpr specified filetype(s).
92
autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
93
" Update signature help on jump placeholder.
94
autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
95
augroup end
96
97
" Applying codeAction to the selected region.
98
" Example: `<leader>aap` for current paragraph
99
xmap <leader>a <Plug>(coc-codeaction-selected)
100
nmap <leader>a <Plug>(coc-codeaction-selected)
101
102
" Remap keys for applying codeAction to the current buffer.
103
nmap <leader>ac <Plug>(coc-codeaction)
104
" Apply AutoFix to problem on the current line.
105
nmap <leader>qf <Plug>(coc-fix-current)
106
107
" Run the Code Lens action on the current line.
108
nmap <leader>cl <Plug>(coc-codelens-action)
109
110
" Map function and class text objects
111
" NOTE: Requires 'textDocument.documentSymbol' support from the language server.
112
xmap if <Plug>(coc-funcobj-i)
113
omap if <Plug>(coc-funcobj-i)
114
xmap af <Plug>(coc-funcobj-a)
115
omap af <Plug>(coc-funcobj-a)
116
xmap ic <Plug>(coc-classobj-i)
117
omap ic <Plug>(coc-classobj-i)
118
xmap ac <Plug>(coc-classobj-a)
119
omap ac <Plug>(coc-classobj-a)
120
121
" Remap <C-f> and <C-b> for scroll float windows/popups.
122
if has('nvim-0.4.0') || has('patch-8.2.0750')
123
nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
124
nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
125
inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
126
inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
127
vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
128
vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
129
endif
130
131
" Use CTRL-S for selections ranges.
132
" Requires 'textDocument/selectionRange' support of language server.
133
nmap <silent> <C-s> <Plug>(coc-range-select)
134
xmap <silent> <C-s> <Plug>(coc-range-select)
135
136
" Add `:Format` command to format current buffer.
137
command! -nargs=0 Format :call CocActionAsync('format')
138
139
" Add `:Fold` command to fold current buffer.
140
command! -nargs=? Fold :call CocAction('fold', <f-args>)
141
142
" Add `:OR` command for organize imports of the current buffer.
143
command! -nargs=0 OR :call CocActionAsync('runCommand', 'editor.action.organizeImport')
144
145
" Add (Neo)Vim's native statusline support.
146
" NOTE: Please see `:h coc-status` for integrations with external plugins that
147
" provide custom statusline: lightline.vim, vim-airline.
148
set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}
149
150
" Mappings for CoCList
151
" Show all diagnostics.
152
nnoremap <silent><nowait> <space>a :<C-u>CocList diagnostics<cr>
153
" Manage extensions.
154
nnoremap <silent><nowait> <space>e :<C-u>CocList extensions<cr>
155
" Show commands.
156
nnoremap <silent><nowait> <space>c :<C-u>CocList commands<cr>
157
" Find symbol of current document.
158
nnoremap <silent><nowait> <space>o :<C-u>CocList outline<cr>
159
" Search workspace symbols.
160
nnoremap <silent><nowait> <space>s :<C-u>CocList -I symbols<cr>
161
" Do default action for next item.
162
nnoremap <silent><nowait> <space>j :<C-u>CocNext<CR>
163
" Do default action for previous item.
164
nnoremap <silent><nowait> <space>k :<C-u>CocPrev<CR>
165
" Resume latest coc list.
166
nnoremap <silent><nowait> <space>p :<C-u>CocListResume<CR>

Additionally, you can add the following for some spacing preferences and line numbers:

1
" tab size
2
set tabstop=2
3
set shiftwidth=2
4
5
" spaces instead of tab
6
set expandtab
7
8
" show line numbers
9
set number

Themes

You can use Vim themes by downliading them and adding to the ~/.config/nvim/colors folder. For example, you can use the Molokai Theme

Then, use the :Colors command to select at theme - this should automatically load any themes in the colors directory as available

You can also set a default theme like so:

1
" Molokai theme options
2
colorscheme molokai

FZF

FZF.vim GitHub

FZF Is a Command Line Fuzzy Search and can be installed in the init.vim file like so:

1
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
2
Plug 'junegunn/fzf.vim'

I’m using this along with the below settings:

1
" FZF settings
2
" Open at bottom 40% of screen
3
let g:fzf_layout = { 'down': '~40%' }

After that, resource and install plugins, and then you can use the following commands:

CommandDescription
:FilesSearch all Files
:GFilesSearch all Git Tracked Files
:BuffersView Open Buffers
:RgSearch in Files (see below)

You can then search for files and press enter to open a file

Adding a ! to the end of the FZF Command will open the search window in full screen

Additionally, we can use ripgrep via the :Rg command to search for text content inside of files

It should also be noted that unless bat is installed, you will not have syntax highlighting in the FZF search results

NERDTree

:NERDTree provides a file explorer within NVIM

CommandDescription
:NERDTreeOpen the file explorer
?View Help
mOpen the file manu

Note that NERDTree can also be used from the :Explore menu by using :Explore followed by x (special option) which will launch NERDTree in place of the explore but will be in the file context so you can do things like create files, etc. more easily

Useful Keybindings

ShortcutDescription
[space] cView Commands w/ Search
[space] aView Language Server Errors
\f [enter]Format File
\rnRename Symbol
gdGo to Definition
grGo to References
\aCode Action
[gPrevious Error
]gNext Error
qfCode Fix
[ctr] [space]View Suggestions
[shift] kView Code Doc
[space] oView Symbols
[ctrl] tFrom GFiles View, open in new tab
gt gTGo to next tab/previous tab

Using NuShell with Vim

You can configure Nushell with Vim using Lua config as:

1
-- setting the shell to use "nu" - all of these are required for correct behaviour
2
-- not setting all the below options will break the `:!command` mode in vim
3
vim.opt.shell = 'nu'
4
vim.opt.shellcmdflag = '-c'
5
vim.opt.shellquote = ""
6
vim.opt.shellxquote = ""

Telescope + Quickfix

Telescope is used often as a UI for finding stuff and integrates with a lot of other tools in the Neovim ecosystem. Something particularly handy with telescope is the ability to create a quickfix list from a telescope search/filter. This can be done from Telescope with ctrl + q which will close telescope and open a quickfix list with the current set of results

Using telescope this way is a nice method to get quickfix lists from a few other things:

  • LSP references
  • LazyGit Status (faster than the viewing the git file tree)
  • Ripgrep
  • Telescope file search