Saturday, November 29, 2014

Intro to Vim and the .vimrc Configuration

Vim is an excellent editor and IDE. It's portable and highly customizeable. I've been using it over TextMate, Aptana, Sublime, for over 3 years, now and I'm still learning new things about its built-in functions. If you're a Web Developer or a Software Engineer, you may not have heard of Vim. Vim is a utility Sysadmins come across more than either of these two professions because Vi is built into the shell of most server OSes. Notice I said Vi that time instead of Vim. Think of Vim as Vi improved. It's easy enough to install over Vi. Vim's adoption numbers have also been hindered by its severely steep learning curve. There's a growing camp of engineers, especially in the startup world, that have had to expose themselves to Sysadmin tasks and, upon opening Vim for the first time, have been downright frustrated by how non-intuitive it is. It really is terribly non-intuitive, depending on muscle memory and months of patience. However, if you can get over that curve, it will pay off.

Basic commands

From the terminal window, navigate to your home page by typing in cd ~ and typing vim test.txt. Whenever you start Vim, you're presented with something similar to the following screen.

              VIM - Vi IMproved

               version 7.4.258
           by Bram Moolenaar et al.
 Vim is open source and freely distributable

        Help poor children in Uganda!
type  :help iccf       for information

type  :q               to exit
type  :help  or    for on-line help
type  :help macvim     for MacVim help
This is the standard output on a Mac OS X device with both Vim and MacVim, the Vim GUI, installed. From this point on, you'll be able to run all of the built-in commands. Now we're not going to go too much into detail, because they're beyond the scope of this article, but we will go into two basic Vim modes and how to switch between them.

Normal Mode

This is the mode you start out in. To return to this mode, you can press the escape key one or several times. This mode maps all of your keys to a variety of different commands. Let's start by hitting one of those commands. Proceed to the next section to learn about Insert Mode.

Insert Mode

Press i to enter Insert Mode. This mode maps all of your keys to text output the way a text editor would. Go ahead and type "Hello world" to the screen and then hit the escape key to return to Normal mode. Now press :wq to "write" and "quit". If you have any trouble saving out, hit escape a few times and repeat the write quit command.
So there you have it. You've edited a text file in vim. You should now see that file in your home directory. Not so bad right? We won't go into any more commands at this time because, as I mentioned earlier, Vim has a very steep learning curve so make sure to check out this playlist and other resources to learn more. Let's go back to talking about Vim's strength's over other IDEs.


As I mentioned before, Vi is built into the shell of most server OSes. So at any given time, as long as you have access to your terminal, you can run Vi by typing vi and hitting enter. It's a good idea to install vim if it isn't already available. Vim also doesn't require a operating systems with a graphical user interface because it's running in the shell. This means that any device that has a terminal and can ssh into a server can run Vim, even tablets and mobile phones. Just connect a keyboard to your device and you're good to go. Now for most people, you're not going to want to use the barebones version of Vim the OS provides. You'll want your own custom version. This is done by editing the ~/.vimrc file. The reason the .vimrc is located in your home directory is to provide each user with their own custom instance of Vim. Check out Vundle on github if you'd like to learn about how to set up your instance with plugins. After you've carried out those steps, return to this article and read on about the .vimrc file. It's also a good idea to check out this page about dotfiles.


The .vimrc file houses all of your custom Vim configurations. Some of those configurations include the ability to display a file directory in the sidebar, import custom color schemes, display a detailed status bar, or class / method breakdown. Vim can also be configured to include linting, code hinting and autocompletion. I've included my configuration file at the bottom of this page and a screenshot of my instance of Vim below.

Preventing Carpal Tunnel

The more you interface with Vim, the more you'll understand all of its quirks and conventions. Some of these you'll accept, while others you'll override in your configuration file. Vim was designed to keep your hands on the home row both for ergonomic reasons and because of the fact that mice are useless in the shell. Navigating around the file with the HJKL keys as opposed to the arrow keys are, frankly, better for your wrists. If you think about the most ergonomic position for prolonged periods of typing, it's one that doesn't involve rotating your wrists in the direction of the outlier keys. That's another reason deleting in vim is handled by the x key in normal mode and the use of the backspace key is discouraged.

Vim was also designed to challenge you to be creative with the command keys to reduce the number of keystrokes you're inputting. This might be counterintuitive to some people because it's a workflow in which you're both programming and playing with Vim at the same time. The best UI/UX experience is oftentimes one that's invisible, which Vim clearly isn't. But you have to look at Vim from a different perspective. Vim allows you to take small steps as you program to reduce the total number of steps in the end. It's a very interesting mentality that can applied everywhere.

An Example .vimrc

Now you won't be able to understand all of these configurations from the outset, but take the time to start building our your own .vimrc file from the ground up. Again, remember to check out this article to get a breakdown of this file.

