" This is my vimrc
" There are many like it but this will eventually be mine
"
" vim: ts=2 sw=2 expandtab
" vint: +ProhibitAbbreviationOption +ProhibitSetNoCompatible
"*****************************************************************************
"" Vim-Plug core
"*****************************************************************************
let vimplug_exists=expand('$HOME/.config/autoload/plug.vim')
if has('win32') && !has('win64')
  let curl_exists=expand('C:\Windows\Sysnative\curl.exe')
else
  let curl_exists=expand('curl')
endif

let g:vim_bootstrap_langs = "go,html,javascript,lua,php,python,typescript"
let g:vim_bootstrap_editor = "vim" " nvim or vim
let g:vim_bootstrap_theme = "pencil"
let g:vim_bootstrap_frams = "vuejs"

" ale
let g:ale_fixers = {}
let g:ale_linters = { "python": [ "flake8" ] }

if !filereadable(vimplug_exists)
  if !executable(curl_exists)
    echoerr "You have to install curl or first install vim-plug yourself!"
    execute "q!"
  endif
  echo "Installing Vim-Plug..."
  echo ""
  silent exec "!"curl_exists" -fLo " . shellescape(vimplug_exists) . " --create-dirs https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim"
  let g:not_finish_vimplug = "yes"

  autocmd VimEnter * PlugInstall
endif

" {{{
call plug#begin(expand('$HOME/.config/vim/plugged'))
  " vim-sensible
  Plug 'tpope/vim-sensible'
  " coc.nvim - Intellisense engine
  Plug 'neoclide/coc.nvim', {'branch': 'release'}
  " editorconfig-vim - EditorConfig plugin
  Plug 'editorconfig/editorconfig-vim'
  " nerdtree - File system explorer
  Plug 'scrooloose/nerdtree'
  Plug 'jistr/vim-nerdtree-tabs'
  " vim-commentary - Commenting plugin
  Plug 'tpope/vim-commentary'
  " vim-fugitive - Git wrapper
  Plug 'tpope/vim-fugitive'
  " vim-gitgutter - Git diff in the gutter
  Plug 'airblade/vim-gitgutter'
  " grep.vim - Grep plugin
  Plug 'vim-scripts/grep.vim'
  " CSApprox - Approximate color scheme
  Plug 'vim-scripts/CSApprox'
  " tagbar - Tag list
  Plug 'majutsushi/tagbar'
  " ale - Asynchronous Lint Engine
  Plug 'dense-analysis/ale'
  " indentLine - Show indent lines
  Plug 'Yggdroot/indentLine'
  " vim-bootstrap-updater - Update vim-bootstrap
  Plug 'editor-bootstrap/vim-bootstrap-updater'
  " vim-rhubarb - Fugitive extension
  Plug 'tpope/vim-rhubarb' " required by fugitive to :GBrowse
  " ctrlp.vim - Fuzzy file finder
  Plug 'ctrlpvim/ctrlp.vim'

  " vim-airline
  Plug 'vim-airline/vim-airline'

  " fzf.vim - Fuzzy finder
  if isdirectory('~/.config/vim/extra/fzf')
    Plug '~/.config/vim/extra/fzf' | Plug 'junegunn/fzf.vim'
  else
    Plug 'junegunn/fzf', { 'dir': '~/.config/vim/extra/fzf', 'do': './install --bin' }
    Plug 'junegunn/fzf.vim'
  endif

  let g:make = 'gmake'
  if exists('make')
    let g:make = 'make'
  endif

  " vim-wordy - Uncover usage problems in your writing
  Plug 'preservim/vim-wordy'

  " vimproc.vim - Asynchronous execution
  Plug 'Shougo/vimproc.vim', {'do': g:make}

  " Vim-Session
  Plug 'xolox/vim-misc'
  Plug 'xolox/vim-session'

  " go
  Plug 'fatih/vim-go', {'do': ':GoInstallBinaries'}

  " html
  Plug 'hail2u/vim-css3-syntax'
  Plug 'gko/vim-coloresque'
  Plug 'tpope/vim-haml'
  Plug 'mattn/emmet-vim'

  " javascript
  Plug 'jelera/vim-javascript-syntax'

  " lua
  Plug 'xolox/vim-lua-ftplugin'
  Plug 'xolox/vim-lua-inspect'

  " php
  Plug 'phpactor/phpactor', {'for': 'php', 'do': 'composer install --no-dev -o'}
  Plug 'stephpy/vim-php-cs-fixer'

  " python
  Plug 'davidhalter/jedi-vim'
  Plug 'raimon49/requirements.txt.vim', {'for': 'requirements'}

  " typescript
  Plug 'leafgarland/typescript-vim'
  Plug 'HerringtonDarkholme/yats.vim'

  " vimrc
  Plug 'Vimjas/vint'

  " vuejs
  Plug 'posva/vim-vue'
  Plug 'leafOfTree/vim-vue-plugin'

