" ●

if &shell =~# 'fish$'
    set shell=bash
endif

runtime vimrc-config

let g:vimrc_load_dev_plugins = exists('g:vimrc_load_dev_plugins')
  \ ? g:vimrc_load_dev_plugins : 0
let g:vimrc_enable_statusline = exists('g:vimrc_enable_statusline')
  \ ? g:vimrc_enable_statusline : 0
let g:vimrc_enable_tabline = exists('g:vimrc_enable_tabline')
  \ ? g:vimrc_enable_tabline : 0
let g:vimrc_auto_window_settings = exists('g:vimrc_auto_window_settings')
  \ ? g:vimrc_auto_window_settings : 0
"}}}

" #plugins {{{
if empty(glob('~/.vim/autoload/plug.vim'))"{{{
  silent !curl -fLo ~/.vim/autoload/plug.vim --create-dirs
    \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
  autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
endif
"}}}

if !has('nvim')
  call plug#begin('~/.vim/bundle')

  Plug '~/.config/vim/vim/bundle/vim-learnxiny'

"   #Netrw {{{

  let g:netrw_liststyle=3
  let g:netrw_list_hide='^\..*'
  let g:netrw_preview = 0

  "}}}
"   #MatchTagAlways{{{
  " https://github.com/Valloric/MatchTagAlways
  Plug 'Valloric/MatchTagAlways'
let g:mta_filetypes = {
    \ 'jinja' : 1,
    \ 'html' : 1,
    \ 'vue' : 1,
    \ 'xhtml' : 1,
    \ 'xml' : 1,
    \}
  "}}}
"   #Obsession{{{
  " fork of tpope/vim-obsession
  Plug 'studio-vx/vim-obsession'

  "}}}
"   #switch {{{
  "https://github.com/AndrewRadev/switch.vim
  Plug 'AndrewRadev/switch.vim'

  let g:switch_mapping = '<space>-'
  let g:switch_custom_definitions = [
    \ ['0', '1'],
    \ ['ease-in', 'ease-out', 'ease-in-out', 'linear'],
    \ ['auto', 'none'],
    \ ['left', 'right'],
    \ ['top', 'bottom'],
    \ ['row', 'column'],
    \ ['relative', 'absolute', 'fixed'],
    \ ['private', 'public', 'protected']
  \ ]

  "}}}
"   #undotree {{{
  Plug 'mbbill/undotree'
  nnoremap <space>ut :UndotreeToggle<cr>

  "}}}
"   #tcomment_vim{{{
  " https://github.com/tomtom/tcomment_vim
  Plug 'tomtom/tcomment_vim'

"}}}
"   #vim-easy-align {{{
  " https://github.com/junegunn/vim-easy-align
  Plug 'junegunn/vim-easy-align'

  xmap ga <Plug>(EasyAlign)
  nmap ga <Plug>(EasyAlign)

  "}}}
"   #vim-fzf {{{
" https://github.com/junegunn/fzf.vim
if executable('fzf') && v:version >= 704
  Plug 'junegunn/fzf.vim'

  nnoremap <space>fg :GFiles<CR>
  nnoremap <space>ff :Files<CR>
  nnoremap <space>fr :History<CR>
  nnoremap <space>ft :Tags<CR>
  nnoremap <space>fb :Buffers<CR>
  nnoremap <space>fh :Helptags<CR>
  nnoremap <space>fa :Ag<CR>
  nnoremap <space>fA :Ag!<CR>

  " Ag! gives fullscreen with preview
  command! -bang -nargs=* Ag
    \ call fzf#vim#ag(<q-args>,
    \                 <bang>0 ? fzf#vim#with_preview('up:60%')
    \                         : fzf#vim#with_preview('right:50%:hidden', '?'),
    \                 <bang>0)
  
  let g:fzf_colors =
  \ { 'fg':      ['fg', 'Normal'],
    \ 'bg':      ['bg', 'Normal'],
    \ 'hl':      ['fg', 'Label'],
    \ 'fg+':     ['fg', 'CursorLine', 'CursorColumn', 'Normal'],
    \ 'bg+':     ['bg', 'CursorLine', 'CursorColumn'],
    \ 'hl+':     ['fg', 'WildMenu'],
    \ 'info':    ['fg', 'Comment'],
    \ 'border':  ['fg', 'Ignore'],
    \ 'prompt':  ['fg', 'Constant'],
    \ 'pointer': ['fg', 'Special'],
    \ 'marker':  ['fg', 'Keyword'],
    \ 'spinner': ['fg', 'Label'],
    \ 'header':  ['fg', 'Comment'] }
endif

"}}}
"   #vim-markdown{{{
"   https://github.com/plasticboy/vim-markdown
Plug 'plasticboy/vim-markdown'
let g:vim_markdown_toc_autofit = 1
let g:vim_markdown_fenced_languages = ['bash=sh']
"}}}
"   #vim-qlist {{{
" Original: https://github.com/romainl/vim-qlist
Plug 'studio-vx/vim-qlist'
"}}}
"   #vim-repeat{{{
  " https://github.com/tpope/vim-repeat
  Plug 'tpope/vim-repeat'

  "}}}
"   #vim-rsi{{{
  "https://github.com/tpope/vim-rsi
  Plug 'tpope/vim-rsi'

  "}}}
"   #vim-surround{{{
  Plug 'tpope/vim-surround'

  "}}}
"   #vim-fugitive{{{
  " https://github.com/tpope/vim-fugitive/blob/master/README.markdown
  Plug 'tpope/vim-fugitive'
  nnoremap <silent> <space>gs :Gstatus<CR>
  nnoremap <silent> <space>gd :tabedit %<CR>:Gdiff<CR>
  nnoremap <silent> <space>gc :Gcommit<CR>
  nnoremap <silent> <space>gl :Glog<CR>
  nnoremap <silent> <space>gp :Gpush<CR>:copen<CR>
  nnoremap <silent> <space>gp :Gpushjob<CR>:copen<CR>

  "}}}
"   #wakatime{{{
  " https://wakatime.com/vim
  Plug 'wakatime/vim-wakatime'

  "}}}
"   #wal.vim {{{
  " https://github.com/dylanaraps/wal.vim
  Plug 'dylanaraps/wal.vim'

  "}}}
" development plugins
if g:vimrc_load_dev_plugins
"   #ALE {{{
  " https://github.com/w0rp/ale
  Plug 'w0rp/ale'
  " let g:ale_completion_enabled = 1

  let g:ale_sign_column_always = 1
  let g:ale_open_list = 0
  let g:ale_fix_on_save = 1

  " when coc enabled
  " let g:ale_linters = {'scss': ['stylelint'], 'javascript': [], 'php':['php'], 'html':['htmlhint'], 'python': [], 'vue': []}

  " when coc not enabled
  let g:ale_linters = {'scss': ['stylelint'], 'javascript': ['tsserver', 'eslint'], 'json': ['jsonlint'], 'php':['php'], 'python': ['pyls'], 'html':['htmlhint'], 'vue': ['vls', 'stylelint', 'eslint']}
  let g:ale_linter_aliases = {'vue': ['css', 'javascript', 'typescript']}
  let g:ale_fixers = {'scss': ['prettier'], 'javascript': ['eslint'], 'json': ['jq'], 'python': ['black'], 'vue': ['prettier', 'eslint']}

  let g:ale_html_htmlhint_options = '-c ~/.htmlhintrc --format=unix'

  let g:ale_python_pyls_config = {
\   'pyls': {
\     'pycodestyle': { 'enabled': v:false },
\     'configurationSources': ['flake8']
\   }
\ }

  let g:ale_sign_error = 'Α'
  let g:ale_sign_warning = 'α'

  nmap \\ <Plug>(ale_detail)
  nmap \f <Plug>(ale_fix)
  nmap \r <Plug>(ale_find_references)
  nmap \g <Plug>(ale_go_to_definition)
  nmap \d <Plug>(ale_documentation)
  nmap \h <Plug>(ale_hover)
  nmap \n <Plug>(ale_next)
  nmap \p <Plug>(ale_previous)

  "}}}