" Author - Rob Layton
" Author - Rob Layton
" General
 set nocompatible
 filetype off
    set shell=/bin/bash
" Vundle
    set rtp+=~/.vim/bundle/Vundle.vim
    call vundle#begin()
    Plugin 'gmarik/Vundle.vim'
    Plugin 'xolox/vim-misc'
    Plugin 'xolox/vim-session'
    "Plugin 'ervandew/supertab'
    Plugin 'scrooloose/nerdtree'
    Plugin 'scrooloose/nerdcommenter'
    Plugin 'scrooloose/syntastic'
    Plugin 'majutsushi/tagbar'
    Plugin 'Lokaltog/vim-easymotion'
    Plugin 'tpope/vim-fugitive'
    Plugin 'Lokaltog/vim-powerline'
    Plugin 'uguu-org/vim-matrix-screensaver'
    Plugin 'jsbeautify'
    Plugin 'jshint.vim'
    Plugin 'docunext/closetag.vim'
    Plugin 'ctrlp.vim'
    Plugin 'pyflakes.vim'
    Plugin 'Raimondi/delimitMate'
    Plugin 'snipMate'
    Plugin 'surround.vim'
    Plugin 'saltstack/salt-vim'
    Plugin 'taglist.vim'
    Plugin 'AutoTag'
    Plugin 'PyDiction'
    Plugin 'AutoComplPop'
    Plugin 'virtualenv.vim'
    Plugin 'terryma/vim-multiple-cursors'

    " All of your Plugins must be added before the following line
    call vundle#end()            " required
    filetype plugin indent on    " required

" Color scheme
    colorscheme northland
 syntax on
 set t_Co=256
 set laststatus=2
 highlight LineNr ctermfg=Yellow
" Auto Indenting
    set backspace=indent,eol,start
    set smartindent
    set tabstop=2
    set softtabstop=2
    set shiftwidth=2
    set expandtab
" Auto folding
    set nofoldenable
" Searching
    " Incremental search allows me to see found characters as I type them. Fast!
    set incsearch 
    " Highlight all instances
    set hlsearch
" Make it easier to see what line and column you're on
    set cursorline
    set number
    set ruler
" Cursor to mouse position
    "set mouse=a
" Pasting
    " Allows pasting to os x clipboard
    set clipboard=unnamed
    " Vim sometimes confuses pasting with linebreak with really fast typing...
    "   ... so turn on paste more before pasting
    set pastetoggle=<F2>
    set paste
" Save swp files outside of the project
    set backupdir=~/.vim/swp,.,/tmp
    set directory=~/.vim/backup,.,./.backup,/tmp
" Intellisense (Ammo boost!)
    autocmd FileType python set omnifunc=pythoncomplete#Complete
    autocmd FileType javascript set omnifunc=javascriptcomplete#CompleteJS
    autocmd FileType html set omnifunc=htmlcomplete#CompleteTags
    autocmd FileType css set omnifunc=csscomplete#CompleteCSS
    autocmd FileType xml set omnifunc=xmlcomplete#CompleteTags
    autocmd FileType php set omnifunc=phpcomplete#CompletePHP
    autocmd FileType c set omnifunc=ccomplete#Complete
" NERDTree configurations for Linux
    let g:NERDTreeDirArrows=0
    "au VimEnter * NERDTree
" Taglist configurations
    let Tlist_Use_Right_Window = 1
    "let Tlist_Auto_Open = 1
    "au VimEnter * TlistToggle
" Supertab configurations
    " let g:SuperTabDefaultCompletionType = 'context'
    " let g:SuperTabMappingForward = '<nul>'
    " let g:SuperTabMappingBackward = '<s-nul>'
" Only allow CloseTag plugin to affect html/xml files
    autocmd FileType html,htmldjango,jinjahtml,eruby,mako let b:closetag_html_style=1
    autocmd FileType html,xhtml,xml,htmldjango,jinjahtml,eruby,mako source ~/.vim/bundle/closetag.vim/plugin/closetag.vim
" Run v8
    let d8_command = '/usr/local/bin/d8'
" Tagbar fix
    let g:tagbar_compact = 1
    let g:tagbar_foldlevel = 0
    let g:tagbar_iconchars = ['+', '-']
    ":source /home/rob/.vim/autoload/scoped_tags.vim
    ":call scoped_tags#DefaultKeyBindings()
" search first in current directory then file directory for tag file
    " set tags=tags,./tags

