All Articles

Vim IDE setup

Without doubt vim is an essential tool for coding on linux, and in this post, I’ll demonstrate how I configure my vim, to make it suitable for my needs. And For some of the background introduction, shortcuts cheatsheets, please check the other post.

Before we start, if you are a new user to vim, rather than following what I’m doing, probably you should google for ready to use vim configurations, because doing the configuration and tweaking can be very frustrating. Here are some great resources, that I haved used and learnt from.

  1. The ultimate vimrc
  2. Vim is the perfect IDE
  3. Vim as IDE
  4. Vim awesome

My needs

I’m not a professional programmer, but I do programming everyday. I commonly program in Fortran, C++, python, Shell, javascript, html, css and some times write blog in markdown, or paper using latex. Among all of these use cases, I think the support for Fortran, C++, python and Shell are most important, because in these cases I need to do the programming remotely on a linux server. And the other usages, such as building website and writing in markdown or latex, are what I usually do on my own computer, thus I can use other editors such as Visual Studio Code.

Besides from the supports to these languages, git capability is also a necessary.

Installation

Before we even start to configure vim, we need to first install vim and some other supporting packages, which is not as trivial as you might thought. Though for any remote server, I would assume it already has vim installed, that version of vim might not be suitable for all of your needs, because some plugins request latest version of vim and some plugins are depending on other packages such as lua, perl, so the best solution is always download the source code and compile it by yourself. Of course, if you’re using your own computer and your systems package manager provides the suitable vim you need, then you can skip this step and start directly from the Plugin section.

The necessary packages on the remote server are:

  1. Python3
  2. Perl
  3. Lua
  4. Ctags
  5. Cscope
  6. findent
  7. vim

Since there are quite a few packages involved, I recommend you setup your folder structure properly. For me, I created a usr folder, which will be the prefix for all installation, and I’ll put all of the source codes into usr/src.

The system version is as follows Linux version 2.6.32-754.el6.x86_64 (mockbuild@x86-033.build.eng.bos.redhat.com) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-23) (GCC) ) #1 SMP Thu May 24 18:18:25 EDT 2018

The download, configuration and make install could be down with the following commands/script:

# Necessary tools to build vim with
# perl5
git clone https://github.com/Perl/perl5.git
cd perl5
./Configure -des -Dusedevel -Duseshrplib -Dprefix=/your/install/path
make
make install
cd ..
# Lua
git clone https://github.com/lua/lua.git
cd lua
sed -i '/^INSTALL_TOP= */c\INSTALL_TOP= /your/install/path' Makefile
make linux
make install
cd ..
# Python3
git clone https://github.com/python/cpython.git
cd cpython
./configure --prefix=/your/install/path --enable-optimizations --with-openssl=/path/to/your/openssl
make
make install
cd ..
# Necessay external commands some vim plugins will use
# Ctags
git clone https://github.com/universal-ctags/ctags.git
cd ctags
./autogen.sh
./configure --prefix=/your/install/path
make
make install
cd ..
# Cscope
git clone https://github.com/lboulard/cscope.git
cd cscope
./configure --prefix=/your/install/path LDFLAGS='-ltinfo'
make
make install
cd ..
# findent
git clone https://github.com/wvermin/findent.git
cd findent/findent
./configure --prefix=/your/install/path
make
make install
cd ..

The python3 config dir is where you will find the cocnfig.c file

# Vim
git clone https://github.com/vim/vim.git
cd vim
./configure --with-features=huge \
    --enable-multibyte \
    --enable-python3interp=yes \
    --with-python3-config-dir=/your/install/path/lib/python3.8/config-3.8m-x86_64-linux-gnu \
    --enable-luainterp=yes \
    --with-lua-prefix=/your/install/path \
    --enable-perlinterp=yes \
    --enable-gui=gtk2 \
    --enable-cscope \
    --prefix=/your/install/path
make
make install
cd ..

Extremely important! It took me almost half a day to figure out how to let the icon properly showing up on both window, mac and linux. Once you know how, it is actually very simple!