call plug#end()
" }}}

let mapleader=' '                 " Map leader to <space>
filetype off                      " disable filetype detection (but re-enable later, see below)

" find matching tags in html/xml documents using matchit
filetype plugin on
packadd! matchit
" disable super buggy netrw
let g:loaded_netrw=1
let g:netrw_loaded_netrwPlugin=1
" show JSDoc highlight colors
let g:javascript_plugin_jsdoc=1

set backspace=indent,eol,start    " Backspace behavior
set cindent                       " Use 'C' style program indenting
set cursorline                    " Highlight current line
set encoding=utf-8                " UTF-8
set expandtab                     " Use spaces instead of tabs
set fileformats=unix,dos,mac      " File formats
set foldmethod=indent             " Fold based on indent
set foldlevel=99                  " Open all folds
set guioptions=egmrti             " GUI options
set hidden                        " Enable hidden buffers
set ignorecase                    " Always case-insensitive
set incsearch                     " Searches for strings incrementally
set laststatus=2                  " Always show statusline (even with only single window)
set linespace=3                   " Set line spacing
set list                          " Show invisible characters
set listchars=tab:⌴\ ,trail:◼,nbsp:•,extends:…,precedes:… " Invisible characters
set modeline                      " Enable modelines
set modelines=3                   " Number of lines to check for modelines
set mouse=a                       " Enable mouse support
set mousemodel=popup              " Enable mouse support
set nobackup                      " Disable backup files
set nocompatible                  " disable compatibility mode with vi
set nowritebackup                 " Disable backup files
set number                        " Show line numbers
set relativenumber                " Show relative line numbers
set ruler                         " Show row and column ruler information
set scrolloff=8                   " Minimum number of lines to keep above and below the cursor
set shiftwidth=4                  " Number of auto-indent spaces
set shortmess+=A                  " Don't show autocommand messages
set shortmess+=F                  " Avoid showing the "file-info" message
set shortmess+=I                  " Don't show intro message
set shortmess+=O                  " Avoid showing the "file-read" message
set shortmess+=O                  " Don't show overlength messages
set shortmess+=T                  " Don't show title messages
set shortmess+=W                  " Don't show "written" messages
set shortmess+=a                  " Avoid showing the "ATTENTION" message
set shortmess+=c                  " Avoid showing the "ins-completion-menu" message
set shortmess+=c                  " Don't pass messages to |ins-completion-menu|
set shortmess+=o                  " Avoid showing the "overlength" message
set shortmess+=t                  " Avoid showing the "trailing whitespace" message
set showcmd                       " Show command in status line
set showmatch                     " Highlight matching brace
set signcolumn=yes                " Show sign column
set smartcase                     " Enable smart-case search
set smartindent                   " Enable smart-indent
set smarttab                      " Enable smart-tabs
set softtabstop=4                 " Number of spaces per Tab
set spelllang=fi,en               " Set the spell language
set spellsuggest=double           " Suggest the first word when spell checking
set t_Co=256                      " 256 colors
set termguicolors                 " Enable 24-bit RGB color in the terminal
set timeoutlen=500                " By default timeoutlen=1000 (ms)
set ttimeoutlen=0                 " By default ttimeoutlen=-1 (ms)
set undolevels=1000               " Number of undo levels
set visualbell                    " Use visual bell (no beeping)
set wildmenu                      " Enable wildmenu
set wildmode=longest,list:longest " Command-line completion mode
set wrap                          " Wrap lines
set wrapscan                      " Searches wrap around the end of the file

