" Initialisation
" {{{

  set nocompatible

  " force old regex engine
  " if exists('+re')
  "   set re=1
  " endif

  let s:has_ag  = executable('ag')
  let s:has_ack = executable('ack')

  " set up pathogen
  runtime bundle/pathogen/autoload/pathogen.vim
  let g:pathogen_disabled = [ 'cursorcross' ]

  " neocomplete requires Vim 7.3 and Lua
  if v:version < 703 || !has('lua') || (v:version == 703 && !has('patch885'))
    call add(g:pathogen_disabled, 'neocomplete')
  endif

  " load bundles
  call pathogen#infect()

  if has('gui_running')
    " avoid loading the menu, has to be set before loading filetypes
    set guioptions+=M
  endif

" }}}

" General Settings
" {{{

  " file handling
  filetype plugin indent on
  set hidden
  set nobackup
  set autowrite
  set encoding=utf-8
  set modeline
  set modelines=2
  if v:version > 703
    set cryptmethod=blowfish
  endif

  " searching
  set ignorecase
  set smartcase
  set incsearch
  set hlsearch

  if s:has_ag
    let &grepprg = "ag --smart-case --nogroup"
  elseif s:has_ack
    let &grepprg = "ack --smart-case --noheading --with-filename --column"
  endif

  set directory=~/.vim/tmp/swap//,.,/var/tmp//,/tmp//
  set dictionary=/usr/share/dict/words

  " create temporary directory in ~/.vim/tmp
  let s:tmpdir = expand("~") . "/.vim/tmp"
  if !isdirectory(s:tmpdir)
    call mkdir(s:tmpdir, 'p')
  endif

  " enable persistent undo
  if has('persistent_undo')
    set undofile
    set undodir=~/.vim/tmp/undo

    if !isdirectory(&undodir)
      call mkdir(&undodir, 'p')
    endif
  endif

" }}}

" Display Settings
" {{{

  " interface
  syntax on

  colorscheme desertink
  set errorbells
  set visualbell t_vb= " disable bells
  set synmaxcol=1000 " disable syntax highlighting on long lines
  set lazyredraw

  " windows
  set splitbelow
  set splitright

  " disable preview window for completion
  "set completeopt-=preview

  " line numbers
  set number
  set numberwidth=6

  " scrolling
  set scrolloff=5
  set sidescrolloff=8
  set sidescroll=1
  set virtualedit+=block
  set nostartofline
  set display+=lastline

  if has('conceal')
    set conceallevel=2
  endif

  " command prompt and status line
  set showcmd
  set ruler
  set laststatus=2
  set history=1000
  set report=0
  set wildmenu
  set wildmode=list:longest,full
  set wildignore=*.pyc,*.o,*.lo,*.la,*.exe,*.swp,*.db,*.bak,*.old,*.dat,*.,tmp,*.mdb,*~,~*

  " automatically open quickfix window after commands that modify the quickfix list
  autocmd QuickFixCmdPost *grep* if len(getqflist()) | copen | endif

  " highlight trailing whitespace
  autocmd VimEnter,Colorscheme * highlight Whitespace ctermbg=235 guibg=#333333
  autocmd VimEnter,Colorscheme * match Whitespace /[^ \t]\s\+$/

  " go to last cursor position when opening files
  autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") && &ft != 'gitcommit'
                          \| exe "normal g'\"" | endif

  " window titles
  set title
  if match($TERM, '^screen-') == 0
    set t_ts=k
    set t_fs=\
  endif

  if $STY
    " show filename in screen title
    set titlestring=%t\ %m
  else
    "set titlestring=%r%m\ %t\ \[%{substitute(expand('%:p:h'),\ $HOME,\ '~',\ 'g')}\]\ -\ %{v:servername}
  endif

" }}}