The necessary package for your client side is Nerd fonts, please check out the official site https://github.com/ryanoasis/nerd-fonts and choose the font you want. For example, I like the Droid sans, so

  • On windows, I download the fonts from here, then simply double click to install it.
  • On mac, I use the suggested homebrew way with the following two commands brew tap caskroom/fonts and then brew cask install font-droidsansmono-nerd-font-mono
  • On linux, download specific font from here, and then install manually. Or if you don’t mind clone the whole package, which is huge, you can git clone then install with the install.sh script.

Next step is to set the font in your terminal emulator, one thing is you’re using iTerm on mac, remember to set both the ascii and non-ascii character.

FYI, some ttf fonts are not working properly on Windows and Mac, but the otf ones seems to be fine, so if the font you choose is not displaying those dev icons, maybe you want to check out fonts of the other format.

Plugins

Vim has a lot of useful plugins, and you definitely want to have a plugin manager make your life easier. You can easily find there are three most popular manager, vim-plug, vundle and pathogen. I won’t go into detail comparison between the three, you can choose any one you like, and I’ll choose vim-plug.

Install vim-plug

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

And then you can put the following lines into your ~/.vimrc file for using plugins

call plug#begin('~/.vim/plugged')
" Contains the actual plugins, such as nerdtree
call plug#end()

My plugins

All of the following plugins could be downloaded from the Vim awesome website, which is so awesome!

  1. NERDTree: a tree shape file system explorer

  2. fzf: a fuzzy finder for file/text

  3. Tagbar: buffer displaying tags generated by ctags, requires ctags to generate the tags externally.

  4. neocomplete: code autocomplete tool, requires Lua

  5. vim-airline: a better looking status bar

  6. vim-devicons: better looking icon for all file formats, used in the nerdtree and ariline.
  7. nerdcommenter: commenting utilities
  8. gitgutter: showing git diff on the gutter
  9. fugitive: git operations within vim
  10. surround: quoting, bracketing utilities
  11. multiple-cursors: enable sublimetext style multicursor
  12. ale or syntastic: linting services, syntastic works right out of the box, but it is slow and will block the editor when it’s linting. ale need to install other linter, but it’s asynchronous. I choose to use ale.
  13. indent-guides: visual guide for indentation
  14. cscope: similar function as ctags, but cscope supporting going to places that use the function rather than just goto definition
  15. ultisnip: a snippets manager for vim, it doesn’t provide the snippet though, you need to install vim-snippets.
  16. gruvbox: a theme that simply jsut works for both Xshell on windows and iTerm2 on Mac.
  17. findent: auto indentation for fortran file, since the default indentation with ’==’ is awful for fortran.
  18. supertab: to make neocomplete and ultisnip work together
  19. lexima: for auto closing parenthesis.
  20. move: move the whole line

Here is a quick view of how each plugin is influencing the look of vim.

NERDTree

nerdtree

Tagbar

tagbar

fzf

fzf

Neocomplete

neocomplete

Airline

airline

Devicon

devicon

Syntastic

syntastic

Ale

ale

Gitgutter

gitgutter

Multi cursor

multicursor

Indent guides

indent-guide

Ultisnip + vim-snippets

ultisnip

So now the .vimrc file looks like this

call plug#begin('~/.vim/plugged')
Plug 'morhetz/gruvbox'
Plug 'scrooloose/nerdtree'
Plug 'majutsushi/tagbar'
Plug 'junegunn/fzf', { 'dir': '~/.fzf', 'do': './install --all' }
Plug 'junegunn/fzf.vim'
Plug 'shougo/neocomplete.vim'
Plug 'vim-airline/vim-airline'
Plug 'ryanoasis/vim-devicons'
Plug 'scrooloose/nerdcommenter'
Plug 'tpope/vim-fugitive'
Plug 'airblade/vim-gitgutter'
Plug 'tpope/vim-surround'
Plug 'terryma/vim-multiple-cursors'
Plug 'w0rp/ale'
Plug 'nathanaelkane/vim-indent-guides'
Plug 'sirver/ultisnips'
Plug 'honza/vim-snippets'
Plug 'brookhong/cscope.vim'
Plug 'lambdalisue/vim-findent'
Plug 'ervandew/supertab'
Plug 'cohama/lexima.vim'
Plug 'matze/vim-move'
call plug#end()

