"set runtimepath^=~/.vim runtimepath+=~/.vim/after
"let &packpath = &runtimepath
"source ~/.vimrc

set suffixes+=.aux,.bbl,.blg,.brf,.cb,.dvi,.idx,.ilg,.ind,.inx,.jpg,.log,.out,.png,.toc
set suffixes-=.h
set suffixes-=.obj

set tabstop=3 softtabstop=3
set shiftwidth=3
set expandtab
set smartindent
" set foldmethod=indent
" set foldlevel=0

set undodir=~/.vim/undo
set undofile

set guifont=SauceCodePro\ NF\ Regular

set hlsearch
set hidden
set ignorecase
set smartcase
set wrap
set linebreak
" set guicursor= " always use the block cursor
syntax on
set redrawtime=1000 " max syntax highlight time
set number relativenumber
set noerrorbells
set encoding=UTF-8
set cursorline
set mouse=a
set incsearch
set scrolloff=6
" set wildmenu
" set wildmode=full
" TextEdit might fail if hidden is not set.
set hidden
set cmdheight=1 " Give more space for displaying messages.
" Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
" delays and poor user experience.
set updatetime=300
" Don't pass messages to |ins-completion-menu|.
set shortmess+=c
" Spell check!
set spell spelllang=en_us
" spell check in git commits
autocmd Filetype gitcommit setlocal spell
set showcmd
set signcolumn=yes
" disable spell check in help files
autocmd FileType help setlocal nospell
filetype plugin on
" Macro for opening a new terminal with spell check off
command! Term tabnew | setlocal nospell | term
autocmd FileType help setlocal nospell
" test whitespace ->
" more test whitespace ->
         " Indented text
         " even more test whitespace ->

" Key bindings
let mapleader = " "
" *sigh*...
command! Q q
command! W w
command! Wq wq
command! WQ wq
" nnoremap ; :
" vnoremap ; :
" Press Alt h to toggle highlighting on/off, and show current value.
noremap <M-h> :set hlsearch! hlsearch?<CR>
" Escape to enter normal mode in the terminal
tnoremap <Esc> <C-\><C-n>
" Replace with alt S
nnoremap <M-s> :%s//g<Left><Left>
" Wrapped line movement (hold ctrl to move like a word processor)
nmap <C-h> h
nmap <C-j> gj
nmap <C-k> gk
nmap <C-l> l
" nmap <C-4> g$
nmap <C>$  g$
nmap <C-6> g^
nmap <C-^> g^
nmap <C-0> g^
vmap <C-h> h
vmap <C-j> gj
vmap <C-k> gk
vmap <C-l> l
vmap <C-4> g$
vmap <C>$  g$
vmap <C-6> g^
vmap <C-^> g^
vmap <C-0> g^
" " Hold ctrl to move between windows, shift to reorder the windows
" nmap <C-h> <C-w>h
" nmap <C-j> <C-w>j
" nmap <C-k> <C-w>k
" nmap <C-l> <C-w>l
" nmap <C-H> <C-w>H
" nmap <C-J> <C-w>J
" nmap <C-K> <C-w>K
" nmap <C-L> <C-w>L
"  " and for visual mode
" vmap <C-h> <C-w>h
" vmap <C-j> <C-w>j
" vmap <C-k> <C-w>k
" vmap <C-l> <C-w>l
" vmap <C-H> <C-w>H
" vmap <C-J> <C-w>J
" vmap <C-K> <C-w>K
" vmap <C-L> <C-w>L

