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/plugged')
Plug 'tpope/vim-vinegar'
Plug 'tpope/vim-surround'
Plug 'tpope/vim-commentary'
Plug 'junegunn/fzf'
Plug 'junegunn/fzf.vim'
Plug 'prabirshrestha/vim-lsp'
call plug#end()

syntax enable
filetype on
filetype plugin on
filetype indent on

set ruler
set encoding=utf-8    " utf8 by default for new files
set nocompatible      " it's not 1985
set nobackup          " don't create ~backup files
set noswapfile        " don't create .swp file 
set number            " show line numbers
set nowrap            " disable wrapping
set cursorline        " highlight current line
set ttyfast           " improve scrolling speed
set lazyredraw        " improve draw speed
set foldlevelstart=99 " unfold everything by default
set noerrorbells      " disable bell/flash
set history=1000      " command history length
set so=10             " horizontal scrollover
set backspace=2       " make backspace work normally
set nopaste           " normal behavior for paste (don't try to indent)
set tabpagemax=15     " max 15 tabs open
set laststatus=2      " always display statusbar
set previewheight=3   " maximum height for preview window
set showmatch         " highlight matching brace
set updatetime=750    " improve latency for plugins
set showcmd           " show commands as they're being input
set autoread          " automatically reload when changed externally
set hlsearch          " highlight all search matches
set incsearch         " start searching before hitting 'enter'
set ignorecase        " perform case-insensitive search
set smartcase         " ...unless search term has a capital letter
set hidden            " hide buffers instead of closing them
set wildmenu          " autocomplete for command menu
set modelines=1       " obey file modelines
set timeoutlen=1000   " no key delays
set ttimeoutlen=0     " no key delays
set completeopt=menu,menuone,longest,preview

set smartindent       " autoindent
set expandtab         " replace hard tabs with spaces
set shiftwidth=2      " tab width = 2 spaces
set tabstop=2
set softtabstop=2
"set textwidth=80     " default max line length
set colorcolumn=81   " display a marker 1 column after the text width
" whitespace visibility
set list listchars=tab:>-,nbsp:~,trail:X

" Mappings {{{1
" Leader {{{2
let mapleader = ","
let g:mapleader = ","

" Fast saving {{{2
nmap <leader>w :w!<cr>

" Visual mode pressing * or # searches for the current selection
" Super useful! From an idea by Michael Naumann
vnoremap <silent> * :<C-u>call VisualSelection('', '')<CR>/<C-R>=@/<CR><CR>
vnoremap <silent> # :<C-u>call VisualSelection('', '')<CR>?<C-R>=@/<CR><CR>

" Search {{{2
map <space> /
map <c-space> ?

" Disable highlight when <leader><cr> is pressed
map <silent> <leader><cr> :noh<cr>

" Windows {{{2
noremap <leader>h <C-w>s
noremap <leader>v <C-w>v
map <C-j> <C-W>j
map <C-k> <C-W>k
map <C-h> <C-W>h
map <C-l> <C-W>l

" Buffers {{{2
noremap <leader>bq :q<cr>
map <leader>bd :Bclose<cr>
map <leader>ba :bufdo bd<cr>
map <leader>bo :only<cr>

" Tabs {{{2
map <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr>
noremap <S-l> gt
noremap <S-h> gT
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove
map <leader>t<leader> :tabnext
let g:lasttab = 1
nmap <Leader>tl :exe "tabn ".g:lasttab<CR>
au TabLeave * let g:lasttab = tabpagenr()
map <leader>te :tabedit <c-r>=expand("%:p:h")<cr>/

" Switch CWD to the directory of the open buffer
map <leader>cd :cd %:p:h<cr>:pwd<cr>

" Remap VIM 0 to first non-blank character
noremap 0 ^
noremap ^ 0


" Pressing ,ss will toggle and untoggle spell checking
map <leader>ss :setlocal spell!<cr>

