If you don’t use VIM, learn VIM!
It’s quite daunting learning this text editor. When I was starting up with Linux, a colleague launched vim
on my terminal and asked me to quit out of it. I was pressing Ctrl+C, escape, Ctrl+C AND escape and all kinds of key combinations but I simply could not figure it out without cheating (yes, the Internet)!
I then discovered that typing vimtutor
will launch the best tutorial you will ever have, I highly encourage you to do so before proceeding with this post.
VIM is extremely powerful on its own, but more magic comes in the form of plugins that attach to it. Below you can find my configuration but first, let’s add a plugin manager.
I started with vim-plug and it was so simple to use that I stuck with it. To install, simply copy the following in your terminal:
curl -fLo ~/.vim/autoload/plug.vim --create-dirs \
https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
After installing vim-plug, you need to edit your ~/.vimrc
file. Let’s add the airline plugin, which adds a lightweight status bar with nice information at the bottom of the window:
# Plugins will be downloaded under the specified directory.
call plug#begin('~/.vim/plugged')
" Declare the list of plugins
Plug 'vim-airline/vim-airline'
" List ends here. Plugins become visible to Vim after this call.
call plug#end()
Note that lines starting with "
are comments, and therefore “ignored” by the configuration
Relaunch vim and voila! If you don’t see the status bar, type the following inside vim:
:PlugInstall
and hit Enter (don’t forget the :
at the beginning of the command.) This will load the plugins included in the .vimrc
file.
This is what vim looked liked before:
And this is what it looks like now:
Huge difference, right?
Here’s my full .vimrc configuration:
" Make Pretty
set number
set ai
set tabstop=4
highlight LineNr term=bold cterm=NONE ctermfg=DarkGrey ctermbg=NONE gui=NONE guifg=DarkGrey guibg=NONE
let mapleader=","
set encoding=UTF-8
" Move between tabs with F8 and Shift-F8.
set switchbuf=usetab
nnoremap <C-t> :tabnew<CR>
inoremap <C-t> <Esc>:tabnew<CR>
nnoremap <F8> :sbnext<CR>
nnoremap <S-F8> :sbprevious<CR>
" Press F4 to toggle highlighting on/off, and show current value.
:noremap <F4> :set hlsearch! hlsearch?<CR>
" NERDTree stuff
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
map <C-n> :NERDTreeToggle<CR>
autocmd bufenter * if (winnr("$") == 1 && exists("b:NERDTree") && b:NERDTree.isTabTree()) | q | endif
" Plugins will be downloaded under the specified directory.
call plug#begin('~/.vim/plugged')
" Declare the list of plugins.
Plug 'tpope/vim-sensible'
Plug 'junegunn/seoul256.vim'
Plug 'vim-airline/vim-airline'
Plug 'vim-airline/vim-airline-themes'
Plug 'jreybert/vimagit'
Plug 'tpope/vim-fugitive'
Plug 'preservim/nerdtree'
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'
Plug 'ryanoasis/vim-devicons'
" List ends here. Plugins become visible to Vim after this call.
call plug#end()
" Files + devicons + floating fzf
function! FzfFilePreview()
let l:fzf_files_options = '--preview "bat --theme="OneHalfDark" --style=numbers,changes --color always {3..-1} | head -200" --expect=ctrl-v,ctrl-x'
let s:files_status = {}
function! s:cacheGitStatus()
let l:gitcmd = 'git -c color.status=false -C ' . $PWD . ' status -s'
let l:statusesStr = system(l:gitcmd)
let l:statusesSplit = split(l:statusesStr, '\n')
for l:statusLine in l:statusesSplit
let l:fileStatus = split(l:statusLine, ' ')[0]
let l:fileName = split(l:statusLine, ' ')[1]
let s:files_status[l:fileName] = l:fileStatus
endfor
endfunction
function! s:files()
call s:cacheGitStatus()
let l:files = split(system($FZF_DEFAULT_COMMAND), '\n')
return s:prepend_indicators(l:files)
endfunction
function! s:prepend_indicators(candidates)
return s:prepend_git_status(s:prepend_icon(a:candidates))
endfunction
function! s:prepend_git_status(candidates)
let l:result = []
for l:candidate in a:candidates
let l:status = ''
let l:icon = split(l:candidate, ' ')[0]
let l:filePathWithIcon = split(l:candidate, ' ')[1]
let l:pos = strridx(l:filePathWithIcon, ' ')
let l:file_path = l:filePathWithIcon[pos+1:-1]
if has_key(s:files_status, l:file_path)
let l:status = s:files_status[l:file_path]
call add(l:result, printf('%s %s %s', l:status, l:icon, l:file_path))
else
" printf statement contains a load-bearing unicode space
" the file path is extracted from the list item using {3..-1},
" this breaks if there is a different number of spaces, which
" means if we add a space in the following printf it breaks.
" using a unicode space preserves the spacing in the fzf list
" without breaking the {3..-1} index
call add(l:result, printf('%s %s %s', ' ', l:icon, l:file_path))
endif
endfor
return l:result
endfunction
function! s:prepend_icon(candidates)
let l:result = []
for l:candidate in a:candidates
let l:filename = fnamemodify(l:candidate, ':p:t')
let l:icon = WebDevIconsGetFileTypeSymbol(l:filename, isdirectory(l:filename))
call add(l:result, printf('%s %s', l:icon, l:candidate))
endfor
return l:result
endfunction
function! s:edit_file(lines)
if len(a:lines) < 2 | return | endif
let l:cmd = get({'ctrl-x': 'split',
\ 'ctrl-v': 'vertical split',
\ 'ctrl-t': 'tabe'}, a:lines[0], 'e')
for l:item in a:lines[1:]
let l:pos = strridx(l:item, ' ')
let l:file_path = l:item[pos+1:-1]
execute 'silent '. l:cmd . ' ' . l:file_path
endfor
endfunction
call fzf#run({
\ 'source': <sid>files(),
\ 'sink*': function('s:edit_file'),
\ 'options': '-m --preview-window=right:70%:noborder --prompt Files\> ' . l:fzf_files_options,
\ 'down': '40%',
\ 'window': 'call FloatingFZF()'})
endfunction
I will not go through all the plugins in this post but I encourage you to look them up and experiment.
However, some basic information regarding what the above configuration applies:
set number
will set line numbersCtrl-T
will launch a new tab, andF8
will switch between tabs.Shift-F8
to go backwards.- If you search for a keyword (usually by typing
/
followed by the keyword and then Enter), you can toggle highlighting all other similar keywords withF4
- NERDTree is also amazing. If you simply launch vim without specifying a file, NERDTree will display a tree explorer that you can use to select whatever you need to edit.
You can also call it by typing:NERDTree
in Normal mode or toggle it withCtrl+N
- FZF (or fuzzy finder) is a whole different beast and deserves a post on its own but, as a starting point, you can use
:FZF
to find files in your working directory.Esc
will close that search. Note that for this functionality you may need to install FZF from the link.
I hope this will help you kickstart your vim experience! Again, I highly encourage you to google everything and read as much as you can, add/remove lines and functions from your .vimrc config and see where things break.
Because hey, you gotta break some eggs!
To reset everything, simply empty out your .vimrc file and reload vim.
Finally, the only way to truly learn vim and harness its power is by using it for whatever editing purpose you can think of.
Enjoy!