Plugin settings

" Open nerdtree when no file is opened
autocmd StdinReadPre * let s:std_in=1
autocmd VimEnter * if argc() == 0 && !exists("s:std_in") | NERDTree | endif
let NERDTreeShowHidden=1

let use_findent = 0
let findent = "/gpfs/group/lqc3/default/findent/bin/findent"
let use_findent_indentexpr = 1
let findent_flags = "-i4"

" use powerline font for airline
let g:airline_powerline_fonts = 1
let g:airline_theme='gruvbox'

" Indent guide
let g:indent_guides_enable_on_vim_startup = 1

" Ultisnips
let g:UltiSnipsExpandTrigger="<tab>"
let g:UltiSnipsEditSplit="vertical"

" lexima
call lexima#add_rule({'char': '$','input_after':'$','filetype':'latex'})
call lexima#add_rule({'char': '<','input_after':'>'})
call lexima#add_rule({'char': '>','at':'<\%#>','leave':1})

" Use ctrl for moving line up and down
let g:move_key_modifier='C' 

" Neocomplete
"Note: This option must be set in .vimrc(_vimrc).  NOT IN .gvimrc(_gvimrc)!
" Disable AutoComplPop.
let g:acp_enableAtStartup = 0
" Use neocomplete.
let g:neocomplete#enable_at_startup = 1
" Use smartcase.
let g:neocomplete#enable_smart_case = 1
" Set minimum syntax keyword length.
let g:neocomplete#sources#syntax#min_keyword_length = 3

" Define dictionary.
let g:neocomplete#sources#dictionary#dictionaries = {
    \ 'default' : '',
    \ 'vimshell' : $HOME.'/.vimshell_hist',
    \ 'scheme' : $HOME.'/.gosh_completions'
        \ }

" Define keyword.
if !exists('g:neocomplete#keyword_patterns')
    let g:neocomplete#keyword_patterns = {}
endif
let g:neocomplete#keyword_patterns['default'] = '\h\w*'

" Plugin key-mappings.
inoremap <expr><C-g>     neocomplete#undo_completion()
inoremap <expr><C-l>     neocomplete#complete_common_string()

" Recommended key-mappings.
" <CR>: close popup and save indent.
inoremap <silent> <CR> <C-r>=<SID>my_cr_function()<CR>
function! s:my_cr_function()
  return (pumvisible() ? "\<C-y>" : "" ) . "\<CR>"
  " For no inserting <CR> key.
  "return pumvisible() ? "\<C-y>" : "\<CR>"
endfunction
" <TAB>: completion.
inoremap <expr><TAB>  pumvisible() ? "\<C-n>" : "\<TAB>"
" <C-h>, <BS>: close popup and delete backword char.
inoremap <expr><C-h> neocomplete#smart_close_popup()."\<C-h>"
inoremap <expr><BS> neocomplete#smart_close_popup()."\<C-h>"
" Close popup by <Space>.
"inoremap <expr><Space> pumvisible() ? "\<C-y>" : "\<Space>"

" AutoComplPop like behavior.
"let g:neocomplete#enable_auto_select = 1

" Shell like behavior(not recommended).
"set completeopt+=longest
"let g:neocomplete#enable_auto_select = 1
"let g:neocomplete#disable_auto_complete = 1
"inoremap <expr><TAB>  pumvisible() ? "\<Down>" : "\<C-x>\<C-u>"

" 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#input_patterns = {}
endif
"let g:neocomplete#sources#omni#input_patterns.php = '[^. \t]->\h\w*\|\h\w*::'
"let g:neocomplete#sources#omni#input_patterns.c = '[^.[:digit:] *\t]\%(\.\|->\)'
"let g:neocomplete#sources#omni#input_patterns.cpp = '[^.[:digit:] *\t]\%(\.\|->\)\|\h\w*::'