" "   #coc.nvim{{{
"   " https://github.com/neoclide/coc.nvim
"   Plug 'neoclide/coc.nvim', {'tag': '*', 'do': { -> coc#util#install()}}
"
"   let g:coc_snippet_next = '<tab>'
"   let g:coc_snippet_prev = '<s-tab>'
"
"   inoremap <silent><expr> <c-n> coc#refresh()
"   nnoremap <silent> K :call <SID>show_documentation()<CR>
"   nnoremap <silent> \d <Plug>(coc-definition)
"   nnoremap <silent> \y <Plug>(coc-type-definition)
"   nnoremap <silent> \i <Plug>(coc-implementation)
"   nnoremap <silent> \r <Plug>(coc-references)
"   nnoremap \n <Plug>(coc-rename)
"   vnoremap \f  <Plug>(coc-format-selected)
"   nnoremap \f  <Plug>(coc-format-selected)
"   command! -nargs=0 Format :call CocAction('format')
"   command! -nargs=? Fold :call     CocAction('fold', <f-args>)
"
"   function! s:show_documentation()
"     if &filetype == 'vim' || &filetype == 'help'
"       execute 'h '.expand('<cword>')
"     else
"       call CocAction('doHover')
"     endif
"   endfunction
" "  }}}
"   #colorV {{{
  " original:
  " https://github.com/gu-fan/colorv.vim
  " Plug 'gu-fan/colorv.vim'
  " custom fork:
  " https://github.com/studio-vx/colorv.vim
  Plug 'studio-vx/colorv.vim'

  let g:ColorVForceGuiColors = 1

  let g:colorv_no_global_map = 1
  let g:colorv_win_pos = 'top'
  let g:colorv_preview_area = 0

  nnoremap <space>cv :ColorV<CR>
  nnoremap <space>ce :ColorVEdit<CR>
  nnoremap <space>cc :call ToggleColorPreview()<CR>
  nnoremap <space>ci :ColorVInsert<CR>
  nnoremap <space>cp :ColorVPicker<CR>

  let w:colorv_is_previewing = 0
  function! ToggleColorPreview() abort "{{{
    if !exists('w:colorv_is_previewing')
      let w:colorv_is_previewing = 0
    endif
    if w:colorv_is_previewing == 0
      execute 'ColorVPreview'
      let w:colorv_is_previewing = 1
    else
      execute 'ColorVClear'
      let w:colorv_is_previewing = 0
    endif
  endfunction "}}}


  "}}}
"   #css3-syntax{{{
  Plug 'hail2u/vim-css3-syntax'

  "}}}
"   #delimitMate{{{
" https://github.com/Raimondi/delimitMate
  Plug 'Raimondi/delimitMate'
  let delimitMate_expand_cr = 1
  let delimitMate_expand_space = 1
  "}}}
"   #emmet-vim {{{
  " https://github.com/mattn/emmet-vim
  Plug 'mattn/emmet-vim'
  let g:user_emmet_leader_key=',,'
  let g:user_emmet_settings = {
  \  'indentation': '  ',
  \}

  "}}}
