repos/dotfiles

Config files from my daily system
Commits Files Refs README
.config/nvim/init.vim (625 lines)
   1 "                              _
   2 "        _ __   ___  _____   _(_)_ __ ___
   3 "       | '_ \ / _ \/ _ \ \ / / | '_ ` _ \
   4 "       | | | |  __/ (_) \ V /| | | | | | |
   5 "       |_| |_|\___|\___/ \_/ |_|_| |_| |_|
   6 "
   7 "       by github.com/mjkloeckner
   8 
   9 " Automatically install vim-plug (plugin manager) if not already installed
  10 let data_dir = has('nvim') ? stdpath('data') . '/site' : '~/.vim'
  11 if empty(glob(data_dir . '/autoload/plug.vim'))
  12   silent execute '!curl -fLo ' . data_dir . '/autoload/plug.vim --create-dirs '.
  13           \' https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim'
  14 autocmd VimEnter * PlugInstall --sync | source $MYVIMRC
  15 endif
  16 
  17 " Plugins call
  18 call plug#begin('~/.config/nvim/plugged')
  19     Plug 'jiangmiao/auto-pairs'
  20     Plug 'alvan/vim-closetag'
  21     Plug 'ayosec/hltermpaste.vim'
  22     Plug 'chrisbra/Colorizer'
  23     Plug 'christoomey/vim-tmux-navigator'
  24     Plug 'flazz/vim-colorschemes'
  25     Plug 'flw-cn/vim-nerdtree-l-open-h-close'
  26     Plug 'hattya/vcs-info.vim'
  27     Plug 'iamcco/markdown-preview.nvim',
  28                 \{ 'do': { -> mkdp#util#install() },
  29                 \'for': [ 'markdown', 'vim-plug' ]}
  30     Plug 'junegunn/fzf', { 'do': { -> fzf#install() } }
  31     Plug 'junegunn/fzf.vim'
  32     Plug 'junegunn/vim-easy-align'
  33     Plug 'justinmk/vim-syntax-extra'
  34     Plug 'preservim/nerdtree'
  35     Plug 'ryanoasis/vim-devicons'
  36     Plug 'sainnhe/edge'
  37     Plug 'sainnhe/gruvbox-material'
  38     Plug 'skywind3000/asyncrun.vim'
  39     Plug 'tikhomirov/vim-glsl'
  40     Plug 'tpope/vim-commentary'
  41     Plug 'tpope/vim-surround'
  42     Plug 'tpope/vim-fugitive'
  43     Plug 'vim-python/python-syntax'
  44     Plug 'mjkloeckner/autosave.vim'
  45 call plug#end()
  46 
  47 " Basic settings
  48 syntax on
  49 set title
  50 " remove the `NVIM` ending from the title
  51 " (see https://neovim.io/doc/user/options.html#'titlestring')
  52 set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
  53 set encoding=utf-8
  54 scriptencoding utf-8
  55 set fileencoding=utf-8
  56 set noemoji
  57 set tabstop=4
  58 set shiftwidth=4
  59 set scrolloff=5
  60 set path+=./**
  61 set lcs+=space:·
  62 set iskeyword-=(,)
  63 set wildmenu
  64 set incsearch
  65 set smartcase
  66 " set noshowmode
  67 set number
  68 set relativenumber
  69 set cursorline
  70 set listchars=tab:\|\ ,trail:-,nbsp:+,space:·
  71 set list
  72 set mouse=a
  73 set undofile
  74 set undodir=~/.cache/nvim/undo
  75 set dir=~/.cache/nvim/swap
  76 set backupdir=~/.cache/nvim/backup
  77 set clipboard=unnamedplus
  78 
  79 " Enable blinking together with different cursor shapes for
  80 " insert/command mode, and cursor highlighting:
  81 set guicursor=n-v:block,i-ci-ve-c:ver25,r-cr:hor20,o:hor50
  82 \,a:blinkwait700-blinkoff4000-blinkon2500-Cursor/lCursor
  83 \,sm:block-blinkwait175-blinkoff150-blinkon175
  84 
  85 " Set colorscheme and transparent background
  86 function! AdaptColorscheme()
  87     hi Normal guibg=NONE ctermbg=NONE
  88     hi LineNr guibg=NONE ctermbg=NONE
  89     hi Folded guibg=NONE ctermbg=NONE
  90     hi FoldColumn ctermbg=NONE
  91     hi EndOfBuffer guibg=NONE ctermbg=NONE ctermfg=12
  92     hi SpecialKey guibg=NONE ctermbg=NONE
  93     hi VertSplit guibg=NONE ctermbg=NONE
  94     hi SignColumn guibg=NONE ctermbg=NONE
  95     hi TabLineSel ctermfg=LightGreen ctermbg=NONE
  96     hi TabLineFill ctermfg=Gray ctermbg=NONE
  97     hi Title ctermfg=LightBlue ctermbg=NONE
  98     hi MatchParen ctermfg=234 ctermbg=208
  99 
 100     if &bg == 'light'
 101         hi ColorColumn ctermbg=254
 102     else
 103         hi ColorColumn ctermbg=240
 104         hi CursorLine ctermbg=240
 105     endif
 106 endfunction
 107 
 108 function! DarkTheme()
 109     set bg=dark
 110     let g:gruvbox_contrast_dark='hard'
 111     colorscheme gruvbox
 112     call AdaptColorscheme()
 113 endfunction
 114 
 115 function! LightTheme()
 116     set bg=light
 117     let g:gruvbox_contrast_light='hard'
 118     colorscheme gruvbox
 119     call AdaptColorscheme()
 120 endfunction
 121 
 122 hi TrailingWhitespace ctermbg=yellow guibg=yellow
 123 call matchadd("TrailingWhitespace", '\v\s+$')
 124 
 125 if filereadable('/home/mk/.config/scheme/light')
 126     call LightTheme()
 127 else
 128     call DarkTheme()
 129 endif
 130 
 131 function ToggleTheme()
 132     if &bg == 'dark'
 133         call LightTheme()
 134     else
 135         call DarkTheme()
 136     endif
 137 endfunction
 138 
 139 nnoremap <silent> <F12> :call ToggleTheme()<CR>
 140 
 141 " Key remaps
 142 let mapleader =' '
 143 map <leader>f :NERDTreeToggle<CR>
 144 map <leader>F :NERDTreeFocus<CR>
 145 map <leader>r :NERDTreeFind<CR>
 146 map <leader>s :source $HOME/.config/nvim/init.vim<CR>
 147 map <leader>c :make
 148 
 149 " Disable ex-mode keybinding (type visual thing)
 150 map Q <NOP>
 151 
 152 " Improves indenting chunks of code with '<' '>' keys
 153 vnoremap < <gv
 154 vnoremap > >gv
 155 
 156 " Type a replacement term and press . to repeat the replacement again. Useful
 157 " for replacing a few instances of the term (comparable to multiple cursors).
 158 nnoremap <silent> s* :let @/='\<'.expand('<cword>').'\>'<CR>cgn
 159 xnoremap <silent> s* "sy:let @/=@s<CR>cgn
 160 
 161 " Stops highlight after a search hitting return;
 162 nnoremap <silent> <CR> :nohlsearch<CR>
 163 
 164 " Shortcut for split navigation
 165 noremap <C-Down> <C-W>j<CR>
 166 noremap <C-Up> <C-W>k<CR>
 167 noremap <C-Left> <C-W>h<CR>
 168 noremap <C-Right> <C-W>l<CR>
 169 
 170 " Move between windows with Ctrl + hjkl
 171 noremap <C-h> <C-w>h
 172 noremap <C-j> <C-w>j
 173 noremap <C-k> <C-w>k
 174 noremap <C-l> <C-w>l
 175 
 176 " Go to next/prev quickfix
 177 nnoremap <C-n> :cnext<CR>zz
 178 nnoremap <C-p> :cprev<CR>zz
 179 
 180 " Go to tab by number
 181 noremap <leader>1 1gt
 182 noremap <leader>2 2gt
 183 noremap <leader>3 3gt
 184 noremap <leader>4 4gt
 185 noremap <leader>5 5gt
 186 noremap <leader>6 6gt
 187 noremap <leader>7 7gt
 188 noremap <leader>8 8gt
 189 noremap <leader>9 9gt
 190 noremap <leader>0 :tablast<cr>
 191 
 192 " Scroll half page with PageUp/PageDown
 193 nnoremap <PageUp> <C-u>
 194 nnoremap <PageDown> <C-d>
 195 
 196 " Start interactive EasyAlign in visual mode (e.g. vipga)
 197 xmap ga <Plug>(EasyAlign)
 198 
 199 " Start interactive EasyAlign for a motion/text object (e.g. gaip)
 200 nmap ga <Plug>(EasyAlign)
 201 
 202 " Highlight whitespace problems.
 203 " flags is '' to clear highlighting, or is a string to
 204 " specify what to highlight (one or more characters):
 205 "   e  whitespace at end of line
 206 "   i  spaces used for indenting
 207 "   s  spaces before a tab
 208 "   t  tabs not at start of line
 209 function! ShowWhitespace(flags)
 210     let bad = ''
 211     let pat = []
 212     for c in split(a:flags, '\zs')
 213         if c == 'e'
 214             call add(pat, '\s\+$')
 215         elseif c == 'i'
 216             call add(pat, '^\t*\zs \+')
 217         elseif c == 's'
 218             call add(pat, ' \+\ze\t')
 219         elseif c == 't'
 220             call add(pat, '[^\t]\zs\t\+')
 221         else
 222             let bad .= c
 223         endif
 224     endfor
 225     if len(pat) > 0
 226         let s = join(pat, '\|')
 227         exec 'syntax match ExtraWhitespace "'.s.'" containedin=ALL'
 228     else
 229         syntax clear ExtraWhitespace
 230     endif
 231     if len(bad) > 0
 232         echo 'ShowWhitespace ignored: '.bad
 233     endif
 234 endfunction
 235 
 236 function! ToggleShowWhitespace()
 237     if !exists('b:ws_show')
 238         let b:ws_show = 0
 239     endif
 240     if !exists('b:ws_flags')
 241         let b:ws_flags = 'est'  " default (which whitespace to show)
 242     endif
 243     let b:ws_show = !b:ws_show
 244     if b:ws_show
 245         call ShowWhitespace(b:ws_flags)
 246     else
 247         call ShowWhitespace('')
 248     endif
 249 endfunction
 250 
 251 nnoremap <Leader>ws :call ToggleShowWhitespace()<CR>
 252 highlight ExtraWhitespace ctermbg=red guibg=red
 253 
 254 nnoremap <A-j> :m .+1<CR>==
 255 nnoremap <A-k> :m .-2<CR>==
 256 
 257 nnoremap <Leader>/ :vsplit<CR>
 258 nnoremap <Leader>" :split<CR>
 259 
 260 inoremap <A-j> <Esc>:m .+1<CR>==gi
 261 inoremap <A-k> <Esc>:m .-2<CR>==gi
 262 
 263 vnoremap <A-j> :m '>+1<CR>gv=gv
 264 vnoremap <A-k> :m '<-2<CR>gv=gv
 265 
 266 nnoremap n nzzzv
 267 nnoremap N Nzzzv
 268 
 269 function! ToggleQuickFix()
 270     if empty(filter(getwininfo(), 'v:val.quickfix'))
 271         copen
 272     else
 273         cclose
 274     endif
 275 endfunction
 276 
 277 nnoremap <silent> <leader>c :call ToggleQuickFix()<cr>
 278 
 279 set laststatus=1
 280 autocmd VimEnter * set laststatus=1
 281 
 282 let NERDTreeHijackNetrw=1
 283 let NERDTreeMinimalUI=1
 284 
 285 " Highjack nerdtree's highjacking to keep normal nerdtree from loading on directories
 286 " let g:NERDTreeHijackNetrw=0
 287 " augroup NERDTreeHijackNetrw
 288 "    autocmd VimEnter * silent! autocmd! FileExplorer
 289 " augroup END
 290 
 291 " autocmd VimEnter * call CloseExtraNERDTree()
 292 
 293 " If vim is started with a file, simply show that file
 294 " If vim is started with nothing or a directory close extra NERDTree buffer
 295 " function CloseExtraNERDTree()
 296 "   wincmd l " move to right pane
 297 "   let l:main_bufnr = bufnr('%')
 298 "   let l:fname = expand('%') " get name of current buffer
 299 "   if l:fname ==# 'NERD_tree_1'
 300 "   exe bufwinnr(l:main_bufnr) . "wincmd w"
 301 "   bd
 302 "   endif
 303 " endfunction
 304 
 305 function VerboseMark()
 306     echo ''
 307     let c = getchar()
 308     if ((c >= 0x41) && (c <= 0x5A)) || ((c >= 0x61) && (c <= 0x7A))
 309         normal! m nr2char(c)
 310         echon "mark `" nr2char(c) "`: line " line(".")  ", col " col(".")
 311     else
 312         return
 313     endif
 314 endfunction
 315 
 316 let g:asyncrun_open = 12
 317 
 318 " Pressing Ctrl-C during command mode breaks highlight
 319 cnoremap <C-c> <Esc>
 320 
 321 " Oposite of <Shift-k>
 322 nnoremap K :m-2<CR>J
 323 
 324 function Compile()
 325     echohl Question
 326     let l:input = split(input("Compile command: ", &makeprg, "filetype"), ' ')
 327     echohl None
 328 
 329     if empty(l:input)
 330         return
 331     endif
 332     redraw
 333 
 334     if(!empty(matchstr(l:input, "%")))
 335         if(empty(expand('%')))
 336             echohl Question
 337             echo 'Filename empty'
 338             echohl None
 339             return
 340         endif
 341     endif
 342 
 343     let string = join(l:input, ' ')
 344     " exe "set makeprg = " .. string
 345     let &makeprg = string
 346     let l:s = &makeprg
 347     exe "AsyncRun " .. l:s
 348     mod
 349 endfunction
 350 
 351 " autocmd BufEnter *.txt if &filetype == 'help' | wincmd T | endif
 352 function SearchHelp()
 353     mod
 354     echohl Question
 355     let l:input = substitute(input("Search vim help: ", "", "help"), "\\\'\\\|\\\"", '', 'g')
 356     echohl None
 357     mod
 358 
 359     if empty(l:input)
 360         return
 361     endif
 362 
 363     let v:errmsg = ""
 364     let l:cmd = "help " .. l:input
 365     silent! execute(l:cmd)
 366 
 367     if matchstr(v:errmsg, "no help") != ""
 368         echohl WarningMsg
 369         mod
 370         echo "Sorry, no help for: `" .. l:input .. "`"
 371         echohl None
 372     else
 373         exe "wincmd T | mod | set nornu"
 374     endif
 375 endfunction
 376 
 377 " autocmd BufEnter *.txt if &filetype == 'man' | wincmd T | endif
 378 function SearchMan()
 379     echohl Question
 380     " let l:input = input("Search man page: ")
 381     let l:input = substitute(input("Search man page: "), "\\\'\\\|\\\"", '', 'g')
 382     echohl None
 383     mod
 384 
 385     if empty(l:input)
 386         return
 387     endif
 388 
 389     " let l:string = join(l:input, ' ')
 390     let l:cmd = "man " .. l:input .. " > /dev/null 2>&1"
 391     call system(l:cmd)
 392     if v:shell_error == 0
 393         if matchstr(expand('%'), "man://") == ""
 394             exe "tabnew"
 395             exe "Man " .. l:input
 396             exe "only"
 397         else
 398             exe "Man " .. l:input
 399         endif
 400 
 401     else
 402         echohl WarningMsg
 403         mod
 404         echon l:input .. ": nothing appropriate."
 405         echohl None
 406     endif
 407 endfunction
 408 
 409 function Search()
 410     echohl Question
 411     let l:input = split(input("Search keyword in CWD: "), ' ')
 412     echohl None
 413     if empty(l:input)
 414         return
 415     endif
 416     mod
 417 
 418     let l:string = join(l:input, ' ')
 419     echo l:string
 420     exe "silent grep -r -I -s --exclude-dir=.git " .. l:string .. " *"
 421     copen
 422 endfunction
 423 
 424 function JumpBuffer()
 425     let l:prev_buffer = expand("#:t")
 426     echohl Question
 427     let l:input = split(input("Change buffer: ", l:prev_buffer, "buffer"), ' ')
 428     echohl None
 429     if empty(l:input)
 430         return
 431     endif
 432     mod
 433 
 434     let l:string = join(l:input, ' ')
 435     echo l:string
 436     if bufexists(l:string)
 437         exe "b " .. l:string
 438     else
 439         if filereadable(l:string)
 440             exe "e " .. l:string
 441         else
 442             exe "e " .. l:string
 443             mod
 444             echo "Buffer doesn't exists: editinig new file `".. l:string .. "`"
 445         endif
 446     endif
 447 endfunction
 448 
 449 function FindFile()
 450     echohl Question
 451     let l:input = split(input("Find file: ", expand('%'), "file"), ' ')
 452     echohl None
 453     if empty(l:input)
 454         return
 455     endif
 456     mod
 457 
 458     let l:string = join(l:input, ' ')
 459     echo l:string
 460     if bufexists(l:string)
 461         exe "b " .. l:string
 462     else
 463         if filereadable(l:string)
 464             exe "e " .. l:string
 465         else
 466             exe "e " .. l:string
 467             mod
 468             echo "file doesn't exists: editinig new file `".. l:string .. "`"
 469         endif
 470     endif
 471 endfunction
 472 
 473 nnoremap <C-x><C-f> :call FindFile()<CR>
 474 nnoremap <Leader>cc :call Compile()<CR>
 475 nnoremap <Leader>cC :make<CR>
 476 nnoremap <Leader>v :call Search()<CR>
 477 nnoremap <Leader>m :call SearchMan()<CR>
 478 nnoremap <Leader>h :call SearchHelp()<CR>
 479 nnoremap <Leader>b :call JumpBuffer()<CR>
 480 
 481 function Text()
 482     if winwidth('%') > 86
 483         set nuw=8
 484     endif
 485     set tw=80
 486     set colorcolumn=80
 487     set spelllang=es,en
 488     set spell
 489 endfunction
 490 
 491 let g:TextMode = 0
 492 function ToggleText()
 493     if g:TextMode == 0
 494         let g:TextMode = 1
 495         call Text()
 496     else
 497         let g:TextMode = 0
 498         set nuw=4
 499         set tw=0
 500         set colorcolumn=0
 501         set nospell
 502     endif
 503 endfunction
 504 
 505 let g:mkdp_browser = 'qutebrowser'
 506 
 507 " make MarkdownPreview's tableofcontents pattern same as latex (for use
 508 " with pandoc)
 509 let g:mkdp_preview_options = {
 510     \ 'toc': { 'placeholder': '\\tableofcontents' }
 511     \ }
 512 
 513 nnoremap <silent> <Leader>T :call ToggleText()<CR>
 514 nnoremap m :call VerboseMark()<CR>
 515 
 516 au TextYankPost * silent! lua vim.highlight.on_yank()
 517 let g:python_highlight_all = 1
 518 
 519 autocmd ColorScheme gruvbox call AdaptColorscheme()
 520 
 521 " close if quickfix is the last window
 522 au BufEnter * call MyLastWindow()
 523 function! MyLastWindow()
 524   " if the window is quickfix go on
 525   if &buftype=="quickfix"
 526     " if this window is last on screen quit without warning
 527     if winbufnr(2) == -1
 528       quit!
 529     endif
 530   endif
 531 endfunction
 532 
 533 " enable auto_save for only these filetypes, to see all posible ifletypes
 534 " see: https://vi.stackexchange.com/questions/5780/list-known-filetypes
 535 let g:auto_save_file_types = [ 'markdown' ]
 536 
 537 " enable auto_save for all filetypes
 538 let g:auto_save_all_filetypes = 0
 539 
 540 " Switch to last-active tab
 541 if !exists('g:Lasttab')
 542     let g:Lasttab = 1
 543     let g:Lasttab_backup = 1
 544 endif
 545 autocmd! TabLeave * let g:Lasttab_backup = g:Lasttab | let g:Lasttab = tabpagenr()
 546 autocmd! TabClosed * let g:Lasttab = g:Lasttab_backup
 547 nmap <silent> <Leader>; :exe "tabn " . g:Lasttab<cr>
 548 
 549 " Markdown mode
 550 function MarkdownMode()
 551     so ~/.config/nvim/md-toc.vim
 552     function! GeneratePDF()
 553         mod
 554         let l:filename = expand("%:r")
 555         let l:md_filename = l:filename .. ".md"
 556         let l:pdf_filename = l:filename .. ".pdf"
 557 
 558         if filereadable(l:md_filename)
 559             let l:pdf_generate_cmd = "!md2pdf " .. l:md_filename
 560             mod
 561             " exe l:pdf_generate_cmd
 562             exe "AsyncRun -mode=term -pos=bottom -rows=3 " .. l:pdf_generate_cmd
 563         else
 564             mod
 565             echohl WarningMsg
 566             echo "File `" .. l:md_filename .. "` not found in CWD"
 567             echohl None
 568         endif
 569     endfunction
 570 
 571     " requires neovim-remote to clear command line
 572     function! OpenPDF()
 573         let l:filename = expand("%:r")
 574         let l:pdf_filename = l:filename .. ".pdf"
 575         let l:server_name = v:servername
 576 
 577         " Check if pdf exists
 578         if filereadable(l:pdf_filename)
 579             let l:open_pdf_cmd = "!xdg-open " .. l:pdf_filename .. " &"
 580             silent exe l:open_pdf_cmd
 581             mod
 582             echohl Question
 583             echon "Opening `" .. l:pdf_filename .. "`"
 584             echohl None
 585         else
 586             echohl WarningMsg
 587             echo "File `" .. l:pdf_filename .. "` not found in CWD"
 588             echohl None
 589         endif
 590     endfunction
 591 
 592     nnoremap <buffer> <F9> :MarkdownPreviewToggle<CR>
 593     autocmd TermOpen * set cmdheight=0 | set laststatus=0 | exe 
 594                 \"au WinClosed <buffer> set cmdheight=1 | set laststatus=1 | mod"
 595                 \| nnoremap <silent> <buffer> <Esc> :close<CR> | mod
 596     nnoremap <silent> <buffer> <F11> :call GeneratePDF()<CR>
 597     nnoremap <silent> <buffer> <F12> :call OpenPDF()<CR>
 598     nnoremap <silent> <tab> :TocToggle<CR>
 599 
 600     " do not treat underscore as errors in certain contexts
 601     " https://github.com/tpope/vim-markdown/issues/21
 602     hi link markdownError NONE
 603 endfunction
 604 
 605 au FileType markdown silent! call MarkdownMode()
 606 " au CursorHold,CursorHoldI * mod
 607 
 608 " delete word in command/prompt mode with Ctrl + Backspace
 609 cnoremap <C-H> <C-w>
 610 cnoremap <C-BS> <C-H>
 611 
 612 let $FZF_DEFAULT_OPTS = ""
 613 let g:fzf_layout = {'down':'10'}
 614 " let g:fzf_layout = { 'window': { 'width': 1.0, 'height': 0.25, 'relative': v:true, 'yoffset': 1.0 } }
 615 
 616 autocmd! FileType fzf
 617 autocmd  FileType fzf set laststatus=0 noshowmode noruler nonumber norelativenumber cmdheight=0
 618   \| autocmd BufLeave <buffer> set laststatus=1 showmode ruler number relativenumber cmdheight=1
 619 
 620 " enable syntax highlight inside markdown codeblocks
 621 let g:markdown_fenced_languages = [
 622             \"html", "javascript", "js=javascript", "go", "golang=go",
 623             \"css", "dot", "xml", "python", "c", "c++=cpp", "sh",
 624             \"bash=sh", "vim", "lua" ]
 625