"  ___                _   _           _              
" | _ ) __ _ _ _ __ _| |_( )___  __ _(_)_ __  _ _ __ 
" | _ \/ _` | '_/ _` | / //(_-<  \ V / | '  \| '_/ _|
" |___/\__,_|_| \__,_|_\_\ /__/ (_)_/|_|_|_|_|_| \__|
"                                                    
"
" ** BASIC EDITOR SETTINGS **
"
" First, we are vim, not vi, so start as many others do with
set nocompatible

" Allow background buffers. Super important for various tab modes.
set hidden

" Set default spacing.
" Hard tabs should show as 8.
set ts=8
" Soft tabs should be 2 wide, and we should use spaces.
" (This is the Googler in me. I've converted to spaces over 
" the years because it really is more consistent.)
set softtabstop=2
set shiftwidth=2
set expandtab
" I like comma instead of slash, but that probably comes from playing
" Nethack and Angband
let mapleader = ","
let maplocalleader = "\\"

" Set 'smart' things in Vim
" Search case insensitive, unless it contains Uppercase letters
set smartcase
" Use all the indent features
set autoindent
set smartindent
set cindent
" Make backspace remove indents and line breaks, like a normal editor
set backspace=indent,eol,start

" Keep a bigger history
set history=1000
" Allow tab completion for files in command mode. 
set wildmenu
set wildmode=list:longest
" Show where you are in the file in the statusbar.
set ruler

" I hate split above, so make it split below. Likewise, to the right.
set splitbelow
" For autocomplete, follow requirements for nvim-compe
set completeopt=menuone,noselect
set signcolumn=yes
set shortmess+=c

