view dot_config/nvim/init.vim @ 319:b93f12d23fbd

Rename init.lua to config.lua init.lua is now automatically sourced, and runs before init.vim causing issues like lspconfig that cannot be found. Renaming to something that will not be sourced automatically and manually load it from init.vim when all plugins are loaded
author Zeger Van de Vannet <zegervdv@me.com>
date Thu, 17 Dec 2020 17:49:14 +0100
parents 7d73e664f702
children 4daaf43a2b28
line wrap: on
line source

" vim:fdm=marker:ts=2:sw=2

let s:darwin = has('mac')
let s:windows = has('win32')

" Include Vim-Plug {{{
if !s:windows
  if has('nvim')
    if empty(glob('~/.config/nvim/autoload/plug.vim'))
      silent !mkdir -p ~/.config/nvim/autoload
      silent !curl -fLo ~/.config/nvim/autoload/plug.vim
            \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
      autocmd VimEnter * PlugInstall
    endif
  else
    if empty(glob('~/.vim/autoload/plug.vim'))
      silent !mkdir -p ~/.vim/autoload
      silent !curl -fLo ~/.vim/autoload/plug.vim
            \ https://raw.githubusercontent.com/junegunn/vim-plug/master/plug.vim
      autocmd VimEnter * PlugInstall
    endif
  endif
endif

" }}}
" Vim-Plug {{{
let g:plug_window='topleft new'

if has('nvim')
  call plug#begin('~/.config/nvim/plugged')
else
  call plug#begin('~/.vim/plugged')
endif

" General Plugins
Plug 'tpope/vim-sensible'

if s:darwin
  Plug 'vim-scripts/gitignore'
endif

Plug 'sjl/splice.vim'

Plug 'tpope/vim-repeat'
Plug 'tpope/vim-rsi'
Plug 'einfachtoll/didyoumean'

" Session Management
Plug 'tpope/vim-obsession'

" Spelling
Plug 'tpope/vim-abolish'

" Settings
Plug 'sgur/vim-editorconfig'

" Brackets
Plug 'tpope/vim-surround'
Plug 'raimondi/delimitMate'
Plug 'zegervdv/vim-endwise'

" Formatting
Plug 'junegunn/vim-easy-align', { 'on' : [] }
augroup load_easy_align
  autocmd!
  autocmd CursorHold,CursorHoldI * call plug#load('vim-easy-align') | autocmd! load_easy_align
augroup END

" Comments
Plug 'tpope/vim-commentary'

" Moving in files
Plug 'wellle/targets.vim', { 'on': [] }
augroup load_targets
  autocmd!
  autocmd InsertEnter * call plug#load('targets.vim') | autocmd! load_targets
augroup END
Plug 'mhinz/vim-grepper', { 'on' : 'Grepper' }

" Indentation
" Plug 'nathanaelkane/vim-indent-guides'
Plug 'Yggdroot/indentline'
Plug 'lukas-reineke/indent-blankline.nvim', { 'branch': 'lua' }

" Command line
Plug 'tpope/vim-eunuch', { 'on' : ['Remove', 'Unlink', 'Move', 'Rename', 'Mkdir', 'Chmod', 'Find', 'Locate', 'SudoEdit', 'SudoWrite']}

" Undoing
Plug 'sjl/gundo.vim', { 'on': 'GundoToggle' }

" Tabs
Plug 'gcmt/taboo.vim'

" Other
Plug 'yuttie/comfortable-motion.vim'
Plug 'tpope/vim-apathy'

" Tmux
Plug 'christoomey/vim-tmux-navigator'
Plug 'tmux-plugins/vim-tmux-focus-events'

" Background make
Plug 'tpope/vim-dispatch'

" Completing and snippets
Plug 'sirver/ultisnips'
Plug 'honza/vim-snippets'
if has('nvim')
   Plug 'neovim/nvim-lsp'
   Plug 'nvim-lua/completion-nvim'
   Plug 'nvim-treesitter/nvim-treesitter'
   Plug 'nvim-treesitter/nvim-treesitter-refactor'
   Plug 'nvim-treesitter/nvim-treesitter-textobjects'
   Plug 'nvim-treesitter/playground'
   Plug 'steelsojka/completion-buffers'
   Plug 'nvim-treesitter/completion-treesitter'
   Plug 'nvim-lua/popup.nvim'
   Plug 'nvim-lua/plenary.nvim'
   Plug 'nvim-telescope/telescope.nvim'
endif

" Copying
Plug 'ShikChen/osc52.vim'

" Vim file navigation
Plug 'justinmk/vim-dirvish'
Plug 'tpope/vim-projectionist'

" Theme
Plug 'NLKNguyen/papercolor-theme'
Plug 'zegervdv/nvcode-color-schemes.vim'

"Tcl
Plug 'vim-scripts/tcl.vim--smithfield-indent', { 'for': 'tcl'}

Plug 'sbdchd/neoformat'

Plug 'Glench/Vim-Jinja2-Syntax'