" Ignore these files in wildmenu
set wildignore+=*.o,*.obj,.git,*.rbc,*.pyc,__pycache__,vendor

colorscheme pencil                " Set the color scheme
filetype plugin indent on         " enable filetype detection, plugins and indenting

" Set the shell
if exists('$SHELL')
  set shell=$SHELL
else
  set shell=/bin/sh
endif


" COC
let g:coc_global_extensions = [
      \ '@yaegassy/coc-intelephense',
      \ '@yaegassy/coc-laravel',
      \ '@yaegassy/coc-phpstan',
      \ 'coc-blade',
      \ 'coc-git',
      \ 'coc-json',
      \ 'coc-php-cs-fixer',
      \ 'coc-phpls',
      \ 'coc-prettier',
      \ 'coc-sh',
      \ 'coc-toml',
      \ 'coc-tsserver',
      \ 'coc-vimlsp',
      \ 'coc-yaml',
      \ 'coc-yank',
      \ 'coc-marketplace'
      \ ]

" session management
let g:session_directory = "~/.local/state/vim/session"
let g:session_autoload = "yes"
let g:session_autosave = "yes"
let g:session_command_aliases = 1

syntax on

" Search mappings: These will make it so that going to the next one in a
" search will center on the line it's found in.
nnoremap n nzzzv
nnoremap N Nzzzv

