Vim is a simple terminal based text editor that can be configured. This config is also on my github

Requirements

  • vim

Lets start

It is important to have a good configuration structure, so you can extend your configuration easily

Vim uses a .vimrc file located in your home directory for configuration but using that file can be messy, especially when your configuration gets more and more complex

So we will create a folder in ~/.config called vim which we will store all our configurations in. to start, we should create a file called init.vim in this ~/.config/vim directory

But we have to import this file in vims configuration file, .vimrc like this:

1
source ~/.config/vim/init.vim

This will “import” the file ~/.config/vim/init.vim

Options

Now, lets set some simple options

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
" Set tab size to 2 spaces
set tabstop=2
set softtabstop=2
set shiftwidth=2
set expandtab

set number          " Enable line numbers
set relativenumber  " make line numbers relative to cursor

set autoindent      " Automatically indent
set smartindent     " Indent smartly
set nowrap          " dont wrap at end of line
set nobackup        " dont backup files (dont create .<filename>.swp files)
set scrolloff=10    " add 10 lines of padding before and after cursor

set hlsearch    " highlight searches

" lower priority for these file extensions when tab completing
set suffixes+=.info,.aux,.log,.dvi,.bbl,.out,.o,.lo

" enable syntax highlighting
syntax on

for clarity, create a new file opts.vim for these options, and “import” this file in the init.vim file like this:

1
source ~/.config/vim/opts.vim

Mappings

now lets create some new mappings, again in a new file remap.vim which is imported in init.vim

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
" Move selected lines up/down
vnoremap J :m '>+1<CR>gv=gv
vnoremap K :m '<-2<CR>gv=gv

" open new buffer/file
nnoremap <Leader>n :enew<CR>

" Escape terminal using ESC key
tnoremap <Esc> <C-\><C-n>

" :W to sudo save
command! W w !sudo tee % > /dev/null

Plugins

I will use vim-plug for plugins it can be installed using this command (from vim-plug readme):

1
2
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
    https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim

we have installed vim-plug, now we can actually install plugins, for that i will create a new file plugs.vim that i will also import in init.vim

to ensure vim-plug is installed i will use this snippet (also from vim-plug readme):

1
2
3
4
5
let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
if empty(glob(data_dir . '/autoload/plug.vim'))
  silent execute '!curl -fLo '.data_dir.'/autoload/plug.vim --create-dirs  https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
  autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif

we can install plugins now by using call plug#begin() and call plug#end() between these two calls we can install plugins using Plug 'example/whatever'

Theme

i will install the tokyonight theme like this:

1
Plug 'ghifarit53/tokyonight-vim'

tpope

I will also install some of tpope’s plugins:

1
2
3
4
Plug 'tpope/vim-commentary' " Comment stuff
Plug 'tpope/vim-surround'   " Surround stuff
Plug 'tpope/vim-dispatch'   " Async Make
Plug 'tpope/vim-fugitive'   " Git

FZF

and i will also install fzf.vim this requires fzf to be installed on your system