if s:darwin
  " Ruby
  Plug 'tpope/vim-rails', { 'for': 'ruby' }
  Plug 'vim-ruby/vim-ruby', { 'for': 'ruby' }
  Plug 'tpope/vim-bundler', { 'for': 'ruby' }
  Plug 'tpope/vim-rake', { 'for': 'ruby' }
  Plug 'slim-template/vim-slim', { 'for': 'ruby' }
  Plug 'duwanis/tomdoc.vim', { 'for': 'ruby' }
  Plug 'keith/rspec.vim', { 'for': 'rspec' }

  " Markdown
  Plug 'tpope/vim-markdown', { 'for': 'markdown' }

  " Jade
  Plug 'digitaltoad/vim-jade', { 'for': 'jade' }

  " Latex
  Plug 'lervag/vimtex', { 'for': 'tex' }
endif

" Coffeescript
Plug 'kchmck/vim-coffee-script', { 'for': 'coffee' }

" C
Plug 'NLKNguyen/c-syntax.vim', { 'for': 'c'  }

" Python
Plug 'Vimjas/vim-python-pep8-indent', { 'for': 'python' }
Plug 'vim-python/python-syntax', { 'for': 'python' }

" Git
Plug 'tpope/vim-git'
call plug#end()
" }}}

" Activate built in plugins {{{
if !has('nvim')
  if has('packages')
    packadd! matchit
    packadd! shellmenu
  endif
endif
source $VIMRUNTIME/ftplugin/man.vim

if has('packages')
  silent! packadd! log_file
  silent! packadd! browsify
  silent! packadd! snippets
  silent! packadd! chipscoper
endif

if has("nvim")
  let g:python3_host_prog=expand('$HOME/.config/virtualenvs/python3/bin/python')
  let g:python_host_prog=expand('$HOME/.config/virtualenvs/python2/bin/python')
endif
" }}}

" General Settings and options {{{

" Backspace over everything, like normal 
set backspace=2

" Buffers
set autoread " Read external changes
set hidden " Change between buffers without saving
set autowriteall " Write changes when losing focus

" Visuals
set number
set relativenumber
set ruler
syntax on
set title
set scrolloff=4 " Stay 4 lines from top/bottom
set showcmd

" Theme and style

let g:PaperColor_Theme_Options = {
      \ 'theme': {
      \   'default': {
      \     'allow_bold': 0
      \   }
      \ }
      \}

set termguicolors

let g:one_allow_italics=1
let g:nvcode_termcolors=256
colorscheme one
set background=dark

if s:darwin
  set background=dark
  colorscheme tomorrow-night
  set guifont=inconsolata:h13
elseif s:windows
  set background=light
  colorscheme PaperColor
  set guifont=consolas:h10
endif

set showmatch " Highlight matching brackets

set wrap " Wrap lines
set wrapmargin=2 " Stay 2 chars from side
set textwidth=79
set colorcolumn=81
set linebreak " Smarter wrapping
if v:version > 703
  set breakindent " Indent wrapped lines to same level
endif

set fixendofline

set expandtab " Expand tabs to spaces
set tabstop=2 shiftwidth=2 " Tab is 2 spaces

set shiftround " Round shift indents to nearest value

" Searching
set magic  " Use magic regexes
set hlsearch " Highlight all matches
set incsearch " Show matches while typing
set ignorecase " Ignore case when searching
set smartcase " Be case sensitive if at least one uppercase char is used
set gdefault " Default substitute all matches on a line
if has('nvim')
  set inccommand=nosplit
endif

set autoindent " Automatically indent
set cindent " Indent based on C syntax
set cinwords+=foreach

set updatetime=300

if s:darwin
  set vb
endif
set noerrorbells " Don't beep

set guioptions-=r
set guioptions-=l
set guioptions-=R
set guioptions-=L
set guioptions-=a
set guioptions-=m
set guioptions-=T
set guioptions+=c

set history=100 " Set history 100
set wildmenu " Command completion
set wildmode=longest:full,full " Complete to fullest match
set ttyfast " Use a fast terminal
set lazyredraw " No need to redraw constantly
set shortmess+=c

set ttimeoutlen=-1 " Set the timeout to a minimum
set diffopt+=iwhite " Ignore spaces in diffs"

set tags=.git/tags,tags,/project/asic_fpga/tools/vim/share/vim/vimfiles/tags

