" #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
call plug#begin('~/.vim/bundle')

"css3-syntax
Plug 'hail2u/vim-css3-syntax'

"scss-syntax
Plug 'cakebaker/scss-syntax.vim'

"tagbar
Plug 'majutsushi/tagbar'

"vim-surround
Plug 'tpope/vim-surround'

"undotree
Plug 'mbbill/undotree'

" Ctrlp
Plug 'ctrlpvim/ctrlp.vim'
"
" Obsession
Plug 'tpope/vim-obsession'

" vim-css-color
" Plug 'ap/vim-css-color'
" vim-javascript
Plug 'pangloss/vim-javascript'

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

" ALE
" https://github.com/w0rp/ale
Plug 'w0rp/ale'

" MatchTag
" https://github.com/gregsexton/MatchTag
" DISABLED DUE TO KNOWN ISSUE - https://github.com/gregsexton/MatchTag/issues/40
" Plug 'gregsexton/MatchTag'

" 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

"Plug 'dsawardekar/wordpress.vim'
" disabled - doesn't support universal ctags?

" vim-vue
" https://github.com/posva/vim-vue
Plug 'posva/vim-vue'

" vim-commentary
" https://github.com/tpope/vim-commentary
Plug 'tpope/vim-commentary'

" vim-repeat
" https://github.com/tpope/vim-repeat
Plug 'tpope/vim-repeat'

" https://github.com/mattn/emmet-vim
Plug 'mattn/emmet-vim'

" vimwiki
" https://github.com/vimwiki/vimwiki
Plug 'vimwiki/vimwiki'

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

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

" vim-qlist
" https://github.com/romainl/vim-qlist/
" Plug 'romainl/vim-qlist'

" fugitive-vim
" https://github.com/tpope/vim-fugitive/blob/master/README.markdown
Plug 'tpope/vim-fugitive'

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

" colorV
" https://github.com/gu-fan/colorv.vim
Plug 'gu-fan/colorv.vim'

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

" gitv
" https://github.com/gregsexton/gitv
Plug 'gregsexton/gitv'

" wakarime
" https://wakatime.com/vim
Plug 'wakatime/vim-wakatime'

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

" vim-instant-markdown
" https://github.com/suan/vim-instant-markdown
" Plug 'suan/vim-instant-markdown'

" asyncomplete.vim
" https://github.com/prabirshrestha/asyncomplete.vim
" Plug 'prabirshrestha/asyncomplete.vim'
" Plug 'yami-beta/asyncomplete-omni.vim'
" Plug 'prabirshrestha/asyncomplete-ultisnips.vim'
" Plug 'prabirshrestha/asyncomplete-file.vim'
" Plug 'prabirshrestha/asyncomplete-buffer.vim'
" Plug 'prabirshrestha/asyncomplete-tags.vim'
" Plug 'prabirshrestha/asyncomplete-lsp.vim'
" Plug 'Shougo/neco-vim'
" Plug 'prabirshrestha/asyncomplete-necovim.vim'

" vim-lsp
" https://github.com/prabirshrestha/vim-lsp
Plug 'prabirshrestha/async.vim'
Plug 'prabirshrestha/vim-lsp'

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

" Activity Watch
" https://github.com/ActivityWatch/aw-watcher-vim
Plug 'ActivityWatch/aw-watcher-vim'

call plug#end()

runtime macros/matchit.vim

"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #plugin settings {{{

" 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>
"}}}

" 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 :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
"}}}

" ALE {{{
nnoremap <space>ne :lnext<cr>
nnoremap <space>pe :lprev<cr>

let g:ale_sign_error = '>>'
let g:ale_sign_warning = '>'
let g:ale_sign_column_always = 1
let g:ale_open_list = 0

" let g:ale_linters = {'scss': ['stylelint'], 'javascript': ['eslint'], 'php':['php'], 'html':['htmlhint'], 'python': [], 'vue': []}
let g:ale_linters = {'scss': ['stylelint'], 'javascript': [], 'php':['php'], 'html':['htmlhint'], 'python': [], 'vue': []}
" let g:ale_linters_explicit = 1
let g:ale_html_htmlhint_options = '-c ~/.htmlhintrc --format=unix'
let g:ale_fixers = {'javascript': ['eslint']}
"}}}

" vim-easy-align {{{

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

" switch.vim{{{

let g:switch_mapping = '<space>-'
let g:switch_custom_definitions = [
  \ ['0', '1'],
  \ ['ease-in', 'ease-out'],
  \ ['auto', 'none'],
  \ ['left', 'right'],
  \ ['top', 'bottom'],
  \ ['relative', 'absolute', 'fixed']
\ ]
"}}}

