In the last few articles, I commented on why I adopted Neovim as my main editor and went through the basics for using the program. However, it does not come with plugins or nice looks by default. Here, I show you how I set up my Neovim.
The programming languages I use in my daily life are JavaScript (JSX and TypeScript), CSS, Sass and lately I'm studying Python, too. Therefore, my configuration supports these technologies.
About my choices for the configuration
As you can imagine, Neovim is configured by text files.
There are two ways to configure it: using the Lua language, or VimScript, created for Vim. Here I will use the last one, as it works for both Vim and Neovim. So I kill two birds with one stone.
I have no experience with Lua, and at the moment I have no plans on learning the language just to configure the application. I'm aware that there are more modern ways to do this, but I prefer to keep my settings concise.
At the end of this guide, you will not have a tangle of files and directories, as you may have seen elsewhere, but rather a single file, just enough for comfortable use.
Setting options
As with most software, there is a way to edit options and preferences. These can be tested with the command :set <option-name>
. Try opening an instance of Vim/Neovim now and type :set number
, you'll notice that the line numbers will appear on the side. The problem with this is that these commands will have to be repeated each time you reopen the program.
Saving settings
To keep these settings saved, just write these commands in a file in your user folder. The name and location will vary depending on whether you use Vim or Neovim:
-
Vim:
<username>/.vimrc
-
Neovim:
<username>/.config/nvim/init.vim
If these files/directories do not exist in your home folder, just create them manually. Remember that files starting with "." are hidden by default on Unix systems (Linux, BSDs and macOS). Make sure you are showing hidden files in your file manager or terminal.
Basic options in the configuration file
Before we get into more complex things like extensions and their settings, let's stick to the basics. There are many options to tinker with, however, the ones I put below are the ones I currently use. Note that in the file will have the commands that would have to be typed every time the editor opened.
" Options
set background=dark
set clipboard=unnamedplus
set completeopt=noinsert,menuone,noselect
set cursorline
set hidden
set inccommand=split
set mouse=a
set number
set relativenumber
set splitbelow splitright
set title
set ttimeoutlen=0
set wildmenu
" Tabs size
set expandtab
set shiftwidth=2
set tabstop=2
Here is the explanation of each command above:
-
background=dark
: apply the color set for dark screens. Not just the background of the screen, as it might look. -
clipboard=unnamedplus
: enables the clipboard between Vim/Neovim and other applications. -
cursorline
: highlights the current line in the editor. -
completeopt
: modifies the auto-complete menu to behave more like an IDE. -
hidden
: hide unused buffers1. -
inccommand=split
: show replacements in a split screen, before applying to the file. -
mouse=a
: allows the use of the mouse in the editor. -
number
: shows line numbers. -
relativenumber
: show line numbers starting from the current one. Useful for using multiline commands. -
splitbelow splitright
: changes split screen behavior with the command:split
(split horizontally) and:vsplit
(vertically). In this case, the screens will always split below the current screen and to the right. -
title
: show the file title -
ttimeoutlen=0
: time in milliseconds to run commands. -
wildmenu
: shows a more advanced menu for auto-completion suggestions. -
expandtab
: transforms tabs into spaces. -
shiftwidth=2
: number of spaces for indentation. -
tabstop=2
: number of spaces for tabs.
Syntax
To add automatic syntax support for open files:
filetype plugin indent on
syntax on
Color support
To enable 256 colors on the terminal:
set t_Co=256
Below is a logic I made for Vim to detect if the system supports a greater number of colors. Note that I made a conditional to detect if the terminal emulator is Apple's one. For some reason the colors behave differently in the versions I used.
" True color if available
let term_program=$TERM_PROGRAM
" Check for conflicts with Apple Terminal app
if term_program !=? 'Apple_Terminal'
set termguicolors
else
if $TERM !=? 'xterm-256color'
set termguicolors
endif
endif
If you don't use the Apple terminal, ignore that part and just add the code inside the else
.
Support for true italics
If you're like me and like fonts with true italic support, add these lines:
" Italics
let &t_ZH="\e[3m"
let &t_ZR="\e[23m"
Don't ask me what these codes there mean. All I know is that a terminal with italic support will recognize them as italic.
NetRW: Vim's default file manager
Notice: If you already know a little about Vim and are not interested in NetRW, skip this part.
If you've ever used an IDE in your life, you might have noticed that there's always a tree on the side with the project files. Vim/Neovim use NetRW by default, which brings this same function.
When opening Vim or Neovim using the [n]vim .
command to open the project directory, the file listing will appear inside it. It can also be opened using the :Ex
,:Vex
or :Sex
commands.
You can use it with the default settings, but personally, some things bother me, so I used the following settings:
" File browser
let g:netrw_banner=0
let g:netrw_liststyle=0
let g:netrw_browse_split=4
let g:netrw_altv=1
let g:netrw_winsize=25
let g:netrw_keepdir=0
let g:netrw_localcopydircmd='cp -r'
Here's the explanation:
-
g:netrw_banner=0
: hides the top banner that appears by default. -
g:netrw_liststyle=0
: change the display of files.-
0
shows only one directory at a time. -
1
shows file data. -
2
shows files in columns. -
3
shows as a tree where open directories are expanded.
-
-
g:netrw_browse_split=4
: changes how files are opened.-
1
opens files in a horizontal split. -
2
opens in a vertical split. -
3
opens in a new tab. -
4
opens in a previous window, avoiding the creation of more divisions.
-
-
g:netrw_altv=1
: switches the NetRW display to the left. -
g:netrw_winsize=25
: limits window size to 25% of available screen space. -
g:netrw_keepdir=0
: keeps the directory you accessed previously. -
g:netrw_localcopydircmd
: modifies the command used to copy files. By default, NetRW just copies empty folders. To change this, I set the default command tocp -r
so that the copy occurs recursively.
To make creating files easier, I've added more settings:
" Create file without opening buffer
function! CreateInPreview()
let l:filename = input('please enter filename: ')
execute 'silent !touch ' . b:netrw_curdir.'/'.l:filename
redraw!
endfunction
" Netrw: create file using touch instead of opening a buffer
function! Netrw_mappings()
noremap <buffer>% :call CreateInPreview()<cr>
endfunction
augroup auto_commands
autocmd filetype netrw call Netrw_mappings()
augroup END
This prevents NetRW from opening an empty screen just to create a file.
If you want to use NetRW, I believe this is the minimum needed to use it comfortably.
NetRW and its problems
There are several criticisms of NetRW for the way it causes a buffer mess. From what I've researched, it seems that using g:netrw_liststyle=3
tree mode tends to make this behavior worse. Errors are random, making fixing it a difficult process, and updating only NetRW is more complex than it should be.
That's why there are several alternatives to NetRW, and the most famous one is NERDTree, which I use in my main configuration.
Plugins
Neovim using the tweaks we made so far
Plugin manager setup
Finally, it's time to configure the plugins. Unlike VS Code or other editors, there are several options for extension installers: Neobundle, Vundle, Vim-Plug, etc. Here I will use the last one, which seems to be the most used nowadays. To install it, open a terminal and run the following command:
For Vim:
$ curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
For Neovim:
$ sh -c 'curl -fLo "${XDG_DATA_HOME:-$HOME/.local/share}"/nvim/site/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
These commands above do all the necessary to have Vim-Plug available in your editor.
Installing plugins
Vim-Plug reads a part of your configuration file to find the extension in Github and install it in the editor. This part is delimited by the following structure:
call plug#begin()
Plug '<github-user>/<repo-name>'
call plug#end()
You can add multiple extensions at once, just add multiple Plug
as desired. There is a website that catalogs these plugins for easy discovery, if you want to visit. It's called Vim Awesome. The link is at the end of the article.
Plugins I use
Here's what I use on my Vim/Neovim:
call plug#begin()
" Appearance
Plug 'vim-airline/vim-airline'
Plug 'ryanoasis/vim-devicons'
" Utilities
Plug 'sheerun/vim-polyglot'
Plug 'jiangmiao/auto-pairs'
Plug 'ap/vim-css-color'
Plug 'preservim/nerdtree'
" Completion / linters / formatters
Plug 'neoclide/coc.nvim', {'branch': 'master', 'do': 'yarn install'}
Plug 'plasticboy/vim-markdown'
" Git
Plug 'airblade/vim-gitgutter'
call plug#end()
- Vim Airline: modifies the status bar to make it more pleasant than the default one.
- Vim Devicons: shows icons in the interface, based on icon fonts2.
- Vim Polyglot: syntax highlighting for several programming languages.
- Auto Pairs: automatically closes parentheses, square brackets and braces when typing.
- Vim CSS Color: shows colors (hex, RGB, HSL) directly in the code.
- NERDTree: sidebar to access project files. Replaces the NetRW I mentioned earlier.
- CoC (Conquer of Completion): provides auto-completion, very similar to what is available in VS Code. I'll go into details about it later.
- Vim Markdown: better support for Markdown file syntax.
- Vim GitGutter: Shows Git changes in open files.
Writing these lines with addresses is not enough to install extensions. First, you must save the configuration file and restart Vim in order for the editor to comply with the newly added settings. After that, run the :PlugInstall
command.
A window will open and show the installation process for each extension. After installation, you will have to restart Vim one more time to use the new extensions.
To uninstall, remove the line of the plugin you want to get rid of from the configuration file and after restarting the editor, run the command :PlugClean
.
Color schemes
If there's something critical to a good development experience, it's a good color scheme. These are installed in the same way as extensions.
First, add the line with the path to the theme's Github repository:
call plug#begin()
Plug 'morhetz/gruvbox'
call plug#end()
To use the theme, add the command colorscheme gruvbox
in the configuration file. This will be enough to get rid of that black screen and stark colors that come by default.
Color scheme I use
Sobrio: the theme I use in my daily life
Despite setting the example with the GruvBox theme, this is not the theme I use. Color schemes are very subjective things and as I used this theme, I ended up getting a little bored with it. The same happened with others. Since I couldn't find one I liked, I made my own. It's called Sobrio. If you want to test it, just follow the same recipe above, changing only the repository:
call plug#begin()
Plug 'elvessousa/sobrio'
call plug#end()
Then just add colorscheme sobrio
and restart the editor. Please feel free to leave your comment and suggestion about it. I would like to know your opinion. If you want to know more about it, the link for the website is at the end of the article.
Plugins configuration
Devicons
Devicons is an extension that adds icons to Vim's interface. In order to work, it is necessary to have fonts with icon support installed on the system.
Look for "NERD Fonts" on the internet, and you'll find plenty of them. The way to install fonts on the system varies a lot depending on the operating system, and I won't go into details here. Download it, install and apply the font for your terminal emulator. Other than that, no other configuration is required.
Airline
Little to set up here. Basically it's saying which theme to use and if you want to use "Powerline" mode, which are these lines with arrow shapes.
let g:airline_theme='sobrio'
let g:airline_powerline_fonts = 1
let g:airline#extensions#tabline#enabled = 1
The last option above shows enables Airline for the tab bar.
NERDTree
NERDTree is the replacement for NetRW. By default, it works fine. I just added a line to show hidden files by default.
" File browser
let NERDTreeShowHidden=1
You know, I like to see .env
or .gitignore
files without having to type I
first.
Neovim com as configurações até agora
CTRLP
This plugin enables file search in your project's folder. It is activated by the same keyboard shortcut that gives its name. If you've ever used VS Code, you will get used to it very quickly. The only setting I made was this one:
let g:ctrlp_user_command = ['.git/', 'git --git-dir=%s/.git ls-files -oc --exclude-standard']
Putting the line above into plain English: CTRLP will ignore every file or directory mentioned inside your project's .gitignore
file.
Vim Markdown
If you don't use Markdown, skip this part.
As I use the Markdown format a lot to write on my blog, I installed this extension to improve the display of this type of file on my Neovim.
" Disable math tex conceal feature
let g:tex_conceal = ''
let g:vim_markdown_math = 1
" Markdown
let g:vim_markdown_folding_disabled = 1
let g:vim_markdown_frontmatter = 1
let g:vim_markdown_conceal = 0
let g:vim_markdown_fenced_languages = ['tsx=typescriptreact']
I use YAML headers (Frontmatter) at the top so that Gatsby does its magic. Without this plugin the frontmatter and code blocks syntax is not recognized.
Coc: Conquer of Completion
This is the plugin that requires the most configuration. Conquer of Completion works as a server that provides auto-completion and code correction tools, working similar to VS Code. It supports extensions too, and these are responsible for adding support for the desired programming languages.
The weakness of CoC is that it is based on NodeJS, so the dependencies of installed packages will take up a certain amount of disk space, like all Node projects. Of the ones I've tested so far, it has met my expectations the most, with the least configuration.
Installing extensions is simple: just run the command :CocInstall <extension-name>
and the features will be available for you to use.
Here are the extensions I use:
- coc-tsserver: support for JavaScript, TypeScript and React.
- coc-css: support for CSS, Sass and SCSS.
- coc-eslint: lints JavaScript and TypeScript files.
- coc-emmet: adds shortcuts to write less in HTML, CSS, Sass, SCSS and extended JavaScript files (JSX,TSX)
- coc-pyright: Python support.
- coc-prettier: formats the code according to well accepted standards in the community.
To install them all at once, just run the command:
:CocInstall coc-tsserver coc-css coc-eslint coc-emmet coc-pyright coc-prettier
Prettier with coc-prettier
" Language server stuff
command! -nargs=0 Prettier :call CocAction('runCommand', 'prettier.formatFile')
The command above will run Prettier and format the file whenever you save the file. This helps a lot, as I spend less time pressing Tab
to indent code.
Coc settings in JSON
Apart from the init.vim
or .vimrc
we've used so far, I also use a separate file called coc-settings.json
. With it it is possible to modify the behavior of your extensions.
{
"coc.preferences.formatOnSaveFiletypes": [
"css",
"sass",
"scss",
"markdown",
"html",
"json",
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"python"
],
"python.formatting.provider": "black",
"python.formatting.blackPath": "~/.local/bin/black",
"prettier.singleQuote": true,
"javascript.autoClosingTags": true,
"typescript.autoClosingTags": true,
"emmet.includeLanguages": [
"javascript",
"javascriptreact",
"typescript",
"typescriptreact",
"html"
],
"codeLens.enable": false
}
Here is the explanation of the settings above:
- Configure CoC to format some file types when saving.
- Configure Prettier to prefer single quotes in formatting.
- Inform which code formatter for python, "black" in this case, and passed the path to black on my system.
- Enable auto-close for extended JavaScript tags (JSX)
- Enable Emmet for more file formats.
- Disable Code Lens, as it crashed occasionally.
Note that if you don't use Python, just ignore the settings for it. For the Python formatter to work, it must be installed on the system:
$ pip install black
Keyboard shortcuts
As with other programs, there is a way to configure keyboard shortcuts. This can be done for each editor mode. The possibilities are many. To add a keyboard shortcut in Vim, just add the expression:
[first-letter-of-target-mode]noremap <key-or-letters> :Command
The strange word noremap
comes from "Non Recursive Mapping", "Non-Recursive Mapping". This means that the created shortcut will not overwrite another similar shortcut, avoiding conflicts.
As I'm a bit minimalist, I didn't add many shortcuts.
" Normal mode remappings
nnoremap <C-q> :q!<CR>
nnoremap <F4> :bd<CR>
nnoremap <F5> :NERDTreeToggle<CR>
nnoremap <F6> :sp<CR>:terminal<CR>
" Tabs
nnoremap <S-Tab> gT
nnoremap <Tab> gt
nnoremap <silent> <S-t> :tabnew<CR>
Here is the explanation of the above mappings:
-
Ctrl+q
: closes the open screen. -
F4
: closes the open file. -
F5
: shows or hides NERDTree. -
F6
: opens a terminal in a lower split window. -
Shift+Tab
: switch to the previous tab. -
Shift+t
: creates a tab. -
Tab
: switch to the next open tab.
Note that there are several <CR>
. These represent all the times you would have to press Enter
in command mode. CR is the abbreviation for "Carriage Return": a term from the time when typewriters were used. Today, we understand it as the Enter
or Return
key.
All shortcuts I used are for normal mode, so nnoremap
is on every line. If it was for insert mode it would be inoremap
, vnoremap
for visual mode and so on.
Automatic commands
To automate some things, Vim makes it possible to define what it calls autocmd
: automatic commands performed on certain events.
" Auto Commands
augroup auto_commands
autocmd BufWrite *.py call CocAction('format')
autocmd FileType scss setlocal iskeyword+=@-@
augroup END
Above, I defined two actions: one to format the Python code when saving the file, and another to resolve an inconsistency I had with SCSS files.
Wrap up
Without a doubt, this was the longest article I've made so far, but if you followed the instructions, you have a very functional editor now. There are other plugins, but as you get used to it and build confidence, you will test out others better suitable for your needs.
Ideally, try to keep the init file simple. Too much extensions can affect performance. I use other settings that I haven't detailed in this article, as they are not important for most cases. I'm providing the link to my dotfiles repository for you to check at the end of this article if you want.
See you in the next article!
Links
If this article helped you in some way, consider donating. This will help me to create more content like this!
Top comments (14)
Great post, so simple and helped a lot! thank you!
I'd like to add a tip regarding nerd fonts for the complete linux beginners like me.
If you have GNOME then probably you are using
gnome-terminal
like me and it didn't find the fonts after installing them.One work-around is to install gnome-tweaks
sudo apt install gnome-tweaks
Then run it with the same name
gnome-tweaks
, and go to the fonts tab, then set the "system mono" (or something like that :D ) to the nerd font you downloadedNow in the gnome-terminal preferences, uncheck the "custom font" box.
And after a day of struggling, it works :D
Well at least for me on Pop!_os 21.10
Hope this helps :D
Thanks a lot, Khaled!
If Gnome shipped with Tweaks already installed, stuff would be much easier for beginners. I don't know the reason behind it... Maybe they don't want you tweaking stuff by default...
Anyway... Enjoy your setup!
Thanks, this helped me get my
airline
andNerdTREE
to be a bit nicer looking!Nice!
This config is what I searched for a long time, minimalist an efficient. Thank you very much !!
Thank you! It helped a lot!
This is an awesome post. And nice setup.
I do feel the need to defend lua a little bit here. After version 0.5 the lua api got better.
I'd say there is no need to learn everything about lua. Knowing just the most basic things can get you far.
Here's a simple lua config if anyone is curious.
For a config full of hacks and shenanigans here is mine: link.
I didn't mean to criticize Lua... It's a good language and I wish it gets more popular.
But for my simple goals I think it is a bit overkill. As I said, the setup should work on both Vim and Neovim, and that wouldn't be possible with Lua, as Vim doesn't support it.
Don't worry, I don't have any emotional attachment to lua. Was just trying to say a lua config doesn't have to be complex.
Hey man, thanks for this amazing and helpful post.
I was having a hard time configuring my NeoVim to fit my needs.
I use NeoVim for JavaScript development and you have helped me set it up.
Thanks a lot, once again and keep up the great work.
Nice! I'm glad it was helpful!
This is an excelent guide, I have tweaked everything, but thanks to you I have configured nvim for first time! I always get overwhelmed with bad tutorials out there and you give me all knowledge to understand how init.vim works. Thanks bro
Very good setup and very well explained. +1
Thanks a lot!