"   #gitgutter {{{
  " https://github.com/airblade/vim-gitgutter/blob/master/README.mkd
  Plug 'airblade/vim-gitgutter'

  nmap ]h <Plug>GitGutterNextHunk
  nmap [h <Plug>GitGutterPrevHunk
  omap ih <Plug>GitGutterTextObjectInnerPending
  omap ah <Plug>GitGutterTextObjectOuterPending
  xmap ih <Plug>GitGutterTextObjectInnerVisual
  xmap ah <Plug>GitGutterTextObjectOuterVisual

  "}}}
"   #gitv{{{
  " https://github.com/gregsexton/gitv
  Plug 'gregsexton/gitv'

  "}}}
"   #html5{{{
  " https://github.com/othree/html5.vim
  Plug 'othree/html5.vim'

  "}}}
"   #i3config.vim{{{
  " https://github.com/mboughaba/i3config.vim
  Plug 'mboughaba/i3config.vim'

  "}}}
"   #inline_edit.vim {{{
  " https://github.com/AndrewRadev/inline_edit.vim
  Plug 'AndrewRadev/inline_edit.vim'

  let g:inline_edit_patterns = [{
      \ 'main_filetype':     '*html',
      \ 'sub_filetype':      'scss',
      \ 'indent_adjustment': 1,
      \ 'start':             '<style\>[^>]*lang=.scss[^>]*>',
      \ 'end':               '</style>'
    \ }]

  let g:inline_edit_autowrite = 1
  let g:inline_edit_proxy_type = 'tempfile'
  let g:inline_edit_new_buffer_command ='tabedit'
  let g:inline_edit_modify_statusline = 0

  nnoremap <space>ie :InlineEdit<cr>

  "}}}
"   #livedown.vim {{{
  " https://github.com/shime/vim-livedown
  Plug 'shime/vim-livedown'

  let g:livedown_port = 4343
  let g:livedown_command = '/home/ray/.npm-global/bin/livedown'
  let g:livedown_open = 0
  let g:livedown_browser = 'qutebrowser'
  nnoremap <space>md :LivedownToggle<CR>
"}}}
"   #php.vim{{{
  " https://github.com/StanAngeloff/php.vim
  Plug 'StanAngeloff/php.vim'

  "}}}
"   #phpcomplete.vim{{{
  " https://github.com/shawncplus/phpcomplete.vim
  Plug 'shawncplus/phpcomplete.vim'
  " https://github.com/dsawardekar/wordpress.vim
  " For up to date Wordpress Files see:
  "   https://github.com/joseluis/wordpress.vim-generator

  "}}}
"   #quickscope{{{
  " https://github.com/unblevable/quick-scope
  Plug 'unblevable/quick-scope'
  let g:qs_highlight_on_keys = ['f', 'F', 't', 'T']
  "}}}
"   #rainbow{{{
  " https://github.com/luochen1990/rainbow/blob/master/README.md
  Plug 'luochen1990/rainbow'
  let g:rainbow_active = 0
  nnoremap <silent><space>rt :RainbowToggle<cr>
  "}}}
"   #scss-syntax{{{
  Plug 'cakebaker/scss-syntax.vim'

  "}}}
"   #tagbar {{{
  Plug 'majutsushi/tagbar'

  nnoremap <space>tb :TagbarOpen fj<CR>
  nnoremap <space>] :tag /[.#@]<c-r>=expand('<cword>')<cr><cr>
  let g:tagbar_autoclose = 1
  " let g:tagbar_autopreview = 1
  " let g:tagbar_previewwin_pos = ''

  let g:tagbar_type_css = {
  \  'ctagstype' : 'css',
  \  'kinds' : [
  \    'c:classes',
  \    'i:ids',
  \    't:tags',
  \    'm:medias'
  \  ]
  \}

  let g:tagbar_type_scss = {
  \  'ctagstype' : 'scss',
  \  'kinds' : [
  \    'v:variables',
  \    'c:classes',
  \    'i:ids',
  \    't:tags',
  \    'd:medias',
  \    'm:mixins',
  \    'f:functions'
  \  ]
  \}

  let g:tagbar_type_vue = {
  \ 'ctagstype' : 'vue',
  \ 'kinds' : [
  \ 'o:objects',
  \ 'f:functions',
  \ 'a:array',
  \ 's:string',
  \ 'b:boolean',
  \ 'n:number',
  \ 'v:variable'
  \ ]
  \ }

  "}}}
"   #ultisnips {{{
  " https://github.com/sirver/UltiSnips
  Plug 'SirVer/ultisnips'
  " and some snippets
  " https://github.com/honza/vim-snippets
  " Plug 'honza/vim-snippets'

  nnoremap <space>ul :call ListUltisnips()<cr>
  inoremap jkul <c-o>:call ListUltisnips()<cr>

  let g:UltiSnipsSnippetsDir='~/.vim/UltiSnips'
  " Trigger configuration. Do not use <tab> if you use https://github.com/Valloric/YouCompleteMe.
  let g:UltiSnipsExpandTrigger='<tab>'
  let g:UltiSnipsJumpForwardTrigger='<tab>'
  let g:UltiSnipsJumpBackwardTrigger='<s-tab>'
  let g:UltiSnipsEditSplit='horizontal'

  function! ListUltisnips() abort"{{{
    let l:snips = UltiSnips#SnippetsInCurrentScope(1)
    let l:keylist = sort(keys(l:snips))
    echo ' --------------------------------------------------'
    for l:key in l:keylist
      echo printf(" %-10s\t%s", l:key, l:snips[l:key])
    endfor
    echo '---------------------------------------------------'
  endfunction

  "}}}
  function! CompleteSnippets(findstart, base)"{{{
    if a:findstart
      let l:line = getline('.')
      let l:start = col('.') - 1
      while l:start > 0 && l:line[l:start - 1] =~ '\a'
        let l:start -= 1
      endwhile
      return l:start
    else
      let l:res = []
      let l:snips = UltiSnips#SnippetsInCurrentScope(1)
      let l:keylist = sort(keys(l:snips))
      for l:key in l:keylist
        if l:key =~ '^' . a:base
          let l:item = {'word': l:key, 'menu': l:snips[l:key]}
          call add(l:res, l:item)
        endif
      endfor
      return l:res
    endif
  endfunction

  "}}}

  set completefunc=CompleteSnippets

  "}}}
"   #vim-dispatch{{{
  " https://github.com/tpope/vim-dispatch
  Plug 'tpope/vim-dispatch'

  "}}}
"   #vim-fish{{{
  " https://github.com/dag/vim-fish
  Plug 'dag/vim-fish'

  "}}}
"   #vim-gutentags {{{
  " https://github.com/ludovicchabant/vim-gutentags
  Plug 'ludovicchabant/vim-gutentags'

  let g:gutentags_ctags_tagfile = '.tags'
  let g:gutentags_ctags_exclude = ['package.json', 'Session.vim', 'package-lock.json', 'TODO.txt']

  "}}}
"   #vim-javascript{{{
  Plug 'pangloss/vim-javascript'

  "}}}
"   #vim-Jinja2-Syntax{{{
" https://github.com/studio-vx/Vim-Jinja2-Syntax
" original: https://github.com/Glench/Vim-Jinja2-Syntax
  Plug 'studio-vx/Vim-Jinja2-Syntax'

  "}}}
"   #vim-json{{{
  " https://github.com/elzr/vim-json
  Plug 'elzr/vim-json'

  "}}}
"   #vim-lsp {{{
  " https://github.com/prabirshrestha/vim-lsp
  " Plug 'prabirshrestha/async.vim'
  " Plug 'prabirshrestha/vim-lsp'
  "
  " let g:lsp_signs_enabled = 1
  " let g:lsp_signs_error = {'text': '▶'}
  " let g:lsp_signs_warning = {'text': '▶'}
  " let g:lsp_signs_information = {'text': '◆'}
  " let g:lsp_signs_hint = {'text': '◆'}
  " let g:lsp_diagnostics_echo_cursor = 1
  " let g:lsp_diagnostics_echo_delay = 0
  " nnoremap \l :cclose<CR>:LspDocumentDiagnostics<cr>
  " nnoremap \h :LspHover<cr>
  " nnoremap \d :LspDefinition<cr>
  " nnoremap \r :LspReferences<cr>
  " nnoremap \n :LspRename<cr>
  " nnoremap \s :LspDocumentSymbol<cr>
  " nnoremap \w :LspWorkspaceSymbol<cr>
  " nnoremap \ff :LspDocumentFormat<cr>
  " nnoremap \fr :LspDocumentRangeFormat<cr>
  " augroup User lsp_setup
  "   autocmd!
  "   if executable('vls') "{{{
  "     autocmd User lsp_setup call lsp#register_server({
  "           \ 'name': 'vue',
  "           \ 'cmd': {server_info->['vls']},
  "           \ 'whitelist': ['vue'],
  "           \ })
  "   endif
  " "}}}
  "   if executable('pyls') "{{{
  "     autocmd User lsp_setup call lsp#register_server({
  "           \ 'name': 'pyls',
  "           \ 'cmd': {server_info->['pyls']},
  "           \ 'whitelist': ['python'],
  "           \ })
  "   endif
  " "}}}
  "   if executable('typescript-language-server') "{{{
  "     au User lsp_setup call lsp#register_server({
  "       \ 'name': 'typescript-language-server',
  "       \ 'cmd': { server_info->[&shell, &shellcmdflag, 'typescript-language-server --stdio']},
  "       \ 'root_uri': { server_info->lsp#utils#path_to_uri(lsp#utils#find_nearest_parent_directory(lsp#utils#get_buffer_path(), '.git/..'))},
  "       \ 'whitelist': ['typescript', 'javascript', 'javascript.jsx']
  "       \ })
  "   endif
  " "}}}
  " augroup END

  ""}}}
"   #vim-SyntaxRange{{{
" https://github.com/inkarkat/vim-SyntaxRange
  " Plug 'inkarkat/vim-SyntaxRange'
  " command! HiJinja call SyntaxRange#Include('{{', '}}', 'jinja', 'jinjaBraces', 'jinjaVariable')
  " command! HiJinja call SyntaxRange#IncludeEx('start=/{{-\?/hs=s+2 end=/-\?}}/he=s-1', 'jinja')
"}}}
"   #vim-vue {{{
  " https://github.com/posva/vim-vue
  Plug 'posva/vim-vue'

  " disable preprocessor checking for vue files - increases speed
  let g:vue_disable_pre_processors=0
  " set custom syntax highlighting
  augroup fixhighlighting
    autocmd!
    autocmd BufNewFile,BufRead *.vue syntax sync fromstart
  augroup END

  "   #vim-yaml
    " https://github.com/stephpy/vim-yaml
    Plug 'stephpy/vim-yaml'

  "   #python-syntax
    " https://github.com/vim-python/python-syntax
    Plug 'vim-python/python-syntax'
    let g:python_highlight_all = 1


  "}}}
"   #vimwiki {{{
  " https://github.com/vimwiki/vimwiki
  Plug 'vimwiki/vimwiki'
  let g:vimwiki_list = [{'path': '~/vimwiki/', 'path_html': '~/vimwiki_html/'}]

  "}}}
"   #wordpress.vim{{{
  " doesn't support universal ctags
"   #Plug 'dsawardekar/wordpress.vim'
  " This fork does:
  " https://github.com/DArcMattr/wordpress.vim/tree/universal-ctags
  " Using studio-vx fork
  Plug 'studio-vx/wordpress.vim', { 'branch': 'universal-ctags' }

  "}}}
"   #vim-git{{{
  " https://github.com/tpope/vim-git
  Plug 'tpope/vim-git'

  "}}}
endif
  call plug#end()
endif

runtime macros/matchit.vim

"----------------------------------------------------------------------------}}}
" #functions {{{