" 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
"}}}

" Use the silver searcher ag command instead of grep{{{

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

  " Use ag in CtrlP for listing files. Lightning fast and respects .gitignore
  let g:ctrlp_user_command = 'ag %s -l --nocolor -g ""'

  " ag is fast enough that CtrlP doesn't need to cache
  let g:ctrlp_use_caching = 0
endif

"vim-wiki
let g:vimwiki_list = [{'path': '~/vimwiki/', 'path_html': '~/vimwiki_html/'}]

" emmet
let g:user_emmet_leader_key=',,'
let g:user_emmet_settings = {
\  'indentation': '  ',
\  'html': {
\    'indentation': '    ',
\  }
\}
"}}}

" vue-vim{{{

" 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
"}}}

" ultisnips{{{

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='<c-j>'
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





"}}}

" Netrw{{{

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

" undotree{{{

nnoremap <space>ut :UndotreeToggle<cr>
"}}}

" 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'
\ ]
\ }
"}}}

" gutentags{{{

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

" colorV{{{

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>

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
"}}}

" vim-instant-markdown{{{
" this doesn't work - issue is open in guthub
let g:instant_markdown_open_to_the_world = 1
"}}}

"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #functions {{{

function! DoInsertEnter() "{{{
  " call SetColor('LineNr', '#262626', '', '#cccccc', '', '')
  " call SetColor('CursorLineNr', '#bcbcbc', '', '#999999', '', 'bold')
endfunction
"}}}

function! DoInsertLeave() "{{{
  " call SetColor('LineNr', '#3a3a3a', '', '#999999', '', '')
  " call SetColor('CursorLineNr', '#767676', '', '#777777', '', 'bold')
endfunction
"}}}

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
  let l:line = substitute(getline(v:foldstart), '\{\{\{', '', '')
  " don't display vim comment quotation marks
  let l:line = substitute(l:line, "\^\"\\s\\?", '', '')

  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! SyntaxItem() abort "{{{
" get name of syntax item

  return synIDattr(synID(line('.'),col('.'),1),'name') . ' -> ' . synIDattr(synIDtrans(synID(line('.'),col('.'),1)), 'name' )
endfunction
nnoremap <space>pp :echom SyntaxItem()<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! SetColorColumn() abort"{{{
  if &buftype == ''
    setlocal colorcolumn=80,120
  endif
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/','')

  echom v:fname

  return substitute(substitute(a:file,'^[\\~@]\/','./',''),'^[\\~@]','./node_modules/','')

endfunction"}}}

"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #settings {{{
scriptencoding utf-8
set ttyfast

if &term ==? 'xterm-256color'
  set termguicolors
endif

syntax on
set background=light
" set fillchars=stl:\ ,stlnc:\ ,vert:│
set fillchars=stl:\ ,stlnc:\ ,vert:┃
colorscheme monotonous2

set guioptions-=mTrLb
set guioptions+=c

set updatetime=100
set timeoutlen=500
set lazyredraw

set backupdir=~/.vimtmp
set directory=~/.vimtmp

set tags+=./.tags,.tags;/home/ray/

" persisitent undo file
set undodir=/home/ray/.vim/undodir
set undofile

set clipboard=unnamedplus

set viewoptions-=options

set ignorecase
set smartcase

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

set hidden

set number relativenumber
set hlsearch

" set previewheight=24
" set splitbelow

set completeopt=longest,menuone
set completeopt-=preview

set nospell
set spelllang=en_gb
set dictionary+=/usr/share/dict/brit-a-z.txt,/usr/share/dict/britcaps.txt
set thesaurus+=/usr/share/dict/mthesaur.txt