""""""" Quality of life things that aren't one line (also from stack overflow and stuff)
"Use 24-bit (true-color) mode in Vim/Neovim when outside tmux.
"If you're using tmux version 2.2 or later, you can remove the outermost $TMUX check and use tmux's 24-bit color support
"(see < http://sunaku.github.io/tmux-24bit-color.html#usage > for more information.)
if (empty($TMUX))
   if (has("nvim"))
      "For Neovim 0.1.3 and 0.1.4 < https://github.com/neovim/neovim/pull/2198 >
      let $NVIM_TUI_ENABLE_TRUE_COLOR=1
   endif
   "For Neovim > 0.1.5 and Vim > patch 7.4.1799 < https://github.com/vim/vim/commit/61be73bb0f965a895bfb064ea3e55476ac175162 >
   "Based on Vim patch 7.4.1770 (`guicolors` option) < https://github.com/vim/vim/commit/8a633e3427b47286869aa4b96f2bfc1fe65b25cd >
   " < https://github.com/neovim/neovim/wiki/Following-HEAD#20160511 >
   if (has("termguicolors"))
      set termguicolors
   endif
endif

" 'Visual At' plugin (https://github.com/stoeffel/.dotfiles/blob/master/vim/visual-at.vim)
xnoremap @ :<C-u>call ExecuteMacroOverVisualRange()<CR>
function! ExecuteMacroOverVisualRange()
  echo "@".getcmdline()
  execute ":'<,'>normal @".nr2char(getchar())
endfunction

" Make shift-insert work like in Xterm
if has('gui_running')
   map <S-Insert> <MiddleMouse>
   map! <S-Insert> <MiddleMouse>
endif
set exrc