" Functions
    "let g:flag = 0
    "function! OpenTagbar()
    "    :TagbarOpen fjc<CR>
    "    if g:flag == 0 
    "        :call CleanTagbarOutput()
    "        let g:flag=1
    "    endif

    "function! CleanTagbarOutput()
    "    exe 1 
    "    exe 'normal i//'
    "    exe line("$")
    "    exe 'normal i//'
    "    :TagbarOpen fjc<CR>
    "    set modifiable
    "   :%s/%anonymous_function//g
    "   :%s/ : .*//g
    "   :%s///g
    "   :v/\S/d
    function! MarkWindowSwap()
        let g:markedWinNum = winnr()

    function! DoWindowSwap()
        "Mark destination
        let curNum = winnr()
        let curBuf = bufnr( "%" )
        exe g:markedWinNum . "wincmd w"
        "Switch to source and shuffle dest->source
        let markedBuf = bufnr( "%" )
        "Hide and open so that we aren't prompted and keep history
        exe 'hide buf' curBuf
        "Switch to dest and shuffle source->dest
        exe curNum . "wincmd w"
        "Hide and open so that we aren't prompted and keep history
        exe 'hide buf' markedBuf 

    " Change leader key because , is easier to reach than \
    let mapleader = ","
    let g:mapleader = ","
    noremap <C-S> :w<CR>
    vnoremap <C-S> <C-C>:w<CR>
    inoremap <C-S> <C-O>:w<CR>
    "Alt+arrow Navigation
    map <C-K> <C-W>k
    map <C-J> <C-W>j
    map <C-H> <C-W>h
    map <C-L> <C-W>l
    " TagList
    map <leader>tl <Esc>:TlistToggle<CR>
    " NERDTree
    map <leader>n <Esc>:NERDTreeToggle<CR>
    " For turning off highlights quickly
    map <leader>. <Esc>:nohlsearch<CR>
    " For switching between my favorite foldmethods
    map <leader>fs <Esc>:set foldmethod=syntax<CR>
    map <leader>fm <Esc>:set foldmethod=manual<CR>
    " For fast directory navigation
    map <leader>o <Esc>:CtrlP<CR>
    map <leader>O <Esc>:CrtlPBuffer<CR>
    " For linting
    map <leader>jsh <Esc>:JSHint<CR>
    " Leave Ex Mode, For Good 
    nnoremap Q <nop>
    " JsBeautify
    nnoremap <silent> <leader>jsb <Esc>:call g:Jsbeautify()<CR>
    " Syntastic
    map <leader>st <Esc>:SyntasticToggleMode<CR>
    map <leader>sc <Esc>:SyntasticCheck<CR>
    map <leader>e <Esc>:Errors<CR>
    " Tagbar
    nmap <leader>tt :TagbarToggle<CR>
    nmap <leader>to :TagbarOpen fjc<CR>
    " Window swapping
    noremap <silent> <leader>mw :call MarkWindowSwap()<CR>
    noremap <silent> <leader>sw :call DoWindowSwap()<CR> 
    " Autocomplete
    inoremap <C-space> <C-x><C-o>

" Don't beep because fuck that
    set visualbell
    set noerrorbells
" Disable arrow keys (double experience points and level up faster)
    "map <up> <nop>
    "map <down> <nop>
    "map <left> <nop>
    "map <right> <nop>
" Remember more history and undo levels (Buffer SDU +900 Claptrap storage upgrade!)
    set history=1000
    set undolevels=1000
" Automatically save and load folds, which I currently leave off 
    " au BufWinLeave * silent! mkview
    " au BufWinEnter * silent! loadview
" Automatically save sessions on exit with 'SQ'
    "nmap SQ <ESC>:mksession! ~/.vim/sessions/Session.vim<CR>:wqa<CR>
" Automatically restore sessions when vim is opened without arguments
    "autocmd VimEnter * if argc() == 0 | source ~/.vim/Session.vim' | endif 
    "autocmd VimEnter * if argc() == 0 | source ~/.vim/sessions/Session.vim | endif 
" Automatic source reloading everytime this .vimrc is edited
   :let g:session_autoload = 'no'
    augroup reload_vimrc " {
        autocmd BufWritePost $MYVIMRC source $MYVIMRC
    augroup END " }

function! SuperCleverTab()
    if strpart(getline('.'), 0, col('.') - 1) =~ '^\s*$'
        return "\<Tab>"
        if &omnifunc != ''
            return "\<C-X>\<C-O>"
        elseif &dictionary != ''
            return "\<C-K>"
            return "\<C-N>"

inoremap <Tab> <C-R>=SuperCleverTab()<cr>

autocmd BufWritePost *
      \ if filereadable('tags') |
      \   call system('ctags -a '.expand('%')) |
      \ endif

let g:pydiction_location = '~/.vim/bundle/PyDiction/complete-dict'
autocmd FileType python set complete+=k/home/rob/.vim/pydiction-0.5/pydiction isk+=.,( 

No comments:

Post a Comment