" Text Formatting
" {{{

  set selection=inclusive
  set backspace=indent,eol,start
  set whichwrap+=<,>,[,],h,l
  set iskeyword+=$

  " indents
  set autoindent
  "set smartindent
  "set nocindent

  " avoid auto-indenting hash signs
  "inoremap # x<C-H>#

  " tabs
  set noexpandtab
  set smarttab
  set shiftround

  " matching
  set matchpairs=(:),{:},[:],<:>
  set showmatch
  runtime macros/matchit.vim
  let b:match_ignorecase = 1

  " diffing
  "set diffopt+=iwhite

  " folding
  set foldenable foldmethod=marker
  autocmd Syntax * set foldmethod=marker

" }}}

" Filetype Settings
" {{{

  autocmd FileType alsaconf,applescript,asm,autoit,coffee,conf,context,css,dot,eruby,html,io,javascript,lisp,markdown,ocaml,perl,php,puppet,smarty,sql,plaintex,ruby,scss,sh,svn,tex,text,textile,vb,vim,vimwiki,xhtml,xml,xslt,yaml setlocal ts=2 sts=2 sw=2 expandtab nocindent
  autocmd FileType css,scss setlocal iskeyword+=%
  autocmd FileType c,cs,cpp,php setlocal ts=3 sts=3 sw=3 expandtab
  autocmd FileType python,lua,sshconfig setlocal ts=4 sts=4 sw=4 expandtab
  autocmd FileType apache setlocal ts=4 sts=4 sw=4
  autocmd FileType mail setlocal ts=2 sts=2 sw=2 expandtab tw=80 lbr
  autocmd FileType tex,plaintex,context setlocal lbr
  autocmd FileType gitcommit,gitrebase setlocal colorcolumn=50,72
  autocmd FileType crontab setlocal nobackup nowritebackup
  autocmd FileType puppet setlocal commentstring=#%s

  autocmd BufNewFile,BufRead *.md setf markdown
  autocmd BufEnter *.run setf sh
  autocmd BufNewFile,BufRead *.inc,*.thtml setf php
  autocmd BufNewFile,BufRead *.boo setf python
  autocmd BufNewFile,BufRead Gemfile setf ruby
  autocmd BufNewFile,BufRead ~/.devilspie/* setf lisp
  autocmd BufNewFile,BufRead *.pac setf javascript

  " Ruby syntax highlighting
  let g:ruby_operators = 1
  let g:ruby_no_expensive = 1

  " Ruby auto-completion
  " let g:rubycomplete_rails = 1
  " let g:rubycomplete_buffer_loading = 1

  " force initialisation of the ruby environment to avoid stack errors
  " if has('ruby')
  "   silent! ruby nil
  " endif

  " PHP syntax highlighting
  let php_htmlInStrings = 1
  let php_baselib = 1
  let php_special_functions = 1
  let php_alt_comparisons = 1
  let php_alt_AssignByReference = 1
  let php_folding = 1

" }}}

" Commands
" {{{

  " helper to preserve search and cursor position
  command! -nargs=1 Preserve call <SID>Preserve(<args>)
  function! s:Preserve(command) " {{{
    let search=@/
    let line = line('.')
    let column = col('.')
    execute a:command
    let @/ = search
    call cursor(line, column)
  endfunction " }}}

  command! -nargs=1 PreserveSearch call <SID>PreserveSearch(<args>)
  function! s:PreserveSearch(command) " {{{
    let search=@/
    execute a:command
    let @/ = search
  endfunction " }}}

  " Replace a builtin command using cabbrev
  " http://vim.wikia.com/wiki/Replace_a_builtin_command_using_cabbrev
  command! -nargs=+ CommandAlias call <SID>CommandAlias(<f-args>)
  function! s:CommandAlias(abbreviation, expansion) " {{{
    execute 'cabbrev ' . a:abbreviation . ' <c-r>=getcmdpos() == 1 && getcmdtype() == ":" ? "' . a:expansion . '" : "' . a:abbreviation . '"<CR>'
endfunction " }}}

  CommandAlias E e
  CommandAlias E! e!
  CommandAlias Q Q
  CommandAlias Q! Q!
  CommandAlias QA qa
  CommandAlias Qa qa
  CommandAlias qA qa
  CommandAlias QA! qa!
  CommandAlias Qa! qa!
  CommandAlias qA! qa!
  CommandAlias WQ wq
  CommandAlias Wq wq
  CommandAlias wQ wq
  CommandAlias WQ! wq!
  CommandAlias Wq! wq!
  CommandAlias wQ! wq!

  " diff shortcuts for visual mode
  command! Dg diffget
  command! Dp diffput

  " shortcuts for online searches
  if has('mac')
    let g:open_command = 'open'
  elseif has('unix')
    let g:open_command = 'xdg-open'
  else
    let g:open_command = 'start'
  endif
  command! -nargs=+ Google call system(g:open_command.' "https://www.google.com/search?q=<args>"')
  command! -nargs=+ Dict call system(g:open_command.' "http://dict.leo.org/?lp=ende&search=<args>"')
  command! -nargs=+ Wikipedia call system(g:open_command.' "http://en.wikipedia.org/wiki/Special:Search?search=<args>"')

" }}}

" Keybindings
" {{{

  " disable Ex mode
  noremap Q <nop>

  " shortcut for desktop clipboard
  noremap + "+

  " jump to lines with <count><Tab>
  nmap <expr> <Tab> v:count ? "gg" : "<Tab>"

  " don't use exact searches for */#
  noremap * g*
  noremap # g#

  " repeat command for each line in selection
  xnoremap . :normal .<CR>

  " shortcuts for diff
  nnoremap du :diffupdate<CR>

  " map Ctrl+C to Escape
  inoremap <C-c> <Esc>
  autocmd CmdWinEnter * nnoremap <buffer> <C-c> :

  " indent with Tab/Shift+Tab in visual mode
  vmap <Tab> >
  vmap <S-Tab> <

  " keep cursor position when yanking in visual mode
  xnoremap <silent><expr> y "ygv" . mode()
  xnoremap <silent><expr> Y "Ygv" . mode()

  " reselect visual block after indent
  xnoremap <silent> > >gv
  xnoremap <silent> < <gv

  " select pasted text
  nmap vp `[v`]

  " toggle paste mode with F12
  set pastetoggle=<f12>

  " navigate windows with Ctrl+jkhl
  nnoremap <silent> <C-j> <C-w>j
  nnoremap <silent> <C-k> <C-w>k
  nnoremap <silent> <C-h> <C-w>h
  nnoremap <silent> <C-l> <C-w>l

  " alias Ctrl-v as Ctrl-q
  noremap <C-q> <C-v>
  inoremap <C-q> <C-v>
  cnoremap <C-q> <C-v>

  " ,q and ,e - toggle quickfix window and location list
  nnoremap <silent> ,q :call <SID>ToggleList('Quickfix List', 'c')<CR>
  nnoremap <silent> ,e :call <SID>ToggleList('Location List', 'l')<CR>
  function! GetBufferList() " {{{
    redir =>buflist
    silent! ls
    redir END
    return buflist
  endfunction " }}}
  function! s:ToggleList(bufname, pfx) " {{{
    let buflist = GetBufferList()
    for bufnum in map(filter(split(buflist, '\n'), 'v:val =~ "'.a:bufname.'"'), 'str2nr(matchstr(v:val, "\\d\\+"))')
      if bufwinnr(bufnum) != -1
        exec(a:pfx.'close')
        return
      endif
    endfor

    if a:pfx == 'c' && !len(getqflist())
      echohl Question
      echo "Quickfix list is empty."
      return
    elseif a:pfx == 'l' && !len(getloclist(0))
      echohl Question
      echo "Location list is empty."
      return
    endif

    let winnr = winnr()
    exec(a:pfx.'open')
    if winnr() != winnr
      wincmd p
    endif
  endfunction " }}}

  " resize quickfix windows to their content, or 20 lines maximum
  autocmd FileType qf call <SID>ResizeWindow(2, 20)
  function! s:ResizeWindow(min, max) " {{{
    let max = min([a:max, &lines / 3])
    execute max([a:min, min([max, line('$') + 1])]).'wincmd _'
  endfunction " }}}

  " Ctrl-c - remove highlighted search
  nnoremap <silent> <C-c> :nohlsearch<CR>

  " <count>` - switch buffers
  nnoremap <silent><expr> ` v:count ? ":<C-u>b<C-r>=v:count<CR><CR>" : "`"

  " <count>~ - delete buffers
  nnoremap <silent><expr> ~ v:count ? ":<C-u>bd<C-r>=v:count<CR><CR>" : "~"

  " ,n / ,p - next/previous buffer
  nnoremap <silent> ,n :call SwitchBuffer(1)<CR>
  nnoremap <silent> ,p :call SwitchBuffer(-1)<CR>
  function! SwitchBuffer(delta)
    let buffers  = []
    for nr in range(1, bufnr('$'))
      if buflisted(nr) && getbufvar(nr, 'current_syntax') != 'qf'
        call add(buffers, nr)
      end
    endfor

    let position = index(buffers, bufnr('%')) + a:delta

    if position < 0
      let position = len(buffers) - 1
    elseif position > len(buffers) - 1
      let position = 0
    endif

    execute 'buffer' . buffers[position]
  endfunction

  " ,c - close current window, unless it's the only one
  nnoremap <silent> ,c :call <SID>CloseWindow(0)<CR>
  nnoremap <silent> ,C :call <SID>CloseWindow(1)<CR>
  function! s:CloseWindow(resize) " {{{
    " get number of visible buffers
    let buffers = len(filter(range(1, bufnr('$')), 'buflisted(v:val)'))

    if winnr('$') > 1
      if a:resize
        let height = winheight(0) + 2 + (&showtabline ? 1 : 0) " add statusline and tabline height
        let width = winwidth(0)

        if height < &lines
          let &lines = &lines / 6 * 5
        elseif width < &columns
          let &columns = &columns / 3 * 2
        endif
      endif

      if bufname('%') == '[Command Line]'
        close
      else
        lclose
        wincmd c
      endif
    endif
  endfunction " }}}

  " ,x - close the current buffer
  nnoremap <silent> ,x :lclose<CR>:BD<CR>

  " ,X - write and close the current buffer
  nnoremap <silent> ,X :lclose<CR>:w<CR>:BD<CR>

  " ,d - open definition in new window
  nmap <silent> ,d <C-w>f

  " ,r - reload current buffer
  nnoremap <silent> ,r :edit<CR>

  " ,R - reload vimrc
  nnoremap <silent> ,R :runtime! vimrc gvimrc<CR>:let &ft=&ft<CR>:syn on<CR>:nohlsearch<CR>

  " ,s - split horizontally
  nnoremap <silent> ,s :split<CR>

  " ,S - split horizontally, increase window height
  nnoremap <silent> ,S :let &lines = &lines * 6 / 5<CR>:split<CR>

  " ,v - split vertically
  nnoremap <silent> ,v :vsplit<CR>

  " ,V - split vertically, increase window width
  nnoremap <silent> ,V :let &columns = &columns * 3 / 2<CR>:echomsg &columns<CR>:vsplit<CR>

  " ,w - write all files
  nnoremap <silent> ,w :write<CR>

  " ,W - force write current file
  nnoremap <silent> ,W :write!<CR>

  " ,$ - clear trailing whitespace
  nnoremap <silent> ,$ :call <SID>ClearTrailingWhitespace()<CR>
  function! s:ClearTrailingWhitespace() " {{{
    Preserve 'silent %s/\s\s*$//e'
    echohl Question
    echo "Trailing whitespace cleared"
    echohl none
  endfunction " }}}

  " ,F - toggle fold method
  nnoremap <silent> ,F :call ToggleFoldMethod()<CR>
  function! ToggleFoldMethod() " {{{
    if &foldcolumn == 0
      echohl Question
      echomsg "Folding..."
      echohl none
      if &filetype == 'python'
        setlocal foldmethod=indent
      else
        setlocal foldmethod=syntax
      endif
      setlocal foldcolumn=3
    else
      setlocal foldcolumn=0 foldmethod=marker
    endif
  endfunction " }}}

  " ,g and ,G - grep the current file or path
  nnoremap <silent> ,g :call <SID>GrepWrapper('%')<CR>
  nnoremap <silent> ,G :call <SID>GrepWrapper('.')<CR>
  function! s:GrepWrapper(path) " {{{
    if a:path == '%' && empty(expand('%'))
      echo "Can't grep unsaved file."
      return
    endif

    echohl Question
    let pattern = substitute(input("Grep " . (a:path == '%' ? 'buffer' : 'recursive') . ": /", expand('<cword>')), '"', '\"', '')

    if !empty(pattern)
      echohl Question
      echo "/ searching..."
      execute 'silent! grep ' . shellescape(pattern) . ' ' . a:path . ' /dev/null'
      redraw!

      let matches = len(getqflist())
      if matches > 0
        echo matches . " " . (matches == 1 ? "match" : "matches") . " found"
      else
        echohl WarningMsg
        echo "Pattern not found: " . pattern
      endif
    endif

    echohl None
  endfunction " }}}

  " ,N - toggle line numbers
  nnoremap <silent> ,N :call <SID>ToggleLineNumbers()<CR>
  function! s:ToggleLineNumbers() " {{{
    let &number=!&number
  endfunction " }}}

  " F4 / F5 - change window height
  nnoremap <silent> <F4> <C-w>+
  imap <silent> <F4> <C-o><F4>
  nnoremap <silent> <F5> <C-w>-
  imap <silent> <F5> <C-o><F5>

  " F6 / F7 - change window width
  nnoremap <silent> <F6> <C-w>>
  imap <silent> <F6> <C-o><F6>
  nnoremap <silent> <F7> <C-w><
  imap <silent> <F7> <C-o><F7>