" Automatically jump to the last position in a file when opening
if has("autocmd")
   au BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal! g`\"" | endif
endif

"" Plugins
" disable polyglot in markdown (needs to go before it loads)
let g:polyglot_disabled = ['markdown']
" make ALE work with CoC
let g:ale_disable_lsp = 1
call plug#begin('$HOME/.vim/plugins/')
   """ Colors
   Plug 'joshdick/onedark.vim'            " Theme (status line)
   Plug 'romgrk/doom-one.vim'             " Theme (UI)
   Plug 'vim-airline/vim-airline'         " Status line theme
   Plug 'Yggdroot/indentLine'             " Indent lines
   Plug 'sheerun/vim-polyglot'            " Syntax highlighting
   Plug 'nvim-treesitter/nvim-treesitter', {'do': ':TSUpdate'}  " Syntax highlighting (neovim 0.5)
   Plug 'airblade/vim-gitgutter'          " Inline git info
   " Plug 'tribela/vim-transparent'         " Transparency always

   """ IDE features/LSP
   Plug 'editorconfig/editorconfig-vim'   " editorconfig support
   Plug 'neoclide/coc.nvim', {'branch': 'release'} " Code completion
   Plug 'dense-analysis/ale'              " Code formatting, linting
   Plug 'dbeniamine/cheat.sh-vim'         " cheat.sh

   """ Smaller IDE features
   Plug 'mbbill/undotree'                 " Undo tree
   Plug 'jiangmiao/auto-pairs'            " Quote pairing
   Plug 'junegunn/vim-easy-align'
   Plug 'tpope/vim-repeat'                " Repeatability for various tpope plugins
   Plug 'tpope/vim-surround'              " Quote/parenthesis changing
   Plug 'tpope/vim-sensible'              " Some sensible defaults
   Plug 'tpope/vim-commentary'            " Comments
   Plug 'tpope/vim-fugitive'              " git integration

   " File explorer
   Plug 'preservim/nerdtree', { 'on':  'NERDTreeToggle' }
      Plug 'tiagofumo/vim-nerdtree-syntax-highlight'   " File type colors
      Plug 'ryanoasis/vim-devicons'                    " File icons
      Plug 'Xuyuanp/nerdtree-git-plugin'               " File git status

   " Misc
   Plug 'junegunn/goyo.vim', {'for': 'markdown', 'on': 'Goyo'} " Minimalist writing mode
   Plug 'glacambre/firenvim', { 'do': { _ -> firenvim#install(0) } } " Firefox nvim integration

call plug#end()

"""""""""""""""""""""""""""""" Things set as a result of plugins
""" Colors
set background=dark
if match(&runtimepath, 'doom-one') != -1
   let g:doom_one_terminal_colors = v:true
   colorscheme doom-one
elseif match(&runtimepath, 'one') != -1
   let g:one_allow_italics = 1
   colorscheme one
else
   colorscheme slate
   set nocursorline
endif

""" Transparency
if match(&runtimepath, 'transparent') != -1
   call g:background#clear_background()
endif

"""  Airline
if match(&runtimepath, 'airline') != -1
   let g:airline_powerline_fonts = 1
   let g:airline_detect_spell=0 " (*YES*, I KNOW I have spell check on all the time)
   let g:airline#extensions#tabline#enabled = 1
   let g:airline#extensions#tabline#formatter = 'unique_tail_improved'
   if match(&runtimepath, 'onedark') != -1
      let g:airline_theme='onedark'
   elseif match(&runtimepath, 'one') != -1
      let g:airline_theme='one'
   endif

   "  this is the first bit of vimscript I ever wrote
   "  This also turned out to be the last bit of vimscript I would ever write
   function! Tabline_auto_show_hide()
      let tab_count = tabpagenr("$")
      if tab_count == 2
         " if there is one tab
         if &lines > 3
            set showtabline=2
         endif
         " echom 'The tab bar was enabled'
      elseif tab_count == 1
         if &lines > 3
            set showtabline=1
         endif
         " echom 'The tab bar was disabled'
      endif
   endfunction

   augroup TablineShowHide
      " autocmd! BufEnter * call Tabline_auto_show_hide()
      autocmd! TabNew * call Tabline_auto_show_hide()
      autocmd! TabClosed * call Tabline_auto_show_hide()
      autocmd! VimEnter * call Tabline_auto_show_hide()
      autocmd! User GoyoLeave * call Tabline_auto_show_hide()
   augroup END
endif

""" Commentary
if match(&runtimepath, 'commentary') != -1
   nnoremap <Leader>l :Commentary<CR>
endif

""" indentline
if match(&runtimepath, 'indentline') != -1
   let g:indentLine_char = '▏'
   let g:indentLine_conceallevel = 1
   let g:indentLine_fileTypeExclude = ['markdown']
endif

""" CtrlP
if match(&runtimepath, 'indentline') != -1
   let g:ctrlp_map = '<c-p>'
   let g:ctrlp_cmd = 'CtrlP'
   let g:ctrlp_working_path_mode = 'ra'
   " set wildignore+=*/tmp/*,*.so,*.swp,*.zip,*.     " ignored file extensions
   " let g:ctrlp_user_command = ['.git', 'cd %s && git ls-files -co --exclude-standard'] " Ignoer files in .gitignore's
endif

""" Undotree
if match(&runtimepath, 'undotree') != -1
   nnoremap <F5> :UndotreeToggle<CR>
endif

""" Asynchronous Lint Engine (ALE)
" if match(&runtimepath, 'ale') != -1
" endif

""" Auto-pairs
if match(&runtimepath, 'autopairs') != -1
   let g:AutoPairsFlyMode = 1
endif

""" Goyo
if match(&runtimepath, 'indentline') != -1
   function! s:goyo_enter()
      if executable('tmux') && strlen($TMUX)
         silent !tmux set status off
         silent !tmux list-panes -F '\#F' | grep -q Z || tmux resize-pane -Z
      endif
      " silent Limelight
      echo
   endfunction

   function! s:goyo_leave()
      if executable('tmux') && strlen($TMUX)
         silent !tmux set status on
         silent !tmux list-panes -F '\#F' | grep -q Z && tmux resize-pane -Z
      endif
      " set showmode
      " set showcmd
      " set scrolloff=5
      " silent Limelight!
      echo
   endfunction

   autocmd! User GoyoEnter nested call <SID>goyo_enter()
   autocmd! User GoyoLeave nested call <SID>goyo_leave()
endif

""" Treesitter
if match(&runtimepath, 'treesitter') != -1
   lua << EOF
      require'nvim-treesitter.configs'.setup {
      ensure_installed = "maintained", -- one of "all", "maintained" (parsers with maintainers), or a list of languages
      --ignore_install = { "javascript", "java" }, -- List of parsers to ignore installing
      highlight = {
      enable = true,              -- false will disable the whole extension
      -- disable = { "c", "rust" },  -- list of language that will be disabled
      -- Setting this to true will run `:h syntax` and tree-sitter at the same time.
      -- Set this to `true` if you depend on 'syntax' being enabled (like for indentation).
      -- Using this option may slow down your editor, and you may see some duplicate highlights.
      -- Instead of true it can also be a list of languages
      additional_vim_regex_highlighting = true,
      },
     indent = {
     enable = true
     }
   }
EOF
endif

""" CoC
if match(&runtimepath, 'coc') != -1
   " Set internal encoding of vim, not needed on neovim, since coc.nvim using some
   " unicode characters in the file autoload/float.vim
   set encoding=utf-8

   " TextEdit might fail if hidden is not set.
   set hidden

   " Some servers have issues with backup files, see #649.
   set nobackup
   set nowritebackup

   " Give more space for displaying messages.
   set cmdheight=1

   " Having longer updatetime (default is 4000 ms = 4 s) leads to noticeable
   " delays and poor user experience.
   set updatetime=300

   " Don't pass messages to |ins-completion-menu|.
   set shortmess+=c

   " Always show the signcolumn, otherwise it would shift the text each time
   " diagnostics appear/become resolved.
   if has("patch-8.1.1564")
      " Recently vim can merge signcolumn and number column into one
      set signcolumn=number
   else
      set signcolumn=yes
   endif

   " Use tab for trigger completion with characters ahead and navigate.
   " NOTE: Use command ':verbose imap <tab>' to make sure tab is not mapped by
   " other plugin before putting this into your config.
   inoremap <silent><expr> <TAB>
            \ pumvisible() ? "\<C-n>" :
            \ <SID>check_back_space() ? "\<TAB>" :
            \ coc#refresh()
   inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<C-h>"

   function! s:check_back_space() abort
      let col = col('.') - 1
      return !col || getline('.')[col - 1]  =~# '\s'
   endfunction

   " Use <c-space> to trigger completion.
   if has('nvim')
      inoremap <silent><expr> <c-space> coc#refresh()
   else
      inoremap <silent><expr> <c-@> coc#refresh()
   endif

   " Make <CR> auto-select the first completion item and notify coc.nvim to
   " format on enter, <cr> could be remapped by other vim plugin
   inoremap <silent><expr> <cr> pumvisible() ? coc#_select_confirm()
            \: "\<C-g>u\<CR>\<c-r>=coc#on_enter()\<CR>"

   " Use `[g` and `]g` to navigate diagnostics
   " Use `:CocDiagnostics` to get all diagnostics of current buffer in location list.
   nmap <silent> [g <Plug>(coc-diagnostic-prev)
   nmap <silent> ]g <Plug>(coc-diagnostic-next)

   " GoTo code navigation.
   nmap <silent> gd <Plug>(coc-definition)
   nmap <silent> gy <Plug>(coc-type-definition)
   nmap <silent> gi <Plug>(coc-implementation)
   nmap <silent> gr <Plug>(coc-references)

   " Use K to show documentation in preview window.
   nnoremap <silent> K :call <SID>show_documentation()<CR>

   function! s:show_documentation()
      if (index(['vim','help'], &filetype) >= 0)
         execute 'h '.expand('<cword>')
      elseif (coc#rpc#ready())
         call CocActionAsync('doHover')
      else
         execute '!' . &keywordprg . " " . expand('<cword>')
      endif
   endfunction

   " Highlight the symbol and its references when holding the cursor.
   autocmd CursorHold * silent call CocActionAsync('highlight')

   " Symbol renaming.
   nmap <leader>rn <Plug>(coc-rename)

   " Formatting selected code.
   xmap <leader>f  <Plug>(coc-format-selected)
   nmap <leader>f  <Plug>(coc-format-selected)

   augroup mygroup
      autocmd!
      " Setup formatexpr specified filetype(s).
      autocmd FileType typescript,json setl formatexpr=CocAction('formatSelected')
      " Update signature help on jump placeholder.
      autocmd User CocJumpPlaceholder call CocActionAsync('showSignatureHelp')
   augroup end

   " Applying codeAction to the selected region.
   " Example: `<leader>aap` for current paragraph
   xmap <leader>a  <Plug>(coc-codeaction-selected)
   nmap <leader>a  <Plug>(coc-codeaction-selected)

   " Remap keys for applying codeAction to the current buffer.
   nmap <leader>ac  <Plug>(coc-codeaction)
   " Apply AutoFix to problem on the current line.
   nmap <leader>qf  <Plug>(coc-fix-current)

   " Map function and class text objects
   " NOTE: Requires 'textDocument.documentSymbol' support from the language server.
   xmap if <Plug>(coc-funcobj-i)
   omap if <Plug>(coc-funcobj-i)
   xmap af <Plug>(coc-funcobj-a)
   omap af <Plug>(coc-funcobj-a)
   xmap ic <Plug>(coc-classobj-i)
   omap ic <Plug>(coc-classobj-i)
   xmap ac <Plug>(coc-classobj-a)
   omap ac <Plug>(coc-classobj-a)

   " Remap <C-f> and <C-b> for scroll float windows/popups.
   if has('nvim-0.4.0') || has('patch-8.2.0750')
      nnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
      nnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
      inoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(1)\<cr>" : "\<Right>"
      inoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? "\<c-r>=coc#float#scroll(0)\<cr>" : "\<Left>"
      vnoremap <silent><nowait><expr> <C-f> coc#float#has_scroll() ? coc#float#scroll(1) : "\<C-f>"
      vnoremap <silent><nowait><expr> <C-b> coc#float#has_scroll() ? coc#float#scroll(0) : "\<C-b>"
   endif

   " Use CTRL-S for selections ranges.
   " Requires 'textDocument/selectionRange' support of language server.
   nmap <silent> <C-s> <Plug>(coc-range-select)
   xmap <silent> <C-s> <Plug>(coc-range-select)

   " Add `:Format` command to format current buffer.
   command! -nargs=0 Format :call CocAction('format')

   " Add `:Fold` command to fold current buffer.
   command! -nargs=? Fold :call     CocAction('fold', <f-args>)

   " Add `:OR` command for organize imports of the current buffer.
   command! -nargs=0 OR   :call     CocAction('runCommand', 'editor.action.organizeImport')

   " Add (Neo)Vim's native statusline support.
   " NOTE: Please see `:h coc-status` for integrations with external plugins that
   " provide custom statusline: lightline.vim, vim-airline.
   set statusline^=%{coc#status()}%{get(b:,'coc_current_function','')}

   " Mappings for CoCList
   " Show all diagnostics.
   nnoremap <silent><nowait> <space>a  :<C-u>CocList diagnostics<cr>
   " Manage extensions.
   nnoremap <silent><nowait> <space>e  :<C-u>CocList extensions<cr>
   " Show commands.
   nnoremap <silent><nowait> <space>C  :<C-u>CocList commands<cr>
   " Find symbol of current document.
   nnoremap <silent><nowait> <space>o  :<C-u>CocList outline<cr>
   " Search workspace symbols.
   nnoremap <silent><nowait> <space>s  :<C-u>CocList -I symbols<cr>
   " Do default action for next item.
   nnoremap <silent><nowait> <space>j  :<C-u>CocNext<CR>
   " Do default action for previous item.
   nnoremap <silent><nowait> <space>k  :<C-u>CocPrev<CR>
   " Resume latest coc list.
   nnoremap <silent><nowait> <space>p  :<C-u>CocListResume<CR>
endif
"""""""""""""""""""""""""""" END Plugin-dependent settings