function! SetColor(name, fg, bg, fg_l, bg_l, style) abort"{{{

  if &background ==? 'dark'
    if a:fg ==? 'normal'
      let l:guifg = ' guifg=' . g:d_normal_fg
      let l:ctermfg = 'ctermfg=black'
      " let l:termfg = 'termfg=black'
    elseif a:fg ==? 'none'
      let l:guifg = ' guifg=' . g:d_normal_bg
      let l:ctermfg = ' ctermfg=white'
      " let l:termfg = ' termfg=white'
    elseif a:fg ==? ''
      let l:guifg = ''
      let l:ctermfg = ''
      " let l:termfg = ''
    else
      let l:guifg = ' guifg=' . a:fg
      let l:ctermfg = ' ctermfg=black'
      " let l:termfg = ' termfg=black'
    endif

    if a:bg ==? 'none'
      let l:guibg = ' guibg=NONE'
      let l:ctermbg = ' ctermbg=none'
      " let l:termbg = ' termbg=none'
    elseif a:bg ==? ''
      let l:guibg = ''
      let l:ctermbg = ''
      " let l:termbg = ''
    else
      let l:guibg = ' guibg=' . a:bg
      let l:ctermbg = ' ctermbg=black'
    endif
  else " light background
    if a:fg_l ==? 'normal'
      let l:guifg = ' guifg=' . g:l_normal_fg
      let l:ctermfg = ' ctermfg=black'
      " let l:termfg = ' termfg=black'
    elseif a:fg_l ==? 'none'
      let l:guifg = ' guifg=' . g:l_normal_bg
      let l:ctermfg = ' ctermfg=white'
      " let l:termfg = ' termfg=white'
    elseif a:fg_l ==? ''
      let l:guifg = ''
      let l:ctermfg = ''
      let l:termfg = ''
    else
      let l:guifg = ' guifg=' . a:fg_l
      let l:ctermfg = ' ctermfg=black'
      " let l:termfg = ' termfg=black'
    endif

    if a:bg_l ==? 'none'
      let l:guibg = ' guibg=NONE'
      let l:ctermbg = ' ctermbg=none'
      " let l:termbg = ' termbg=none'
    elseif a:bg_l ==? ''
      let l:guibg = ''
      let l:ctermbg = ''
      " let l:termbg = ''
    else
      let l:guibg = ' guibg=' . a:bg_l
      let l:ctermbg = ' ctermbg=white'
      " let l:termbg = ' termbg=white'
    endif
  endif

  if a:style ==? ''
    let l:style = ' term=none cterm=none gui=NONE'
  else
    let l:style = ' term=' . a:style . ' cterm=' . a:style . ' gui=' . a:style
  endif

  let l:histring = 'hi! ' . a:name . l:guifg . l:guibg . l:style
  let l:histring .= l:ctermfg . l:ctermbg
  " let l:histring .= l:termfg . l:termbg

  execute 'hi clear ' . a:name
  execute l:histring

endfunction

"}}}
function! GetStatusFrag(condition, colorname, conditionprefix, text) abort "{{{
" TODO better name
  let l:frag='%#' . a:colorname . '#'
  let l:frag.=a:conditionprefix
  let l:frag.='%{(' . a:condition . ")?'" . a:text . "':''}"
  return l:frag
endfunction

"}}}
function! MyFoldText() "{{{
  if !exists('g:foldtext_column')
    let g:foldtext_column = 80 " column to right align foldtext with
  endif

  if !exists('b:foldtext_column')
    let b:foldtext_column = g:foldtext_column " column to right align foldtext with
  endif

  if !exists('g:foldtext_maxcolumn')
    let g:foldtext_maxcolumn = 120
  endif

  let l:linecount = v:foldend - v:foldstart
  " don't display foldmarker braces
  " put one of the braces in brackets so vim doesn't treat
  " it as an actual fold marker
  let l:line = substitute(getline(v:foldstart), '"\?{\({\){', '', '')
  " don't display vim comment quotation marks
  " TODO other comment markers
  let l:line = substitute(l:line, "\^\"\\s\\?", '', '')

  " let l:postfix = l:linecount . ' ' . substitute(v:folddashes, '-', '•', 'g')
  let l:postfix = l:linecount . ' ' . substitute(v:folddashes, '-', '↓', 'g')
  while strchars(l:postfix) < 7
    let l:postfix = ' ' . l:postfix
  endwhile
  " let l:postfix = '  ↓ ' . l:postfix

  let l:len_line = len(l:line)
  let l:len_postfix = strchars(l:postfix)

  if l:len_line + l:len_postfix <= b:foldtext_column
    let l:padding = '                                                                                                                                                                        '[l:len_line + l:len_postfix + 0:b:foldtext_column - 1]
    let l:foldtext = l:line . l:padding . l:postfix
  else
    let l:sniptext = ' ⋯'
    let l:foldtext = l:line[:b:foldtext_column - 1 - strchars(l:sniptext) - l:len_postfix] . l:sniptext . l:postfix
  endif

  return l:foldtext
endfunction

"}}}
function! IndentFoldTextColumn(amount) abort "{{{
  if !exists('g:foldtext_column')
    " column to right align foldtext with
    let g:foldtext_column = 80
  endif

  if !exists('b:foldtext_column')
    " column to right align foldtext with
    let b:foldtext_column = g:foldtext_column
  endif

  if a:amount == 0
    let b:foldtext_column = g:foldtext_column
    return
  endif

  let l:newcolumn = b:foldtext_column + a:amount
  if l:newcolumn < 20
    let l:newcolumn = 20
  elseif l:newcolumn > g:foldtext_maxcolumn
    let l:newcolumn = g:foldtext_maxcolumn
  endif

  let b:foldtext_column = l:newcolumn

endfunction

nnoremap <space>z, :<C-U>call IndentFoldTextColumn(-5 * (v:count == 0 ? 1 : v:count))<CR>
nnoremap <space>z. :<C-U>call IndentFoldTextColumn(5 * (v:count == 0 ? 1 : v:count))<CR>
nnoremap <space>z= :call IndentFoldTextColumn(0)<CR>

"}}}
function! <SID>SynStack()"{{{
  if !exists('*synstack')
    return
  endif
  echo map(synstack(line('.'), col('.')), 'synIDattr(v:val,"name")') '-> ' . synIDattr(synIDtrans(synID(line('.'),col('.'),1)), 'name' )
endfunc
nmap <space>pp :call <SID>SynStack()<CR>
"}}}
function! s:Get_env() abort "{{{
" devdocs DD
" https://gist.github.com/romainl/8d3b73428b4366f75a19be2dad2f0987#file-devdocs-vim
    if has('win64') || has('win32') || has('win16')
        return 'WINDOWS'
    else
        return toupper(substitute(system('uname'), '\n', '', ''))
    endif
endfunction
" What command to use on what system
let s:cmds = {'DARWIN': 'open', 'LINUX': 'qutebrowser', 'WINDOWS': 'start'}

" Build the URL stub
let s:stub = s:cmds[<SID>Get_env()] . " 'http://devdocs.io/?q="

command! -nargs=* DD silent! call system(len(split(<q-args>, ' ')) == 0 ?
            \ s:stub . &ft . ' ' . expand('<cword>') . "'" : len(split(<q-args>, ' ')) == 1 ?
            \ s:stub . &ft . ' ' . <q-args> . "'" : s:stub . <q-args> . "'")

"}}}
if !exists('*RangerExplorer') "{{{
" use ranger as file manager
  function RangerExplorer() abort
    exec 'silent !ranger --choosefile=/tmp/vim_ranger_current_file ' . expand('%:p:h')
    if filereadable('/tmp/vim_ranger_current_file')
      exec 'edit ' . system('cat /tmp/vim_ranger_current_file')
      call system('rm /tmp/vim_ranger_current_file')
    endif
    redraw!
  endfun
map <space>ra :call RangerExplorer()<CR>
endif

"}}}
function! WinEnterColorColumn() abort"{{{
  if &buftype != ''
    setlocal colorcolumn=0
  elseif exists('b:colorcolumn_restore')
    execute 'setlocal colorcolumn=' . b:colorcolumn_restore
  endif