" if fugitive is installed, add the statusline
if exists("*fugitive#statusline")
  set statusline+=%{fugitive#statusline()}
endif

" vim-airline
let g:airline#extensions#ale#enabled = 1
let g:airline#extensions#branch#enabled = 1
let g:airline#extensions#tabline#enabled = 1
let g:airline#extensions#tagbar#enabled = 1
let g:airline_powerline_fonts = 1
let g:airline_skip_empty_sections = 1
let g:airline_theme = 'pencil'

" NERDTree configuration
let g:NERDTreeChDirMode=2
let g:NERDTreeIgnore = [ 'node_modules', 'vendor', '\.rbc$', '\~$', '\.pyc$', '\.db$', '\.sqlite$', '__pycache__' ]
let g:NERDTreeSortOrder = [ '^__\.py$', '\/$', '*', '\.swp$', '\.bak$', '\~$' ]
let g:NERDTreeShowBookmarks = 1
let g:nerdtree_tabs_focus_on_files = 1
let g:NERDTreeMapOpenInTabSilent = '<RightMouse>'
let g:NERDTreeWinSize = 50
set wildignore+=*/tmp/*,*.so,*.swp,*.zip,*.pyc,*.db,*.sqlite,*node_modules/,*vendor/
nnoremap <silent> <F2> :NERDTreeFind<CR>
nnoremap <silent> <leader>t :NERDTreeToggle<CR>

" grep.vim configuration
nnoremap <silent> <leader>f :Rgrep<CR>
let Grep_Default_Options = '-IR'
let Grep_Skip_Files = '*.log *.db .DS_Store'
let Grep_Skip_Dirs = '.git node_modules vendor plugged'

" CoC (code suggestions, diagnostics and refactoring)
" find or update definitions
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)
nmap <silent> gn <Plug>(coc-rename)
" autoformat code based on linter
function! s:auto_format()
    " eslint is no longer exposed as a proper linter to coc
    if index(['js', 'jsx', 'javascript', 'javascriptreact', 'ts', 'typescript', 'typescriptcommon', 'typescriptreact'], &filetype) >= 0
        silent! CocCommand eslint.executeAutofix
    else
        call CocActionAsync('format')
    endif
endfunction
noremap <silent> <leader>f :call <SID>auto_format()<cr>
" jump to diagnostics or the documentation
nmap <silent> <C-k> <Plug>(coc-diagnostic-prev)
nmap <silent> <C-j> <Plug>(coc-diagnostic-next)
function! s:show_documentation()
    if index(['vim','help'], &filetype) >= 0
        execute 'h '.expand('<cword>')
    else
        call CocActionAsync('doHover')
    endif
endfunction
noremap <silent> K :call <SID>show_documentation()<cr>
" scroll popup windows
function s:find_cursor_popup(...)
  let radius = 50
  let srow = screenrow()
  let scol = screencol()
  for r in range(srow - radius, srow + radius)
    for c in range(scol - radius, scol + radius)
      let winid = popup_locate(r, c)
      if winid != 0
        return winid
      endif
    endfor
  endfor
  return 0
endfunction
function s:scroll_cursor_popup(down)
  let winid = <SID>find_cursor_popup()
  if winid == 0
    return 0
  endif
  let pp = popup_getpos(winid)
  call popup_setoptions(winid, {'firstline': pp.firstline + a:down})
  return 1
endfunction
imap <expr> <C-f> <SID>scroll_cursor_popup(1) ? '' : ''
imap <expr> <C-b> <SID>scroll_cursor_popup(-1) ? '' : ''
" expand snippets, completion or copilot with tab key based on selection
imap <silent> <S-Tab> <Nop>
let g:copilot_no_tab_map = v:true
inoremap <silent><expr> <Tab>
      \ coc#pum#has_item_selected() ? coc#_select_confirm() :
      \ exists('b:_copilot.suggestions') ? copilot#Accept("\<CR>") : ""
" automatically fix diagnostics and/or refactor
noremap <silent> <leader>d :CocList diagnostics<cr>
nmap <leader>c <Plug>(coc-codeaction)
xmap <leader>c <Plug>(coc-codeaction-selected)

let g:wordy#ring = [
    \ 'weak',
    \ [ 'being', 'passive-voice', ],
    \ 'business-jargon',
    \ 'weasel',
    \ 'puffery',
    \ [ 'problematic', 'redundant', ],
    \ [ 'colloquial', 'idiomatic', 'similies', ],
    \ 'art-jargon',
    \ [ 'contractions', 'opinion', 'vague-time', 'said-synonyms', ],
    \ 'adjectives',
    \ 'adverbs',
    \ ]

"*****************************************************************************
"" Commands
"*****************************************************************************

" remove trailing whitespaces
command! FixWhitespace :%s/\s\+$//e

"*****************************************************************************
"" Functions
"*****************************************************************************

" setup wrapping function
if !exists('*s:setupWrapping')
  function s:setupWrapping()
    set wrap
    set wm=2
    set textwidth=79
  endfunction
endif

"*****************************************************************************
"" Custom configs
"*****************************************************************************

" javascript
let g:javascript_enable_domhtmlcss = 1

" vim-javascript
augroup vimrc-javascript
  autocmd!
  autocmd FileType javascript setl tabstop=4|setl shiftwidth=4|setl expandtab softtabstop=4
augroup END

" python
" vim-python
augroup vimrc-python
  autocmd!
  autocmd FileType python setlocal expandtab shiftwidth=4 tabstop=8 colorcolumn=79 formatoptions+=croq softtabstop=4 cinwords=if,elif,else,for,while,try,except,finally,def,class,with
augroup END

"" jedi-vim for python
let g:jedi#popup_on_dot = 0
let g:jedi#goto_assignments_command = "<leader>g"
let g:jedi#goto_definitions_command = "<leader>d"
let g:jedi#documentation_command = "K"
let g:jedi#usages_command = "<leader>n"
let g:jedi#rename_command = "<leader>r"
let g:jedi#show_call_signatures = "0"
let g:jedi#completions_command = "<C-Space>"
let g:jedi#smart_auto_mappings = 0

" ale
:call extend(g:ale_linters, {
            \ 'python': [ 'black' ],
            \ })

:call extend(g:ale_fixers, {
            \ '*': [ 'remove_trailing_lines', 'trim_whitespace' ],
            \ 'python': [ 'autopep8', 'isort' ],
            \ })

let g:ale_sign_column_always = 1
let g:ale_fix_on_save = 1

" editorconfig
let g:EditorConfig_exclude_patterns = ['fugitive://.*']
au FileType gitcommit let b:EditorConfig_disable = 1

" Syntax highlight
let python_highlight_all = 1

" typescript
let g:yats_host_keyword = 1

" vuejs
" vim vue
let g:vue_disable_pre_processors=1
" vim vue plugin
let g:vim_vue_plugin_load_full_syntax = 1