" }}}

" Plugin Settings
" {{{

  " man {{{
  runtime ftplugin/man.vim
  " }}}

  " rails {{{
  hi! link rubyRailsARMethod Statement
  " }}}

  " jedi {{{
  let g:jedi#auto_vim_configuration = 0
  let g:jedi#completions_enabled = 0
  " }}}

  " cursorcross {{{
  let g:cursorcross_dynamic = 'clw'
  " }}}

  " javascript-libraries-syntax {{{
  let g:used_javascript_libs = 'jquery,requirejs'
  " }}}

  " project {{{
  let g:project_enable_welcome = 0
  " }}}

  " gitv {{{
  let g:Gitv_OpenHorizontal = 1
  let g:Gitv_WipeAllOnClose = 1
  let g:Gitv_DoNotMapCtrlKey = 1
  " }}}

  " signature {{{
  let g:SignatureMarkTextHL = 'SpecialKey'
  let g:SignatureEnableDefaultMappings = 2
  " }}}

  " undotree {{{
  let g:undotree_SetFocusWhenToggle = 1
  nnoremap <silent> ,u :UndotreeToggle<CR>
  " }}}

  " unimpaired {{{
  nmap <C-n> ]eV=gv
  nmap <C-p> [eV=gv
  xmap <C-n> ]egv=gv
  xmap <C-p> [egv=gv
  " }}}

  " ragtag {{{
  imap <C-]> <C-x>/
  autocmd User Ragtag silent! iunmap <buffer> <C-v>%
  autocmd User Ragtag silent! iunmap <buffer> <C-v>&
  " }}}

  " gitshade {{{
  let g:GitShade_ColorGradient = 'black_to_red'
  let g:GitShade_ColorWhat = 'bg'
  command! Gshade GitShade
  " }}}

  " indentline {{{
  let g:indentLine_char = '│'
  let g:indentLine_color_term = 235
  let g:indentLine_color_gui = '#333333'
  " }}}

  " rooter {{{
  let g:rooter_manual_only = 1
  let g:rooter_change_directory_for_non_project_files = 1
  autocmd BufEnter * :Rooter
  " }}}

  " matchparen {{{
  let g:matchparen_timeout = 50
  let g:matchparen_insert_timeout = 50
  " }}}

  " colorizer {{{
  let g:colorizer_startup = 0
  if has('gui_running')
    autocmd FileType css,scss silent ColorToggle
  endif
  " }}}

  " cycle {{{
  autocmd FileType *    call AddCycleGroup('global', [ 'return', 'break', 'continue' ])
  autocmd FileType ruby call AddCycleGroup('global', [ 'return', 'break', 'continue', 'next', 'retry' ])
  autocmd FileType sh   call AddCycleGroup('sh', [ 'if', 'elif', 'else', 'fi' ])
  autocmd FileType sh   call AddCycleGroup('sh', [ 'do', 'then' ])
  " }}}

  " sneak {{{
  let g:sneak#use_ic_scs = 1
  let g:sneak#map_netrw = 0

  nmap ,j <Plug>Sneak_s
  nmap ,k <Plug>Sneak_S
  xmap ,j <Plug>Sneak_s
  xmap ,k <Plug>Sneak_S
  " }}}

  " conque {{{
  let g:ConqueTerm_ReadUnfocused = 1

  command! Shell silent ConqueTermSplit bash --login
  command! Rlog silent! ConqueTermSplit tail -f log/development.log
  command! Irb silent ConqueTermSplit irb
  command! Ipython silent ConqueTermSplit ipython
  " }}}

  " tabular {{{
  noremap ,a :Tabular /
  noremap ,a{ :Tabular /{<CR>
  noremap ,a} :Tabular /}<CR>
  noremap ,a= :Tabular /=<CR>
  noremap ,a> :Tabular /=><CR>

  noremap ,a, :Tabular /,\zs/l0r1<CR>
  noremap ,a: :Tabular /\w:\zs/l0r1<CR>
  noremap ,a\|= :Tabular /\|\|=/<CR>
  " }}}

  " netrw {{{
  let g:netrw_silent = 1
  let g:netrw_ftpmode = 'ascii'
  let g:netrw_longlist = 1
  let g:netrw_winsize = 40
  let g:netrw_altv = 1
  let g:DrChipTopLvlMenu = 'Plugins.'
  if has('unix') && exists("$DISPLAY")
    let g:netrw_browsex_viewer = 'xdg-open'
  endif
  " }}}

  " syntastic {{{
  nnoremap <silent>,l :call <SID>ToggleLinter()<CR>
  function! s:ToggleLinter() " {{{
    if &ft == 'ruby'
      if g:syntastic_ruby_checkers == [ 'mri' ]
        let g:syntastic_ruby_checkers = [ 'mri', 'rubocop' ]
      else
        let g:syntastic_ruby_checkers = [ 'mri' ]
      endif
    endif

    SyntasticCheck
  endfunction " }}}

  let g:syntastic_check_on_open = 0
  let g:syntastic_enable_signs = 1

  let g:syntastic_javascript_checkers = [ 'jshint' ]
  let g:syntastic_php_checkers = [ 'php', 'phpmd' ]
  let g:syntastic_python_checkers = [ 'python' ]
  let g:syntastic_ruby_checkers = [ 'mri', 'rubocop' ]
  let g:syntastic_sh_checkers = [ 'sh' ]

  let g:syntastic_puppet_puppetlint_args = '--no-documentation-check'
  let g:syntastic_ruby_rubocop_args = '-D'

  if !&diff
    let g:syntastic_auto_loc_list = 1
    let g:syntastic_auto_jump = 0
  endif
  " }}}

  " neocomplete {{{
  if index(g:pathogen_disabled, 'neocomplete') == -1
    let g:neocomplete#data_directory = '~/.vim/tmp/neocomplete'
    let g:neocomplete#enable_at_startup = 1
    let g:neocomplete#enable_auto_select = 1
    "let g:neocomplete#enable_refresh_always = 1
    let g:neocomplete#enable_smart_case = 1
    let g:neocomplete#auto_completion_start_length = 2
    let g:neocomplete#force_overwrite_completefunc = 1

    " always use completions from all buffers
    if !exists('g:neocomplete#same_filetypes')
      let g:neocomplete#same_filetypes = {}
    endif
    let g:neocomplete#same_filetypes._ = '_'

    " enable omni-completion for Ruby and PHP
    call neocomplete#util#set_default_dictionary(
          \'g:neocomplete#sources#omni#input_patterns', 'ruby',
          \'[^. *\t]\.\h\w*\|\h\w*::\w*')
    call neocomplete#util#set_default_dictionary(
          \'g:neocomplete#sources#omni#input_patterns',
          \'php',
          \'[^. \t]->\h\w*\|\h\w*::\w*')

    " disable for Python
    call neocomplete#util#set_default_dictionary(
          \'g:neocomplete#sources#omni#input_patterns',
          \'python',
          \'')

    " from neocomplete.txt:
    " ---------------------

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

    " Recommended key-mappings.
    " <CR>: cancel popup and insert newline.
    inoremap <silent> <CR> <C-r>=neocomplete#smart_close_popup()<CR><CR>
    " <TAB>: completion.
    inoremap <expr> <Tab> pumvisible() ? "\<C-y>" : "\<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>"
    inoremap <expr> <C-y> neocomplete#close_popup()
    inoremap <expr> <C-e> neocomplete#cancel_popup()
  endif
  " }}}

  " airline {{{
  if index(g:pathogen_disabled, 'airline') == -1
    let g:airline_theme = 'desertink'
    let g:airline_inactive_collapse = 0
    let g:airline_detect_paste = 0
    let g:airline_detect_iminsert = 0
    let g:airline_detect_whitespace = 0

    " show file format and encoding separated by a colon
    let g:airline_section_y = "%{strlen(&fenc)>0?&fenc.':':''}%{strlen(&ff)>0?&ff:''}"
    "let g:airline_section_z = "%3p%% %{g:airline_symbols.linenr} %3l "

    let g:airline#extensions#syntastic#enabled = 0
    let g:airline#extensions#tagbar#enabled = 0

    let g:airline#extensions#tabline#enabled = 1
    let g:airline#extensions#tabline#formatter = 'unique_tail'
    let g:airline#extensions#tabline#buffer_nr_show = 1
    let g:airline#extensions#tabline#buffer_min_count = 2

    if has('gui_running') || exists('$POWERLINE_FONT')
      let g:airline_powerline_fonts = 1

      let g:airline#extensions#tabline#left_sep = ''
      let g:airline#extensions#tabline#left_alt_sep = ''
    else
      " unicode symbols
      let g:airline_left_sep = '»'
      let g:airline_left_sep = '▶'
      let g:airline_right_sep = '«'
      let g:airline_right_sep = '◀'
      let g:airline_linecolumn_prefix = '␊ '
      let g:airline_linecolumn_prefix = '␤ '
      let g:airline_linecolumn_prefix = '¶ '
      let g:airline_branch_prefix = '@ '
      let g:airline_paste_symbol = 'ρ'
      let g:airline_paste_symbol = 'Þ'
      let g:airline_paste_symbol = '∥'
      let g:airline_whitespace_symbol = 'Ξ'

      let g:airline#extensions#tabline#left_sep = g:airline_left_sep
      let g:airline#extensions#tabline#left_alt_sep = ' '
    endif

    let g:airline_mode_map = {
      \ '__' : '#',
      \ 'n'  : 'n',
      \ 'i'  : 'i',
      \ 'R'  : 'r',
      \ 'v'  : 'v',
      \ 'V'  : 'V',
      \ 'c'  : 'c',
      \ '' : 'v•b',
      \ 's'  : 's',
      \ 'S'  : 'S',
      \ '' : 's•b',
      \ }
  endif
  " }}}

  " unite {{{
  if index(g:pathogen_disabled, 'unite') == -1
    let g:unite_data_directory = '~/.vim/tmp/unite'
    let g:unite_source_rec_max_cache_files = 5000
    let g:unite_source_file_mru_long_limit = 5000
    let g:unite_source_file_mru_time_format = '(%A %e %b, %T) '
    let g:unite_source_history_yank_enable = 1

    " speed up recursive file searches
    if s:has_ag
      let g:unite_source_rec_async_command = 'ag -l .'
      let g:unite_source_grep_command = 'ag'
      let g:unite_source_grep_default_opts = '--smart-case --nogroup --nocolor --line-numbers'
      let g:unite_source_grep_recursive_opt = ''
    elseif s:has_ack
      let g:unite_source_rec_async_command = 'ack -f --nofilter'
      let g:unite_source_grep_command = 'ack'
      let g:unite_source_grep_default_opts = '--no-color --no-heading'
      let g:unite_source_grep_recursive_opt = ''
    endif

    " shortcut for bookmarks
    command! -nargs=? -complete=file Bookmark UniteBookmarkAdd <args>

    " sort file results by length
    call unite#custom#source('file', 'sorters', 'sorter_length')
    call unite#custom#source('file_rec/async', 'sorters', 'sorter_length')

    " sort buffers by number
    call unite#custom#source('buffer', 'sorters', 'sorter_reverse')

    " settings for neomru
    let g:neomru#file_mru_limit = 10
    let g:neomru#file_mru_ignore_pattern = 'COMMIT_EDITMSG'

    " map our keys in all Unite buffers
    autocmd FileType unite call <SID>unite_buffer_mappings()
    function! s:unite_buffer_mappings() " {{{
      " use ; to toggle insert mode
      nmap <silent><buffer> ; i
      inoremap <silent><buffer> ; <Esc>

      " use <C-c> to close Unite
      nmap <silent><buffer> <C-c> <Plug>(unite_exit)
      imap <silent><buffer> <C-c> <Plug>(unite_exit)

      " use <Tab> to run the default action
      nmap <silent><buffer> <Tab> <Plug>(unite_do_default_action)
      imap <silent><buffer> <Tab> <Plug>(unite_do_default_action)

      " use <C-a> to show all actions
      nmap <silent><buffer> <C-a> <Plug>(unite_choose_action)
      imap <silent><buffer> <C-a> <Plug>(unite_choose_action)

      " use <C-n> and <C-p> to move between lines in normal mode too
      noremap <silent><buffer> <C-n> j
      noremap <silent><buffer> <C-p> k

      " use ' to start quick-match mode
      nmap <silent><buffer> ' <Plug>(unite_quick_match_default_action)
      imap <silent><buffer> ' <Plug>(unite_quick_match_default_action)
    endfunction " }}}

    " wrapper for default Unite arguments
    function! UniteWrapper(action, arguments)
      return ":\<C-u>silent! Unite -no-split -toggle " . a:action . " " . a:arguments . "\<CR>"
    endfunction

    " ,f - show files in the current working directory and project tree
    nnoremap <silent><expr> ,f UniteWrapper('file' . (empty(expand('%')) ? '' : ':%:.:h') . ' file_rec/async:!' . (empty(expand('%')) ? '' : ':%:.:h') . ' file/new' . (empty(expand('%')) ? '' : ':%:.:h'), '-buffer-name=unite-files -start-insert')

    " ,<Space> - show Git changes and recently edited files
    nnoremap <expr> ,<Space> UniteWrapper((empty(system('git rev-parse --is-inside-work-tree 2>/dev/null')) ? '' : 'giti/status ') . 'file_mru:all', '-buffer-name=unite-changes -start-insert')

    " ,b - show open buffers
    nnoremap <silent><expr> ,b UniteWrapper('buffer', '-buffer-name=unite-buffers -start-insert')

    " ,y - show yank history
    nnoremap <silent><expr> ,y UniteWrapper('history/yank', '-buffer-name=unite-yank-history')

    " ,t - show file outline
    nnoremap <silent><expr> ,t UniteWrapper('outline', '-start-insert')

    " ,T - show TODO and FIXME notes
    nnoremap <silent><expr> ,T empty(system('git rev-parse --is-inside-work-tree 2>/dev/null')) ? ":echoerr 'Not a git repository: ' . getcwd()\<CR>" : UniteWrapper('grep:.:-p\ .todoignore:(TODO\|FIXME)', '')

    " run ,<Space> on startup if no arguments were given
    au VimEnter *
      \ if !argc() && (line2byte('$') == -1) && (v:progname =~? '^[gm]\=vim\%[\.exe]$') |
      \   execute "normal , " |
      \ endif
  endif
  " }}}

" }}}