endfunction

"}}}
function! WinLeaveColorColumn() abort"{{{
  let b:colorcolumn_restore = &colorcolumn
  setlocal colorcolumn=0
endfunction

"}}}
function! GetLinterStatus(key) abort "{{{

  let l:statuscount = 0

  if exists('b:ale_linted')
    let l:linter = ale#statusline#Count(bufnr(''))
  else
    let l:linter = GetDiagnosticCountsFromSigns(bufnr(''))
  endif

  if has_key(l:linter, a:key)
    let l:statuscount = l:linter[a:key]
  endif
  return l:statuscount
endfunction

"}}}
function! s:RunShellCommand(cmdline) abort"{{{
" Shell command
" http://vim.wikia.com/wiki/VimTip1599

  let l:expanded_cmdline = a:cmdline
  for l:part in split(a:cmdline, ' ')
     if l:part[0] =~ '\v[%#<]'
        let l:expanded_part = fnameescape(expand(l:part))
        let l:expanded_cmdline = substitute(l:expanded_cmdline, l:part, l:expanded_part, '')
     endif
  endfor

  if g:shell_scratch_buffer_nr > -1
    let l:win_nr = bufwinnr(g:shell_scratch_buffer_nr)
    if l:win_nr < 0
      execute 'bdelete' g:shell_scratch_buffer_nr
      top new
      let g:shell_scratch_buffer_nr = bufnr('%')
    else
      execute l:win_nr. ' wincmd w'
      setlocal modifiable
      %delete _
    endif
  else
    top new
    let g:shell_scratch_buffer_nr = bufnr('%')
  endif

  setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile nowrap
  nnoremap <buffer> q :bdelete<CR>
  augroup ResetShellBufferNr
    autocmd! * <buffer>
    autocmd BufUnload <buffer> let g:shell_scratch_buffer_nr = -1
  augroup END

  " call setline(1, 'You entered:    ' . a:cmdline)
  " call setline(2, 'Expanded Form:  ' .l:expanded_cmdline)
  " call setline(3,substitute(getline(2),'.','=','g'))
  execute '$read !'. l:expanded_cmdline
  1

  setlocal nomodifiable
  if !exists('b:shell_line_count')
    let b:shell_line_count = line('$')
    if b:shell_line_count > 25
      let b:shell_line_count = 20
    endif
    execute 'resize' b:shell_line_count + 1
  endif

  wincmd p
endfunction

command! -complete=shellcmd -nargs=+ Shell call s:RunShellCommand(<q-args>)
let g:shell_scratch_buffer_nr = -1

"}}}
function! GetDiagnosticCountsFromSigns(buffer) abort "{{{
    let l:error = 0
    let l:warn = 0
    let l:info = 0
    let l:hint = 0

    redir => l:result
    silent exec 'sign place buffer=' . a:buffer
    redir end

    let l:lines = split(l:result, '\n')

    for l:line in l:lines
        if l:line =~? 'Error'
            let l:error += 1
        endif
        if l:line =~? 'Warning'
            let l:warn += 1
        endif
        if l:line =~? 'Info'
            let l:info += 1
        endif
        if l:line =~? 'Hint'
            let l:hint += 1
        endif
    endfor

    return {'error': l:error, 'warning': l:warn, 'info': l:info, 'hint': l:hint}

endfunction

"}}}
function! SaveAndExecute(ex_command) abort "{{{
" https://stackoverflow.com/a/40195855
" ex_command: command to run to execute file
    " SOURCE [reusable window]: https://github.com/fatih/vim-go/blob/master/autoload/go/ui.vim

    " save and reload current file
    silent execute 'update | edit'

    " get file path of current file
    let s:current_buffer_file_path = expand('%')

    let s:output_buffer_name = 'Output'
    let s:output_buffer_filetype = 'output'

    " reuse existing buffer window if it exists otherwise create a new one
    if !exists('c:buf_nr') || !bufexists(s:buf_nr) || bufwinnr(s:buf_nr) == -1
        silent execute 'top new ' . s:output_buffer_name
        let s:buf_nr = bufnr('%')
    elseif bufwinnr(s:buf_nr) != bufwinnr('%')
        silent execute bufwinnr(s:buf_nr) . 'wincmd w'
    endif

    silent execute 'setlocal filetype=' . s:output_buffer_filetype
    setlocal bufhidden=delete
    setlocal buftype=nofile
    setlocal noswapfile
    setlocal nobuflisted
    setlocal winfixheight
    setlocal cursorline " make it easy to distinguish
    setlocal nonumber
    setlocal norelativenumber
    setlocal showbreak=""

    nnoremap <silent> <buffer> q :bdelete!<CR>'.zz

    " clear the buffer
    setlocal noreadonly
    " setlocal modifiable
    %delete _

    " add the console output
    silent execute '.!'. a:ex_command . ' ' . shellescape(s:current_buffer_file_path, 1)

    " resize window to content length
    " Note: This is annoying because if you print a lot of lines then your code buffer is forced to a height of one line every time you run this function.
    "       However without this line the buffer starts off as a default size and if you resize the buffer then it keeps that custom size after repeated runs of this function.
    "       But if you close the output buffer then it returns to using the default size when its recreated
    "execute 'resize' . line('$')

    " make the buffer non modifiable
    setlocal readonly
    " setlocal nomodifiable
endfunction

"}}}
function! JsIncludeExpr(file)"{{{
  " substitute(substitute(v:fname,'^[\\~@]\/','./',''),'^[\\~@]','./node_modules/','')
  return substitute(substitute(a:file,'^[\\~@]\/','./',''),'^[\\~@]','./node_modules/','')

endfunction

"}}}
function! Redir(cmd) "{{{
  for win in range(1, winnr('$'))
    if getwinvar(win, 'scratch')
      execute win . 'windo close'
    endif
  endfor
  if a:cmd =~ '^!'
    let output = system(matchstr(a:cmd, '^!\zs.*'))
  else
    redir => output
    execute a:cmd
    redir END
  endif
  vnew
  let w:scratch = 1
  setlocal buftype=nofile bufhidden=wipe nobuflisted noswapfile
  call setline(1, split(output, "\n"))
endfunction

command! -nargs=1 -complete=command Redir silent call Redir(<q-args>)
" Usage:
" 	:Redir hi ............. show the full output of command ':hi' in a scratch window
" 	:Redir !ls -al ........ show the full output of command ':!ls -al' in a scratch window
"}}}
function Test() abort "{{{
  let job = job_start('ls -lah', {'callback': 'Testcallback'})
endfunction
"}}}
function Testcallback(channel, msg) abort
  echom a:channel . ': ' . a:msg
endfunction
"}}}
"----------------------------------------------------------------------------}}}
"#commands{{{
"   TrimWhitespace{{{
command! -range=% TrimWhitespace let b:wv = winsaveview() |
  \ keeppattern <line1>,<line2>s/\s\+$// |
  \ call winrestview(b:wv)
"}}}
"   Scratch, ScratchVertical{{{
command! Scratch new | setlocal buftype=nofile | setlocal bufhidden=hide | setlocal noswapfile
command! ScratchVertical vnew | setlocal buftype=nofile | setlocal bufhidden=hide | setlocal noswapfile
"}}}
"}}}
" #settings {{{
scriptencoding utf-8

syntax on
set fillchars=stl:\ ,stlnc:\ ,vert:┃

set guioptions-=mTrLb
set guioptions+=c

set updatetime=100
set timeoutlen=500
set lazyredraw

" the ;/home/ray tells vim to stop searching at /home/ray
set tags+=./.tags,.tags,./tags-py,.tags-py;/home/ray/

" persisitent undo file
set undofile

set viewoptions-=options

set ignorecase
set smartcase

set wildmenu
set wildmode=longest:full,full
set wildignore+=/node_modules/,dist/