set diffopt+=vertical
" Some stuff for 256-Color consoles that I've forgotten.
set t_Co=256
set t_Sf=ESC[3%dm
set t_Sb=ESC[4%dm
set t_ut=
"set t_SH=
"set t_kb=

" This is like HiglightTooLongLines below, but for modern vim. The problem is
" that it highlights the column, even if your short. Good for measuring, bad for
" my eyes.
"if v:version >= 703
  "set relativenumber
  "set colorcolumn=81
"endif
" ** PATH SETTINGS **

let g:loaded_python_provider = 0
let $RUST_SRC_PATH="/usr/src/rust/src/"

"let g:ft_ignore_pat = '.org'
"

if exists('veonim')
  let g:vscode_extensions = [
        \'ms-python.python',
        \'ms-vscode.go',
        \]
  set guifont=Droid\ Sans\ Mono\ Dotted:h20
" set linespace=10
endif

if exists('g:neovide')
  let g:neovide_floating_blur_amount_x = 2.0
  let g:neovide_floating_blur_amount_y = 2.0
  let g:neovide_transparency = 0.95
  let g:neovide_scroll_animation_length = 0.1
  let g:neovide_cursor_animation_length = 0.05
  let g:neovide_cursor_trail_size = 0.5
endif


" * Polyglot

let g:tex_flavor = 'latex'
let g:polyglot_disabled = ['latex']
let g:powerline_loaded = 1


" Required:
set runtimepath+=$HOME/.vim/bundle/repos/github.com/Shougo/dein.vim

" Required:
call plug#begin($HOME . '/.vim/bundle')

" Plugins that must be first
Plug $HOME . '/.vim/bundle/repos/github.com/Shougo/dein.vim'
Plug 'let-def/vimbufsync'
Plug 'lambdalisue/suda.vim'
Plug 'skywind3000/asyncrun.vim'
Plug 'barakmich/vim-code-dark'

" Plugins that I almost never use
"Plug 'vim-scripts/DrawIt'
"Plug 'vim-scripts/EasyGrep'
Plug 'chrisbra/NrrwRgn'
"Plug 'mattn/calendar-vim'
"Plug 'rstacruz/sparkup'
"Plug 'tristen/vim-sparkup'
"Plug 'tpope/vim-fireplace', {'for': 'clojure'}
""Plug 'terryma/vim-multiple-cursors'
"Plug 'ambv/black'
Plug 'kana/vim-textobj-user'


" Plugins I wish I used more
"Plug 'hsitz/VimOrganizer'
Plug 'jceb/vim-orgmode'
Plug 'tpope/vim-speeddating'

Plug 'tpope/vim-fugitive'
Plug 'tpope/vim-unimpaired'
Plug 'b4winckler/vim-angry'
Plug 'tpope/vim-surround'
Plug 'junegunn/vim-easy-align'
Plug 'bps/vim-textobj-python'

" Plugins I NEED
Plug 'scrooloose/nerdcommenter'
Plug 'sjbach/lusty'
"Plug 'w0rp/ale'
"Plug 'airblade/vim-gitgutter'
Plug 'mhinz/vim-signify'
"Plug 'vim-airline/vim-airline'
"Plug 'vim-airline/vim-airline-themes'
Plug 'nvim-lualine/lualine.nvim'
Plug 'linrongbin16/lsp-progress.nvim'
"Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
"Plug 'junegunn/fzf.vim'
Plug 'airblade/vim-rooter'
"Plug 'bling/vim-bufferline'
Plug 'majutsushi/tagbar'
"Plug 'SirVer/ultisnips'
Plug 'dcampos/nvim-snippy'
Plug 'rafamadriz/friendly-snippets'

Plug 'honza/vim-snippets'
"Plug 'fatih/vim-go'
Plug 'tpope/vim-abolish'
"Plug 'sheerun/vim-polyglot'
Plug 'Shougo/denite.nvim'
"Plug 'plytophogy/vim-virtualenv'
"Plug 'ervandew/supertab'
"Plug 'ncm2/ncm2'
"Plug 'roxma/nvim-yarp'


" Plugins I NEEDED
"Plug 'scrooloose/nerdtree'
"Plug 'scrooloose/syntastic'
"Plug 'Valloric/YouCompleteMe'
"Plug 'vim-scripts/fish-syntax'
"Plug 'kchmck/vim-coffee-script'
"Plug 'rodjek/vim-puppet'
"Plug 'JuliaLang/julia-vim'
"Plug 'rust-lang/rust.vim'
"Plug 'hashivim/vim-terraform'
"Plug 'HerringtonDarkholme/yats.vim'
"Plug 'kien/ctrlp.vim'
"Plug 'farseer90718/vim-taskwarrior'
"Plug 't-yuki/vim-go-coverlay'

" Plugins for syntax
Plug 'lunaru/vim-less'
Plug 'hylang/vim-hy', {'for': 'hy'}
Plug 'jneen/ragel.vim'
Plug 'NoahTheDuke/vim-just'
"Plug 'mhartington/nvim-typescript'
"Plug 'leafgarland/typescript-vim'
Plug 'leafOfTree/vim-svelte-plugin'
"Plug 'posva/vim-vue'
Plug 'Shougo/context_filetype.vim'
"Plug 'idris-hackers/idris-vim', {'for': 'idris'}
Plug 'fedorenchik/AnsiEsc'
Plug 'hwayne/tla.vim'
Plug 'zchee/vim-goasm'
Plug 'cappyzawa/starlark.vim'

" Plugins that autocomplete
"Plug 'Shougo/deoplete.nvim'
"Plug 'zchee/deoplete-clang'
"Plug 'zchee/deoplete-go', {'build': {'unix': 'make'}}
"Plug 'zchee/deoplete-jedi'
"Plug 'davidhalter/jedi-vim'
"Plug 'eagletmt/neco-ghc', {'for': 'haskell'}
"Plug 'eagletmt/ghcmod-vim', {'for': 'haskell'}
"Plug 'racer-rust/vim-racer', {'for': 'rust'}
"Plug 'autozimu/LanguageClient-neovim', {
    "\ 'branch': 'next',
    "\ 'do': 'bash install.sh',
    "\ }
"Plug 'ensime/ensime-vim', { 'do': ':UpdateRemotePlugins' }
"Plug 'neoclide/coc.nvim', {'branch': 'release'}
"Plug 'romainl/vim-qf'
Plug 'neovim/nvim-lspconfig'
Plug 'nvim-lua/lsp_extensions.nvim'
Plug 'hrsh7th/nvim-compe'
"Plug 'nvim-lua/completion-nvim'
Plug 'onsails/lspkind-nvim'

Plug 'nvim-lua/popup.nvim'
Plug 'nvim-lua/plenary.nvim'
Plug 'nvim-telescope/telescope.nvim'
Plug 'sindrets/diffview.nvim'

Plug 'kyazdani42/nvim-web-devicons' " for file icons
"Plug 'kyazdani42/nvim-tree.lua'

Plug 'ray-x/lsp_signature.nvim'
Plug 'ray-x/go.nvim'

Plug 'RishabhRD/popfix'
Plug 'RishabhRD/nvim-lsputils'
Plug 'stevanmilic/nvim-lspimport'
Plug 'folke/trouble.nvim'
Plug 'creativenull/efmls-configs-nvim', { 'tag': 'v1.*' }

" Plugins that do specific things
"Plug 'Shougo/vimproc.vim'
"Plug 'Shougo/vimfiler.vim'

Plug 'tamago324/lir.nvim'

Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}
Plug 'nvim-treesitter/playground'
Plug 'nvim-treesitter/nvim-treesitter-textobjects'


"Plug 'ggandor/lightspeed.nvim'
"Plug 'justinmk/vim-sneak'
Plug 'ggandor/leap.nvim'
Plug 'ggandor/flit.nvim'
Plug 'simrat39/rust-tools.nvim'

Plug 'Shougo/unite.vim'
" TODO: Look into Coqtail, same author
Plug 'whonore/coquille', {'branch': 'pathogen-bundle', 'for': 'coq'}  
"Plug 'dhruvasagar/vim-zoom'
Plug 'gabrielelana/vim-markdown'
Plug 'lervag/vimtex'
Plug 'Shougo/echodoc.vim'
"Plug 'python-rope/ropevim'
Plug 'windwp/nvim-autopairs'
Plug 'danymat/neogen'

" Unclear
"Plug 'ncm2/float-preview.nvim'
Plug 'lambdalisue/gina.vim'
Plug 'edolphin-ydf/goimpl.nvim'

call plug#end()

filetype plugin indent on
syntax enable

" enable ncm2 for all buffers
"autocmd BufEnter * call ncm2#enable_for_buffer()


" **** Configure LSP

luafile $HOME/.vim/nvim.lua


" Code navigation shortcuts
nnoremap <silent> gd <cmd>lua vim.lsp.buf.definition()<CR>
nnoremap <silent> gi    <cmd>lua vim.lsp.buf.implementation()<CR>
nnoremap <silent> gy   <cmd>lua vim.lsp.buf.type_definition()<CR>
nnoremap <silent> K     <cmd>lua vim.lsp.buf.hover()<CR>
nnoremap <silent> gs <cmd>lua vim.lsp.buf.signature_help()<CR>
nnoremap <silent> gR <cmd>lua vim.lsp.buf.rename()<CR>
"nnoremap <silent> gr    <cmd>lua vim.lsp.buf.references()<CR>
nnoremap <silent> gr   <cmd>lua require('telescope.builtin').lsp_references({initial_mode = "normal"})<cr>
nnoremap <silent> g0    <cmd>lua vim.lsp.buf.document_symbol()<CR>
nnoremap <silent> gW    <cmd>lua vim.lsp.buf.workspace_symbol()<CR>
"nnoremap <silent> gd    <cmd>lua vim.lsp.buf.declaration()<CR>
nnoremap <silent> ga    <cmd>lua vim.lsp.buf.code_action()<CR>
"nnoremap <silent> ga   <cmd>lua require('telescope.builtin').lsp_code_actions({initial_mode = "normal"})<cr>
vnoremap <silent> ga <cmd>lua vim.lsp.buf.code_action()<CR>
"vnoremap <silent> ga   :<C-U>lua require('telescope.builtin').lsp_range_code_actions({initial_mode = "normal"})<cr>
"nnoremap <silent> ge    <cmd>lua vim.lsp.diagnostic.show_line_diagnostics({show_header = false, focusable = false})<CR>
"nnoremap <silent> ge    <cmd>lua vim.diagnostic.open_float({focusable = false})<CR>

nnoremap <silent> <leader>xx <cmd>TroubleToggle<cr>
nnoremap <silent> <leader>xq <cmd>lua vim.diagnostic.setqflist()<CR>
"nnoremap <silent> <leader>nc    <cmd>lua neogen_dwim()<CR>
nnoremap <silent> <leader>nc    <cmd>lua require('neogen').generate({ type = 'any' })<CR>
nnoremap <silent> gm <cmd>lua require('lspimport').import()<CR>


" Set updatetime for CursorHold
" 300ms of no cursor movement to trigger CursorHold
set updatetime=500
" Show diagnostic popup on cursor hold
autocmd CursorHold * lua vim.diagnostic.open_float({focusable = false})

" Autoformat on save
autocmd BufWritePre *.lua lua vim.lsp.buf.format({ async = false })
autocmd BufWritePre *.py lua vim.lsp.buf.format({ async = false })
autocmd BufWritePre *.rs lua vim.lsp.buf.format({ async = false })
autocmd BufWritePre *.go lua vim.lsp.buf.format({ async = false })
autocmd BufWritePre *.go silent! lua org_imports(3000)
autocmd BufWritePre *.ts lua vim.lsp.buf.format({ async = false })

" Goto previous/next diagnostic warning/error
nnoremap <silent> g[ <cmd>lua vim.diagnostic.goto_prev()<CR>
nnoremap <silent> g] <cmd>lua vim.diagnostic.goto_next()<CR>

let g:completion_matching_strategy_list = ['exact', 'substring', 'fuzzy']
let g:completion_matching_smart_case = 1
let g:completion_sorting = 'length'

inoremap <silent><expr> <CR>      compe#confirm('<CR>')
inoremap <silent><expr> <C-e>     compe#close('<C-e>')
inoremap <silent><expr> <C-f>     compe#scroll({ 'delta': +4 })
inoremap <silent><expr> <C-d>     compe#scroll({ 'delta': -4 })


" **** End LSP



"let g:qf_auto_open_quickfix = 1
"let g:qf_auto_open_loclist = 0

"nmap <PageUp> <Plug>(qf_qf_previous)
"nmap <PageDown>  <Plug>(qf_qf_next)
"nmap ge <Plug>(qf_qf_toggle)

"" Sources
"source ~/.vim/supertab.vim
"source ~/.vim/charm.vim
"source ~/.vim/plugin/AppleT.vim
runtime macros/matchit.vim

" Completion features (TODO: Add to filetype.vim)
autocmd FileType ruby,eruby set omnifunc=rubycomplete#Complete
autocmd FileType python set tags+=$HOME/.vim/tags/python.ctags
"autocmd FileType python set omnifunc=pythoncomplete#Complete
"autocmd FileType python call SuperTabSetCompletionType("<C-X><C-O>")

" Set filetype for VimOrganizer
"au! BufRead,BufWrite,BufWritePost,BufNewFile *.org 
"au BufEnter *.org            call org#SetOrgFileType()

command! OrgCapture :call org#CaptureBuffer()
command! OrgCaptureFile :call org#OpenCaptureFile()

" Cull trailing whitespace for all files.
autocmd BufWritePre * :call AutoTrimWhitespace()

" Set syntax and highlighting
syntax on
" baraknew is my own colorscheme. I used to use slate or dante.
"colorscheme baraknew
"let g:codedark_conservative = 1
let g:codedark_null_background=1
let g:codedark_italics=1
colorscheme codedark
"colorscheme slate
"colorscheme dante


" Turn on the cursorline (highlight on line under cursor) but only for the
" window and buffer you're currently in. A handy trick, I'm trying out as of
" 2013-04-12 but the jury is still out.
"
" 2022-07-24 -- It's essential and I got a laugh reading this 9 years later.
autocmd BufEnter * setlocal cursorline
autocmd WinEnter * setlocal cursorline
autocmd WinLeave * setlocal nocursorline
setlocal cursorline


" ** PLUGIN CONFIGURATION **

" * SuperTab
let g:SuperTabDefaultCompletionType = "<c-n>"

" Change the source rank
"call deoplete#custom#option('sources', {
            "\ 'python': ['LanguageClient'],
            "\ 'cpp': ['LanguageClient'],
            "\})
"call deoplete#custom#source('buffer', 'rank', 1)
"let g:deoplete#sources#clang#libclang_path = '/usr/lib/llvm-6.0/lib/libclang.so'
"let g:deoplete#sources#clang#clang_header = '/usr/lib/llvm-6.0/lib/clang'
let g:deoplete#enable_at_startup = 1
"let g:deoplete#sources = {}
"let g:deoplete#sources.scala = ['buffer', 'tags', 'omni']
"let g:deoplete#omni#input_patterns = {}
"let g:deoplete#omni#input_patterns.scala = ['[^. *\t0-9]\.\w*',': [A-Z]\w', '[\[\t\( ][A-Za-z]\w*']
" * Vim general/Unknown
let python_highlight_all = 1
let g:Tb_MaxSize=0
let g:Tb_MapCTabSwitchBufs = 1
let g:UseGooglePythonSettings = 0

" * sneak.vim
"let g:sneak#label = 1
"map f <Plug>Sneak_f
"map F <Plug>Sneak_F
"map t <Plug>Sneak_t
"map T <Plug>Sneak_T

" * Jedi
let g:jedi#goto_command = "gd"
"let g:jedi#completions_enabled = 0

" * Eclim
let g:EclimCompletionMethod = 'omnifunc'

" * Syntastic
let g:syntastic_python_checkers = ['python', 'pylint']
let g:syntastic_go_checkers=['go', 'govet', 'govetshadow', 'golintc']
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_auto_loc_list = 2
let g:syntastic_loc_list_height = 10 
" E111 = Spaces should be multiples of 4. I use 2.
"
" * Polyglot
let g:polyglot_disabled = ['latex']

" * ALE
let g:airline#extensions#ale#enabled = 1
let g:ale_set_highlights = 0

" * LanguageServer 
let g:LanguageClient_serverCommands = {
    \ 'python': ['pyls'],
    \ 'cpp': ['ccls'],
    \ 'go': ['gopls'],
    \ }
let g:LanguageClient_diagnosticsDisplay = {
  \1: {'name': 'Error', 'texthl': 'ALEError', 'signText': 'E>', 'signTexthl': 'ALEErrorSign',},
  \2: {"name": "Warning", "texthl": "ALEWarning", "signText": "W>", "signTexthl": "ALEWarningSign",},
  \3: {"name": "Information", "texthl": "ALEInfo", "signText": "i-", "signTexthl": "ALEInfoSign",},
  \4: {"name": "Hint", "texthl": "ALEInfo", "signText": "--", "signTexthl": "ALEInfoSign",},
\}
"nmap <silent> gd <Plug>(lcn-definition)
"nmap <silent> K <Plug>(lcn-hover)
"nmap <silent> <Leader>m <Plug>(lcn-menu)

" * Configure browser for haskell_doc.vim
let g:haddock_browser = "open"
let g:haddock_browser_callformat = "%s %s"

" * Lusty plugins
let g:LustyExplorerSuppressRubyWarning = 1
let g:LustyJugglerSuppressRubyWarning = 1
let g:LustyJugglerShowKeys = 'a'

" * Buftabs
let g:buftabs_only_basename = 1
"let g:buftabs_in_statusline=1

" Bufferline
let g:bufferline_echo = 0
let g:bufferline_modified = '+'
let g:bufferline_show_bufnr = 1
let g:bufferline_rotate = 1

" * NERDTree
"let g:NERDChristmasTree = 1
"let g:NERDChristmasTree = 1
let g:NERDTreeQuitOnOpen = 1
let g:NERDTreeWinPos = "right"
let g:NERDTreeWinSize = 40
let g:NERDTreeDirArrows=0

let g:NERDTreeMarkBookmarks = 0
let g:NERDTreeMinimalUI = 1

" * Signify
let g:signify_realtime = 1
let g:signify_vcs_list = ['git']
let g:signify_sign_change = '~'
let g:signify_sign_changedelete = g:signify_sign_change
let g:signify_sign_show_count = 0
let g:signify_priority = 5

" * Nvim Tree
let g:nvim_tree_add_trailing = 1
let g:nvim_tree_side = 'right'
let g:nvim_tree_width = 40
let g:nvim_tree_quit_on_open = 1
let g:nvim_tree_disable_window_picker = 1
let g:nvim_tree_root_folder_modifier = ':p:.'

" * Tagbar plugin settings
let g:tagbar_width = 40
let g:tagbar_autofocus = 1
let g:tagbar_autoclose = 1
let g:tagbar_compact = 1

" * Taglist plugin settings (deprecated)
let Tlist_GainFocus_On_ToggleOpen = 1
let Tlist_Use_Right_Window = 1
let Tlist_Inc_Winwidth = 0
let Tlist_File_Fold_Auto_Close = 1
let Tlist_WinWidth = 40
let Tlist_Show_One_File = 0

" * ConqueTerm
let g:ConqueTerm_CWInsert = 1
let g:ConqueTerm_InsertOnEnter = 0
let g:ConqueTerm_SendVisKey = '<Leader>ss'

" * YouCompleteMe
let g:ycm_global_ycm_extra_conf = '~/.ycm_extra_conf.py'
let g:ycm_confirm_extra_conf = 0
let g:ycm_key_invoke_completion = "<Leader><Tab>"
let g:ycm_use_ultisnips_completer = 1
"let g:ycm_add_preview_to_completeopt = 1
"let g:ycm_autoclose_preview_window_after_completion = 1

" * UltiSnips
let g:UltiSnipsSnippetDirectories=["UltiSnips", "usnips"]
let g:UltiSnipsExpandTrigger="<Leader>,"
"let g:UltiSnipsJumpForwardTrigger="<Leader>,"
let g:UltiSnipsJumpBackwardTrigger="<Leader><s-,>"

" * MinBufExplorer
"let g:miniBufExplMapWindowNavVim = 1
"let g:miniBufExplMapWindowNavArrows = 1
"let g:miniBufExplMapCTabSwitchBufs = 1
"let g:miniBufExplModSelTarget = 1 
"let g:miniBufExplForceSyntaxEnable = 1

" Markdown
"let g:markdown_enable_folding = 1
let g:markdown_enable_mappings = 1
let g:markdown_enable_spell_checking = 0
let g:markdown_enable_input_abbreviations = 0

" * CommandT
let g:CommandTMaxFiles = 1000
let g:CommandTMaxDepth = 7

" * vim-rooter
let g:rooter_cd_cmd="lcd"
let g:rooter_manual_only = 1
set autochdir

" " * FZF
let g:rg_command = '
  \ rg --column --line-number --no-heading --fixed-strings --ignore-case --no-ignore --hidden --follow --color "always"
  \ -g "!{.git,node_modules,vendor}/*" '

"\ -g "*.{js,json,php,md,styl,jade,html,config,py,cpp,c,go,hs,rb,conf}"

"command! -bang -nargs=* RipGrep call fzf#vim#grep(g:rg_command .shellescape(<q-args>), 1, <bang>0)
"command! -bang -nargs=* RipGrepCword call fzf#vim#grep(g:rg_command . "-q " . expand('<cword>'), 1, <bang>0)

"command! -bang -nargs=* RgRoot call fzf#vim#grep("rg --column --line-number --no-heading --color=always --smart-case " . shellescape(<q-args>), 1, {"dir": FindRootDirectory()})

"let g:fzf_buffers_jump = 1
" Empty value to disable preview window altogether
"let g:fzf_preview_window = ''

" * VimOrganizer
" default Tag list.  Will be changed in near future so
" that these are defined by config lines in each .org
" file itself, but now these are where you can change things:
" let g:org_todo_setup='TODO | DONE'
" while g:org_tag_setup is itself a string
"let g:org_tag_setup='{@home(h) @work(w) @tennisclub(t)} \n {easy(e) hard(d)} \n {computer(c) phone(p)}'
"au! BufRead,BufWrite,BufWritePost,BufNewFile *.org 
"au BufEnter *.org            call org#SetOrgFileType()

" * Airline
set noshowmode
let g:airline_section_c = '%{StatuslineGit()}'
let g:airline#extensions#branch#enabled = 1
let g:airline#extensions#syntastic#enabled = 1
let g:airline#extensions#tagbar#enabled = 1
let g:airline_theme="murmur"
let g:airline_left_sep = ''
let g:airline_right_sep = ''
let g:airline#extensions#syntastic#enabled = 1
let g:airline#extensions#hunks#non_zero_only = 1
let g:airline#extensions#whitespace#enabled = 0
let g:airline_mode_map = {
      \ '__' : '-',
      \ 'n'  : 'N',
      \ 'i'  : 'I',
      \ 'R'  : 'R',
      \ 'c'  : 'C',
      \ 'v'  : 'V',
      \ 'V'  : 'V',
      \ '' : 'V',
      \ 's'  : 'S',
      \ 'S'  : 'S',
      \ '' : 'S',
      \ }


" * CtrlP
let g:ctrlp_map = ',t'
let g:ctrlp_cmd = 'CtrlP'
let g:ctrlp_working_path_mode = 'ra'
let g:ctrlp_match_window = 'bottom,order:ttb,min:1,max:15'

" * Echodoc
let g:echodoc_enable_at_startup = 1
"let g:echodoc#type = 'floating'
"let g:echodoc#type = 'floating'
"highlight link EchoDocFloat Pmenu

" * Vim-Go
let g:go_fmt_command = "goimports"
"let g:go_auto_type_info = 1
let g:go_updatetime = 300
let g:go_bin_path = $HOME . "/.go/bin"
"let g:go_def_mode = 'gopls'
"let g:go_info_mode = 'gopls'

let g:go_highlight_functions = 1
let g:go_highlight_function_calls = 1
"let g:go_highlight_variable_declarations = 1
"let g:go_highlight_variable_assignments = 1

" ** STATUSLINE **
set laststatus=2
set statusline=%t       "tail of the filename
"set statusline+=[%{&ff}] "file format
"set statusline+=%h      "help file flag
set statusline+=\ %w      "help file flag
set statusline+=%r      "read only flag
set statusline+=%y      "filetype
set statusline+=\ %m      "modified flag
set statusline+=%=      "left/right separator
set statusline+=%{fugitive#statusline()}\ \  
set statusline+=%c,     "cursor column
set statusline+=%l/%L   "cursor line/total lines
set statusline+=\ %P    "percent through file

" ** SMALL FUNCTIONS THAT DON'T FIT AS PLUGINS ***

" Add capital W and Q so I can be lazy about my shift key
if !exists(":W")
	command W :w
endif

if !exists(":Q")
        command Q :q
endif

" CD to the path of the file I'm editing.
command Cdf :cd %:p:h

" Print path of file
command Filepath :echo expand('%:p')

" Save a vim session! Useful if you want to save buffer states and so on
command SaveSession :mksession! ~/.vim_last_session
command LoadSession :source ~/.vim_last_session

" This is a quick way to edit a persistent scratch buffer for me...
command ScratchOpen :e scp://barak@barakmich.com//home/barak/notes/scratch

" Sudo-make-me-a-sandwich write. For when I forget to be root.
"command Wdammit :w !sudo tee > /dev/null %
command Wdammit :w suda://%


" I can never remember markdown fully. Open me a cheatsheet
command MarkdownCheatsheet :rightb vsplit ~/.vim/markdown_cheatsheet.md


" Doesn't quite work right but can be a real savior if needed.
" Oh-shit-what-was-this-like-before-I-changed-it?
function! s:DiffWithSaved()
  let filetype=&ft
  diffthis
  vnew | r # | normal! 1Gdd
  diffthis
  exe "setlocal bt=nofile bh=wipe nobl noswf ro ft=" . filetype
endfunction
com! DiffSaved call s:DiffWithSaved()

" Highlight lines that are longer than textwidth for the filetype, commonly 80
" characters.
function! HighlightTooLongLines()
  highlight def link RightMargin Error
  if &textwidth != 0
    exec 'match RightMargin /\%<' . (&textwidth + 3) . 'v.\%>' . (&textwidth + 1) . 'v/'
  endif
endfunction

" Toggles the quickfix window split.
command -bang -nargs=? QFix call QFixToggle(<bang>0)
function! QFixToggle(forced)
  if exists("g:qfix_win") && a:forced == 0
    cclose
  else
    execute "copen " . 15
  endif
endfunction

" Toggle LocationList
command -bang -nargs=? LFix call LFixToggle(<bang>0)
function! LFixToggle(forced)
  if exists("g:lfix_win") && a:forced == 0
    unlet! g:lfix_win
    lclose
  else
    execute "lopen " . 10
    let g:lfix_win = "t"
  endif
endfunction

"au FileType go nmap <leader>C <Plug>(go-clearlay) 
"clear overlay
command -bang -nargs=? GoCoverlayT call GoCoverlayToggle(<bang>0)
function! GoCoverlayToggle(forced)
  if exists("g:go_coverlay_t") && a:forced == 0
    unlet! g:go_coverlay_t
    GoClearlay
    "call <Plug>(go-clearlay)
  else
    "call <Plug>(go-coverlay)
    GoCoverlay
    let g:go_coverlay_t = "t"
  endif
endfunction


" Toggle GoCoverlay
au FileType go nmap <leader>c :GoCoverlayT<CR>

" Coquille
au FileType coq nmap <leader>a :CoqToCursor<CR>
au FileType coq imap <leader>a <C-O>:CoqToCursor<CR>

" Make the Quickfix window respond well to commands (for instance, q to close,
" Enter to select, etc). In tandem with the above.
augroup QFixToggle
 autocmd!
 autocmd BufWinEnter quickfix let g:qfix_win = bufnr("$")
 autocmd BufWinEnter quickfix exec "nnoremap <silent> <buffer> q :QFix<CR>" 
 autocmd BufWinLeave * if exists("g:qfix_win") && expand("<abuf>") == g:qfix_win | unlet! g:qfix_win | endif
augroup END


" Execute a command that pipes output to window. Captures output into a new,
" appropriately titled, buffer.
function! s:ExecuteInShellOutput(command)
  let command = join(map(split(a:command), 'expand(v:val)'))
  let winnr = bufwinnr('^' . command . '$')
  silent! execute  winnr < 0 ? 'botright new ' . fnameescape(command) : winnr . 'wincmd w'
  setlocal buftype=nowrite bufhidden=wipe nobuflisted noswapfile wrap number
  echo 'Executing ' . command . '...'
  silent! execute 'silent %!'. command
" uncomment this if you want the new buffer to try to grow to accommodate the output
  "silent! execute 'resize ' . line('$')
  silent! redraw
  silent! execute 'au BufUnload <buffer> execute bufwinnr(' . bufnr('#') . ') . ''wincmd w'''
  silent! execute 'nnoremap <silent> <buffer> <LocalLeader>r :call <SID>ExecuteInShell(''' . command . ''')<CR>'
  echo 'Execution of ' . command . ' complete.'
endfunction

" Same as above, doesn't capture output
function! s:ExecuteInShell(command)
  let command = join(map(split(a:command), 'expand(v:val)'))
  silent! execute 'silent !'. command
  redraw!
  echo 'Execution of ' . command . ' complete.'
endfunction

command! -complete=shellcmd -nargs=+ Shell call s:ExecuteInShellOutput(<q-args>)
command! -complete=shellcmd -nargs=+ Exec call s:ExecuteInShell(<q-args>)
command! -nargs=* Make call s:ExecuteInShellOutput('make '.<q-args>)
command! -nargs=* PTW call s:ExecuteInShell('ptw post --client=vim "'.<q-args>.'"')
command! -nargs=* CaptureNote :AsyncRun -silent capture --viewing %:p <q-args> 2>&1 > /dev/null

" Highlight all instances of word under cursor, when idle.
" Useful when studying strange source code.
" Type z/ to toggle highlighting on/off.
nnoremap z/ :if AutoHighlightToggle()<Bar>set hls<Bar>else<Bar>set nohls<Bar>endif<CR>
function! AutoHighlightToggle()
  let @/ = ''
  if exists('#auto_highlight')
    au! auto_highlight
    augroup! auto_highlight
    setl updatetime=4000
    echo 'Highlight current word: off'
    return 0
  else
    augroup auto_highlight
      au!
      au CursorHold * let @/ = '\V\<'.escape(expand('<cword>'), '\').'\>'
    augroup end
    setl updatetime=500
    echo 'Highlight current word: ON'
    return 1
  endif
endfunction

" Removes trailing spaces
function AutoTrimWhitespace()
  if exists("b:auto_trim_whitespace")
    if b:auto_trim_whitespace == 1
      let l:winview = winsaveview()
      silent! %s/\s\+$//
      call winrestview(l:winview)
    endif
  endif
endfunction


function! StatuslineGit()
  let l:root = finddir('.git/..', expand('%:p:h').';')
  return expand('%:p:s!'. l:root . '!/!')
endfunction

function InstallEverything()
  GoUpdateBinaries
  BlackUpgrade
endfunction

command CocReinstall :CocInstall coc-json coc-pyright coc-rust-analyzer coc-snippets coc-svelte coc-tsserver coc-ultisnips


autocmd FileType defx call s:defx_my_settings()
function! s:defx_my_settings() abort
  " Define mappings
  nnoremap <silent><buffer><expr> <CR>
  \ line('.') == 1 ? defx#do_action('cd', ['..']) : defx#do_action('open')
  nnoremap <silent><buffer><expr> c
  \ defx#do_action('copy')
  nnoremap <silent><buffer><expr> m
  \ defx#do_action('move')
  nnoremap <silent><buffer><expr> p
  \ defx#do_action('paste')
  nnoremap <silent><buffer><expr> l
  \ defx#do_action('open')
  nnoremap <silent><buffer><expr> E
  \ defx#do_action('open', 'vsplit')
  nnoremap <silent><buffer><expr> P
  \ defx#do_action('preview')
  nnoremap <silent><buffer><expr> o
  \ defx#do_action('open_tree', 'toggle')
  nnoremap <silent><buffer><expr> K
  \ defx#do_action('new_directory')
  nnoremap <silent><buffer><expr> N
  \ defx#do_action('new_file')
  nnoremap <silent><buffer><expr> M
  \ defx#do_action('new_multiple_files')
  nnoremap <silent><buffer><expr> C
  \ defx#do_action('toggle_columns',
  \                'mark:indent:icon:filename:type:size:time')
  nnoremap <silent><buffer><expr> S
  \ defx#do_action('toggle_sort', 'time')
  nnoremap <silent><buffer><expr> d
  \ defx#do_action('remove')
  nnoremap <silent><buffer><expr> r
  \ defx#do_action('rename')
  nnoremap <silent><buffer><expr> !
  \ defx#do_action('execute_command')
  nnoremap <silent><buffer><expr> x
  \ defx#do_action('execute_system')
  nnoremap <silent><buffer><expr> yy
  \ defx#do_action('yank_path')
  nnoremap <silent><buffer><expr> .
  \ defx#do_action('toggle_ignored_files')
  nnoremap <silent><buffer><expr> ;
  \ defx#do_action('repeat')
  nnoremap <silent><buffer><expr> h
  \ defx#do_action('cd', ['..'])
  nnoremap <silent><buffer><expr> ~
  \ defx#do_action('cd')
  nnoremap <silent><buffer><expr> q
  \ defx#do_action('quit')
  nnoremap <silent><buffer><expr> <Space>
  \ defx#do_action('toggle_select') . 'j'
  nnoremap <silent><buffer><expr> *
  \ defx#do_action('toggle_select_all')
  nnoremap <silent><buffer><expr> j
  \ line('.') == line('$') ? 'gg' : 'j'
  nnoremap <silent><buffer><expr> k
  \ line('.') == 1 ? 'G' : 'k'
  nnoremap <silent><buffer><expr> <C-l>
  \ defx#do_action('redraw')
  nnoremap <silent><buffer><expr> <C-g>
  \ defx#do_action('print')
  nnoremap <silent><buffer><expr> cd
  \ defx#do_action('change_vim_cwd')
endfunction


" ** KEY REMAPPINGS **
"
" I used to use tabs, but then I took an arrow to the knee.
" Tabs in vim suck because they aren't what you want. Use tabbar.
"nnoremap gc :tabnew<CR>
"nnoremap gK :tabclose<CR>
"nnoremap gn gt
"nnoremap gp gT

" I don't know how I came up with gt for opening the tree, but it stuck.
"nmap gt :NERDTreeToggle<CR>
"nmap <silent> gt :VimFilerExplorer -winwidth=40 -toggle -direction=rightbelow -parent -status -force-hide<CR>
"nmap <silent> gt :VimFiler -status -auto-cd -parent -force-quit<CR>
"nmap <silent> gt :Defx  `escape(expand('%:p:h'), ' :')` -search=`expand('%:p')` -columns=icons:indent:filename:type<CR>
nmap <silent> gt :edit .<CR>
""nnoremap <silent> gt :NvimTreeToggle<CR>
" The same for the TagList, useful for large C files.
"nmap gb :TlistToggle<CR>
nmap gb :TagbarToggle<CR>
"nnoremap gx :Kwbd<CR>
" :Kwbd (defined below) really kills a buffer dead, and closes the window.
" gK is similar.
nnoremap gc :Kwbd<CR>
"nnoremap gc :bdelete<CR>
"nnoremap gK :bdelete!<CR>

" I use gn/gp to cycle through open tabs/buffers
nnoremap gn :bn<CR>
nnoremap gp :bp<CR>
nnoremap gz :pclose<CR>
" The single most handy way to get around a file. Cursor over a word, and then
" type g* -- you'll go to the next instance of that word in the file. Make it
" easier to reach by calling it gw (go-word) instead of hidden away.
nnoremap gw g*
" Make shift-p like p except, put the line above instead of below.
nmap P o<Esc>p
" Line-based movement is cute, but it's tricky for files with lines that wrap.
" Attune more to what you see on the screen instead of where the lines actually
" are.
nnoremap <silent> j gj
nnoremap k gk
xnoremap j gj
xnoremap k gk
nnoremap <Down> gj
nnoremap <Up> gk
xnoremap <Down> gj
xnoremap <Up> gk
inoremap <Down> <C-o>gj
inoremap <Up> <C-o>gk
"nnoremap <C-i> <C-a>
" Years of using bash and zsh have caused my fingers to expect these Emacs-like
" mappings to exist. Make them exist in vim as well. But eye them with
" suspicion, as they come from Emacs.
nnoremap <C-a> ^
nnoremap <C-e> $
xnoremap <C-a> ^
xnoremap <C-e> $
inoremap <C-a> <C-O>^
inoremap <C-e> <C-O>$

" Dealing with split windows is a pain. Make it less of a pain, by making
" Ctrl-direction appropriate.
"nnoremap <C-j> <C-w>j
"nnoremap <C-k> <C-w>k
"nnoremap <C-l> <C-w>l
"nnoremap <C-h> <C-w>h
""nnoremap <C-j> <C-w>w
""nnoremap <C-k> <C-w>W
"inoremap <C-j> <C-w>j
"inoremap <C-k> <C-w>k
"inoremap <C-l> <C-w>l
"inoremap <C-h> <C-w>h

"if has('nvim')
  "tnoremap <Esc> <C-\><C-n>
  "tnoremap <C-j> <C-\><C-n><C-w>j
  "tnoremap <C-k> <C-\><C-n><C-w>k
  "tnoremap <C-l> <C-\><C-n><C-w>l
  "tnoremap <C-h> <C-\><C-n><C-w>h
"endif

" Make it easier to clear highlighting, with no functionality penalty
nnoremap <CR> :noh<CR><CR>

" Better fold mappings
nnoremap <silent> <Space> @=(foldlevel('.')?'za':'l')<CR>
vnoremap <Space> zf
" Just to be handy, Ctrl-C acts like escape. So does jj, which never really
" comes up in practice. If you really need to type jj do so slowly.
imap <C-c> <Esc>
inoremap jj <Esc>

" Leader key functions
" See quickfix.
"nnoremap <Leader>ff :LFix<CR>
" See quickfix.
nnoremap <Leader>ss :SyntasticSetLoclist<CR>
" Next quickfix.
nnoremap <Leader>fn :lnext<CR>
" Prev quickfix.
nnoremap <Leader>fp :lprev<CR>
"nnoremap <silent> <Leader>aa :<C-u>Denite -mode=normal -buffer-name=search-buffer grep<CR>
nnoremap <silent> <Leader>ac :<C-u>Denite -resume -buffer-name=search-buffer grep<CR>
"nnoremap <silent> <Leader>aw :<C-u>DeniteCursorWord -buffer-name=search-buffer grep<CR>
"
nnoremap <silent> <Leader>nn :CaptureNote 
call denite#custom#map('insert', '<Enter>', '<C-o>')
"call denite#custom#var('grep', 'command', ['rg'])
"call denite#custom#var('grep', 'default_opts',
      "\ ['--no-heading', '--color', 'never', '--smart-case'])
"call denite#custom#var('grep', 'recursive_opts', [])
"call denite#custom#var('grep', 'pattern_opt', [])
"call denite#custom#var('grep', 'separator', ['--'])
"call denite#custom#var('grep', 'final_opts', [])
"call denite#custom#option('search-buffer', 'highlight_matched_char', 'deniteMatchedChar')
call denite#custom#var('grep', {
        \ 'command': ['rg'],
        \ 'default_opts': ['-i', '--vimgrep', '--no-heading'],
        \ 'recursive_opts': [],
        \ 'pattern_opt': ['--regexp'],
        \ 'separator': ['--'],
        \ 'final_opts': [],
        \ })
"nnoremap <silent> <Leader>g :<C-u>Denite -buffer-name=search-buffer grep<CR>
"nnoremap <silent> <Leader>aa :<C-u>RipGrep!<CR>
nnoremap <silent> <Leader>aa :<C-u>RgRoot!<CR>
"nnoremap <silent> <Leader>aw :<C-u>RgRoot! <C-r><C-w><CR>
"nnoremap <C-l> :<C-u>Files! `git rev-parse --show-toplevel`<CR>
"nnoremap <C-k> :<C-u>GFiles<CR>
nnoremap <silent> <C-k> <cmd>lua require('telescope.builtin').git_files{}<cr>
nnoremap <silent> <Leader>ag <cmd>lua require('telescope.builtin').live_grep{ word_match = "-w", only_sort_text = true, cwd = vim.fn.systemlist("git rev-parse --show-toplevel")[1], search = ''}<cr>
nnoremap <silent> <Leader>aw <cmd>lua require('telescope.builtin').grep_string{ word_match = "-w", only_sort_text = true, cwd = vim.fn.systemlist("git rev-parse --show-toplevel")[1]}<cr>
nnoremap <silent> <Leader>q <cmd>lua require('telescope.builtin').quickfix{}<cr>
nnoremap <silent> <Leader>ff <cmd>lua require('telescope.builtin').quickfix{}<cr>

" For C++ -- A is a great plugin which allows you to jump from the c file to the
" header and vice-versa. Mneumonic here is headerheader.
nnoremap <Leader>hh :A<CR>
" CommandT is useful, but if I'm juggling lots of buffers, limit it to another
" one I have open (instead of standard <Leader>t).
"nnoremap <silent> <Leader>o :<C-u>Buffers<CR>
nnoremap <silent> <Leader>o <cmd>lua require('telescope.builtin').buffers{initial_mode = "insert"}<cr>
nnoremap <silent> <C-j> <cmd>lua require('telescope.builtin').buffers{prompt_prefix = " "}<cr>
"nnoremap <Leader>j <C-^>
"nnoremap <Leader>p  :PTW 
nnoremap <Leader>p  :LustyJugglePrevious<CR>
nnoremap <Leader>jd :YcmCompleter GoToDefinitionElseDeclaration<CR>
nnoremap <Leader>mm :w<CR>:make!<CR>

" ** EXTRA INCLUDES **
"
let s:extrarc = expand($HOME . '/.vimrc_google')
if filereadable(s:extrarc)
  exec ':so ' . s:extrarc
endif

" ** SEE ALSO **
" filetype.vim

"call remote#host#RegisterPlugin('python3', '/home/barak/.vim/bundle/deoplete.nvim/rplugin/python3/deoplete', [
      "\ {'sync': v:true, 'name': '_deoplete', 'type': 'function', 'opts': {}},
     "\ ])
"
if !empty($VIRTUAL_ENV)
"  let g:python_host_prog = $VIRTUAL_ENV . '/bin/python'
"  let g:python3_host_prog = $VIRUTAL_ENV . '3/bin/python'
endif

autocmd FileType denite call s:denite_my_settings()
function! s:denite_my_settings() abort
  nnoremap <silent><buffer><expr> <CR>
  \ denite#do_map('do_action')
  "nnoremap <silent><buffer><expr> d
  "\ denite#do_map('do_action', 'delete')
  "nnoremap <silent><buffer><expr> p
  "\ denite#do_map('do_action', 'preview')
  nnoremap <silent><buffer><expr> q
  \ denite#do_map('quit')
  nnoremap <silent><buffer><expr> i
  \ denite#do_map('open_filter_buffer')
  nnoremap <silent><buffer><expr> <Space>
  \ denite#do_map('toggle_select').'j'
endfunction

map <F10> :echo "hi<" . synIDattr(synID(line("."),col("."),1),"name") . '> trans<' . synIDattr(synID(line("."),col("."),0),"name") . "> lo<" . synIDattr(synIDtrans(synID(line("."),col("."),1)),"name") . ">"<CR>

function! Syn()
  for id in synstack(line("."), col("."))
    echo synIDattr(id, "name")
  endfor
endfunction
map <F10> command! -nargs=0 Syn call Syn()

" Final hi links for TreeSitter

hi link @type.rust TSCSecondaryTypeParam

let s:gptool_temp = expand($HOME . '/src/gptool/bindings.vim')
if filereadable(s:gptool_temp)
  exec ':so ' . s:gptool_temp
endif