" For perlomni.vim setting.
" https://github.com/c9s/perlomni.vim
let g:neocomplete#sources#omni#input_patterns.perl = '\h\w*->\h\w*\|\h\w*::'

Setting

This section listed settings for vim itself.

" set encoding
set encoding=utf8
" use unix type file ending format
set ffs=unix,dos,mac
" enable the use of mouse
set mouse=a

" make backspace behave normally
set backspace=eol,start,indent

" enable move to the next or previous line
set whichwrap+=<,>,h,l

" lines of history to remember
set history=500

" vim plugin
filetype plugin on
filetype indent on

" auto read when file is changed from outside
set autoread

" 10 lines away from boundary when moving up and down
set so=10

" Wildmenu
set wildmenu
set wildmode=list:longest,full

" ignoring pattern for wildcard expanding
set wildignore=*.o,*~,*.pyc,*.so,*.exe

" show the line number in gutter
set number

" show current position with highlight
set cursorline

" set the command buffer height to be 2
set cmdheight=2

" hide buffer when it is abandoned
set hid

" case insensitive when searching
set ignorecase
set smartcase
set hlsearch
set incsearch 

" lazyredraw for doing macro, making things fast
set lazyredraw

" Show matching brackets
set showmatch

" no error sound
set noerrorbells
set novisualbell

" set the font to be used for gui vim
if has('gui_running')
  set guifont=Ubuntu\ Nerd\ Font
  set t_Co=256
endif

" use color scheme gruvbox
colorscheme gruvbox
set background=dark

" tab related setting
set tabstop=2
set shiftwidth=2
set expandtab
set smarttab

" auto indent, smart indent
set ai
set si

" soft wrap line
set wrap

Keybindings

" use F1 for save file under insert mode
nnoremap <F1> <C-\><C-o>:w<CR>
inoremap <F1> <C-\><C-o>:w<CR>

" use F2 for opening .vimrc file, extremely useful, since
" you should form your own key binding through the usage
noremap <F2> :e! ~/.vimrc<cr>
autocmd! bufwritepost ~/.vimrc source ~/.vimrc

" use F9 to toggle the nerd tree
noremap <F9> :NERDTreeToggle<CR>

" use F10 to toggle the tagbar
noremap <F10> :TagbarToggle<CR>

" in addition to the move plugin, us ctrl j/k to move line in insert mode
inoremap <C-j> <Esc>:m .+1<CR>==gi
inoremap <C-k> <Esc>:m .-2<CR>==gi 

" use */# to search for text within the selected region
vnoremap <silent> * :<C-u>call VisualSelection('', '')<CR>/<CR>=@/<CR><CR>
vnoremap <silent> # :<C-u>call VisualSelection('', '')<CR>?<CR>=@/<CR><CR>

" space for searching
map <space> /
map <c-space> ?

" leader key (\) enter for remove highlight
map <silent> <leader><CR> :noh<CR>

" ctrl+f for fzf finding files
nnoremap <C-f> :Files<CR>

" leader (\) + f for Rg finding
nnoremap <leader>f :Rg<CR>

" leader(\) + ; for horizontal split
nnoremap <leader>; :sp<CR>

" leader(\) + " for vertical split
nnoremap <leader>' :vsp<CR>

" leader(\)+fa for cscope find
nnoremap <leader>fa :call CscopeFindInteractive(expand('<cword>'))<CR>

Summary

Up till now, we have finished all of the Vim IDE setup!

For a quick overview of how we did it. First, we install or compile the proper build of Vim, with Lua, python, perl supported. Second, we install the necessary plugins to enable various features. In order to give vim the ide feel and look, the NERDTree, Tagbar, Neocomplete and Ale are probably the most important plugins. The gruvbox theme, airline and devicon also significantly improve the user experience of coding in vim. Third, we did some configuration and added our hotkeys for easy usages.

The beauty of using Vim, just like using Linux, lies in the high configurability, it will grow as you use it more. I hope my configuration can help you get started and eventually create your own Vim setup.