" Have find look through all folders
set path+=**
" Add PRJROOT and subdirs to path if it is set
if exists('$PRJROOT')
  set path+=$PRJROOT/**
endif

set formatoptions=
set formatoptions+=c " Format comments
set formatoptions+=r " Continue comments by default
set formatoptions+=o " Make comment when using o or O from comment line
set formatoptions+=q " Format comments with gq
set formatoptions+=n " Recognize numbered lists
set formatoptions+=2 " Use indent from 2nd line of a paragraph
" set formatoptions+=l " Don't break lines that are already long
set formatoptions+=1 " Break before 1-letter words

set signcolumn=yes

" Enable cursorline
set cursorline
augroup cline
  au!
  autocmd WinEnter * setlocal cursorline
  autocmd WinLeave * setlocal nocursorline
augroup END

if !s:windows
  set list
  set listchars=tab:»\ ,trail:·,extends:>,precedes:<,nbsp:+
endif

set sessionoptions-=options

" Scan files for completion
set complete=.,w,b,u,k,kspell,t,i,d
" set completeopt=menuone,longest,preview,noinsert,noselect
set completeopt=noinsert,menuone,noselect

set splitright
set virtualedit=block

if v:version > 703
  set conceallevel=0
  if !has('nvim')
    set cryptmethod=blowfish2
  endif
endif

filetype plugin indent on

set pastetoggle=<F2> " Toggle to paste mode

if v:version >= 703
  set undofile
endif
set undolevels=1000
set backup
set noswapfile
if has('nvim')
  " set viminfo+=n~/.config/nvim/.viminfo
  set backupdir=~/.config/nvim/tmp/backup/,.
  set directory=~/.config/nvim/tmp/swap//,.
else
  set viminfo+=n~/.vim/.viminfo
  set backupdir=~/.vim/tmp/backup/,.
  set directory=~/.vim/tmp/swap//,.
endif
if !isdirectory(expand(&backupdir))
  call mkdir(expand(&backupdir), "p")
endif
if !isdirectory(expand(&directory))
  call mkdir(expand(&directory), "p")
endif

if v:version >= 703
  if has('nvim')
    set undodir=~/.config/nvim/tmp/undo//,.
  else
    set undodir=~/.vim/tmp/undo//,.
  endif
  if !isdirectory(expand(&undodir))
    call mkdir(expand(&undodir), "p")
  endif
endif


set wildignore+=*/tmp/*,*.so,*.swp,*.zip,*.o,*.bin,*.elf,*.hex,*.eps,.git/**,*.dup,.hg/**,*.orig,*.*~

" No selecting via mouse (stops visual selection when scrolling)
set mouse=nic

" }}}
" Status line {{{
hi StatusLine ctermfg=0 ctermbg=3 cterm=NONE
hi StatusLineNC ctermfg=8 ctermbg=7 cterm=NONE
hi User1 ctermfg=0 ctermbg=7
hi User2 ctermfg=NONE ctermbg=NONE
hi User3 ctermfg=0 ctermbg=3
hi User4 ctermfg=0 ctermbg=5
function! Status()
  let l:statusline=''
  let l:statusline.=' %t'
  let l:statusline.=' %1*'
  let l:statusline.=' %Y'
  let l:statusline.=' %2*'
  let l:statusline.='%='
  let l:statusline.=' %1*'
  let l:statusline.=' line '
  let l:statusline.=''
  let l:statusline.='%l'
  let l:statusline.=' %3*'
  let l:statusline.=' of '
  let l:statusline.=''
  let l:statusline.='%L '
  let l:statusline.=''
  return l:statusline
endfunction
set laststatus=2
set statusline=%!Status()
" }}}
" Fix Colors in colorscheme {{{
function! SpellHighlights() abort
  highlight SpellBad ctermbg=256 ctermfg=210
  highlight SpellLocal ctermbg=240 ctermfg=010
  highlight SpellCap ctermbg=256 ctermfg=211
endfunction
augroup SpellColors
  autocmd!
  autocmd ColorScheme * call SpellHighlights()
augroup END
"}}}

" Mappings {{{
" Set leader to spacebar
map <space> <leader>

" See long lines as line breaks
noremap <expr> j (v:count? 'j' : 'gj')
noremap <expr> k (v:count? 'k' : 'gk')

" Remap tag-search to better place
nnoremap <C-$> g<C-]>
nnoremap <C-w>y <C-w>g<C-]>

nnoremap <C-s> <C-e>

" Move while in insert mode
inoremap <C-f> <right>

" Switch between the last two files
" nnoremap <space><space> <C-^>

" " Very Magic search patterns
nnoremap / /\v
vnoremap / /\v

" Keep search matches in the middle of the window.
nnoremap n nzzzv
nnoremap N Nzzzv

" Search for beginning of command
cnoremap <c-n>  <down>
cnoremap <c-p>  <up>

" Move whole lines
nnoremap [e  :<c-u>execute 'move -1-'. v:count1<cr>
nnoremap ]e  :<c-u>execute 'move +'. v:count1<cr>

" Insert empty lines
nnoremap [<space>  :<c-u>put! =repeat(nr2char(10), v:count1)<cr>'[
nnoremap ]<space>  :<c-u>put =repeat(nr2char(10), v:count1)<cr>

" Clear highlight
nnoremap <silent><leader>l :noh<CR>

inoremap £ \

" Highlight last inserted text
nnoremap gV `[v`]

" Highlight VCS conflict markers
match ErrorMsg '^\(<\|=\|>\)\{7\}\([^=].\+\)\?$'

" Use backspace as delete in visual mode
vmap <BS> x

" Redraw screen
nnoremap <F3> :redraw!<CR>

" Keep selection when shifting
vmap <expr> > KeepVisualSelection(">")
vmap <expr> < KeepVisualSelection("<")

function! KeepVisualSelection(cmd)
  set nosmartindent
  if mode() ==# "V"
    return a:cmd . ":set smartindent\<CR>gv"
  else
    return a:cmd . ":set smartindent\<CR>"
  endif
endfunction

" Swap backticks and quotes
nnoremap ` '
nnoremap ' `

" Open vimrc
nnoremap <leader>ve :e $MYVIMRC<CR>
nnoremap <leader>vs :so $MYVIMRC<CR>

" Open dup in diffmode
nnoremap <leader>d :call OpenDup(@%)<CR>

function! OpenDup(file)
  let l:filename = a:file . ".dup"
  execute 'vsplit' l:filename
  windo diffthis
endfunction

" Do not move on *
nnoremap <silent> * :let stay_star_view = winsaveview()<cr>*:call winrestview(stay_star_view)<cr>

" Search for selected text, forwards or backwards.
vnoremap <silent> * :<C-U>
  \let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
  \gvy/<C-R><C-R>=substitute(
  \escape(@", '/\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
  \gV:call setreg('"', old_reg, old_regtype)<CR>
vnoremap <silent> # :<C-U>
  \let old_reg=getreg('"')<Bar>let old_regtype=getregtype('"')<CR>
  \gvy?<C-R><C-R>=substitute(
  \escape(@", '?\.*$^~['), '\_s\+', '\\_s\\+', 'g')<CR><CR>
  \gV:call setreg('"', old_reg, old_regtype)<CR>

" nnoremap <F10> :botright copen<CR>

xnoremap <silent> p p:if v:register == '"'<Bar>let @@=@0<Bar>endif<CR>

" Error navigation
nnoremap <UP> :cprev<CR>
nnoremap <DOWN> :cnext<CR>
nnoremap <RIGHT> :cnf<CR>
nnoremap <LEFT> :cpf<CR>

nnoremap <leader>y :ptjump <c-r><c-w><CR>

function! ToggleDiff()
  if &diff == 1
    windo diffoff
  else
    windo diffthis
  endif
endfunction
nnoremap <leader>g :call ToggleDiff()<CR>

if has('nvim')
  tnoremap <space><esc> <C-\><C-n>
  tnoremap <C-h> <C-\><C-n><C-w>h
  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
  augroup enter_term
    au!
    au BufEnter * if &buftype == 'terminal' | :startinsert | endif
  augroup END
endif

" Open buffers, tags... in vertical splits
nnoremap <leader>b :vert sbuffer 
nnoremap <leader>t :vert stjump 
nnoremap <leader>f :vert sfind 


" }}}

" Functions {{{
" When editing a file, always jump to the last known cursor position.
" Don't do it for commit messages, when the position is invalid, or when
" inside an event handler (happens when dropping a file on gvim).
autocmd BufReadPost *
      \ if &ft != 'gitcommit' && line("'\"") > 0 && line("'\"") <= line("$") |
      \   exe "normal g`\"" |
      \ endif

" Thg mappings
function! s:HGhist(file)
  if !empty(a:file)
    let path = a:file
  else
    let path = expand('%')
  endif
  exec 'silent! !thg filelog ' . path . ' &'
endfunction

command! -nargs=? -complete=file HGhist call s:HGhist(<q-args>)

augroup focus_lost
  au!
  au FocusLost * if !&readonly | :wa | endif
augroup END

augroup LuaHighlight
  autocmd!
  autocmd TextYankPost * silent! lua require'vim.highlight'.on_yank()
augroup END

" Resize splits after window resize {{{
augroup vim_resize
  au!
  au VimResized * exe "normal! \<c-w>="
augroup END
" }}}

" Automatically reload vimrc when saving {{{
augroup reload_vim
  autocmd!
  autocmd BufWritePost $MYVIMRC nested source $MYVIMRC
augroup END
" }}}

" Reload diffs {{{
augroup diff_files
  au!
  au BufWritePost * if &diff == 1 | diffupdate | endif
augroup END
" }}}

" Custom folding by Steve Losh
function! MyFoldText() " {{{
  let line = getline(v:foldstart)

  let nucolwidth = &fdc + &number * &numberwidth
  let windowwidth = winwidth(0) - nucolwidth - 3
  let foldedlinecount = v:foldend - v:foldstart

  " expand tabs into spaces
  let onetab = strpart('          ', 0, &tabstop)
  let line = substitute(line, '\t', onetab, 'g')

  let line = strpart(line, 0, windowwidth - 2 -len(foldedlinecount))
  let fillcharcount = windowwidth - len(line) - len(foldedlinecount)
  return line . '…' . repeat(" ",fillcharcount) . foldedlinecount . '…' . ' '
endfunction " }}}
set foldtext=MyFoldText()
set foldopen+=jump

" Detect Filetype from content if file has no extension {{{
augroup newFileDetection
  au!
  autocmd CursorMovedI * call CheckFileType()
augroup END

function! CheckFileType()
  if exists("b:countCheck") == 0
    let b:countCheck = 0
  endif
  let b:countCheck += 1
  if &filetype == "" && b:countCheck > 20 && b:countCheck < 200
    filetype detect
    " Delete the function if no filetype can be established, or the type has
    " been found
  elseif b:countCheck >= 200 || &filetype != ""
    autocmd! newFileDetection
  endif
endfunction
" }}}

" Convert hex <-> decimal {{{
command! -nargs=? -range Dec2hex call s:Dec2hex(<line1>, <line2>, '<args>')
function! s:Dec2hex(line1, line2, arg) range
  if empty(a:arg)
    if histget(':', -1) =~# "^'<,'>" && visualmode() !=# 'V'
      let cmd = 's/\%V\<\d\+\>/\=printf("0x%x",submatch(0)+0)/g'
    else
      let cmd = 's/\<\d\+\>/\=printf("0x%x",submatch(0)+0)/g'
    endif
    try
      execute a:line1 . ',' . a:line2 . cmd
    catch
      echo 'Error: No decimal number found'
    endtry
  else
    echo printf('%x', a:arg + 0)
  endif
endfunction

command! -nargs=? -range Hex2dec call s:Hex2dec(<line1>, <line2>, '<args>')
function! s:Hex2dec(line1, line2, arg) range
  if empty(a:arg)
    if histget(':', -1) =~# "^'<,'>" && visualmode() !=# 'V'
      let cmd = 's/\%V0x\x\+/\=submatch(0)+0/g'
    else
      let cmd = 's/0x\x\+/\=submatch(0)+0/g'
    endif
    try
      execute a:line1 . ',' . a:line2 . cmd
    catch
      echo 'Error: No hex number starting "0x" found'
    endtry
  else
    echo (a:arg =~? '^0x') ? a:arg + 0 : ('0x'.a:arg) + 0
  endif
endfunction
" }}}

" Recognize filetype for dup files {{{
autocmd! BufRead *.dup call DupSetSyntax(@%)

function! DupSetSyntax(name)
  let extension = matchlist(a:name, '\v.+.\.([^\.]+).dup')[1]
  if extension == "vhd"
    setlocal filetype=vhdl
  elseif extension == "v"
    setlocal filetype=verilog
  elseif extension == "sv"
    setlocal filetype=verilog
  else
    echo "Unknown filetype"
  endif
endfunction
" }}}

" Create arguments list from files in quickfix list
" Allows to Grep for a pattern and apply an argdo command on each of the
" matching files {{{
command! -nargs=0 -bar Qargs execute 'args' QuickfixFilenames()
function! QuickfixFilenames()
  " Building a hash ensures we get each buffer only once
  let buffer_numbers = {}
  for quickfix_item in getqflist()
    let buffer_numbers[quickfix_item['bufnr']] = bufname(quickfix_item['bufnr'])
  endfor
  return join(map(values(buffer_numbers), 'fnameescape(v:val)'))
endfunction
"}}}

augroup mark_files
  au!
  au BufLeave test.tcl mark T
  au BufLeave case.do mark C
  au BufLeave drv_*.tcl mark D
  au BufLeave *.rtl.vhd mark R
augroup END


" Toggle between opening/closing the quickfix window {{{
function! GetBufferList()
  redir =>buflist
  silent! ls!
  redir END
  return buflist
endfunction

function! ToggleList(bufname, pfx)
  let buflist = GetBufferList()
  for bufnum in map(filter(split(buflist, '\n'), 'v:val =~ "'.a:bufname.'"'), 'str2nr(matchstr(v:val, "\\d\\+"))')
    if bufwinnr(bufnum) != -1
      exec(a:pfx.'close')
      return
    endif
  endfor
  if a:pfx == 'l' && len(getloclist(0)) == 0
    echohl ErrorMsg
    echo "Location List is Empty."
    return
  endif
  let winnr = winnr()
  exec('botright '.a:pfx.'open')
  if winnr() != winnr
    wincmd p
  endif
endfunction

nnoremap <silent> <F10> :call ToggleList("Quickfix List", 'c')<CR>
" }}}


" Make list-like commands more intuitive {{{
" Copied from https://gist.github.com/romainl/047aca21e338df7ccf771f96858edb86
function! CCR()
    let cmdline = getcmdline()
    if cmdline =~ '\v\C^(ls|files|buffers)'
        " like :ls but prompts for a buffer command
        return "\<CR>:b"
    elseif cmdline =~ '\v\C/(#|nu|num|numb|numbe|number)$'
        " like :g//# but prompts for a command
        return "\<CR>:"
    elseif cmdline =~ '\v\C^(dli|il)'
        " like :dlist or :ilist but prompts for a count for :djump or :ijump
        return "\<CR>:" . cmdline[0] . "j  " . split(cmdline, " ")[1] . "\<S-Left>\<Left>"
    elseif cmdline =~ '\v\C^(cli|lli)'
        " like :clist or :llist but prompts for an error/location number
        return "\<CR>:sil " . repeat(cmdline[0], 2) . "\<Space>"
    elseif cmdline =~ '\C^old'
        " like :oldfiles but prompts for an old file to edit
        set nomore
        return "\<CR>:sil se more|e #<"
    elseif cmdline =~ '\C^changes'
        " like :changes but prompts for a change to jump to
        set nomore
        return "\<CR>:sil se more|norm! g;\<S-Left>"
    elseif cmdline =~ '\C^ju'
        " like :jumps but prompts for a position to jump to
        set nomore
        return "\<CR>:sil se more|norm! \<C-o>\<S-Left>"
    elseif cmdline =~ '\C^marks'
        " like :marks but prompts for a mark to jump to
        return "\<CR>:norm! `"
    elseif cmdline =~ '\C^undol'
        " like :undolist but prompts for a change to undo
        return "\<CR>:u "
    else
        return "\<CR>"
    endif
endfunction
cnoremap <expr> <CR> CCR()
" }}}

" Text objects {{{
function! s:inIndentation()
  " select all text in current indentation level excluding any empty lines
  " that precede or follow the current indentationt level;
  "
  " the current implementation is pretty fast, even for many lines since it
  " uses "search()" with "\%v" to find the unindented levels
  "
  " NOTE: if the current level of indentation is 1 (ie in virtual column 1),
  "       then the entire buffer will be selected
  "
  " WARNING: python devs have been known to become addicted to this
  " magic is needed for this
  let l:magic = &magic
  set magic

  " move to beginning of line and get virtcol (current indentation level)
  " BRAM: there is no searchpairvirtpos() ;)
  normal! ^
  let l:vCol = virtcol(getline('.') =~# '^\s*$' ? '$' : '.')

  " pattern matching anything except empty lines and lines with recorded
  " indentation level
  let l:pat = '^\(\s*\%'.l:vCol.'v\|^$\)\@!'

  " find first match (backwards & don't wrap or move cursor)
  let l:start = search(l:pat, 'bWn') + 1

  " next, find first match (forwards & don't wrap or move cursor)
  let l:end = search(l:pat, 'Wn')

  if (l:end !=# 0)
    " if search succeeded, it went too far, so subtract 1
    let l:end -= 1
  endif

  " go to start (this includes empty lines) and--importantly--column 0
  execute 'normal! '.l:start.'G0'

  " skip empty lines (unless already on one .. need to be in column 0)
  call search('^[^\n\r]', 'Wc')

  " go to end (this includes empty lines)
  execute 'normal! Vo'.l:end.'G'

  " skip backwards to last selected non-empty line
  call search('^[^\n\r]', 'bWc')

  " go to end-of-line 'cause why not
  normal! $o

  " restore magic
  let &magic = l:magic
endfunction

" "in indentation" (indentation level sans any surrounding empty lines)
xnoremap <silent> ii :<c-u>call <sid>inIndentation()<cr>
onoremap <silent> ii :<c-u>call <sid>inIndentation()<cr>

function! s:aroundIndentation()
  " select all text in the current indentation level including any emtpy
  " lines that precede or follow the current indentation level;
  "
  " the current implementation is pretty fast, even for many lines since it
  " uses "search()" with "\%v" to find the unindented levels
  "
  " NOTE: if the current level of indentation is 1 (ie in virtual column 1),
  "       then the entire buffer will be selected
  "
  " WARNING: python devs have been known to become addicted to this

  " magic is needed for this (/\v doesn't seem work)
  let l:magic = &magic
  set magic

  " move to beginning of line and get virtcol (current indentation level)
  " BRAM: there is no searchpairvirtpos() ;)
  normal! ^
  let l:vCol = virtcol(getline('.') =~# '^\s*$' ? '$' : '.')

  " pattern matching anything except empty lines and lines with recorded
  " indentation level
  let l:pat = '^\(\s*\%'.l:vCol.'v\|^$\)\@!'

  " find first match (backwards & don't wrap or move cursor)
  let l:start = search(l:pat, 'bWn') + 1

  " NOTE: if l:start is 0, then search() failed; otherwise search() succeeded
  "       and l:start does not equal line('.')
  " FORMER: l:start is 0; so, if we add 1 to l:start, then it will match
  "         everything from beginning of the buffer (if you don't like
  "         this, then you can modify the code) since this will be the
  "         equivalent of "norm! 1G" below
  " LATTER: l:start is not 0 but is also not equal to line('.'); therefore,
  "         we want to add one to l:start since it will always match one
  "         line too high if search() succeeds

  " next, find first match (forwards & don't wrap or move cursor)
  let l:end = search(l:pat, 'Wn')

  " NOTE: if l:end is 0, then search() failed; otherwise, if l:end is not
  "       equal to line('.'), then the search succeeded.
  " FORMER: l:end is 0; we want this to match until the end-of-buffer if it
  "         fails to find a match for same reason as mentioned above;
  "         again, modify code if you do not like this); therefore, keep
  "         0--see "NOTE:" below inside the if block comment
  " LATTER: l:end is not 0, so the search() must have succeeded, which means
  "         that l:end will match a different line than line('.')

  if (l:end !=# 0)
    " if l:end is 0, then the search() failed; if we subtract 1, then it
    " will effectively do "norm! -1G" which is definitely not what is
    " desired for probably every circumstance; therefore, only subtract one
    " if the search() succeeded since this means that it will match at least
    " one line too far down
    " NOTE: exec "norm! 0G" still goes to end-of-buffer just like "norm! G",
    "       so it's ok if l:end is kept as 0. As mentioned above, this means
    "       that it will match until end of buffer, but that is what I want
    "       anyway (change code if you don't want)
    let l:end -= 1
  endif

  " finally, select from l:start to l:end
  execute 'normal! '.l:start.'G0V'.l:end.'G$o'

  " restore magic
  let &magic = l:magic
endfunction

" "around indentation" (indentation level and any surrounding empty lines)
xnoremap <silent> ai :<c-u>call <sid>aroundIndentation()<cr>
onoremap <silent> ai :<c-u>call <sid>aroundIndentation()<cr>
" }}}
" }}}

" Filetype specific settings {{{
" Latex {{{
" Open pdf

function! Latexprog()
  if !filereadable("./Makefile")
    setlocal makeprg=latexmk\ -interaction=nonstopmode\ -synctex=1\ -file-line-error\ -pdf\ %:r
  endif
endfunction

augroup latex
  autocmd!
  autocmd FileType tex call Latexprog()
  au BufNewFile,BufRead,BufEnter *.tex setlocal spell spelllang=en_gb
  au BufNewFile,BufRead,BufEnter *.tex setlocal textwidth=0
augroup END
" }}}
" Markdown {{{
let g:vim_markdown_folding_disabled=1
" }}}
" Text {{{
augroup ft_text
  au!
  " au BufNewFile,BufRead,BufEnter *.txt setlocal spell spelllang=en_gb
  au BufNewFile,BufRead,BufEnter *.txt setlocal textwidth=0
augroup END
augroup ft_report
  au!
  au BufNewFile,BufRead,BufEnter *.rpt setlocal nowrap
  au BufNewFile,BufRead,BufEnter *.rpt call ColorRpt()
  au BufNewFile,BufRead,BufEnter *.log call ColorRpt()
augroup END

function! ColorRpt()
  " Color numbers based on length
  syn match String "\v<\d{1,3}>"   
  syn match Number "\v<\d{4,6}>"   
  syn match Statement "\v<\d{7,9}>"

  " Color errors
  syn match Error "\v^ERROR:.*$"
endfunction
" }}}
" Git commit messages {{{
augroup ft_git
  au!
  au FileType gitcommit setlocal spell spelllang=en_gb
augroup END
" }}}
" Ruby {{{
augroup ft_ruby
  au!
  autocmd BufRead *_spec.rb set filetype=rspec
augroup END
" }}}
" Matlab {{{
augroup ft_matlab
  au!
  autocmd FileType matlab setlocal commentstring=\%\ %s
augroup END
" }}}
" C {{{
augroup ft_c
  au!
  au FileType c setlocal foldmethod=syntax
augroup END
" }}}
" VHDL {{{
" VHDL ctags
let g:tlist_vhdl_settings = 'vhdl;d:package declarations;b:package bodies;e:entities;a:architecture specifications;t:type declarations;p:processes;f:functions;r:procedures'
let g:vhdl_indent_genportmap =0
let g:vhdl_indent_rhassign = 1

augroup ft_vhdl
  au!
  autocmd FileType vhdl call VHDLColonAlign()
augroup END

function! SetAutoAlign()
  inoremap <silent> => =><ESC>mzvip:EasyAlign/=>/<CR>`z$a
endfunction

function! VHDLChipScopeMacro()
  let @c = "mtyiw'Sosignal \"_cs : std_logic;'Coattribute mark_debug of \"_cs : signal is \"true\";
attribute dont_touch of \"_cs : signal is \"true\";'Do\"_cs <= \";=='t"
endfunction

function! VHDLColonAlign()
  let g:easy_align_delimiters = {
        \  ':': { 'pattern': ':', 'left_margin': 1, 'right_margin': 1, 'stick_to_left': 0}
        \}
endfunction
" }}}
" TCL {{{

augroup ft_tcl
  au!
  autocmd FileType tcl setlocal commentstring=#\ %s
  " autocmd FileType tcl compiler nagelfar
  autocmd BufRead *.do set filetype=tcl
  autocmd BufRead *.hal set filetype=tcl
  autocmd FileType tcl setlocal iskeyword+=:
  autocmd FileType tcl setlocal breakat-=:
  autocmd FileType tcl setlocal suffixesadd+=.tcl,.do
augroup END
" shortcuts
iabbrev procargs array set arg [::argument_processing::proces_arguments $args];
" }}}
" GPG {{{
" Don't save backups of gpg asc files
set backupskip+=*.asc

" Convenient editing of ascii-armoured encrypted files
augroup GPGASCII
  au!
  au BufReadPost *.asc :%!gpg -q -d
  au BufReadPost *.asc |redraw
  au BufWritePre *.asc :%!gpg -q -e -a
  au BufWritePost *.asc u
  au VimLeave *.asc :!clear
augroup END
" }}}
" System Verilog {{{
augroup ft_systemverilog
  au!
  au FileType systemverilog setlocal suffixesadd+=.sv,.v
  au FileType systemverilog setlocal foldmethod=expr
  au FileType systemverilog setlocal foldexpr=nvim_treesitter#foldexpr()
  au FileType systemverilog,verilog call SVAlign()
  au FileType systemverilog,verilog let b:delimitMate_quotes = "\""
augroup END

function! SVAlign()
  let g:easy_align_delimiters = {
        \  ')': { 'pattern': '[()]', 'left_margin': 0, 'right_margin': 0, 'stick_to_left': 0}
        \}
endfunction
" }}}
" Make {{{
augroup ft_make
  autocmd!
  autocmd BufEnter *.make setlocal filetype=make
  autocmd FileType make setlocal noexpandtab
augroup END
" JSON {{{
augroup ft_json
  autocmd!
  autocmd FileType json setlocal equalprg=jq
augroup END
" }}}
" }}}
" Python {{{
augroup f_python
  autocmd!
  autocmd FileType python setlocal shiftwidth=4
  au FileType python setlocal formatprg=autopep8\ -
  autocmd FileType python setlocal path-=**
  autocmd Filetype python let b:delimitMate_nesting_quotes = ['"', "'"]
augroup END

let g:python_highlight_all=1
" }}}
" }}}

" Plugin settings {{{
" Easy-align {{{
" Start interactive EasyAlign in visual mode (e.g. vip<Enter>)
vmap <Enter> <Plug>(EasyAlign)

" Start interactive EasyAlign for a motion/text object (e.g. gaip)
nmap ga <Plug>(EasyAlign)
" }}}
" Gundo tree {{{
nnoremap <leader>u :GundoToggle<CR>
" }}}
" Projectionist {{{
let g:projectionist_heuristics = {
      \ "*.c": {
      \   "*.c": {
      \     "alternate": "{}.h",
      \     "type": "source",
      \     "template": ["#include \"{}.h\""],
      \     "make": "make -wC {project}"
      \   },
      \   "*.h": {
      \     "alternate": "{}.c",
      \     "type": "header",
      \     "template": ["#ifndef {uppercase}_H", "#define {uppercase}_H", "", "#endif"]
      \   },
      \   "Makefile": {"type": "makefile"},
      \ },
      \ "*.py": {
      \   "*.py": { "make": "ipython {}" }
      \ },
      \ }
" }}}
" Grep {{{
let g:grepper = {
      \ 'tools': ['ag', 'hg'],
      \ 'highlight': 1,
      \ 'ag': { 
      \  'grepprg': 'rg --vimgrep',
      \ }}

nnoremap gs <plug>(GrepperOperator)
xnoremap gs <plug>(GrepperOperator)


command! -nargs=* -complete=file Ag Grepper -noprompt -tool ag -grepprg rg --vimgrep <args>
" }}}
" Vinegar/NetRW {{{
autocmd FileType netrw setl bufhidden=delete
" }}}
" NCM {{{
function! s:check_back_space() abort
  let col = col('.') - 1
  return !col || getline('.')[col - 1]  =~# '\s'
endfunction


" Auto close popup menu when finish completion
autocmd! CompleteDone * if pumvisible() == 0 | pclose | endif

" Use <Tab> and <S-Tab> to navigate through popup menu
inoremap <expr> <Tab>   pumvisible() ? "\<C-n>" : "\<Tab>"
inoremap <expr> <S-Tab> pumvisible() ? "\<C-p>" : "\<S-Tab>"

" Set completeopt to have a better completion experience
set completeopt=menuone,noinsert,noselect

" Avoid showing message extra message when using completion
set shortmess+=c

let g:completion_enable_snippet = 'UltiSnips'
"Fallback for https://github.com/Raimondi/delimitMate expanding on enter
let g:completion_confirm_key_rhs = "\<Plug>delimitMateCR"
let g:UltiSnipsJumpForwardTrigger="<c-b>"
let g:UltiSnipsJumpBackwardTrigger="<c-z>"

let delimitMate_expand_cr = 1
let delimitMate_expand_space = 1
" }}}
" Background make {{{
nnoremap <F9> :PMake<CR>
" }}}
" Splice {{{
let g:splice_initial_diff_grid=1
let g:splice_initial_diff_compare=1
let g:splice_initial_diff_path=0
let g:splice_initial_scrollbind_grid=1
let g:splice_initial_scrollbind_compare=1
let g:splice_initial_scrollbind_path=1
let g:splice_wrap="nowrap"
" }}}
" Chipscoper {{{
nnoremap <leader>cm :call ChipScoperMark()<CR>
nnoremap <leader>ci :call ChipScoperInsert()<CR>
nnoremap <leader>cd :call ChipScoperUnMark()<CR>
augroup cs_vhdl
  autocmd!
  autocmd FileType vhdl packadd chipscoper
  autocmd FileType vhdl silent! call ChipScoperSetup()
augroup END
" }}}
" GDB {{{
let  g:nvimgdb_disable_start_keymaps = 1
" }}}
" Indents {{{
let g:indentLine_char = '|'
" }}}
" }}}

function! SendOSCClipboard(lines, regtype)
   call SendViaOSC52(join(a:lines, "\n"))
endfunction

let g:clipboard = {
      \   'name': 'TMUX',
      \   'copy': {
      \      '+': function('SendOSCClipboard'),
      \      '*': 'tmux load-buffer -',
      \    },
      \   'paste': {
      \      '+': 'tmux save-buffer -',
      \      '*': 'tmux save-buffer -',
      \   },
      \   'cache_enabled': 1,
      \ }

luafile ~/.config/nvim/config.lua

" Load local vimrc
if filereadable($HOME . '/.vimrc.local')
  source ~/.vimrc.local
endif

" Load project local vimrc
if filereadable('.vimrc.local')
  source .vimrc.local
endif