" Use ag over grep
if executable('ag')
  set grepprg=ag\ --nogroup\ --nocolor\ --ignore\ node_modules
endif

set hidden

set number relativenumber
set hlsearch

" set completeopt=menuone,preview
set completeopt=menuone

set nospell
set spelllang=en_gb

set diffopt+=vertical

set tabstop=8
set softtabstop=2
set shiftwidth=2
set shiftround
set expandtab
set autoindent

set textwidth=180
set formatoptions=cq
set wrapmargin=0

set cursorline

set foldcolumn=2
if has('patch-7-4-2201')
  set signcolumn=yes
endif
set colorcolumn=80,120

set iskeyword+=-
set scrolloff=10
set showcmd
set incsearch

set laststatus=2
set shortmess=aoOT
set cmdheight=3

set foldmethod=manual

set showmode

set autoindent
set breakindent
set showbreak=\ \ ↳\

set mouse=a

set listchars=eol:¬,tab:>-,trail:~,extends:>,precedes:<,space:·

set foldtext=MyFoldText()
set conceallevel=2
set concealcursor=
"----------------------------------------------------------------------------}}}
" #mappings {{{
let g:mapleader = ' '
"   search and replace {{{
nnoremap <space>rr :%s/\<<C-r>=expand('<cword>')<CR>\>//g<left><left>
"}}}
"   miscallaneous {{{
nnoremap 0 ^
nnoremap <silent><space>cs :let @/=""<cr>
nnoremap  : :setlocal norelativenumber<CR>:
nnoremap <silent> <space>rc :so $MYVIMRC<CR>
nnoremap <silent> <space>nn :setlocal invrelativenumber<CR>
nnoremap <silent><expr> <space>nh (&hls && v:hlsearch ? ':nohls' : ':set hls')."\n"
nnoremap <silent> <space>sl :set invlist<CR>
nnoremap <space>aa A<left>
nnoremap <space>a2 A<left><left>
nnoremap <space>ab A<C-o>B
nnoremap <space>co :!clear;
nnoremap <space>;; A;<esc>
nnoremap <space>;j jA;<esc>
nnoremap <space>,, A,<esc>
nnoremap <space>,j jA,<esc>
" Focus on current fold, close the rest
nnoremap <silent> <space>zz zMzvzt
" replace current word with last yanked/deleted text
nnoremap <silent> <space>rw "_diwP
" replace current word with last yanked text
nnoremap <silent> <space>ry diw"0P
" quick grep of visual selection
vnoremap <space>gr y:grep! -R <C-r>" .
" open quickfix window of TODOs
nnoremap <space>td :grep! -R 'TODO' .<CR>:botright cwindow<CR>:echo len(getqflist()) 'TODOs'<CR>
" devdocs mapping
nnoremap <space>dd :DD<CR>
" write and delete current buffer
nnoremap <space>bx :w\|bd<cr>
" sync highlighting from start
nnoremap <silent><space>ss :syntax sync fromstart<CR>

"}}}
"   terminal{{{
if has('terminal')
  tnoremap <Esc> <C-\><C-n>
endif
"}}}
"   git mappings {{{
" also see vim-fugitive plugin section
nnoremap <space>gD :!clear; echo 'git diff'; git diff<CR>
nnoremap <space>ga :!clear; git add %; git status<CR>
nnoremap <space>gA :!clear; git add .; git status<CR>
nnoremap <space>gg :!clear; git add %; git commit -m ''<Left>
nnoremap <space>gP :!clear; echo 'git push'; git push<CR>

"}}}
"   netrw {{{
nnoremap <space>ex :Ex<CR>
nnoremap <space>ee :e .<CR>
nnoremap <space>eq :Rex<CR>

"}}}
"   movement/navigation{{{
nnoremap <Esc>j :resize -5<CR>
nnoremap <Esc>k :resize +5<CR>
nnoremap <Esc>l :vertical resize +5<CR>
nnoremap <Esc>h :vertical resize -5<CR>
" alias for :tjump <cword>
nnoremap <space>tj g<C-]>
" alias for :ptjump <cword>
nnoremap <space>tp <C-w>g}

"}}}
"   location list and quickfix mappings {{{
nnoremap <space>lo :botright lwindow<CR>
nnoremap <up>      :lprev<CR>zv
nnoremap <down>    :lnext<CR>zv
nnoremap <space>lc :lclose<CR>
nnoremap <space>lh :lhistory<CR>
nnoremap <space>lp :lolder<CR>
nnoremap <space>ln :lnewer<CR>

nnoremap <space>qo :botright cwindow<CR>
nnoremap <left>    :cprev<CR>zv
nnoremap <right>   :cnext<CR>zv
nnoremap <space>qc :cclose<CR>
nnoremap <space>qh :chistory<CR>
nnoremap <space>qp :colder<CR>
nnoremap <space>qn :cnewer<CR>