" Shortcuts using <leader>
map <leader>sn ]s
map <leader>sp [s
map <leader>sa zg
map <leader>s? z=


" Netrw {{{2
let g:netrw_banner = 0

" Plugin Config {{{1
" FZF {{{2
nmap <leader>fb :Buffers<cr>
nmap <leader>ff :Files<cr>
nnoremap <leader>fg :Rg<space>
let $FZF_DEFAULT_COMMAND = 'rg --files'

" LSP {{{2

" Go {{{3
if executable('gopls')
    au User lsp_setup call lsp#register_server({
        \ 'name': 'gopls',
        \ 'cmd': {server_info->['gopls']},
        \ 'initialization_options': {
        \     'completeUnimported': v:true,
        \     'matcher': 'fuzzy',
        \     'ui.inlayhint.hints': {
        \         'assignVariableTypes': v:true,
        \         'compositeLiteralFields': v:true,
        \         'compositeLiteralTypes': v:true,
        \         'constantValues': v:true,
        \         'functionTypeParameters': v:true,
        \         'parameterNames': v:true,
        \         'rangeVariableTypes': v:true,
        \     },
        \     'codelenses': {
        \         'generate': v:true,
        \         'test': v:true,
        \         'run_vulncheck_exp': v:true,
        \     },
        \ },
        \ 'capabilities': {
        \     'textDocument': {
        \         'documentSymbol': {
        \             'hierarchicalDocumentSymbolSupport': v:true,
        \         },
        \     },
        \ },
        \ 'allowlist': ['go', 'gomod'],
        \ })
endif

" Python {{{3
if executable('pylsp')
    " pip install python-lsp-server
    au User lsp_setup call lsp#register_server({
        \ 'name': 'pylsp',
        \ 'cmd': {server_info->['pylsp']},
        \ 'allowlist': ['python'],
        \ })
endif

" Javascript/Typescript {{{3
if executable('typescript-language-server')
    " npm --global install python-lsp-server
    au User lsp_setup call lsp#register_server({
        \ 'name': 'typescript-language-server',
        \ 'cmd': {server_info->['typescript-language-server', '--stdio']},
        \ 'initialization_options': {
        \   'preferences': {
		\     'includeInlayParameterNameHintsWhenArgumentMatchesName': v:true,
		\     'includeInlayParameterNameHints': 'all',
		\     'includeInlayVariableTypeHints': v:true,
		\     'includeInlayPropertyDeclarationTypeHints': v:true,
		\     'includeInlayFunctionParameterTypeHints': v:true,
		\     'includeInlayEnumMemberValueHints': v:true,
		\     'includeInlayFunctionLikeReturnTypeHints': v:true
		\   },
		\ },
        \ 'allowlist': ['javascript', 'javascriptreact', 'typescript', 'typescriptreact'],
        \ })
endif

" Buffer setup {{{3
function! s:on_lsp_buffer_enabled() abort
    setlocal omnifunc=lsp#complete
    setlocal signcolumn=yes
    if exists('+tagfunc') | setlocal tagfunc=lsp#tagfunc | endif
    nmap <buffer> gd <plug>(lsp-definition)
    nmap <buffer> gs <plug>(lsp-document-symbol-search)
    nmap <buffer> gS <plug>(lsp-workspace-symbol-search)
    nmap <buffer> gr <plug>(lsp-references)
    nmap <buffer> gi <plug>(lsp-implementation)
    nmap <buffer> gt <plug>(lsp-type-definition)
    nmap <buffer> <leader>rn <plug>(lsp-rename)
    nmap <buffer> [g <plug>(lsp-previous-diagnostic)
    nmap <buffer> ]g <plug>(lsp-next-diagnostic)
    nmap <buffer> K <plug>(lsp-hover)
    nnoremap <buffer> <expr><c-f> lsp#scroll(+4)
    nnoremap <buffer> <expr><c-d> lsp#scroll(-4)

    let g:lsp_format_sync_timeout = 1000
    autocmd! BufWritePre *.rs,*.go call execute('LspDocumentFormatSync')

    " refer to doc to add more commands
endfunction

augroup lsp_install
    au!
    " call s:on_lsp_buffer_enabled only for languages that has the server registered.
    autocmd User lsp_buffer_enabled call s:on_lsp_buffer_enabled()
augroup END

" END {{{1

colorscheme slate
set notermguicolors
hi Normal guibg=NONE ctermbg=NONE
hi LineNr guibg=NONE ctermbg=NONE

" vim:fdm=marker:fdl=1