" function! GetGitRoot() abort
"   let gitroot=system("git rev-parse --show-toplevel")
"   if gitroot=~?"^fatal"
"     let gitstring = system("echo ${PWD/#$HOME/'~'}") . "/"
"     let gitstring .= expand("%t")
"   else
"     let gitstring = system("echo ${PWD/#$HOME/'~'}") . "/"
"     let gitstring .= expand("%t")
"     let gitstring .= " [ " . system("git branch | grep '*' | cut -d ' ' -f2")
"     let gitstring .= " ] ( " .  system('basename "' . gitroot . '"') . " )"
"   endif
"   return gitstring
" endfunction
" let &titlestring="%{GetGitRoot()}"
" set title

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
set signcolumn=yes
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()
"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #mappings {{{
let g:mapleader = ' '

" miscallaneous {{{
nnoremap  : :setlocal norelativenumber<CR>:
nnoremap <silent> <space>rc :so $MYVIMRC<CR>
nnoremap <silent> <space>nn :set 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;
" Focus on current fold, close the rest
nnoremap <silent> <space>zz zMzvzt
" replace current word with last yanked/deleted text
nnoremap <silent> <space>rr "_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>

"}}}

" git mappings {{{
nnoremap <space>gs :Gstatus<CR>
nnoremap <space>gd :Gdiff<CR>
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>gc :Gcommit<CR>
nnoremap <space>gg :!clear; git add %; git commit -m ''<Left>
nnoremap <space>gp :!clear; echo 'git push'; git push<CR>
" nnoremap <space>gp :terminal echo ':git push' & git push<CR>
" nnoremap <space>gp :Gpush<CR>
" nnoremap <space>gp :pedit | read ! echo 'git push'; git push<CR>
nnoremap <space>gl :Glog<CR>
"}}}

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

" better window/tab/buffer navigation/management {{{
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>

"}}}

"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>
"}}}

" brace/quotes completion {{{
inoremap {{       {}<left>
inoremap {<CR>    {<CR>}<C-o>O
inoremap {;       {<CR>};<C-o>O
inoremap {,       {<CR>},<C-o>O
inoremap {{{      {{}}<Left><Left>

inoremap ((       ()<Left>
inoremap (<CR>    (<CR>)<C-o>O
inoremap (;       ();<Left><Left>
inoremap (,       (),<Left><Left>

inoremap [[       []<Left>
inoremap [<CR>    [<CR>]<C-o>O

inoremap ""       ""<Left>
inoremap """      ""
inoremap ";       "";<Left><Left>
inoremap ''       ''<Left>
inoremap '''      ''
inoremap ';       '';<Left><Left>

"}}}

"}}}
"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #abbreviations {{{
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
"}}}

" fix higlight problems such as vertical-align etc {{{
augroup VimCSS3Syntax
  autocmd!
  autocmd FileType css setlocal iskeyword+=-
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
  autocmd CmdlineLeave * :set number relativenumber
  " see 'mapping nnoremap :' for setting norelative number.
augroup END
"}}}

" WinEnter, WinLeave {{{
augroup windowenteringleaving
  autocmd!
  autocmd WinEnter * call SetColorColumn()
  autocmd WinEnter * set cursorline
  autocmd WinLeave * setlocal colorcolumn=0
  autocmd WinLeave * set nocursorline
augroup END
"}}}

" InsertEnter, InsertLeave {{{
augroup insertenterleave
  au!
  au InsertEnter * call DoInsertEnter()
  au InsertLeave * call DoInsertLeave()
augroup END

" Automatically reload .vimrc if chanaged {{{
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
"}}}
" }}}

"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #statusline {{{
" set statusline=%!GetStatus(1)

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.="%{strlen(expand('%:e'))?expand('%:e'):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.="%{strlen(expand('%:e'))?expand('%:e'):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

  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
"}}}

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

"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #tabline {{{
if exists('+showtabline')

  " 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#%='
    let l:customtabline .= '%#TabLineItemSel# %{fugitive#statusline()}%   '
    let l:customtabline .= "%#TabLineItemSel# %{ObsessionStatus(fnamemodify(v:this_session,':t'),'---')} %*"

    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 " exists("+showtabline")
"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" #pymode {{{
let g:pymode = 1
let g:pymode_syntax = 1
let g:pymode_syntax_all = 1
let g:pymode_syntax_print_as_function = 1
let g:pymode_syntax_highlight_async_await = 1
let g:pymode_syntax_highlight_equal_operator = 1
let g:pymode_syntax_highlight_stars_operator = 1
let g:pymode_syntax_highlight_self = 1
let g:pymode_syntax_indent_errors = 0
let g:pymode_syntax_space_errors = 0
let g:pymode_syntax_string_formatting = 1
let g:pymode_syntax_string_format = 1
let g:pymode_syntax_string_templates = 1
let g:pymode_syntax_doctests = 1
let g:pymode_syntax_docstrings = 1
let g:pymode_syntax_builtin_objs = 1
let g:pymode_syntax_builtin_types = 1
let g:pymode_syntax_builtin_funcs = 1
let g:pymode_syntax_highlight_exceptions = 1
let g:pymode_syntax_slow_sync = 1
"}}}

""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""

" vim: foldmethod=marker