"}}}
"   insert mode mappings {{{
inoremap jkrg     <c-o>:reg<cr>
inoremap :w<cr>   :w<cr>
inoremap [:w<cr>   :w<cr>
inoremap {:w<cr>   :w<cr>
" Chain multiple path completions with / key. Selects the first suggestion if
" no current selection. Use ctrl-y to finish completion as normal.
inoremap <expr> / pumvisible()
    \ ? len(v:completed_item) ? '<C-Y><C-X><C-F>' : '<C-N><C-Y><C-X><C-F>'
    \ : '/'

"}}}
"   working_with_underscores{{{
nnoremap <space>w f_l
nnoremap <space>b hT_
nnoremap <space>e lt_
onoremap u t_
onoremap U f_
"}}}
"----------------------------------------------------------------------------}}}
" #abbreviations {{{

" spelling"{{{
iabbrev adn and
iabbrev waht what
iabbrev tehn then
iabbrev functin function
iabbrev positin position

"}}}
" css{{{
iabbrev pabs; position: absolute;
iabbrev pfix; position: fixed;
iabbrev prel; position: relative;
iabbrev fdr; flex-direction: row;
iabbrev fdc; flex-direction: column;
iabbrev jcc; justify-content: center;
iabbrev aic; align-items: center;
iabbrev t0; top: 0;
iabbrev b0; bottom: 0;
iabbrev l0; left: 0;
iabbrev r0; right: 0;

iabbrev ct'' content-type: '';

"}}}

"----------------------------------------------------------------------------}}}
" #autocommands {{{

"   persistent folds {{{
  augroup AutoSaveFolds
    autocmd!
  "   autocmd BufWinLeave ?* mkview
    autocmd BufWrite ?* mkview
  "   autocmd BufWinEnter ?* silent loadview
    autocmd BufRead ?* silent! loadview
  augroup END

"  }}}
"   Show trailing whitepace and spaces before a tab: {{{
  augroup whitespaceerrors
    autocmd!
    autocmd Syntax * syn match ExtraWhitespace /\s\+$\| \+\ze\t/ containedin=ALL
  augroup END

"  }}}
"   automatically reload if color scheme file written {{{
"   augroup coloreload
"     autocmd!
"   	autocmd BufWritePost customred256.vim so $MYVIMRC
"   augroup end
"  

"  }}}
"   line numbering {{{
  augroup linenumbering
    autocmd!
    autocmd InsertEnter * :set norelativenumber
    autocmd InsertLeave * :set number relativenumber
    autocmd WinEnter * :set number relativenumber
    autocmd WinLeave * set norelativenumber
    if exists('##CmdlineEnter')
      autocmd CmdlineEnter * :redraw | :set norelativenumber
      autocmd CmdlineLeave * :set number relativenumber
    endif
  augroup END

"  }}}
"   auto_window_settings {{{
if g:vimrc_auto_window_settings
    augroup auto_window_settings
      autocmd!
      autocmd WinEnter * call WinEnterColorColumn()
      autocmd WinEnter * set cursorline | set cursorcolumn
      " autocmd WinLeave * setlocal colorcolumn=0
      autocmd WinLeave * call WinLeaveColorColumn()
      autocmd WinLeave * set nocursorline | set nocursorcolumn
    augroup END

endif
"  }}}
"   Automatically reload .vimrc if changed {{{
  augroup myvimrc
    autocmd!
    autocmd BufWritePost .vimrc,_vimrc,vimrc,.gvimrc,_gvimrc,gvimrc so $MYVIMRC | if has('gui_running') | so $MYGVIMRC | endif
  augroup END

"  }}}
"   Open qfix after grepping {{{
"   augroup qfixopen
"     autocmd!
"     autocmd QuickFixCmdPost *grep* botright cwindow
"   augroup END

"  }}}
"   Open quickfix window{{{
  augroup QuickFixAutoload
      autocmd!
      autocmd QuickFixCmdPost [^l]* nested botright cwindow
      autocmd QuickFixCmdPost l* nested botright lwindow
  augroup END

"  }}}

"----------------------------------------------------------------------------}}}
" #statusline {{{
if g:vimrc_enable_statusline
  set statusline=%!GetStatus(1)

  augroup statusline "{{{
    autocmd!
    autocmd WinNew,WinEnter * setlocal statusline=%!GetStatus(1)
    autocmd WinLeave * setlocal statusline=%!GetStatus(0)
    autocmd Filetype qf setlocal statusline=%!GetStatus(1)
    autocmd Filetype help setlocal statusline=%!GetStatus(1)
  augroup END
"}}}

  function! GetStatus(isactive) abort "{{{
    " let l:linter = ale#statusline#Count(bufnr(''))
    let l:divider = '- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - >'
    let l:separator = '%#StatusLineSeparator# '
    let l:normal = '%#StatusLineNormal#'
    let l:active = '%#StatusLineActive#'
    let l:linterdash = '%#LinterDash#·'
    let l:linterdashactive = '%#LinterDashActive#·'
    let l:statusline = l:separator

    "buffer number {{{
    if a:isactive
      let l:statusline .= '%#StatusLineBufferNrActive#'
    else
      let l:statusline .= '%#StatusLineBufferNr#'
    endif
    let l:statusline .= ' %n ' . l:separator
  "}}}

    " file percentage {{{
    if a:isactive
      let l:statusline .= '%#StatusLinePercentActive#'
      let l:statusline .= ' %P %#StatusLineNoiseActive#of %#StatusLineLinecountActive#%L '
    else
      let l:statusline .= '%#StatusLinePercent#'
      let l:statusline .= ' %P %#StatusLineNoise#of %#StatusLineLinecount#%L '
    endif"}}}

    " non-empty buftype (help, quickfix, etc) {{{
    if a:isactive
      let l:statusline .= l:active . "%{&buftype == '' ? '' : ' '}%q%h%w%#StatusLineActiveNoText#"
    else
      let l:statusline .= l:normal . "%{&buftype == '' ? '' : ' '}%q%h%w%#StatusLineNormalNoText#"
    endif
    let l:statusline .= "%{&buftype == '' ? '' : '                                                                                                                                                                                                                                                '}%s"
  "}}}

    " right/left divider {{{
    let l:statusline.=l:separator
    " modified version
    let l:color = 'StatusLineDivMod' . (a:isactive?'Active':'')
    let l:statusline .= GetStatusFrag("&modified && mode() != 'i'", l:color, '%<', l:divider)

    " unmodified version
    let l:color = 'StatusLineDiv' . (a:isactive?'Active':'')
    let l:statusline .= GetStatusFrag("!&modified && mode() != 'i'", l:color, '%<', l:divider)

    " input mode version
    if a:isactive
      let l:statusline .= GetStatusFrag("mode() == 'i'", 'StatusLineDivInput', '%<', l:divider)
    endif

    let l:statusline.= l:separator . '%*%='
  "}}}

    " file info{{{
    if a:isactive == 1
      " let l:statusline.=l:active
      let l:statusline.='%#StatusLineFileInfo#'
      " let l:statusline.=" %{strlen(&ft)?&ft:'none'} "
      " let l:statusline.=l:separator . l:active
      let l:statusline.='%{strlen(&fenc)?&fenc:&enc}'
      " let l:statusline.=l:separator . l:active
      let l:statusline.=' %{&fileformat}'
      let l:statusline.="%{strlen(expand('%:e')) > 1?'  ' . expand('%:e'):''}"
      " let l:statusline.=l:separator . l:active
      " let l:statusline.=' %{&spelllang} '
      let l:statusline .= l:separator
    endif
  "}}}

    " path/filename.extension {{{
    if a:isactive
      if &readonly
        let l:statusline .= '%#StatusLineWarningActive# %r '
        let l:statusline .= '%#StatusLineFileReadOnlyActive#'
        " let l:statusline.='%#StatusLineDirActive# '
        let l:statusline.="%{expand('%:p:h:t')}/"
        " let l:statusline.='%#StatusLineFileActive#'

        let l:statusline.="%{expand('%:t:r')}"

        " let l:statusline.='%#StatusLineDotActive#'
        let l:statusline.="%{strlen(expand('%:e'))?'.':''}"
        " let l:statusline.='%#StatusLineExtActive#'
        let l:statusline.="%{expand('%:e')} "
      else
        let l:statusline.='%#StatusLineDirActive# '
        let l:statusline.="%{expand('%:p:h:t')}/"
        let l:statusline.='%#StatusLineFileActive#'

        let l:statusline.="%{expand('%:t:r')}"

        let l:statusline.='%#StatusLineDotActive#'
        let l:statusline.="%{strlen(expand('%:e'))?'.':''}"
        let l:statusline.='%#StatusLineExtActive#'
        let l:statusline.="%{expand('%:e')} "
      endif
    else
      let l:statusline .= ' %#StatusLineWarning#%r'
      let l:statusline.='%#StatusLineDir# '
      let l:statusline.="%{fnamemodify(expand('%:p:h'),':~')}/"
      let l:statusline.='%#StatusLineFile#'

      let l:statusline.="%{expand('%:t:r')}"

      let l:statusline.='%#StatusLineDot#'
      let l:statusline.="%{strlen(expand('%:e'))?'.':''}"
      let l:statusline.='%#StatusLineExt#'
      let l:statusline.="%{strlen(expand('%:e'))?expand('%:e'):expand('%:e')} "
    endif
    "}}}

    let l:statusline.='%*' . l:separator

    " linter status {{{
    if a:isactive
      " errors
      let l:statusline .= "%#LinterDashActive#%{(GetLinterStatus('error') == 0?'-':'')}"
      let l:statusline .= "%#LinterErrorActive#%{(GetLinterStatus('error') == 0?'':GetLinterStatus('error'))}"
      " style errors
      let l:statusline .= l:linterdashactive
      let l:statusline .= "%#LinterDashActive#%{(GetLinterStatus('style_error') == 0?'-':'')}"
      let l:statusline .= "%#LinterErrorStyleActive#%{(GetLinterStatus('style_error') == 0?'':GetLinterStatus('style_error'))} "

      " warnings
      let l:statusline .= "%#LinterDashActive#%{(GetLinterStatus('warning') == 0?'-':'')}"
      let l:statusline .= "%#LinterWarningActive#%{(GetLinterStatus('warning') == 0?'':GetLinterStatus('warning'))}"
      " style warnings
      let l:statusline .= l:linterdashactive
      let l:statusline .= "%#LinterDashActive#%{(GetLinterStatus('style_warning') == 0?'-':'')}"
      let l:statusline .= "%#LinterWarningStyleActive#%{(GetLinterStatus('style_warning') == 0?'':GetLinterStatus('style_warning'))} "

      " info
      let l:statusline .= "%#LinterDashActive#%{(GetLinterStatus('info') == 0?'-':'')}"
      let l:statusline .= "%#LinterInfoActive#%{(GetLinterStatus('info') == 0?'':GetLinterStatus('info'))}"
    else
      " errors
      let l:statusline .= "%#LinterDash#%{(GetLinterStatus('error') == 0?'-':'')}"
      let l:statusline .= "%#LinterError#%{(GetLinterStatus('error') == 0?'':GetLinterStatus('error'))}"
      " style errors
      let l:statusline .= l:linterdash
      let l:statusline .= "%{(GetLinterStatus('style_error') == 0?'-':'')}"
      let l:statusline .= "%#LinterErrorStyle#%{(GetLinterStatus('style_error') == 0?'':GetLinterStatus('style_error'))} "

      " warnings
      let l:statusline .= "%#LinterDash#%{(GetLinterStatus('warning') == 0?'-':'')}"
      let l:statusline .= "%#LinterWarning#%{(GetLinterStatus('warning') == 0?'':GetLinterStatus('warning'))}"
      " style warnings
      let l:statusline .= l:linterdash
      let l:statusline .= "%{(GetLinterStatus('style_warning') == 0?'-':'')}"
      let l:statusline .= "%#LinterWarningStyle#%{(GetLinterStatus('style_warning') == 0?'':GetLinterStatus('style_warning'))} "

      " info
      let l:statusline .= "%#LinterInfo#%{GetLinterStatus('info') == 0 ? '-' : GetLinterStatus('info')}"
    endif
  "}}}

    let l:statusline .= ' ' . l:separator

    if exists('gutentags#statusline')
      let l:statusline .= '%#StatusLineWarning#%{gutentags#statusline("", "", "☢")}'
    endif

    return l:statusline

  endfunction
  "}}}

"   highlight groups {{{
  hi def link StatusLineSeparator Ignore
  hi def link StatusLineNormal StatusLineNC
  hi def link StatusLineActive StatusLine
  hi def link StatusLineNormalNoText TabLineFill
  hi def link StatusLineActiveNoText TabLineFill

  hi def link StatusLineNoise StatusLineNormal
  hi def link StatusLineNoiseActive StatusLineNormal

  hi def link StatusLineBufferNr StatusLineNormal
  hi def link StatusLineBufferNrActive StatusLineActive

  hi def link StatusLinePercent StatusLineNormal
  hi def link StatusLinePercentActive StatusLineActive
  hi def link StatusLineLinecount StatusLinePercent
  hi def link StatusLineLinecountActive StatusLinePercentActive

  hi DivActive ctermbg=darkgray ctermfg=darkgray guibg=#666666 guifg=#666666
  hi DivMod ctermbg=darkred ctermfg=darkred guibg=#660000 guifg=#660000
  hi DivModActive ctermbg=red ctermfg=red guibg=#aa0000 guifg=#aa0000
  hi DivInput ctermbg=darkblue ctermfg=darkblue guibg=#000022 guifg=#000022
  hi def link StatusLineDiv TabLineFill
  hi def link StatusLineDivActive DivActive
  hi def link StatusLineDivMod DivMod
  hi def link StatusLineDivModActive DivModActive
  hi def link StatusLineDivInput DivInput

  hi def link StatusLineFileInfo StatusLineActive

  hi def link StatusLineFile StatusLineNormal
  hi def link StatusLineFileActive StatusLineActive
  hi def link StatusLineDir StatusLineFile
  hi def link StatusLineDirActive StatusLineFileActive
  hi def link StatusLineDot StatusLineDir
  hi def link StatusLineDotActive StatusLineDirActive
  hi def link StatusLineExt StatusLineDir
  hi def link StatusLineExtActive StatusLineDirActive

  hi def link StatusLineFileReadOnlyActive WarningMsg
  hi def link StatusLineWarning StatusLineNormal
  hi def link StatusLineWarningActive WarningMsg

  hi def link LinterDash Normal
  hi def link LinterDashActive Normal

  hi def link LinterError Normal
  hi def link LinterErrorActive ErrorMsg

  hi def link LinterErrorStyle Normal
  hi def link LinterErrorStyleActive SpellBad

  hi def link LinterWarning Normal
  hi def link LinterWarningActive SpellCap

  hi def link LinterWarningStyle Normal
  hi def link LinterWarningStyleActive LinterWarningActive

  hi def link LinterInfo Normal
  hi def link LinterInfoActive SpellRare
  "}}}

else
  set statusline=\ 
  set statusline+=[%n]\ \ 
  set statusline+=%p\ of\ %L
  set statusline+=%=
  set statusline+=%y\ 
  set statusline+=%r\ %m\ %F
  set statusline+=\ 
endif

"----------------------------------------------------------------------------}}}
" #tabline {{{
if exists('+showtabline') && g:vimrc_enable_tabline

  " Rename tabs to show tab number.
  " based on:
  " http://stackoverflow.com/questions/5927952/whats-implementation-of-vims-default-tabline-function

  function! MyTabLine() "{{{
    let l:customtabline = ''
    let l:currenttabnum = tabpagenr()
    let l:lasttabnumber = tabpagenr('$')
    let l:tabnumber = 1
    while l:tabnumber <= l:lasttabnumber
      let l:buflist = tabpagebuflist(l:tabnumber)
      let l:winnr = tabpagewinnr(l:tabnumber)

      if l:lasttabnumber > 1
        let l:customtabline .= '%' . l:tabnumber . 'T'
        let l:customtabline .= (l:tabnumber == l:currenttabnum ? '%1*' : '%2*')

        let l:customtabline .= (l:tabnumber == l:currenttabnum ? '%#TabLineNumSel#' : '%#TabLineNum#')
        let l:customtabline .= ' ' . l:tabnumber . ' '
        let l:customtabline .= (l:tabnumber == l:currenttabnum ? '%#TabLineItemSel#' : '%#TabLineItem#')
      endif

      let l:bufnr = l:buflist[l:winnr - 1]
      let l:file = bufname(l:bufnr)
      let l:buftype = getbufvar(l:bufnr, '&buftype')

      if l:buftype ==# 'help'
        let l:file = 'help:' . fnamemodify(l:file, ':t:r')

      elseif l:buftype ==# 'quickfix'
        let l:file = 'quickfix'

      elseif l:buftype ==# 'nofile'
        if l:file =~# '\/.'
          let l:file = substitute(l:file, '.*\/\ze.', '', '')
        endif

      else
        let l:file = fnamemodify(l:file, ':p:t')

      endif

      if l:file ==# ''
        let l:file = "''"
      endif

      let l:customtabline .= l:file . '  '

      let l:tabnumber = l:tabnumber + 1

    endwhile

    let l:customtabline .= '%T%#TabLineFill#%='

    if exists('*gutentags#statusline')
      let l:customtabline .= '%#TabLineItemSel# %{gutentags#statusline("[ ", " ☢ ]  ")}'
    endif
    let l:customtabline .= '%#TabLineItem# %{getcwd()}%   '
    if exists('*fugitive#statusline')
      let l:customtabline .= '%#TabLineItem# %{fugitive#statusline()}%   '
    endif
    if exists('*ObsessionStatus')
      let l:customtabline .= "%#TabLineItemSel# %{ObsessionStatus(fnamemodify(v:this_session,':t'),'---')} %*"
    endif

    return l:customtabline

  endfunction
"}}}

  set showtabline=2
  set tabline=%!MyTabLine()

  hi def link TabLineItem TabLine
  hi def link TabLineItemSel TabLineSel
  hi def link TabLineNum TabLine
  hi def link TabLineNumSel TabLineSel

endif
"----------------------------------------------------------------------------}}}

runtime vimrc-overrides
"}}}


" vim: set foldmethod=marker: