"" My |vimrc| " TODO: Supply chain attacks are getting more common. We should use (mandate?) " commit hashes in `GitAdd`. Also, make sure to use a command format that " ignores tag/branch names (those can be named to look like hashes and are " mutable). " TODO: Do we want to try to integrate with Debian? There seems to be at least " two ways vim-related files are installed: " - Purely auxilliary files as part of some other package: Files are installed " to `/usr/share/vim/addons` which are referenced by files installed to " `/usr/share/vim/registry`. `vim-addons` from the `vim-addon-manager` can be " used to (presumably) symlink them into a path that is listed in " 'runtimepath'. " - As a standalone `vim-${addon}` package: Files are installed to " `/usr/share/vim-${addon}`, presumably symlinked into a `start` or `opt` " 'packpath' during package installation. " <https://vim-team.pages.debian.net/vim/> and the `dh_vim-addon` man page in " the `dh-vim-addon` package contains some further details. """ Formatting " A |'textwidth'| of 79 is used throughout. " Comments are written in Vim's help |notation|, see |help-writing|. They can " be highlighted with " <https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-comment>. " Section headings are not written in the help |notation|, but are instead " indicated with multiple contiguous comment characters. They can form folds " with <https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold>. """ Compatibility " TODO: Test with `nvi`, a "bug-for-bug compatible" clone of the original BSD " `vi`. " TODO: Test with `VIM_POSIX=1 "$vim"` (for different `$vim`s?). See " |$VIM_POSIX|. " This vimrc should work with all configurations of Vim. Manually tested with: " - Versions: TODO: Whatever some old {Debian,Ubuntu,Fedora} ships. " - Features: small, huge (Debian `apt-get install vim-{tiny,gtk3}`) " - Locales: C, UTF-8 (`LC_ALL=C{,.UFT-8}`) " - Colors: 1, 2, 8, 16, 256, termguicolors (`--cmd "set {t_Co=$colors,tgc}"`) " - UI: TUI, GUI (`{,g}vim`) " - Terminals: GUI, VTE, Linux, tmux with the correct `Ss` `terminal-override` " - Platforms: Unix-like " TODO: `man setfont` says: " > Note: if a font has more than 256 glyphs, only 8 out of 16 colors can be " > used simultaneously. It can make console perception worse (loss of " > intensity and even some colors). " The default font on my system has 512 glyphs (`showconsolefont -v`). " TODO: `man setfont` says, in section "CONSOLE MAPS": " > Several mappings are involved in the path from user program output to " > console display. " Might be worth reading up on that. If I already did, document. """ Features " |:version| says "tiny" features are always present and are therefore used in " favor other features whenever possible. "Tiny" features include: " - |+multi_byte| " - |+mouse| " - |+tag_binary| " - |+user_commands| " - |+autocmd| " - |+localmap| " Note that trying to set (run-time, but not compile-time) unsupported options " is silently ignored, and so can be done without checking for support first " (which is good, since that requires |+eval|). Everything between |:if| and " |:endif| is also silently ignored if |+eval| is not available. See " |no-eval-feature|. """ Encoding " |'encoding'| is hard-coded to `utf-8`. However, only characters present in " Code Page 437 should be used in the interface, to ensure font support on most " terminals (in particular, the Linux console, via `CHARMAP` in " `/etc/default/console-setup`). See " - <https://en.wikipedia.org/wiki/Code_page_437> " - <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/vt/cp437.uni> " - `man showconsolefont` """ Re-sourcing " |setglobal| is used where appropriate so that buffer/window-local options are " not overridden when re-sourcing. " A `vimrc` |augroup| is cleared and used for all |autocmd|s. At the time of " writing, |augroup| messes up the highlighting of |autocmd|s within it, so the " `vimrc` group name is added to every |autocmd| instead (the addition of the " group of course makes the highlighting misinterpret it as the " `vimAutoEventList` and the events instead get the erroneous " `VimAutoCmdSfxList` highlighting... file a bug?). This can be checked with " `:g/autocmd`. """ Mappings " Don't make any built-in mappings do something completely different! Another " Vimmer should never be surprised by what happens, unless it is pleasantly " surprised because the functionality is extended in useful and obvious ways. " This includes mappings from popular plugins, for which the defaults should be " kept as far as possible. " |<Leader>| is hard-coded to <Space> so that mappings work without |+eval|. " Setting |mapleader| to a different value after the mappings have been defined " does not change the mappings, so it is not possible to "hot-swap" it for pair " programming anyway. "" Options " TODO: Use |setglobal| for more things? Note that for options with a non-empty " default local value, `setglobal` does nothing useful. Worse, for options with " only a (buffer or window) local value, `setglobal` does nothing, literally. " Is that a problem, should we even set local values here? Maybe identifying " them and getting rid of them is a good idea? " TODO: Maybe source |defaults.vim|? Probably not, but add some documentation? " TODO: Look at |:options| and maybe follow the same grouping? " NOTE that |OptionSet| was added in " <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0081> and may not be available. """ Reset setglobal all& """ Encoding " Force Vim's internal encoding to a Unicode encoding. set encoding=utf-8 """ Buffers " Allow switching away from unsaved buffers. set hidden """ Clipboard " Integrate with any graphical environment's clipboard. set clipboard^=unnamedplus """ Editing set backspace=indent,eol,start set virtualedit=block """ Modeline set nomodeline """ Navigation set nostartofline " <http://ftp.vim.org/pub/vim/patches/9.0/9.0.0640>: Cannot scroll by screen " line if a line wraps. Add the 'smoothscroll' option. if has('patch-9.0.0640') set smoothscroll endif """ Windows " Put newly opened windows below and to the right. set splitbelow set splitright """ Interface set showcmd set noruler set laststatus=1 set showtabline=1 set shortmess+=I set guioptions=cf " console dialogs, foreground (no fork()) set numberwidth=1 """ Interface characters " If |'t_Co'| is empty (or set to 1) the default behavior of |'fillchars'| " `stl:`/`stlnc:` (`=`/`^`) will be used regardless of its setting. Other good " choices for |'listchars'| `fold:` is ` ` and `tab:` is: `→ `, `――>`, `├──`, " `──┤`, `├─┤`. " TODO: `:help 'fillchars'` says "for `stl` and `stlnc` only single-byte values " are supported". Test the current (non-ASCII) values against older versions of " Vim. See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.2569>. " TODO: If Vim cannot tell appart |hl-StatusLine| and |hl-StatusLineNC| (e.g. " because |hl-StatusLine| is a |hl-link|), (ordinary) spaces and `fillchars` " `stl` characters for the statusline of the focused window will be replaced " with `^`. Note that this includes the single character under the `fillchars` " `vert`, which cannot be set with |'statusline'|. set linespace=-1 set list set linebreak set breakindent set breakindentopt=sbr,shift:2 set showbreak=» set fillchars=stl:─,stlnc:─,vert:│,fold:─,diff: " set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff: set listchars=tab:├─,trail:•,extends:›,precedes:‹,nbsp:· " <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0759>: Showing two characters for " tab is limited. Allow for a third character for "tab:" in 'listchars'. if has('patch-8.1.0759') " ab c " set listchars+=tab:├\ ┤ set listchars+=tab:│\ │ endif " TODO: `%f` still shows `[No Name]`, is there a way to remove that? set statusline=%(%f\ %) if has('eval') " TODO: This works poorly with plugins that have windows with their own " statusbar, e.g. |undotree.txt|. " set statusline=%(%{expand('%:.s?^/??')}\ %) " `fillchar_status` function in `src/screen.c:4649` of Vim source. " TODO: Try to use some other non-standard space? Search for "\<SPACE\>" in " |digraphs|. " set fillchars+=stl:\ ,stlnc: set fillchars+=stl: ,stlnc: " set fillchars+=stl:┘,stlnc:┘ " TODO: Standardize on global functions? Or |autoload|s (but that would break " our "single file" policy)? " function! s:statusline() abort function! Statusline() abort " TODO: Make this expansion relative to the window-local cwd? Also do other " substitutions, like `$HOME` to `~`, the expanded `$VIMRUMTIME` to the " string `$VIMRUNTIME`, etc. We used to have `s?^/??`, why? " TODO: Harmonize with `titlestring`. let l:title = !empty(&l:buftype) ? &l:buftype : expand('%:~:.') if &l:buftype =~# 'help\|terminal' let l:title .= ':' . expand('%:t') elseif &l:buftype ==# 'quickfix' && exists('w:quickfix_title') let l:title .= ':' . w:quickfix_title endif if !empty(l:title) let l:title .= ' ' endif " NOTE: `matchstr` looks for the _first_ match. " TODO: This is slow. Cache the `matchstr` result? let l:fill = matchstr(&fillchars, '\(^\|,\)stl:\zs[^,]*') let l:pad = winwidth(0) - strwidth(l:title) return l:title . repeat(l:fill, l:pad) endfunction " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.1347>: Cannot easily get the " script ID. Support expand('<SID>'). " if has('patch-8.2.1347') " let &statusline = '%{'.expandcmd('<SID>statusline()').'}' " else let &statusline = '%{Statusline()}' " function! g:Statusline() abort " return s:statusline() " endfunction " endif endif """ Colors " May be overritten later by Vim for terminals with |t_RB|. set background=dark set guioptions+=d if &t_Co > 16 set t_Co=16 " <https://github.com/neovim/neovim/issues/11974#issuecomment-1658464993> if has('nvim') lua ffi = require "ffi" ffi.cdef "int t_colors" ffi.C.t_colors = 16 endif endif set notermguicolors " <https://github.com/termstandard/colors#truecolor-detection> if empty($COLORTERM) && !has('vcon') set notermguicolors endif if has('gui_running') set termguicolors endif """ Bell set belloff=error """ Title set title " set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:.:s?^/??'))}%) " TODO: Break out into `Title()` function and harmonize with `statusline`. set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{expand('%:.:s?^/??')}%) set titleold= """ Tabs " When reading files written by others, assume default `tabstop=8`. " When Writing files, use 4 space indents. set shiftwidth=4 set shiftround set softtabstop=-1 set expandtab """ Mouse set mouse=a """ Command-line set wildmenu set wildmode=longest:full,full " See also |'suffixes'|. set wildignore+=_* set wildignore+=.git set wildignore+=UPSTREAMS,FORKS " Relative to `$HOME`. set wildignore+=*/.vim/pack,*/.config/vim/pack,*/.config/nvim/pack set wildignore+=*/.cache, set wildignore+=*/.mozilla/firefox set wildignore+=*/.local/lib,*/.local/share/man set wildignore+=*/.vagrant,*/.ansible set wildignore+=*/.local/pipx,__pycache__,.venv,*.egg-info set wildignore+=*/.cargo set wildignore+=*/.npm,node_modules set wildignore+=*/.local/share/tldr set wildignore+=*/snap set wildignore+=*/.wine/dosdevices,*/.wine/drive_* " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325>: 'wildmenu' only shows few " matches. Add the "pum" option: use a popup menu to show the matches. if has('patch-8.2.4325') set wildoptions+=pum endif """ Search set incsearch set shortmess-=S """ Timing set lazyredraw set notimeout set ttimeout set ttimeoutlen=100 """ Diffs set diffopt+=vertical set diffopt+=foldcolumn:0 " <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360>: Using an external diff " program is slow and inflexible. Include the xdiff library. Use it by default. if has('patch-8.1.0360') set diffopt+=internal set diffopt+=algorithm:histogram set diffopt+=indent-heuristic endif """ Formatting " See |auto-format|, |format-comments|, and |fo-table|. set textwidth=79 " set winwidth=80 " set colorcolumn=+1 set autoindent set nojoinspaces " Don't autowrap text, enable comment formatting with |gq|, recognize lists, " remove comment leader when joining. set formatoptions-=t " set formatoptions+=q " TODO: This is the default? set formatoptions+=n set formatoptions+=j set nowrap " See also |breakindent|, |breakindentopt|, |showbreak| set above. " A custom 'formatprg' produces nicer results but is harder to replicate for " others and places undue burden on documentation contributors. Having simple " format rules is more important than slightly prettier formatting. " TODO: At least make the expressions valid (we're lacking spaces, no?). " if executable('par') " let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e']) " let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e', 'j']) " elseif executable('fmt') " let &formatprg = 'fmt' . '-w' . &textwidth '-g' . &textwidth " endif """ Comments " set commentstring=#%s """ Folds set foldlevelstart=999 set foldtext=substitute(getline(v:foldstart),'\\t',repeat('\ ',&ts),'g').'\ ' """ Spelling " set spell set spelllang=en_us set thesaurus=~/.vim/thesaurus/en_us.txt " TODO: We can probably do something better/cleaner for the thesaurus on our " own. In particular, publicly available, clearly licensed, version controlled, " code to generate the vim thesaurus from primary sources. " The current `~/.vim/thesaurus/en_us.txt` is downloaded from the URL " documented in |'thesaurus'|: " <https://github.com/vim/vim/issues/629#issuecomment-443293282>. This zip file " contains a patch to <https://www.openoffice.org/lingucomponent/MyThes-1.zip> " and the results of running the patched code on the included files, as well as " the licenses. `MyThes-1.zip` is linked from " <https://www.openoffice.org/lingucomponent/thesaurus.html> and seems to be " some version of <https://github.com/hunspell/mythes>. MyThes states in its " readme that it is based on WordNet 2.0. However, the latest version as of " this writing is 3.1. When generating a Vim version, it helps to have a " visualization to guide the heuristics that will probably be needed. Searching " <https://wordnet.princeton.edu/related-projects> for "thesaurus" gives " several projects. <https://wordvis.com> looks good (try e.g. "completion"). " Another search hit, " <https://www2.seas.gwu.edu/~simhaweb/software/jword/index.html>, states that " "WordNet's vocabulary is smaller than other "word" databases", so we might " want to use other sources as well, e.g. Roget's Thesaurus. " " WordNet " - <https://wordnet.princeton.edu/download/current-version> " - <https://wordnetcode.princeton.edu/wn3.1.dict.tar.gz> " Data hosted on Project Gutenberg " - <https://www.gutenberg.org/ebooks/3202> (2002) Moby Thesaurus List " - <https://www.gutenberg.org/ebooks/10681> (2004) Roget's Thesaurus of English Words and Phrases " - <https://www.gutenberg.org/ebooks/22> (1991) Roget's Thesaurus " - <https://www.gutenberg.org/ebooks/38390> (2011) A Dictionary of English Synonymes [...] " - <https://www.gutenberg.org/ebooks/51155> (2016) A Complete Dictionary of Synonyms and Antonyms " For Swedish, there is " - <https://folkets-lexikon.csc.kth.se/synlex.html> " - <https://spraakbanken.gu.se/en/resources/saldo> """ Views set viewoptions-=options set viewoptions+=slash set viewoptions+=unix """ Files set swapfile set writebackup set backupcopy=yes set undofile set directory=~/.cache/vim/swap// set backupdir=~/.cache/vim/backup// set undodir=~/.cache/vim/undo// set viewdir=~/.cache/vim/view// set viminfofile=~/.cache/vim/viminfo if has('nvim') set shadafile= endif """ Conceal set conceallevel=2 set concealcursor=nc """ Platform set shellslash """ External tools " Not POSIX: `-H` (suggested in 'grepprg'), `-I`. set grepprg=grep\ -nHI """ Quickfix set switchbuf=useopen "" Mappings " TODO: Categorize into map modes. Use the nonspecific |:map| (|mapmode-nvo|) " and |:map!| (|mapmode-ic|) more often? """ Escape " Overwrites the default |i_CTRL-C|, |v_CTRL-C|. See " <https://vim.fandom.com/wiki/Avoid_the_escape_key>. inoremap <C-C> <Esc> xnoremap <C-C> <Esc> """ Windows nnoremap <C-H> <C-W>h nnoremap <C-J> <C-W>j nnoremap <C-K> <C-W>k nnoremap <C-L> <C-W>l tnoremap <C-H> <C-W>h tnoremap <C-J> <C-W>j tnoremap <C-K> <C-W>k tnoremap <C-L> <C-W>l """ Clear and redraw " <C-L> is overridden above, so use a <Leader> mapping. nnoremap <Space><C-L> <C-L> """ Movement " Up down dispaly lines (unless a count is given). nnoremap <expr> j v:count ? 'j' : 'gj' nnoremap <expr> k v:count ? 'k' : 'gk' " End of pair opened at end of current line. " TODO: These are overridden by `matchit`. nnoremap <silent> g% :<C-U>norm! $%<CR> onoremap <silent> g% :<C-U>norm! $%<CR> xnoremap <silent> g% :<C-U>norm! v$%<CR> """ Scrolling " Put paragraph containing cursor line at the top of the window. " TODO: Preserve jump list somehow? nnoremap zg {jzt<C-O> """ Visual mode repeat " See also `vim-visualrepeat`. xnoremap . :normal! .<CR> """ Clipboard " Yank file and line number of cursor. nnoremap <silent> <Space>yy :let @+ = expand('%:p') . ':' . line('.')<CR> """ `$MYVIMRC` nnoremap <silent> <Space><Space>ve :edit $MYVIMRC<CR> nnoremap <silent> <Space><Space>vs :source $MYVIMRC<CR> """ Keyword " nnoremap K :silent execute "normal! K" \| redraw!<CR> " nnoremap <silent> K :terminal ++close <C-R>=&keywordprg<CR> <cword><CR> " TODO: vnoremap " TODO: `set keywordprg=:help` """ Help " TODO: Make this filetype dependent? Could use |:grep| or |fugitive|'s " |:Ggrep|. On the other hand, there are other built-in mappings that does " keyword search in a codebase. " TODO: Here we use `g` as prefix. Do we do that in other places? Should we not " use <Leader> (i.e. <Space>)? nnoremap <silent> gK :helpgrep \<<C-R><C-W>\><CR> xnoremap <silent> gK y:helpgrep <C-R>"<CR> """ Run " TODO: Standardize where the output goes. " File (with output in pager). nnoremap <silent> <Space><Space>% :!%:p:S \| less -FR<CR> nnoremap <silent> <Space><Space># :!#:p:S \| less -FR<CR> " Command (with output in new window). nnoremap <Space><Space>! :new \| .! """ Quickfix """" Toggle Quickfix window " TODO: Do similar for location list? " TODO: Make the |botright| global with some |autocmd|? nnoremap <expr> <Space><Space>q \ empty(filter(range(1,winnr('$')),'getwinvar(v:val,"&buftype")==#"quickfix"')) \ ? ':botright copen<CR>' \ : ':botright cclose<CR>' """ Make " TODO: |dispatch| provides default mappings, try to emulate them? " TODO: Should these be <silent> as well? " TODO: Use the |terminal-debugger| instead of a make target? nnoremap <Space><Space>m% :!make %:r:S \| less -FR<CR> nnoremap <Space><Space>m# :!make #:r:S \| less -FR<CR> nnoremap <Space><Space>mm :!make \| less -FR<CR> nnoremap <Space><Space>ma :!make all \| less -FR<CR> nnoremap <Space><Space>mt :!make test \| less -FR<CR> nnoremap <Space><Space>md :!make debug \| less -FR<CR> if has('quickfix') nnoremap <Space><Space>m% :silent make! %:r:S \| redraw!<CR> nnoremap <Space><Space>m# :silent make! #:r:S \| redraw!<CR> nnoremap <Space><Space>mm :silent make! \| redraw!<CR> nnoremap <Space><Space>ma :silent make! all \| redraw!<CR> nnoremap <Space><Space>mt :silent make! test \| redraw!<CR> endif if has('terminal') nnoremap <Space><Space>md :terminal make debug<CR> endif """ Improve default mappings """" Disable unconditional quit from Normal mode " As warned about in |zz| these may be typed accidentally when Caps Lock is " enabled and lose data. Redefining them is a bit hostile towards other users, " but deemed worth it. nnoremap <silent> ZZ :quit<CR> nnoremap <silent> ZQ :quit<CR> """" Yank to end of line, not entire line " As suggested in |Y|. Analogous with |D| does `d$` and |C| does `c$`. nnoremap Y y$ """" Don't include newline in Visual mode `$`. xnoremap $ $h """" Visual mode put that doesn't clobber unnamed register " See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4242>. xnoremap P pgvy """ Visual mode """" Visually select last pasted text " TODO: Make a text object as well? " TODO: I use this relatively often, but it clobbers the built in |gp|. I never " use that, but it seems useful, so maybe I should? Find another natural " mapping? " Analogous with how |gv| visually selects last visually selected text. Default " to always using ordinary Visual mode. Linewise and blockwise with |+eval| " support. nnoremap gp `[v`] if has('eval') nnoremap <expr> gp '`[' . getregtype()[0] . '`]' endif """" Restrict Visual mode substitutions to the selected text xnoremap <Space>s :s/\%V """" Visual movement xnoremap <C-h> hoho xnoremap <C-j> jojo xnoremap <C-k> koko xnoremap <C-l> lolo """ Scrolling " Arrow keys scroll. Useful when 'mouse' is empty and the terminal sends arrow " keys when scrolling with the mouse. noremap <Up> <C-Y> noremap <Down> <C-E> noremap <Left> zh noremap <Right> zl """ Mouse " As suggested in |scroll-mouse-wheel|, scroll only one line. noremap <ScrollWheelUp> <C-Y> noremap <ScrollWheelDown> <C-E> noremap <C-ScrollWheelUp> zh noremap <C-ScrollWheelDown> zl noremap <ScrollWheelLeft> zh noremap <ScrollWheelRight> zl " Toggle folds. noremap <RightMouse> <LeftMouse>za noremap <2-RightMouse> <LeftMouse>za noremap <3-RightMouse> <LeftMouse>za noremap <4-RightMouse> <LeftMouse>za """ Command-line " Take already written text into account when searching history. cnoremap <C-P> <Up> cnoremap <C-N> <Down> """ Macros " Repeat the macro in register `q` on current line, lines covered by visual " selection, or line covered by text object. nnoremap QQ @q xnoremap <silent> Q :normal! @q<CR> nnoremap <silent> Q :set operatorfunc=<SID>Q<CR>g@ if has('eval') function! s:Q(...) abort '[,']normal! @q endfunction endif """ Diffs " Current file. " Se also |:DiffOrig|. " TODO: Use a buffer? " <https://gist.github.com/romainl/7198a63faffdadd741e4ae81ae6dd9e6> nnoremap <silent> <Space><Space>dd :w ! \ diff -u --color=always %:S - \ \| tail -n +3 \ \| less -FR \ <CR> nnoremap <silent> <Space><Space>dw :w ! \ diff -u %:S - \ \| tail -n +3 \ \| wdiff -d -n \ -w "$([ "$(tput colors)" -ge 16 ] && tput setaf 9 \|\| { tput bold; tput setaf 1; })" \ -y "$([ "$(tput colors)" -ge 16 ] && tput setaf 10 \|\| { tput bold; tput setaf 2; })" \ -x "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })" \ -z "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })" \ \| less -FR \ <CR> " Requires `vim-fugitive`. nmap <silent> <Space><Space>dg :Gdiffsplit<CR> " Analogous with |dp| |do| in Normal mode. " TODO: Is adding a `diffupdate` at the end useful? nnoremap <silent> <Space>dpp :.diffput<CR> nnoremap <silent> <Space>doo :.diffget<CR> xnoremap <silent> <Space>dp :diffput<CR> xnoremap <silent> <Space>do :diffget<CR> nnoremap <silent> <Space>dp :set operatorfunc=<SID>diffput<CR>g@ nnoremap <silent> <Space>do :set operatorfunc=<SID>diffget<CR>g@ if has('eval') function! s:diffput(...) abort '[,']diffput endfunction function! s:diffget(...) abort '[,']diffget endfunction endif """ Formatting " Format comment (only). NOTE that this requires a `gc` comment text object " plugin. nmap gQ gqgc nmap gW gwgc """ Folds " Focus current fold. nnoremap zV zMzv " Focus next/previous fold. Overwrites default move to start/end of " next/previous fold. " TODO: |c_CTRL-R_=| requires |+eval|? nnoremap <silent> zj m<zjzvm>gvzc'>zv nnoremap <silent> zk zvzckVzvV:<C-R>=prevnonblank(line('.'))<CR><CR>zvzcVoVzv " Open/close nested folds recursively. Overwrites default open/close fold under " cursor recursively. nnoremap <silent> zO zvzczO nnoremap <silent> zC zvzcV:foldclose!<CR>zvzc """ Spelling " Correct last misspelled word with first suggestion without moving the cursor. " See also |compl-spelling|. nnoremap z? [s1z=<C-O> inoremap <C-L> <C-G>u<Esc>[s1z=`]a<C-G>u """ Visual mode operators " Allows for visual selection of text objects that share a name with an " operator. nnoremap <silent> <Space>v :set operatorfunc=<SID>v<CR>g@ nnoremap <silent> <Space>V :set operatorfunc=<SID>V<CR>g@ nnoremap <silent> <Space><C-V> :set operatorfunc=<SID>CV<CR>g@ if has('eval') function! s:v(...) abort execute 'normal!' '`[v`]' endfunction function! s:V(...) abort execute 'normal!' '`[V`]' endfunction function! s:CV(...) abort execute 'normal!' "`[\<C-V>`]" endfunction endif """ Normalize date to ISO 8601 " See |:visual_example|. " See also |abolish-coercion|. " This is hacky but works without |+eval|. xnoremap crd <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date +'\%Y-\%m-\%d' -f -<CR>kJJ """ Go to string in file under cursor " The built-in |gF|, and related |CTRL-W_F|, |CTRL-W_gF|, commands extend |gf| " by also parsing trailing `:{lineno}` (specifically, any non-filename " character optionally surrounded by whitespace, or the literal string " ` line `, followed by a decimal number). This corresponds to common output of " compilers/interpreters/linters. It also happens to roughly correspond to " _one_ of the common (or, for [POSIX.1-2017][], allowed) outputs of `ctags`. " It does not however allow the _other_ format: search strings. Let's fix that. " " Search strings are very useful when you're not sure what version of the file " someone else might have, so it's hard to give an accurate line number, but " the chance is high that a search string will yield the correct location. It " also conveys more information to someone not wanting to _follow_ the " reference right now than a line number would. " " Vim actually allows _any_ Ex command in tag files (subject to |'exrc'| and " |'secure'|, see |tag-security|), not just line numbers and search strings, " see |tags-file-format|. The mapping below only accepts what amounts to " possibly anchored non-regex search strings, for three reasons: 1) security, " 2) implementation simplicity, 3) it is what [POSIX.1-2017][] `ctags` / `ex` / " `vi` supports. " " It is important that we lean on the built-in mappings as much as possible " since they include functionality based on <count>, |'isfname'|, |'path'|, " |'suffixesadd'|, and |'includeexpr'|, special handling of escaped spaces and " trailing punctuation, as well as home directory and environment variable " expansion (|expandcmd|) that would be hard to re-implement, see |gf|. Note " that the built-in mappings only trigger when the cursor is on or before the " _filename_, not on the address. |gF| falls back to |gf| functionality without " giving an error message if a traling line number can't be found, which we " mimic. " " [POSIX.1-2017]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ctags.html#tag_20_27_12 " TODO: Also support `file:line:col`? if has('eval') nnoremap gF :<C-U>call <SID>gf("gF")<CR> nnoremap <C-W>F :<C-U>call <SID>gf("\<lt>C-W>F")<CR> nnoremap <C-W>gF :<C-U>call <SID>gf("\<lt>C-W>gF")<CR> function! s:gf(cmd) abort let back = '\\\\' let fwd = '\\\/' let dollar = '\$\/\@!' let other = '[^\/$]' let chr = '\%(' . join([back, fwd, dollar, other], '\|') . '\)' let str = '\(' . chr . '\+\)' let start = '\(\^\?\)' let end = '\(\$\?\)' let addr = '\/' . start . str . end . '\/' let after = '\%>' . (col('.')-1) . 'c' let file = '[[:fname:]]' let sep = '[[:space:]]*[^[:fname:][:digit:]/][[:space:]]*' let pat = '\m' . after . file . sep . addr let match = matchlist(getline('.'), pat) execute 'normal!' (v:count1 . a:cmd) if !empty(match) let start = match[1] let str = match[2] let end = match[3] let pat = '\C' . '\m' . start . '\V' . str . '\m' . end call cursor(1, 1) if search(pat, 'c') == 0 echo "Could not find search string:" (start . str . end) endif endif endfunction endif "" Commands """ Fill quickfix with output from system command " TODO: |<q-args>| does not seem to escape quotes, so things like `Cexpr echo " 'hello'` does not work. Probably passing it to a function so that we get a " argument variable to call |shellescape| on is required? " TODO: How does this compare to |dispatch|? command! -bang -complete=shellcmd -nargs=+ Cexpr \ execute (empty(<q-bang>)?'cexpr':'cgetexpr') 'system(expandcmd(' escape(<q-args>, "'") '))' """ Run `git ls` and preview commits on cursor move " Requires `vim-fugitive` and a `ls`/`lsa` Git alias. command! -bar Gls \ Git ls | \ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' | \ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' | \ execute 'autocmd vimrc BufUnload <buffer> pclose' | command! -bar Glsa \ Git lsa | \ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' | \ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' | \ execute 'autocmd vimrc BufUnload <buffer> pclose' | "" Auto commands " Make sure to not define any |autocmd|s before this! augroup vimrc autocmd! augroup END """ Hacks for options that Vim likes to reset " `$VIMRUNTIME/colors/default.vim` autocmd vimrc OptionSet background set background=dark """ Save/load view " Roughly as suggested in |:loadview|, load auto-saved view when opening " buffer. Better than |last-position-jump|, |restore-cursor|. See also " |'viewoptions'|. autocmd vimrc BufWinEnter,BufRead * \ if !empty(expand('<afile>')) && empty(&buftype) | \ loadview | \ endif | autocmd vimrc BufWinLeave,BufWrite * \ if !empty(expand('<afile>')) && empty(&buftype) | \ mkview | \ endif | """ Don't show extra things in special buffers " TODO: This needs to be moved to after the plugins for it to work in e.g. " fugitive? if !has('nvim') autocmd vimrc BufReadPost,TerminalWinOpen * \ if !empty(&buftype) | \ silent setlocal nolist nospell | \ endif endif """ QuickFix/Location list """" Open window " See " - <https://github.com/tpope/vim-dispatch/issues/145> " - <https://github.com/tpope/vim-dispatch/issues/254> " - <https://github.com/tpope/vim-dispatch/issues/310> " TODO: Maybe this can be fixed by switching back to the previous window after " opening the quickfix window? Make sure to only switch to the previous if we " actually opened the window. " autocmd vimrc QuickFixCmdPost [^l]* nested botright cwindow " autocmd vimrc QuickFixCmdPost l* nested botright lwindow " autocmd vimrc QuickFixCmdPost {{make,{,vim}grep{,add}},c{,get,add}{expr,file,buffer}} nested botright cwindow " autocmd vimrc QuickFixCmdPost {l{make,{,vim}grep{,add}},l{,get,add}{expr,file,buffer}} nested botright lwindow """" Conceal column numbers autocmd vimrc BufReadPost quickfix \ setlocal conceallevel=2 concealcursor=nvic nonumber | \ syntax match qfColumnNr / col \d\+/ containedin=qfLineNr transparent conceal | """ Highlight all searches " |'incsearch'| only highlights the first match. if has('eval') autocmd vimrc CmdlineEnter /,\? let s:hlsearch = &hlsearch | set hlsearch autocmd vimrc CmdlineLeave /,\? let &hlsearch = s:hlsearch endif "" Colors " See |cterm-colors|, |gui-colors|. silent !. ~/.shrc.d/color.sh " redraw! " TODO: Document that |autocmd| is available in "tiny" (i.e. always) but " |+syntax| requires "normal", so doing it the way we're doing it makes sure it " works everywhere. This is especially important for interface highlights " (|listchars|). " TODO: This is getting ridiculous. |:syntax-on| suggests we can just use " |:highlight| outside any |autocmd|s and it will work. Look into this. " TODO: Support `has('gui_running')` and |'termguicolors'|. Look into e.g. " |g:terminal_ansi_colors|. """ General " Transparent background, grayscale interface. Sensible errors/warnings, " spellchecking, diffs, comments, and todos. See |:hi-normal| and " |:hi-normal-cterm|. if !has('gui_running') autocmd vimrc ColorScheme * nested \ highlight! Normal guibg=NONE | endif " TODO: Look at all in |'highlight'| (in particular |hl-Search|) and |highlight-default|. " TODO: This could be done by setting |'highlight'| instead of monkying around " with highlight groups. Unclear if better. " TODO: For all chromatic colors, use `Light*`. " TODO: Remove all `White` except `Normal` from this list and link them to `Normal`? " TODO: Remove all `Gray` except `Comment` from this list and link them to `Comment`? " NOTE: When |hl-StatusLine| is a |:hi-link| Vim cannot determine if it's equal " to |hl-StatusLineNC| and uses "^^^". Same for `StatusLineTerm{,NC}`. See " `src/drawscreen.c:550` (at the bottom of the funtion `win_redr_status`) in " the Vim source. " TODO: Since the Linux console cannot use `DarkGray` as a background, consider " using any other `Dark*` color (e.g. `DarkYellow`) as (non-`reverse`) `Visual` " `ctermbg` with `ctermfg=NONE`. NOTE: This requires that we standardize on " `__color_set_uniform_diff_low`. `__color_set_uniform_diff_high` works (in " fact is required) for `cterm=reverse ctermfg=NONE ctermbg=NONE`. " TODO: Why do we need the `term=NONE`? Is this tested ever? Is it used in " `vim.tiny`? " TODO: Vim requests the background color from the terinal with the escape " sequence |t_RB| and sets |'background'| when it gets the response " (|v:termrbgresp|). That response may come after |vimrc| has completed, so if " you want to do |:colorscheme| do it in a `autocmd vimrc OptionSet " background`. " autocmd vimrc ColorScheme * nested " \ highlight Normal font='Monospace Regular 10' " \ set background=dark | runtime syntax/syncolor.vim | autocmd vimrc ColorScheme * nested \ highlight Normal term=NONE cterm=NONE gui=NONE ctermbg=NONE ctermfg=White | \ highlight Comment term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=DarkGray | \ highlight Todo term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=White | \ highlight Error term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=LightRed | \ highlight SpellBad term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=LightRed | \ highlight SpellOther term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=LightRed | \ highlight Visual term=NONE cterm=NONE gui=NONE ctermbg=LightGray ctermfg=NONE | \ highlight Search term=NONE cterm=NONE gui=NONE ctermbg=DarkYellow ctermfg=NONE | \ highlight DiffAdd term=NONE cterm=NONE gui=NONE ctermbg=DarkGreen ctermfg=NONE | \ highlight DiffDelete term=NONE cterm=NONE gui=NONE ctermbg=DarkRed ctermfg=NONE | \ highlight DiffChange term=NONE cterm=NONE gui=NONE ctermbg=DarkBlue ctermfg=NONE | \ highlight DiffText term=NONE cterm=NONE gui=NONE ctermbg=DarkYellow ctermfg=NONE | \ highlight diffAdded term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=LightGreen | \ highlight diffRemoved term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=LightRed | \ highlight StatusLine term=NONE cterm=NONE gui=NONE ctermbg=NONE ctermfg=White | \ highlight StatusLineTerm term=NONE cterm=NONE gui=NONE ctermbg=NONE ctermfg=White | \ highlight StatusLineNC term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=DarkGray | \ highlight StatusLineTermNC term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=DarkGray | \ highlight Ignore term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE ctermfg=Black | " \ highlight DiffAdd term=NONE cterm=NONE gui=NONE ctermbg=LightGreen ctermfg=Black | " \ highlight DiffDelete term=NONE cterm=NONE gui=NONE ctermbg=LightRed ctermfg=Black | " \ highlight DiffChange term=NONE cterm=NONE gui=NONE ctermbg=LightBlue ctermfg=Black | " \ highlight DiffText term=NONE cterm=NONE gui=NONE ctermbg=LightYellow ctermfg=Black | """ No bold " Remove all `cterm=bold` set by default in `$VIMRUNTIME/syntax/syncolor.vim`. " The Linux virtual console does typically not have a bold font. autocmd vimrc ColorScheme * nested \ highlight Identifier cterm=NONE ctermfg=LightCyan | """ Debug autocmd vimrc ColorScheme * nested \ highlight debugPC term=reverse cterm=NONE gui=NONE guibg=DarkBlue ctermbg=DarkBlue guifg=NONE ctermfg=NONE | \ highlight debugBreakpoint term=NONE cterm=NONE gui=NONE guibg=NONE ctermbg=NONE guifg=LightRed ctermfg=LightRed | " set highlight-=s:StatusLine " set highlight-=S:StatusLineNC " set highlight-=z:StatusLineTerm " set highlight-=Z:StatusLineTermNC " set highlight+=s:Normal,z:Normal,S:Comment,Z:Comment autocmd vimrc ColorScheme * nested \ highlight! link TabLineSel Normal | \ highlight! link ToolbarButton Comment | " \ highlight! link StatusLine Normal | " \ highlight! link StatusLineTerm Normal | """ Interface autocmd vimrc ColorScheme * nested \ highlight! link TabLine Comment | \ highlight! link TabLineFill Comment | \ highlight! link ToolbarLine Comment | \ highlight! link VertSplit Comment | \ highlight! link LineNr Comment | \ highlight! link Folded Comment | \ highlight! link FoldColumn Comment | \ highlight! link SignColumn Comment | " \ highlight! link StatusLineNC Comment | " \ highlight! link StatusLineTermNC Comment | """ Errors/warnings autocmd vimrc ColorScheme * nested \ highlight! link ErrorMsg Error | \ highlight! link WarningMsg Error | """ Spell autocmd vimrc ColorScheme * nested \ highlight! link SpellCap SpellOther | \ highlight! link SpellRare SpellOther | \ highlight! link SpellLocal SpellOther | """ Visual autocmd vimrc ColorScheme * nested \ highlight! link VisualNOS Visual | \ highlight! link ColorColumn Visual | \ highlight! link CursorColumn Visual | \ highlight! link CursorLine Visual | \ highlight! link CursorLineNr Visual | """ Popup menu " See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`. autocmd vimrc ColorScheme * nested \ highlight Pmenu ctermbg=LightGray ctermfg=DarkGray | \ highlight PmenuSel ctermbg=LightGray ctermfg=White | \ highlight PmenuSbar ctermbg=DarkGray | """ Non-document characters " See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`. autocmd vimrc ColorScheme * nested \ highlight! link NonText Special | \ highlight! link EndOfBuffer Ignore | """ Document non-printables characters " See |'listchars'| `tab`, `space`, `trail`, `nbsp`. autocmd vimrc ColorScheme * nested \ highlight! link SpecialKey Comment | """ Document concealed characters " See |'listchars'| `conceal`. autocmd vimrc ColorScheme * nested \ highlight! link Conceal Ignore | """ Vim comments autocmd vimrc ColorScheme * nested \ highlight! link vimCommentString vimComment | \ highlight! link vimCommentTitle vimComment | """ Apply " TODO: Move `syntax enable` to someplace before this? " TODO: `doautocmd vimrc ColorScheme` worked for everything except when using " Vim as `$MANPAGER`. Not sure if this is a problem with `vimrc` or " `.vim/ftplugin/man.vim`. We don't always `has('eval')` though. " echom &background " if has('eval') " colorscheme default " endif " echom &background doautocmd vimrc ColorScheme " autocmd vimrc VimEnter * nested doautocmd vimrc ColorScheme " autocmd vimrc OptionSet background,t_Co nested doautocmd vimrc ColorScheme "" Plugins if has('eval') """ GitAdd " <https://git.rcrnstn.net/rcrnstn/vim-gitadd> " Make sure to not enable |:syntax| and |:filetype| until all plugins that " interact with them have been added! See |:packadd|. command! -bar -bang -nargs=+ GitAdd call s:GitAdd(<q-bang>, <f-args>) function! s:GitAdd(bang, url, ...) abort let name = split(a:url, '/')[-1] let dir = split(&packpath, ',')[0] . '/pack/gitadd/opt/' . name if !isdirectory(dir) silent execute '!git clone --recurse-submodules' join(a:000) a:url dir if isdirectory(dir . '/doc') execute 'helptags' dir . '/doc' endif endif if empty(a:bang) execute 'packadd!' name endif endfunction """ File type """" Built-in `vim` " See |ft-vim-indent|. let g:vim_indent_cont = 0 """" Built-in `sh` " See |ft-sh-syntax|. let g:is_posix = 1 """" Built-in `man` " See |ft-man-plugin|. let g:ft_man_folding_enable = 1 " TODO: Should be easy to create a |'foldexpr'| that's better than the " built-in `foldmethod=indent`. " function s:manfold() abort " foldlevel() " endfunction " We're using our own |:ManHelp| instead. " runtime ftplugin/man.vim " setglobal keywordprg=:Man """" Built-in `asm` " See |ft-asm-syntax|. let g:filetype_i = 'asm' """" `tpope/vim-markdown` " GitAdd https://github.com/tpope/vim-markdown """" `preservim/vim-markdown` GitAdd https://github.com/preservim/vim-markdown let g:vim_markdown_no_default_key_mappings = 1 let g:vim_markdown_toc_autofit = 1 let g:vim_markdown_math = 1 let g:vim_markdown_frontmatter = 1 let g:vim_markdown_no_extensions_in_markdown = 1 " " Defaults. " " |vim-markdown-fenced-code-block-languages| " let g:vim_markdown_fenced_languages = [ " \ "c++=cpp", " \ "viml=vim", " \ "bash=sh", " \ "ini=dosini", " \ ] " " Additions. " call add(g:vim_markdown_fenced_languages, [ " \ "diff", " \ ]) " <https://github.com/preservim/vim-markdown/issues/232> " let g:vim_markdown_new_list_item_indent = 0 " let g:vim_markdown_auto_insert_bullets = 0 """" `vim-pandoc/vim-pandoc-syntax` " GitAdd https://github.com/vim-pandoc/vim-pandoc-syntax " Roughly as recommended in the readme. " autocmd vimrc BufNewFile,BufFilePre,BufRead *.md set filetype=markdown.pandoc """" `sheerun/vim-polyglot` GitAdd https://github.com/sheerun/vim-polyglot let g:polyglot_disabled = [ \ 'sensible', \ 'autoindent', \ 'markdown', \ ] """" `tpope/vim-sleuth` GitAdd https://github.com/tpope/vim-sleuth """" `tpope/vim-apathy` " GitAdd https://github.com/tpope/vim-apathy """" `tpope/vim-scriptease` GitAdd https://github.com/tpope/vim-scriptease """" `jyscao/vim-greprtpscr` GitAdd! https://github.com/jyscao/vim-greprtpscr """" `vimwiki/vimwiki` " GitAdd https://github.com/vimwiki/vimwiki " let g:vimwiki_list = [{ " \ 'path': '~/notes/', " \ 'syntax': 'markdown', " \ 'ext': '.md', " \ }] """" `mhinz/vim-rfc` GitAdd https://github.com/mhinz/vim-rfc """" `HiPhish/info.vim` GitAdd https://gitlab.com/HiPhish/info.vim """ Normal mode """" Built-in `matchit` packadd! matchit """" `tpope/vim-unimpaired` GitAdd https://github.com/tpope/vim-unimpaired " <https://github.com/tpope/vim-unimpaired/issues?q=conceal> " <https://github.com/tpope/vim-unimpaired/issues/105> " <https://github.com/tpope/vim-unimpaired/pull/152> nnoremap yoe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 2 : 0<CR><CR> nnoremap [oe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 0 : &conceallevel - 1<CR><CR> nnoremap ]oe :setlocal conceallevel=<C-R>=&conceallevel == 2 ? 2 : &conceallevel + 1<CR><CR> """" `tpope/vim-repeat` GitAdd https://github.com/tpope/vim-repeat """" `inkarkat/vim-visualrepeat` " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library> GitAdd https://github.com/inkarkat/vim-visualrepeat """" `tpope/vim-characterize` GitAdd https://github.com/tpope/vim-characterize """" `haya14busa/vim-asterisk` GitAdd https://github.com/haya14busa/vim-asterisk " As suggested by |asterisk-key-mappings|, except the mappings that don't " move the cursor set |'hlsearch'|. map * <Plug>(asterisk-*) map # <Plug>(asterisk-#) map g* <Plug>(asterisk-g*) map g# <Plug>(asterisk-g#) map <silent> z* <Plug>(asterisk-z*): set hlsearch<CR> map <silent> z# <Plug>(asterisk-z#): set hlsearch<CR> map <silent> gz* <Plug>(asterisk-gz*):set hlsearch<CR> map <silent> gz# <Plug>(asterisk-gz#):set hlsearch<CR> """" `AndrewRadev/splitjoin.vim` GitAdd https://github.com/AndrewRadev/splitjoin.vim " TODO: According to |splitjoin_align| this requires either of the Tabular or " Align plugins. We currently prefer vim-lion. Create a pull request? " let g:splitjoin_align = 1 """" `AndrewRadev/switch.vim` GitAdd https://github.com/AndrewRadev/switch.vim let g:switch_custom_definitions = [{ \ '\<0\>': '1', \ '\<1\>': '0', \ '\<OFF\>': 'ON', \ '\<Off\>': 'On', \ '\<off\>': 'on', \ '\<ON\>': 'OFF', \ '\<On\>': 'Off', \ '\<on\>': 'off', \ '\<NO\>': 'YES', \ '\<No\>': 'Yes', \ '\<no\>': 'yes', \ '\<YES\>': 'NO', \ '\<Yes\>': 'No', \ '\<yes\>': 'no', \ '\(\w*\)FALSE\(\w*\)': '\1TRUE\2', \ '\(\w*\)False\(\w*\)': '\1True\2', \ '\(\w*\)false\(\w*\)': '\1true\2', \ '\(\w*\)TRUE\(\w*\)': '\1FALSE\2', \ '\(\w*\)True\(\w*\)': '\1False\2', \ '\(\w*\)true\(\w*\)': '\1false\2', \ '\<\(set *\)no\([a-z]\+\)\>=\@!': '\1\2', \ '\<\(set *\)\([a-z]\+\)\>=\@!': '\1no\2', \ }] """" `terryma/vim-smooth-scroll` " GitAdd https://github.com/terryma/vim-smooth-scroll " Kind of useful when pair programming to give some indication of navigation, " mostly annoying when not. " Roughly as suggested in the readme. " noremap <silent> <C-U> :call smooth_scroll#up( &scroll*1, 20, &scroll/4)<CR> " noremap <silent> <C-D> :call smooth_scroll#down(&scroll*1, 20, &scroll/4)<CR> " noremap <silent> <C-B> :call smooth_scroll#up( &scroll*2, 20, &scroll/2)<CR> " noremap <silent> <C-F> :call smooth_scroll#down(&scroll*2, 20, &scroll/2)<CR> """ Insert mode """" `tpope/vim-endwise` GitAdd https://github.com/tpope/vim-endwise """" `jiangmiao/auto-pairs` GitAdd https://github.com/jiangmiao/auto-pairs " TODO: Look at "Swedish Character Conflict" in the documentation. " Disable meta mappings. let g:AutoPairsShortcutToggle = '' let g:AutoPairsShortcutFastWrap = '' let g:AutoPairsShortcutJump = '' let g:AutoPairsShortcutBackInsert = '' " Don't jump around too much. See |autopairs-options|. let g:AutoPairsCenterLine = 0 let g:AutoPairsMultilineClose = 0 """ Command-line mode """" `tpope/vim-rsi` " GitAdd https://github.com/tpope/vim-rsi """" `tpope/vim-abolish` GitAdd https://github.com/tpope/vim-abolish """ Operators """" `tpope/vim-surround` GitAdd https://github.com/tpope/vim-surround """" `tpope/vim-commentary` GitAdd https://github.com/tpope/vim-commentary """" `tommcdo/vim-lion` GitAdd https://github.com/tommcdo/vim-lion let g:lion_squeeze_spaces = 1 """" `tommcdo/vim-nowchangethat` GitAdd https://github.com/tommcdo/vim-nowchangethat """ Motions / text objects " TODO: Check that none of the later ones are not already defined by " `targets.vim`. """" `wellle/targets.vim` GitAdd https://github.com/wellle/targets.vim " `targets` just pairs up quotes from the beginning of line, which is often " not what we want (especially in shell scripts). xnoremap i" i" xnoremap i' i' xnoremap i` i` onoremap i" i" onoremap i' i' onoremap i` i` """" `bkad/CamelCaseMotion` GitAdd https://github.com/bkad/CamelCaseMotion let g:camelcasemotion_key = '<Space>' """" `tommcdo/vim-exchange` GitAdd https://github.com/tommcdo/vim-exchange """" `qstrahl/vim-dentures` " TODO: I'm not happy with this, replace. GitAdd https://github.com/qstrahl/vim-dentures """" `kana/vim-textobj-user` GitAdd https://github.com/kana/vim-textobj-user " All later plugins in the "Motions / text objects" category depend on this " plugin. See <https://github.com/kana/vim-textobj-user/wiki>. """" `kana/vim-textobj-entire` GitAdd https://github.com/kana/vim-textobj-entire """" `kana/vim-textobj-line` GitAdd https://github.com/kana/vim-textobj-line " As suggested in |textobj-line-default-key-mappings|, except `{a,i}l` is " taken by `targets` "last", so we use uppercase `{a,i}L`. let g:textobj_line_no_default_key_mappings = 1 omap aL <Plug>(textobj-line-a) omap iL <Plug>(textobj-line-i) xmap aL <Plug>(textobj-line-a) xmap iL <Plug>(textobj-line-i) """" `kana/vim-textobj-fold` GitAdd https://github.com/kana/vim-textobj-fold """" `kana/vim-textobj-syntax` GitAdd https://github.com/kana/vim-textobj-syntax """" `kana/vim-textobj-function` GitAdd https://github.com/kana/vim-textobj-function """" `idbrii/textobj-word-column.vim` GitAdd https://github.com/idbrii/textobj-word-column.vim """" `adriaanzon/vim-textobj-matchit` GitAdd https://github.com/adriaanzon/vim-textobj-matchit """" `rhysd/vim-textobj-continuous-line` GitAdd https://github.com/rhysd/vim-textobj-continuous-line """" `rsrchboy/vim-textobj-heredocs` GitAdd https://github.com/rsrchboy/vim-textobj-heredocs """ Colors """" `gruvbox-community/gruvbox` " TODO: This is a stopgap untill we make a Vim colorscheme from " <https://notes/rcrnstn/colors.md>. GitAdd https://github.com/gruvbox-community/gruvbox let g:gruvbox_contrast_dark = 'hard' let g:gruvbox_invert_selection = 0 autocmd vimrc OptionSet termguicolors nested \ execute 'colorscheme' &termguicolors ? 'gruvbox' : 'default' | doautocmd OptionSet termguicolors """ Windows """" `moll/vim-bbye` GitAdd https://github.com/moll/vim-bbye """ Folds """" `rcrnstn/vim-unobtrusive-fold` GitAdd https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold " As suggested in |unobtrusive_fold#text()|. set foldtext=unobtrusive_fold#text() " As suggested in |unobtrusive-fold-example|. " autocmd vimrc FileType * UnobtrusiveFoldComment " autocmd vimrc FileType markdown UnobtrusiveFoldChar # let g:vim_markdown_folding_disabled = 1 """ Undo """" `mbbill/undotree` GitAdd https://github.com/mbbill/undotree nnoremap <silent> <Space><Space>u :UndotreeToggle<CR> " let g:undotree_HighlightChangedText = 0 " let g:undotree_DiffCommand = 'diff -u' """ QuickFix """" Built-in `cfilter` packadd! cfilter """" `romainl/vim-qf` " GitAdd https://github.com/romainl/vim-qf " let g:qf_mapping_ack_style = 1 " let g:qf_shorten_path = 1 " TODO: Check if this causes problems, see the "Open the QuickFix/Location " list window" section. " let g:qf_auto_open_quickfix = 0 """ Spell """" `inkarkat/vim-SpellCheck` " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library> " GitAdd https://github.com/inkarkat/vim-SpellCheck """ Modelines """" `ypcrts/securemodelines` " GitAdd https://github.com/ypcrts/securemodelines " TODO: Last updated 2019 as of writing, can we be sure is this really more " secure than the built-in sandbox? Besides, we don't use modelines much " anyway. " let g:secure_modelines_verbose = 1 """ Environment interaction """" Built-in `netrw` let g:netrw_home = '~/.cache/vim/netrw' let g:netrw_banner = 0 " Netrw versions (roughly) 162h to 170 break `gx`. Never download the remote " file to a temporary. See " - <https://github.com/vim/vim/issues/1386> " - <https://github.com/vim/vim/issues/4738> " - <https://github.com/vim/vim/pull/7188> let g:netrw_nogx = 1 nnoremap <silent> gx :call netrw#BrowseX(netrw#GX(), 0)<CR> xnoremap <silent> gx y:call netrw#BrowseX(@", 0)<CR> """" `bogado/file-line` GitAdd https://github.com/bogado/file-line """" `ctrlpvim/ctrlp.vim` GitAdd https://github.com/ctrlpvim/ctrlp.vim " <https://github.com/kien/ctrlp.vim/issues/337> " <https://github.com/ctrlpvim/ctrlp.vim/pull/316> " <https://github.com/ctrlpvim/ctrlp.vim/issues/450> " NOTE: Highly dependent on non-documented ctrlp internals. function! s:ctrlp_syntax() abort execute 'autocmd vimrc OptionSet cursorline' \ 'if winnr() == ' winnr() ' && &cursorline |' \ ' set nocursorline |' \ 'endif |' syntax region CtrlPLine start="^" end="$" syntax region CtrlPLineSel start="\%#" end="$" highlight! link CtrlPLine Comment highlight! link CtrlPLineSel Normal " TODO: `&term ==# 'linux'` does not do `underline`. highlight CtrlPPrtCursor term=underline cterm=underline endfunction " We need to define the `Syntax` `autocmd` after `ctrlp` has been loaded, but " also when we reload the `vimrc`. " TODO: This still does not work when reloading the `vimrc`. autocmd vimrc VimEnter * \ autocmd vimrc Syntax ctrlp call s:ctrlp_syntax() autocmd vimrc Syntax ctrlp call s:ctrlp_syntax() let g:ctrlp_working_path_mode = '' let g:ctrlp_match_current_file = 1 let g:ctrlp_follow_symlinks = 2 let g:ctrlp_show_hidden = 1 let g:ctrlp_status_func = '' let g:ctrlp_line_prefix = '' let g:ctrlp_use_caching = 0 let g:ctrlp_use_readdir = 0 " Respect 'wildignore'. let g:ctrlp_max_files = 0 " Default 10000. let g:ctrlp_max_depth = 40 " Default 40. let g:ctrlp_match_window = 'max:20' " Default 'max:10' " let g:ctrlp_user_command_async = 1 if has('unix') " TODO: Set `grepprg` to something similar, that skips things in " 'wildignore'. let s:wildignore = split(&wildignore, ',') let s:wildignore_name = filter(copy(s:wildignore), '!count(v:val, "/")') let s:wildignore_path = filter(copy(s:wildignore), ' count(v:val, "/")') let g:ctrlp_user_command = \ 'find' . \ (!g:ctrlp_follow_symlinks ? '' : ' -L') . \ ' %s' . \ ' -mount' . \ ' -maxdepth ' . g:ctrlp_max_depth . \ ' \( -false' . \ (g:ctrlp_show_hidden ? '' : ' -o -name ".*"') . \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) . \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(v:val)')) . \ ' \) -prune -o' . \ ' -type f -print' . \ ' 2> /dev/null' . \ (!g:ctrlp_max_files ? '' : ' | head -n ' . g:ctrlp_max_files) " \ ' -type d -exec test -d {}/.git \; -prune -o' . " \ ' -exec grep -Il . {} +' . " \ ' \(' . " \ (g:ctrlp_follow_symlinks == 2 ? ' -o -type l' : '') . " \ ' \)' . " function! s:ctrl_find_prefix(prefix, list) abort " return map(copy(a:list), '["' . a:prefix . '", shellescape(v:val)]') " endfunction " function! s:ctrl_find_join(join, list) abort " return ['\('] + eval(join(a:list, '+["' . a:join . '"]+')) + ['\)'] " endfunction " let g:ctrlp_user_command = join( " \ ['find', (!g:ctrlp_follow_symlinks ? '' : '-L'), '%s'] + " \ ['-maxdepth', g:ctrlp_max_depth] + " \ s:ctrl_find_join('-o', " \ s:ctrl_find_prefix('-name', g:ctrlp_show_hidden ? [] : ['.*']) + " \ s:ctrl_find_prefix('-name', s:wildignore_name) + " \ s:ctrl_find_prefix('-path', s:wildignore_path) " \ ) + ['-prune', '-o'] + " \ ['-type', 'f', '-print'] + " \ ['2>', '/dev/null'] + " \ (!g:ctrlp_max_files ? [] : ['|', 'head', '-n', g:ctrlp_max_files]) " \ ) endif """" `mhinz/vim-tree` " GitAdd https://github.com/mhinz/vim-tree " As suggesteed in the readme. " autocmd vimrc FileType tree " \ setlocal foldmethod=expr """" `tpope/vim-fugitive` GitAdd https://github.com/tpope/vim-fugitive autocmd vimrc FileType fugitiveblame call fugitive#MapJumps() " http://vimcasts.org/episodes/fugitive-vim-browsing-the-git-object-database/ " TODO: Do we want `bufhidden=wipe`? autocmd vimrc BufReadPost fugitive://* setlocal bufhidden=delete " TODO: Add some `git log -L` (see man page) mapping. """" `tommcdo/vim-fugitive-blame-ext` GitAdd https://github.com/tommcdo/vim-fugitive-blame-ext """" `iberianpig/tig-explorer.vim` " GitAdd https://github.com/iberianpig/tig-explorer.vim """" `tpope/vim-dispatch` GitAdd https://github.com/tpope/vim-dispatch " https://github.com/tpope/vim-dispatch/issues/203 function! s:focus_start_set() abort if get(b:, 'start_local', 1) let b:start_local = get(b:, 'start') endif let b:start = s:start endfunction function! s:focus_start_unset() abort if type(get(b:, 'start_local')) == type('') let b:start = b:start_local else unlet! b:start endif unlet! b:start_local endfunction function! s:focus_start(bang, command) abort if !empty(a:command) let s:start = a:command augroup vimrc_dispatch_start autocmd! augroup END silent bufdo call s:focus_start_set() augroup vimrc_dispatch_start autocmd BufEnter * call s:focus_start_set() augroup END echo 'Set global default to :Start' s:start elseif a:bang unlet! s:start augroup vimrc_dispatch_start autocmd! augroup END silent bufdo call s:focus_start_unset() if type(get(b:, 'start')) == type('') echo 'Reverted default to :Start' b:start else echo 'Reverted default to :Start' endif else if type(get(s:, 'start')) == type('') echo 'Global focus is :Start' s:start elseif type(get(b:, 'start')) == type('') echo 'Buffer default is :Start' b:start else echo 'Global default is :Start' endif endif endfunction command! -bang -nargs=* -range=-1 -complete=customlist,dispatch#command_complete FocusStart \ call s:focus_start(<bang>0, <q-args>) " TODO: Put this in a QuickFix section? " TODO: Stick to the default mappings. nnoremap <Space><Space>m% :Make %:r:S<CR> nnoremap <Space><Space>m# :Make #:r:S<CR> nnoremap <Space><Space>mm :Make<CR> nnoremap <Space><Space>ma :Make all<CR> nnoremap <Space><Space>mt :Make test<CR> """" `tpope/vim-eunuch` GitAdd https://github.com/tpope/vim-eunuch """" `tpope/vim-projectionist` GitAdd https://github.com/tpope/vim-projectionist """ Debugging """" Built-in `termdebug` " See |terminal-debug|. packadd! termdebug " TODO: Add mappings. " TODO: Remove |:Winbar|. " TODO: Do some |termdebug-customizing|, especially |termdebug_shortcuts|. " TODO: Add some signs? ■♦←↑→↓›»•· " let g:termdebug_popup = 0 nnoremap <Space>dd :Termdebug nnoremap <Space>db :Break<CR> nnoremap <Space>dB :Clear<CR> nnoremap <Space>di :Step<CR> nnoremap <Space>do :Over<CR> nnoremap <Space>df :Finish<CR> nnoremap <Space>dr :Run<CR> nnoremap <Space>da :Arguments<CR> nnoremap <Space>ds :Stop<CR> nnoremap <Space>dc :Continue<CR> " nnoremap <Space>de :Evaluate<CR> " nnoremap <Space>dg :Gdb<CR> " nnoremap <Space>ds :Source<CR> " nnoremap <Space>da :Asm<CR> " nnoremap <Space>dw :Winbar<CR> """" `puremourning/vimspector` " GitAdd https://github.com/puremourning/vimspector " Debug Adapter Protocol (DAP) client. See " - <https://microsoft.github.io/debug-adapter-protocol/> " - <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Debugger-Adapter-Protocol.html> " <https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation> """" `vim-vdebug/vdebug` " GitAdd https://github.com/vim-vdebug/vdebug " Supports PHP, Python, Ruby, Perl, Tcl and NodeJS. " Common DeBugGer Protocol (DBGP) client. See " <https://en.wikipedia.org/wiki/DBGp>. endif " has('eval') "" Syntax and file type if has('gui_running') " See |'background'|. " TODO: Causes the GUI cursor to be misplaced? " gui endif if has('eval') filetype plugin indent on syntax enable endif "" File type detection " See |new-filetype|. if has('eval') autocmd! filetypedetect BufRead,BufNewFile *.Xresources setf xdefaults autocmd! filetypedetect BufRead,BufNewFile *.gdb*init setf gdb autocmd! filetypedetect BufRead,BufNewFile *.asy setf cpp autocmd! filetypedetect BufRead,BufNewFile *.gvpr setf c endif "" Language specific |help| if has('eval') function! s:help(cmd, arg, filetype) abort for i in range(len(a:cmd)) let a:cmd[i] = join( \ map(split(a:cmd[i], '%s', 1), 'shellescape(v:val)'), \ shellescape(a:arg) \ ) endfor silent help silent let old_shellredir = &shellredir silent let &shellredir = '>' silent setlocal buftype=nofile bufhidden=delete noswapfile silent setlocal noreadonly modifiable silent execute 'file' a:arg silent keepjumps normal! ggdG silent execute 'read' '!' join(a:cmd) silent keepjumps normal! ggdd silent execute 'setlocal' 'filetype=' . a:filetype silent setlocal readonly nomodifiable nomodified silent setlocal buftype=help silent let &shellredir = old_shellredir endfunction endif command! -nargs=1 -complete=shellcmd ManHelp \ call s:help(['man', '%s'], <q-args>, 'man') command! -nargs=1 PythonHelp \ call s:help(['python3', '-m', 'pydoc', '%s'], <q-args>, 'python') command! -nargs=1 OctaveHelp \ call s:help(['octave', '--eval', 'help("%s")'], <q-args>, 'octave') " TODO: Would be cool to define one for `filetype` `gitconfig` that does " `ManHelp git-config` and then `/^ {7}\zs` whith the first two components of " setion words and `<cowrd>`. "" File type overrides autocmd vimrc FileType * \ setlocal keywordprg=:ManHelp | " TODO: This needs work. We globally override `fillchars` `stl`/`stlnc` and " `statusline` but don't take into account file type plugins setting their own " `statusline`. " TODO: `w:quickfix_title` is not always defined (e.g. when openging the " quickfix list when it has not been populated). Guard the printing in some " way? autocmd vimrc FileType qf \ setlocal statusline=%{Statusline()} | autocmd vimrc FileType help \ setlocal statusline=%{Statusline()} | autocmd vimrc FileType vim \ setlocal keywordprg=:help | autocmd vimrc FileType sh \ setlocal shiftwidth=2 | autocmd vimrc FileType c,cpp,glsl \ setlocal commentstring=//\ %s | \ setlocal matchpairs=(:),{:},[:],<:> | \ setlocal cinkeys-=0# cinoptions=L0,l1,g0,N-s,E-s,t0,c0,C1,(s,u0,W1s,m1,j1,J1,N999,*999 | \ setlocal path=.,**/include,**/src,/usr/include,/usr/local/include,/usr/include/c++/11 | autocmd vimrc FileType man \ setlocal nolist nospell | \ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\(--\S\+\, \)\?\zs-' | autocmd vimrc FileType dot \ setlocal commentstring=//\ %s | autocmd vimrc FileType gitcommit \ setlocal nolist spell | autocmd vimrc FileType markdown \ setlocal spell complete+=kspell | " \ setlocal formatoptions-=q | autocmd vimrc FileType python \ setlocal keywordprg=:PythonHelp | autocmd vimrc FileType octave \ setlocal keywordprg=:OctaveHelp | " Don't insert comment leader after |i_<CR>|, |o|, or |O|. autocmd vimrc FileType * \ setlocal formatoptions-=r formatoptions-=o | " As suggested in |ft-syntax-omni|, use syntax completion if no other " completion has been defined. autocmd vimrc FileType * \ if &omnifunc ==# '' | \ setlocal omnifunc=syntaxcomplete#Complete | \ endif | " TODO: Add a match for `\<TODO\>` (and `\<NOTE\>`?) unconditionally for all " file types. "" Terminal overrides " See |terminal-options|. """ Cursor " See |termcap-cursor-shape|, `:helpgrep t_SH`, and "Parameterized Strings" in " `terminfo(5)`. if has('cursorshape') set noshowmode " Cursor visible/invisible " On Linux the following is the default, which messes with our cursor " shape: " - `t_ve = "\033[?25h\033[?0c"` " - `t_vi = "\033[?25l\033[?1c"` " See " - <https://vt100.net/docs/vt510-rm/DECTCEM> " - `console_codes(4)` let &t_ve = "\033[?25h" let &t_vi = "\033[?25l" " if $TERM =~? '^xterm\(-\|$\)' " See " - <https://vt100.net/docs/vt510-rm/DECSCUSR> " - `:helpgrep t_SH` let &t_EI = "\033[1 q" let &t_SI = "\033[5 q" let &t_SR = "\033[3 q" let &t_SH = "\033[%p1%d q" " endif if $TERM =~? '^linux\(-\|$\)' " See " - <https://www.kernel.org/doc/Documentation/admin-guide/vga-softcursor.rst> " - `console_codes(4)` let &t_EI = "\033[?6c" let &t_SI = "\033[?2c" let &t_SR = "\033[?2c" let &t_SH = "\033[?%?%p1%{3}%<%t%{6}%e%{2}%;%dc" endif endif """ True-color " See |xterm-true-color|. if has('termguicolors') && !has('nvim') " These are the defaults if `$TERM` is `xterm`. let &t_8f = "\033[38;2;%lu;%lu;%lum" let &t_8b = "\033[48;2;%lu;%lu;%lum" " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516>: Terminal window does not " have transparent background when 'termguicolors' is used. Fix the " background color. if !has('patch-8.2.3516') let s:termguicolors = &termguicolors autocmd vimrc OptionSet termguicolors \ let s:termguicolors = &termguicolors autocmd vimrc TerminalOpen,WinEnter * \ let s:newtermguicolors = \ s:termguicolors && \ empty(filter(range(1, bufnr('$')), \ 'getbufvar(v:val, "&buftype") ==# "terminal"' \ )) | \ if s:newtermguicolors != &termguicolors | \ execute 'set' (s:newtermguicolors ? '' : 'no') . 'termguicolors' | \ endif | endif endif