Vim Is The Perfect IDE

June 12, 2018 0 Comments

Vim Is The Perfect IDE



This article was originally published in HackerNoon

Over the years I've jumped back and forth between many code editors, IDEs and tools; but it seems that somehow I always end up coming right back to VIM, and not only for programming – guess which markdown editor I'm using to write this post.

I've have tried Atom, SublimeText, TextMate, Eclipse, Visual Studio, and most of the Jetbrains products, I'm constantly tweaking and looking for a better setup, however Vim always feels like home to me; and I'm to the point now where I rarely use IDEs – exception being messy and complex projects where IDEs can do a lot of heavily lifting (yes, Magento I'm talking about you.)

But other than that Vim is my default Ruby, Elixir, Python, PHP IDE and as well the main tool that I use for writing drafts and books.

What it look like

The Setup

So how does this magical tool work? Is all out of the box right? right? Well no, as with all the worthwhile things in life there is a bit of effort involved on getting the Vim setup just like I wanted it. Fortunately, is far from custom and is mostly the right combination of plugins.

You can find my current Vim configuration and dot files in its corresponding Github repository feel free to fork it and give a shot.

We are in particular interested in the vimrc file, let's break it down:

""""""""""""""""""""""""""""""""""""" " Allan MacGregor Vimrc configuration """"""""""""""""""""""""""""""""""""" set nocompatible
syntax on
set nowrap
set encoding=utf8 """" START Vundle Configuration " Disable file type for vundle
filetype off " required " set the runtime path to include Vundle and initialize
set rtp+=~/.vim/bundle/Vundle.vim
call vundle#begin() " let Vundle manage Vundle, required
Plugin 'gmarik/Vundle.vim' " Utility
Plugin 'scrooloose/nerdtree'
Plugin 'majutsushi/tagbar'
Plugin 'ervandew/supertab'
Plugin 'BufOnly.vim'
Plugin 'wesQ3/vim-windowswap'
Plugin 'SirVer/ultisnips'
Plugin 'junegunn/fzf.vim'
Plugin 'junegunn/fzf'
Plugin 'godlygeek/tabular'
Plugin 'ctrlpvim/ctrlp.vim'
Plugin 'benmills/vimux'
Plugin 'jeetsukumaran/vim-buffergator'
Plugin 'gilsondev/searchtasks.vim'
Plugin 'Shougo/neocomplete.vim'
Plugin 'tpope/vim-dispatch' " Generic Programming Support Plugin 'jakedouglas/exuberant-ctags'
Plugin 'honza/vim-snippets'
Plugin 'Townk/vim-autoclose'
Plugin 'tomtom/tcommentvim'
Plugin 'tobyS/vmustache'
Plugin 'janko-m/vim-test'
Plugin 'maksimr/vim-jsbeautify'
Plugin 'vim-syntastic/syntastic'
Plugin 'neomake/neomake' " Markdown / Writting
Plugin 'reedes/vim-pencil'
Plugin 'tpope/vim-markdown'
Plugin 'jtratner/vim-flavored-markdown'
Plugin 'LanguageTool' " Git Support
Plugin 'kablamo/vim-git-log'
Plugin 'gregsexton/gitv'
Plugin 'tpope/vim-fugitive'
"Plugin 'jaxbot/github-issues.vim' " PHP Support Plugin 'phpvim/phpcd.vim'
Plugin 'tobyS/pdv' " Erlang Support
Plugin 'vim-erlang/vim-erlang-tags'
Plugin 'vim-erlang/vim-erlang-runtime'
Plugin 'vim-erlang/vim-erlang-omnicomplete'
Plugin 'vim-erlang/vim-erlang-compiler' " Elixir Support Plugin 'elixir-lang/vim-elixir'
Plugin 'avdgaag/vim-phoenix'
Plugin 'mmorearty/elixir-ctags'
Plugin 'mattreduce/vim-mix'
Plugin 'BjRo/vim-extest'
Plugin 'frost/vim-eh-docs'
Plugin 'slashmili/alchemist.vim'
Plugin 'tpope/vim-endwise'
Plugin 'jadercorrea/elixir
generator.vim' " Elm Support
Plugin 'lambdatoast/elm.vim' " Theme / Interface
Plugin 'AnsiEsc.vim'
Plugin 'ryanoasis/vim-devicons'
Plugin 'vim-airline/vim-airline'
Plugin 'vim-airline/vim-airline-themes'
Plugin 'sjl/badwolf'
Plugin 'tomasr/molokai'
Plugin 'morhetz/gruvbox'
Plugin 'zenorocha/dracula-theme', {'rtp': 'vim/'}
Plugin 'junegunn/limelight.vim'
Plugin 'mkarmona/colorsbox'
Plugin 'romainl/Apprentice'
Plugin 'Lokaltog/vim-distinguished'
Plugin 'chriskempson/base16-vim'
Plugin 'w0ng/vim-hybrid'
Plugin 'AlessandroYorba/Sierra'
Plugin 'daylerees/colour-schemes'
Plugin 'effkay/argonaut.vim'
Plugin 'ajh17/Spacegray.vim'
Plugin 'atelierbram/Base2Tone-vim'
Plugin 'colepeters/spacemacs-theme.vim' " OSX stupid backspace fix
set backspace=indent,eol,start call vundle#end() " required
filetype plugin indent on " required
"""" END Vundle Configuration """"""""""""""""""""""""""""""""""""" " Configuration Section """"""""""""""""""""""""""""""""""""" " Show linenumbers set number
set ruler " Set Proper Tabs
set tabstop=4
set shiftwidth=4
set smarttab
set expandtab " Always display the status line
set laststatus=2 " Enable Elite mode, No ARRRROWWS!!!!
let g:elitemode=1 " Enable highlighting of the current line
set cursorline " Theme and Styling set t
set background=dark if (has("termguicolors")) set termguicolors
endif let base16colorspace=256 " Access colors present in 256 colorspace
colorscheme spacegray
" colorscheme spacemacs-theme let g:spacegrayunderlinesearch = 1 let g:spacegrayitalicizecomments = 1 " Vim-Airline Configuration
let g:airline#extensions#tabline#enabled = 1
let g:airlinepowerlinefonts = 1 let g:airlinetheme='hybrid'
let g:hybrid
customtermcolors = 1
let g:hybridreducedcontrast = 1 " Syntastic Configuration
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%* let g:syntasticalwayspopulateloclist = 1
let g:syntasticautoloclist = 1
let g:syntastic
checkonopen = 1
" let g:syntasticcheckonwq = 0 " let g:syntasticenableelixirchecker = 1 " let g:syntasticelixircheckers = ["elixir"] " Neomake settings autocmd! BufWritePost * Neomake
let g:neomakeelixirenabledmakers = ['mix', 'credo', 'dogma'] " Vim-PDV Configuration let g:pdvtemplatedir = $HOME ."/.vim/bundle/pdv/templatessnip" " Markdown Syntax Support
augroup markdown au! au BufNewFile,BufRead .md,.markdown setlocal filetype=ghmarkdown
augroup END " Github Issues Configuration
let g:githubaccesstoken = "e6fb845bd306a3ca7f086cef82732d1d5d9ac8e0" " Vim-Alchemist Configuration
let g:alchemist#elixirerlangsrc = "/Users/amacgregor/Projects/Github/alchemist-source"
let g:alchemisttagdisable = 1 " Vim-Supertab Configuration
let g:SuperTabDefaultCompletionType = "<C-X><C-O>" " Settings for Writting
let g:pencil#wrapModeDefault = 'soft' " default is 'hard'
let g:languagetooljar = '/opt/languagetool/languagetool-commandline.jar' " Vim-pencil Configuration
augroup pencil autocmd! autocmd FileType markdown,mkd call pencil#init() autocmd FileType text call pencil#init()
augroup END " Vim-UtilSnips Configuration
" Trigger configuration. Do not use <tab> if you use let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsJumpForwardTrigger="<c-b>"
let g:UltiSnipsJumpBackwardTrigger="<c-z>"
let g:UltiSnipsEditSplit="vertical" " If you want :UltiSnipsEdit to split your window. " Vim-Test Configuration
let test#strategy = "vimux" " Neocomplete Settings
let g:acp
enableAtStartup = 0
let g:neocomplete#enableatstartup = 1
let g:neocomplete#enablesmartcase = 1
let g:neocomplete#sources#syntax#minkeywordlength = 3 " Define dictionary.
let g:neocomplete#sources#dictionary#dictionaries = { \ 'default' : '', \ 'vimshell' : $HOME.'/.vimshellhist', \ 'scheme' : $HOME.'/.goshcompletions' \ } " Define keyword.
if !exists('g:neocomplete#keywordpatterns') let g:neocomplete#keywordpatterns = {}
let g:neocomplete#keywordpatterns['default'] = '\h\w*' function! s:mycrfunction() return (pumvisible() ? "\<C-y>" : "" ) . "\<CR>" " For no inserting <CR> key. "return pumvisible() ? "\<C-y>" : "\<CR>"
endfunction " Close popup by <Space>.
"inoremap <expr><Space> pumvisible() ? "\<C-y>" : "\<Space>" " AutoComplPop like behavior. "let g:neocomplete#enable
autoselect = 1 " Enable omni completion. autocmd FileType css setlocal omnifunc=csscomplete#CompleteCSS
autocmd FileType html,markdown setlocal omnifunc=htmlcomplete#CompleteTags
autocmd FileType javascript setlocal omnifunc=javascriptcomplete#CompleteJS
autocmd FileType python setlocal omnifunc=pythoncomplete#Complete
autocmd FileType xml setlocal omnifunc=xmlcomplete#CompleteTags " Enable heavy omni completion.
if !exists('g:neocomplete#sources#omni#input
patterns') let g:neocomplete#sources#omni#inputpatterns = {}
"let g:neocomplete#sources#omni#input
patterns.php = '[^. \t]->\h\w\|\h\w::' "let g:neocomplete#sources#omni#inputpatterns.c = '[^.[:digit:] *\t]\%(.\|->)' "let g:neocomplete#sources#omni#inputpatterns.cpp = '[^.[:digit:] \t]\%(.\|->)\|\h\w::' " For perlomni.vim setting. " let g:neocomplete#sources#omni#inputpatterns.perl = '\h\w*->\h\w*\|\h\w*::' " Elixir Tagbar Configuration
let g:tagbar
typeelixir = { \ 'ctagstype' : 'elixir', \ 'kinds' : [ \ 'f:functions', \ 'functions:functions', \ 'c:callbacks', \ 'd:delegates', \ 'e:exceptions', \ 'i:implementations', \ 'a:macros', \ 'o:operators', \ 'm:modules', \ 'p:protocols', \ 'r:records', \ 't:tests' \ ] \ } " Fzf Configuration
" This is the default extra key bindings let g:fzf
action = { \ 'ctrl-t': 'tab split', \ 'ctrl-x': 'split', \ 'ctrl-v': 'vsplit' } " Default fzf layout
" - down / up / left / right let g:fzflayout = { 'down': '~40%' } " In Neovim, you can set up fzf window using a Vim command
let g:fzf
layout = { 'window': 'enew' }
let g:fzflayout = { 'window': '-tabnew' } " Customize fzf colors to match your color scheme
let g:fzf
colors =
\ { 'fg': ['fg', 'Normal'], \ 'bg': ['bg', 'Normal'], \ 'hl': ['fg', 'Comment'], \ 'fg+': ['fg', 'CursorLine', 'CursorColumn', 'Normal'], \ 'bg+': ['bg', 'CursorLine', 'CursorColumn'], \ 'hl+': ['fg', 'Statement'], \ 'info': ['fg', 'PreProc'], \ 'prompt': ['fg', 'Conditional'], \ 'pointer': ['fg', 'Exception'], \ 'marker': ['fg', 'Keyword'], \ 'spinner': ['fg', 'Label'], \ 'header': ['fg', 'Comment'] } " Enable per-command history. " CTRL-N and CTRL-P will be automatically bound to next-history and " previous-history instead of down and up. If you don't like the change, " explicitly bind the keys to down and up in your $FZFDEFAULTOPTS. let g:fzfhistorydir = '~/.local/share/fzf-history' """""""""""""""""""""""""""""""""""""
" Mappings configurationn """"""""""""""""""""""""""""""""""""" map <C-n> :NERDTreeToggle<CR>
map <C-m> :TagbarToggle<CR> " Omnicomplete Better Nav
inoremap <expr> <c-j> ("\<C-n>")
inoremap <expr> <c-k> ("\<C-p>") " Neocomplete Plugin mappins
inoremap <expr><C-g> neocomplete#undocompletion()
inoremap <expr><C-l> neocomplete#complete
commonstring() " Recommended key-mappings.
" <CR>: close popup and save indent. inoremap <silent> <CR> <C-r>=<SID>my
crfunction()<CR> " <TAB>: completion.
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>" " <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart
inoremap <expr><BS> neocomplete#smart
closepopup()."\<C-h>" " Mapping selecting Mappings
nmap <leader><tab> <plug>(fzf-maps-n)
xmap <leader><tab> <plug>(fzf-maps-x)
omap <leader><tab> <plug>(fzf-maps-o) " Shortcuts
nnoremap <Leader>o :Files<CR> nnoremap <Leader>O :CtrlP<CR>
nnoremap <Leader>w :w<CR> " Insert mode completion
imap <c-x><c-k> <plug>(fzf-complete-word)
imap <c-x><c-f> <plug>(fzf-complete-path)
imap <c-x><c-j> <plug>(fzf-complete-file-ag)
imap <c-x><c-l> <plug>(fzf-complete-line) " Vim-Test Mappings
nmap <silent> <leader>t :TestNearest<CR>
nmap <silent> <leader>T :TestFile<CR>
nmap <silent> <leader>a :TestSuite<CR>
nmap <silent> <leader>l :TestLast<CR>
nmap <silent> <leader>g :TestVisit<CR> " Vim-PDV Mappings
autocmd FileType php inoremap <C-p> <ESC>:call pdv#DocumentWithSnip()<CR>i
autocmd FileType php nnoremap <C-p> :call pdv#DocumentWithSnip()<CR>
autocmd FileType php setlocal omnifunc=phpcd#CompletePHP " Disable arrow movement, resize splits instead.
if get(g:, 'elite
mode') nnoremap <Up> :resize +2<CR> nnoremap <Down> :resize -2<CR> nnoremap <Left> :vertical resize +2<CR> nnoremap <Right> :vertical resize -2<CR>
endif map <silent> <LocalLeader>ws :highlight clear ExtraWhitespace<CR> " Advanced customization using autoload functions
inoremap <expr> <c-x><c-k> fzf#vim#complete#word({'left': '15%'}) " Vim-Alchemist Mappings
autocmd FileType elixir nnoremap <buffer> <leader>h :call alchemist#exdoc()<CR>
autocmd FileType elixir nnoremap <buffer> <leader>d :call alchemist#exdef()<CR>

Each plugin in this setup is separated in the following categories:


This kind of a miscellaneous category and is comprised of plugins used to enhance or change the behaivour of core vim; the most useful important ones are:

  • Nerdtree: It gives you easy access to the file system in the form of a directory tree on the left side of the screen, as well provides shortcuts for filesystem manipulation(create, delete, move files and directories)

  • Tagbar: Quick tag browser for the current file, a must have if you are using any kind of ctags like exuberant-tags.

  • FZF: Fuzzy finder, another handy utility for finding files and commands.

  • Neocomplete: Vim Autocomplete on steroids.

Generic Programming Support

These plugins fall directly on the category of programming and are used my all or most of the programming languages that I currently have setup:

  • Exuberant-Ctags: tags are named definitions of classes, functions, abstract types and so on; adding support to Vim gives you some of that 'magic' IDE code navigation functionality.

  • Syntastic: THE syntax checking plugin for Vim, if you are familiar with the way that code inspections work on Jetbrains and similar IDEs, syntastic will make feel right at home.

  • Vim-autoclose: Automatically closes a character that could/should have a matching closing counterpart, like () "" [] {} and so on.


As I mentioned Vim is my go to editor for drafting new posts be it books, blogs or random angry letters. From this particular section only language tools deservers a special shot-out as it makes for a great Grammar checker directly from inside Vim.

Erlang/Elixir/PHP/Elm Support

When it comes down to the individual language support there isn't really much to highlight other than I've tried (and somewhat failed) to keep the plugins to a minimum and focus only on the essential language support.

So far elixir is winning the battle in terms of plugins as I've added additional functionality like the ability to run tests and generate content from inside Vim, I have yet to decide if I'm keeping all the plugins for it.

Git Support

Standard git support that I'm afraid I rarely use, I find myself going directly back to the shell and doing the git workflow outside of Vim, so I'm open to suggestions and to hear what everyone else is using in terms of setup.

Themes and Interfaces

Ok this is a big one but mostly because I keep forgetting to remove unused themes and colorschemes, let's highlight the important ones:

  • Vimarline: Lean and mean status/tabline for Vim; it also looks cool as fuck.

  • Vim-Devicons: Because not only atom gets all the fancy icons on the sidebar, highly recommended to if you are using nerdtree.

The remaining parts of the configuration file are either plugin configuration or personal key re-mappings that I use for quality of like; I've done my best to document and segment each section so it should be easy enough to understand what each setting is doing.

For anyone getting starting with Vim, I do want to bring special attention to the following:

" Disable arrow movement, resize splits instead. 
if get(g:, 'elite_mode') nnoremap <Up> :resize +2<CR> nnoremap <Down> :resize -2<CR> nnoremap <Left> :vertical resize +2<CR> nnoremap <Right> :vertical resize -2<CR>

As there is no quickest way to force one-self to use the home row for navigation.

I hope that for some of you this post has been helpful for some, and I'm far from done with my current setup, in that sense this is very much a toy that I continue playing on a nearly daily basis; now that being said and in order to get back to the original premise of the post; it is indeed a very powerful toy, specially when combined with other tools like Tmux, here is a sneak peak of my Elixir 'IDE' powered by Vim and Tmux:

If you want to know more about my setup, or want to share yours please leave a comment below.

Tag cloud