1
2
Plug 'junegunn/fzf', { 'do': { -> fzf#install() } } " Fuzzy Finder
Plug 'junegunn/fzf.vim'                             " More fuzzy stuff

You will notice, there is a { 'do': { -> fzf#install() } } this thing in the Plug call, but what does that actually do? it will run fzf#install() when the plugin is installed or updated

Languages

I also want some plugins for languages i use these are:

1
2
3
4
Plug 'fatih/vim-go' " GoLang support
Plug 'nsf/gocode', { 'rtp': 'vim' }
Plug 'Blackrush/vim-gocode'
Plug 'dgryski/vim-godef'

UI

Until now, we’ve only installed plugins to make working with vim nicer now we will install some plugins for the ui

1
2
3
4
Plug 'preservim/nerdtree'                " File Explorer
Plug 'itchyny/lightline.vim'             " Status bar
Plug 'mengelbrecht/lightline-bufferline' " Bufferline
Plug 'yggdroot/indentline'               " Indicate indents

I use NERDTree as a file explorer, lightline.vim as a status bar, lightline-bufferline as a bufferline, and indentline to highlight indents

LSP

Now lets get some plugins for autocompleteion

1
2
3
4
5
Plug 'prabirshrestha/vim-lsp'              " Lsp
Plug 'mattn/vim-lsp-settings'              " More Lsp
Plug 'prabirshrestha/asyncomplete.vim'     " Autocomplete
Plug 'prabirshrestha/asyncomplete-lsp.vim' " AutoComplete with LSP
Plug 'dense-analysis/ale'                  " ALE

Other

I also use some other plugins for snippets and automatically closing pairs

1
2
3
Plug 'hrsh7th/vim-vsnip'       " Snippets
Plug 'hrsh7th/vim-vsnip-integ' " Snippets integrations for lsp
Plug 'jiangmiao/auto-pairs'

Plugin Configuration

But, these plugins have to be configured, i will create a new folder called plugins which will contain all my configs for plugins

LSP

lets start with configuring lsp:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function! s:on_lsp_buffer_enabled() abort
    setlocal omnifunc=lsp#complete
    setlocal signcolumn=yes
    if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif
    nmap <buffer> gd <plug>(lsp-definition)
    nmap <buffer> gs <plug>(lsp-document-symbol-search)
    nmap <buffer> gS <plug>(lsp-workspace-symbol-search)
    nmap <buffer> gr <plug>(lsp-references)
    nmap <buffer> gi <plug>(lsp-implementation)
    nmap <buffer> gt <plug>(lsp-type-definition)
    nmap <buffer> <leader>rn <plug>(lsp-rename)
    nmap <buffer> [g <plug>(lsp-previous-diagnostic)
    nmap <buffer> ]g <plug>(lsp-next-diagnostic)
    nmap <buffer> K <plug>(lsp-hover)
    nnoremap <buffer> <expr><c-f> lsp#scroll(+4)
    nnoremap <buffer> <expr><c-d> lsp#scroll(-4)

    let g:lsp_format_sync_timeout = 1000
    autocmd! BufWritePre *.rs,*.go call execute('LspDocumentFormatSync')

    " refer to doc to add more commands
endfunction

augroup lsp_install
    au!
    " call s:on_lsp_buffer_enabled only for languages that has the server registered.
    autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END

Go

and the go plugins:

1
2
3
let g:go_highlight_types = 1

au FileType go nmap <leader>d <Plug>(go-def)

This is a very simple configuration, since it just sets <leader>g to call go-def when the filetype is go and making vim-go highlight types

FZF

Lets configure fzf I will start with a small if statement to install fzf

1
2
3
4
if empty(glob("~/.fzf/install"))
  echo "Hello"
  execute '!git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf && ~/.fzf/install'
endif

and i will also make fzf display commits in a specific format

1
let g:fzf_commits_log_options = '--graph --color=always --format="%C(auto)%h%d %s %C(black)%C(bold)%cr"'

Bufferline

lets configure our bufferline next

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
let g:lightline = {
      \ 'colorscheme': 'tokyonight',
      \ 'active': {
      \   'left': [ [ 'mode', 'paste' ], [ 'readonly', 'filename', 'modified' ] ]
      \ },
      \ 'tabline': {
      \   'left': [ ['buffers'] ],
      \   'right': [ ['close'] ]
      \ },
      \ 'component_expand': {
      \   'buffers': 'lightline#bufferline#buffers'
      \ },
      \ 'component_type': {
      \   'buffers': 'tabsel'
      \ }
      \ }
autocmd BufWritePost,TextChanged,TextChangedI * call lightline#update()

and some keybinds to move between buffers

1
2
nmap <Leader><Tab>   <Plug>lightline#bufferline#go_next()
nmap <Leader><S-Tab> <Plug>lightline#bufferline#go_previous()

Autocomplete

And finally lets configure the autocompleteion

1
2
3
4
5
6
7
" Tab to autocomplete
inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"
" inoremap <expr> <cr>    pumvisible() ? asyncomplete#close_popup() : "\<cr>"

" Enter key always insert new line
inoremap <expr> <cr> pumvisible() ? asyncomplete#close_popup() . "\<cr>" : "\<cr>"