"" 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). Maybe we deem some "publishers" worthy of trust, Tim Pope tags
" releases of many of his plugins for instance.
" 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.
" TODO: |unix| says
"
" > Temporary files (for filtering) are put in "/tmp". If you want to place
" > them somewhere else, set the environment variable $TMPDIR to the directory
" > you prefer.
"
" and since we go to some effort to keep other intermediate files in
" `~/.cache/vim` for privacy, we might want to create a shell alias that does
" `alias vim='TMPDIR="$HOME/.cache/vim/tmp" vim'`, as well as making sure that
" directory exists in shell startup files.
"
" Actually, I'm pretty sure we can do this from inside Vim (requires 'eval'
" though), which might be cleaner (although some dotfiles for other programs
" that do similar things do it in shell startup files). Do both?
"
" NOTE: This is an environment variable and affects child processes, including
" ones run from the `:terminal`.
""" 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|
"
" TODO: What category features are placed in depends on Vim version. Look up
" and create some table.
" 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|.
""" Patches
" TODO: Instead of checking for patches we might want to standardize on
" `exists()` instead since it is more descriptive and takes the compile-time
" |+feature-list| into account (which would otherwise require
" `has('patch-{patch}') && has('{feature}')`). The version/patch does indicate
" how old the feature is and so how likely to be supported. Use
" `exists('+option')` (not `exists('&option')`, see e.g. |missing-options|) and
" `exists('##event')`
" See |has-patch|.
" |:helpgrep| |c_CTRL-R_CTRL-A| (mapped to `<Space>K` below).
" - 8.1.0081
""" 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`
" One can find characters by looking at |digraph-table| in a lowest common
" denominator terminal. Some characters tested to work (not all from Code Page
" 437) *myvimrc-characters*:
" - Rectangular: ■█▒░ (not ▌▐▓)
" - Triangular: (not ►◄▲▼)
" - Circular: ●•∙· (not ○☼)
" - Other: ‼︎… (not ⌂♦☺︎☻)
" - Arrows: ‹›«»←→↑↓ (not ↔↕)
" - Box: │─├┤┼ (not ║═)
" - Math: ∩×∆∅
" - Greek: ΔΛλ
""" 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.
" In this file, |<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. |mapleader| is still set though,
" because some plugins expect it.
""" Debugging
" See |load-plugins|, |slow-start|.
""" Novice
" |myvimrc-novice|
" The goal is to make it at least workable to pair program with a Vim novice
" using this configuration.
" From more heavy-handed to less:
" - `$VIMRUNTIME/evim.vim`, |easy|, |evim-keys|, |i_CTRL-L|
" - `$VIMRUNTIME/mswin.vim`
" - |:behave|
" TODO: Mark novice-unfriendly option settings as
" |myvimrc-novice-unfriendly-$option|? (My original motivator for this was that
" I thought setting 'hidden' was a bit dangerous, but it is set automatically
" in easy mode!)
"" Helpers
""" Define and clear autocmd group
" TODO: I seem to remember augroups being closed automatically at end of file,
" in which case we could omit the `augroup END` and group name from our
" `autocmd`s.
augroup vimrc
autocmd!
augroup END
""" Functions
if has('eval')
" See |has-patch|.
" TODO: After and including 7.4.237 `has("patch-{major}.{minor}.{patch}")`
" works and is nicer. If we never check for any version before that we might
" remove this.
function! s:has(major, minor, patch) abort
let version = 100 * major + minor
return v:version > version || (v:version == version && has('patch'.patch))
endfunction
" `$VIMSRC/src/option.h:/P_COMMA/`
" `$VIMSRC/src/option.h:/P_FLAGLIST/`
endif
"" Options
" |:let-option|
" Note that even options listed as local (only) have global variants. E.g.
" 'fileencoding' is listed as "local to buffer" but 'fileencodings' says: "Note
" that 'fileencodings' is not used for a new file, the global value of
" 'fileencoding' is used instead. You can set it with: `:setglobal
" fenc=iso-8859-2`".
" `$VIMSRC/src/optiondefs.h:/Options local to a window/`
" `$VIMSRC/src/structs.h:/Options local to a window/`
" `$VIMSRC/src/structs.h:/options that are local to a window/`
" 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?
""" Reset
" Undoes changes to global options made by any |system-vimrc| or interactively
" (if re-sourced). The value of 'compatible' determines what defaults are
" loaded, but 'nocompatible' is set automatically at startup when a user vimrc
" file (this file!) is found |compatible-default|.
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
" 'modeline' is local to buffer, 'modelines' is global.
" set nomodeline
set modelines=0
""" Navigation
set nostartofline
set sidescroll=1
set sidescrolloff=1
" set scrolloff=1 " Useful for |[[|.
set display=lastline
" <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 " TODO: Local to window.
endif
""" Windows
" Put newly opened windows below and to the right.
" Use |:aboveleft| to override.
set splitbelow
set splitright
""" Interface
set showcmd
" TODO: Also look a bit at <https://github.com/tpope/vim-flagship>? Maybe
" `flagship#tabcwds()` to summarize the tab working directory.
" TODO: We could split the current `Statusline()` into
" `Statusline{Left,Right}()` and have the new `Statusline()` join them with
" 'fillchars', and `Ruler()` join them with `:`. Since the same functionality
" is also used by 'titlestring' maybe name them something less statusline
" centric? `Bufname(fill, right)`?
" set ruler
" set rulerformat=%=%(%{expand('%:t')}:%)%l
set noruler
set laststatus=1
set showtabline=1
set shortmess+=I " See |:intro|.
set guioptions=cf " Console dialogs, foreground (no fork())
set numberwidth=1 " TODO: Local to window.
""" Interface characters
" See also |myvimrc-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 `^` (i.e. the default `fillchars` `stl`). Note that this includes the
" single character under the `fillchars` `vert`, which cannot be set with
" |'statusline'|.
set linespace=-1
set list " TODO: Local to window.
set linebreak " TODO: Local to window.
set breakindent " TODO: Local to window.
set breakindentopt=sbr,shift:2 " TODO: Local to window.
set showbreak=» " TODO: Local to window (or global).
set fillchars=diff: ,stl:─,stlnc:─,vert:│,fold:─
" set fillchars=diff: ,stl:_,stlnc:_,vert:│,fold:─
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')
" set listchars+=tab:├─┤
" set listchars+=tab:├ ┤
set listchars+=tab:│ │
endif
" TODO: `%f` still shows `[No Name]`, is there a way to remove that?
set statusline=%(%f %) " TODO: Local to window (or global).
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! s:opt(opt, key) abort
return matchstr(a:opt, '.*\(^\|,\)' . key . ':\zs[^,]*')
return split(a:opt, )
endfunction
function! s:expand() abort
endfunction
function! Statusline() abort
" TODO: The global CWD, `getcwd(-1)`, might be useful. Also indicate
" `haslocaldir()` somehow?
" 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`.
" TODO: Generalize `&filetype`, `&buftype` and the matched `bufname()`
" `<type>://` somehow?
if &filetype ==# 'man'
let title = &filetype . ':' . expand('%:t')
" elseif &buftype =~# 'nofile\|nowrite'
" let title = &filetype
elseif &buftype ==# 'help'
let title = &buftype . ':' . expand('%:t:s?.txt$??')
elseif &buftype ==# 'terminal'
" TODO: We sometimes want to use some variation of `expand('%')`, e.g.
" when using the |terminal-debugger|.
" TODO: 'statusline' is not re-evaluated when |term_gettitle()| changes,
" can we do something like `let &statusline = &statusline` in some
" |autocmd| (perhaps one that triggers when the terminal content
" changes)? Worst case |CursorMoved|.
let title = &buftype . ':' . substitute(term_gettitle(bufnr()), '[^:]*:', '', '')
" TODO: Change the `&&` into nested `if`? Note that it has different
" semantics because of the `if`/`elseif`/`else` chain.
elseif &buftype ==# 'quickfix' && !empty(get(w:, 'quickfix_title'))
" Remove leading colon (Ex commands) and trailing parenthesis (e.g.
" |dispatch| job number).
let title = w:quickfix_title
let title = substitute(title, '^:', '', '')
let title = substitute(title, '\s*([^)]\+)\s*$', '', '')
let title = &buftype . ':' . title
else
let title = expand('%')
" fugitive:///home/rcrnstn/repo/.git//hash/dir/file.ext
" fugitive:///home/rcrnstn/repo/.git//hash/dir/file.ext
" TODO: |split()| on `:` (info), `://` (fugitive) and `#` (info), do
" processing, and then `join(filter(parts, '!empty(v:val)'), ':')`.
" Replace names of the form `<type>://<path>/.<dot>//<obj>` with
" `<type>:<obj>` where any leading 40 character hex string (hash) in
" `<obj>` is truncated to 7 characters. (Yes, this was designed for
" |fugitive|.)
let parts = matchlist(expand('%'),
\ '^\%(\([^:]\+\)://\)\?\%(\(.*\)//\)\?\(.*\)'
\ )
if !empty(parts)
let [type, prefix, path] = parts[1:3]
if !empty(prefix)
while fnamemodify(prefix, ':t')[:0] ==# '.'
let prefix = fnamemodify(prefix, ':h')
endwhile
let prefix = fnamemodify(prefix . '/', ':~:.:h:t:s?^\.$??')
endif
let path = substitute(path,
\ '^\([0-9a-fA-F]\{7\}\)[0-9a-fA-F]\{33\}\(/.*\|$\)', '\1\2', ''
\ )
let title = join(filter([type, prefix, path], '!empty(v:val)'), ':')
endif
endif
if !empty(title)
let title = substitute(title, ' *$', '', '') . ' '
endif
let title = substitute(title, ' ', ' ', 'g')
" NOTE: `matchstr` looks for the _first_ match.
" TODO: This is slow. Cache the `matchstr` result?
let fillchar = matchstr(&fillchars, '\(^\|,\)stl:\zs[^,]*')
let pad = winwidth(0) - strdisplaywidth(title)
return title . repeat(fillchar, 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
set statusline=%{Statusline()} " TODO: Local to window (or global).
" function! g:Statusline() abort
" return s:statusline()
" endfunction
" endif
" TODO: This doesn't seem to do the trick.
autocmd vimrc CursorMoved *
\ if &buftype ==# 'terminal' |
\ let &statusline = &statusline |
\ 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 titlelen=0
" set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:.:s?^/??'))}%)
" TODO: Break out into `Title()` function and harmonize with `statusline`.
" TODO: Ideas from `tpope/vim-flagship`: `hostname()` and `v:servername`.
set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{expand('%:.:s?^/??')}%)
set titleold=
function! s:cwdname() abort
return fnamemodify(getcwd(), ':~:t:s?^$?/?')
endfunction
function! s:bufname() abort
return expand('%:.:s?^/??')
return pathshorten(expand('%:.:s?^/??'))
endfunction
""" Tabs
" When reading files written by others, assume default `tabstop=8`.
" When Writing files, use 4 space indents.
set shiftwidth=4 " TODO: Local to buffer.
set shiftround
set softtabstop=-1 " TODO: Local to buffer.
set expandtab " TODO: Local to buffer.
""" Mouse
" |scroll-mouse-wheel| is generally useful, the rest for |myvimrc-novice|.
set mouse=a
set mousemodel=popup
set selectmode+=mouse
""" Novice
set keymodel=startsel,stopsel
set selectmode+=key
set whichwrap+=<,>,[,]
""" Command-line
" See also Readline's `menu-complete`, documented in `bash(1)`.
set wildmenu
set wildmode=longest:full,full
" See also |'suffixes'|.
" Source control.
" set wildignore+=_*
set wildignore+=.git
" Programming language specific.
set wildignore+=__pycache__,.venv,*.egg-info
set wildignore+=node_modules
" Relative to `$HOME`.
set wildignore+=$HOME/projects/UPSTREAMS
set wildignore+=$HOME/.vim/pack
set wildignore+=$HOME/.config/vim/pack
set wildignore+=$HOME/.config/nvim/pack
set wildignore+=$HOME/.cache
set wildignore+=$HOME/.local/lib
set wildignore+=$HOME/.local/share/man
set wildignore+=$HOME/.local/share/tldr
set wildignore+=$HOME/.mozilla/firefox
set wildignore+=$HOME/.ansible
set wildignore+=$HOME/.vagrant
set wildignore+=$HOME/.local/pipx
set wildignore+=$HOME/.cargo/register
set wildignore+=$HOME/.cargo
set wildignore+=$HOME/.npm
set wildignore+=$HOME/.wine/dosdevices
set wildignore+=$HOME/.wine/drive_*
set wildignore+=$HOME/snap
" <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 notimeout
""" Terminal
set ttimeout
set ttimeoutlen=100
set ttyfast
set lazyredraw
" A |'ttyscroll'| of 0 is beneficial on local terminals (especially reduces
" flickering on Linux VT), but might be worse on slow remote connections. Set
" |'writedelay'| to a small value (like 1), and maybe |'redrawtime'| to a very
" large value (like 20000), to see what difference this option makes. See also
" |myvimrc-autocmd-ttyscroll|.
set ttyscroll=0
""" 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 |formatting|, |auto-format|, |format-comments|, and |fo-table|.
set textwidth=79 " TODO: Local to buffer.
" set winwidth=80
" set colorcolumn=+1 " TODO: Local to window.
set autoindent " TODO: Local to buffer.
set nojoinspaces
" Don't autowrap text (non-comments), recognize lists, remove comment leader
" when joining.
set formatoptions-=t " TODO: Local to buffer.
set formatoptions+=n
set formatoptions+=j
" See also |breakindent|, |breakindentopt|, |showbreak| set above.
set nowrap " TODO: Local to window.
" 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?).
" TODO: Local to buffer (or global).
" 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 = join(['fmt', '-w'.&textwidth, '-g'.&textwidth])
" endif
""" Comments
" set commentstring=#%s " TODO: Local to buffer.
""" Folds
set foldlevelstart=999
" TODO: Local to window.
set foldtext=substitute(getline(v:foldstart),'\\t',repeat(' ',&ts),'g').' '
""" Spelling
" set spell
set spelllang=en_us " TODO: Local to buffer.
set thesaurus=~/.vim/thesaurus/en_us.txt " TODO: Local to buffer (or global).
" 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>
"
" Other assorted resources:
" - <https://github.com/dahu/vimdictive>
" - <https://dict.org>
""" Views
" TODO: Per the documentation `curdir` is only supposed to save the
" window-local directory as set by |:lcd|, which I wouldn't mind so much and
" might even make use of. But currently it is being set apparently without my
" involvement (perhaps by some plugin, probably |netrw|) far too often, and
" since we do |:loadview| on every opened file this gets annoying fast.
set viewoptions-=options
set viewoptions-=curdir
set viewoptions+=slash
set viewoptions+=unix
""" Files
set swapfile " TODO: Local to buffer.
set writebackup
set backupcopy=yes " TODO: Local to buffer (or global).
set undofile " TODO: Local to buffer.
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('eval')
let $TMPDIR = $HOME . '/.cache/vim/tmp'
call mkdir($TMPDIR, 'p')
endif
if has('nvim')
set shadafile=
endif
""" Conceal
set conceallevel=2 " TODO: Local to window.
set concealcursor=n " TODO: Local to window.
""" Platform
set shellslash
""" Filenames
" I generally allow everything (except control codes) in filenames on the
" filesystem. However, only media files (photos or videos) tend to take
" advantage of that, to be more descriptive/preserve some upstream name. Files
" I will want Vim to be able to cross-reference will be text (code or notes)
" with more constrained names. Disallowing some punctuation makes things like
" |gf| more useful.
" NOTE: This is a global option, but some ftplugins (Perl) change it anyway.
" `:grep -R 'isf\(name\)\?' /usr/share/vim/vim82/ftplugin/`
" *myvimrc-isfname-bug*
set isfname-=, " Common file separator.
set isfname-=; " Common file separator.
set isfname-=: " Common file separator (e.g. when using |gf|).
set isfname-=# " URL fragment separator.
""" External tools
" Not POSIX: `-H` (suggested in 'grepprg'), `-I`.
set grepprg=grep\ -nHI " TODO: Local to buffer (or global).
""" Quickfix
set switchbuf=useopen
"" Mappings
" TODO: Categorize into map modes. Use the nonspecific |:map| (|mapmode-nvo|)
" and |:map!| (|mapmode-ic|) more often?
""" Mapleader
" Prefill command line with query to discover mapleader mappings.
nnoremap <Space>? :verbose nmap <lt>Space>
nnoremap <Space><Space>? :verbose nmap <lt>Space><lt>Space>
""" 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>
""" Novice
" We
""" Windows
"""" Focus
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
"""" Move
if has('eval')
function! s:winmove(dir) abort
let prefix =
\ dir ~=# '[hj]' ? 'leftabove' :
\ dir ~=# '[kl]' ? 'belowright'
winnr(a:dir)
endfunction
endif
"""" Empty vertical split
" See also |CTRL-W_n|, which does |:new|.
nnoremap <C-W>N :vnew<CR>
"""" Resize
" Resize height to number of lines in buffer.
nnoremap <expr> <C-W>? line('$')."<C-W>_"
""" 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).
" TODO: Mappings like these that extend builtin functionality (identify them
" and put them in the same place) could be made more formally feature complete
" by doing the same thing for any aliases (listed in `:help j` etc). If the
" functinonality is implemented in other modes (insert and the various visual
" modes) then that should probably be extended too. Document this general
" principle.
nnoremap <expr> j v:count ? 'j' : 'gj'
nnoremap <expr> k v:count ? 'k' : 'gk'
" When moving to the next/previous '{'/'}' in the first column (function
" body/struct definition start/end), make visible the matching '}'/'{'
" (function body/struct definition end/start) and paragraph containing '{'
" (function prototype/struct name and preceeding comments). A prefix of 'g'
" aligns the paragraph containing '{' to the top of the window.
" TODO: Keep jumps somehow? `:keepjumps normal!`?
" TODO: |]]| says "[count] sections forward or to the next '{' in the first
" column". |section| says "a section begins after a form-feed (<C-L>) in the
" first column and [...]". We completely ignore the form-feed aspect. It's not
" commonly seen in code, but the GNU Coding Standards recommends them
" <https://www.gnu.org/prep/standards/standards.html#index-formfeed>.
nnoremap ]] ]]%%m'vipo<Esc>''
nnoremap g]] ]]%%m'vipozt<Esc>''
nnoremap [[ [[%%m'vipo<Esc>''
nnoremap g[[ [[%%m'vipozt<Esc>''
nnoremap ][ ][m'%vipo<Esc>''
nnoremap g][ ][m'%vipozt<Esc>''
nnoremap [] []m'%vipo<Esc>''
nnoremap g[] []m'%vipozt<Esc>''
""" Search and edit file
" See also |ctrlp|.
nnoremap <C-P> :edit **/**<Left>
""" Visual line insert and append
" TODO: This breaks text object that start with `A` or `I`. Ironically, those
" two characters specifically are prefixes in `wellle/targets.vim`.
" xnoremap <expr> A mode() !=# 'V' ? 'A' : ':normal A'
" xnoremap <expr> I mode() !=# 'V' ? 'I' : ':normal I'
" End of pair opened at end of current line.
" TODO: These are overridden by `matchit`, use `<Space>%` instead?
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/bottom of the window.
" TODO: Preserve jump list somehow?
" TODO: If |+eval|, also account for |scrolloff|?
nnoremap z{ {jzt<C-O>
nnoremap z} }kzb<C-O>
""" Visual mode repeat
" See also `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>:lcd %:h<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>)?
" TODO: We do have a `<Space>K` `FileType vim,help` mapping.
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
"""" Go to first/last valid entry
" |:cfirst|, |:clast|, |[Q|, and |]Q| (the last ones being
" `vim-unimpaired` mappings) go to the first/last entry regardless of whether
" it is |quickfix-valid| (includes a file name). I prefer to go to the
" first/last entry that includes a file name (even if I was already
" before/after that entry).
nnoremap [Q :cfirst \| silent! execute "cnext\|cprev"<CR>
nnoremap ]Q :clast \| silent! execute "cprev\|cnext"<CR>
"""" Toggle Quickfix window
" TODO: Do similar for location list?
" TODO: Make the |botright| global with some |autocmd|? Is it implied by our
" `set split{below,right}`?
nnoremap <expr> <Space><Space>q
\ empty(filter(getwininfo(),
\ 'getbufvar(v:val.bufnr, "&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 `$`.
" TODO: Do you just want `set selection=old`? Nope, the builtin `matchit`
" doesn't work correctly with `selection=old`, this is probably a bug though
" and might get fixed.
" set selection=old
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
""" Mouse
"""" Scroll vertically by single lines
" As suggested in |scroll-mouse-wheel|.
nnoremap <ScrollWheelUp> <C-Y>
xnoremap <ScrollWheelUp> <C-Y>
inoremap <ScrollWheelUp> <C-O><C-Y>
nnoremap <ScrollWheelDown> <C-E>
xnoremap <ScrollWheelDown> <C-E>
inoremap <ScrollWheelDown> <C-O><C-E>
"""" Scroll horizontally by single columns with <C-Scrollwheel>
nnoremap <C-ScrollWheelUp> zh
xnoremap <C-ScrollWheelUp> zh
inoremap <C-ScrollWheelUp> <C-O>zh
nnoremap <C-ScrollWheelDown> zl
xnoremap <C-ScrollWheelDown> zl
inoremap <C-ScrollWheelDown> <C-O>zl
nnoremap <ScrollWheelLeft> zh
xnoremap <ScrollWheelLeft> zh
inoremap <ScrollWheelLeft> <C-O>zh
nnoremap <ScrollWheelRight> zl
xnoremap <ScrollWheelRight> zl
inoremap <ScrollWheelRight> <C-O>zl
"""" Toggle folds with <2-RightMouse>
" 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>
" Try not to interfere with |'wildmenu'|.
if has('eval')
cnoremap <expr> <C-P> wildmenumode() ? "\<C-P>" : "\<Up>"
cnoremap <expr> <C-N> wildmenumode() ? "\<C-N>" : "\<Down>"
endif
""" Wildmenu
" <Left> and <Right> moves the cursor, not the completion selection. As
" suggested in 'wildmenu'.
cnoremap <Left> <Space><BS><Left>
cnoremap <Right> <Space><BS><Right>
""" Terminal
" TODO: Call a function that:
" - Find (the first) buffer with `&buftype ==# 'terminal'`
" - If it doesn't have window, create one and make it focused
" - Switch to the terminal buffer
" - If none, do `:terminal`
" NOTE: The proceedure described above is more or less `:Start` from
" `vim-dispatch`.
nnoremap <Space><Space>t :terminal<CR>
""" 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
" Toggle 'diffopt' ignores
" See also |unimpaired|'s |yod|. Mapping suffix based on the `diff` flags.
" TODO: `&diffopt=~'iwhite'` will match if `&diffopt` contains e.g.
" `iwhiteall`, use `'\(^\|,\)iwhite\(,\|$\)'` instead. Introduce a helper
" function that does the wrapping. Update: We're trying out word boundaries.
" TODO: Maybe even introduce a helper that does the toggling. Look at
" `vim-unimpaired` implementation?
nnoremap yoDB :set diffopt<C-R>=&diffopt=~'\<iblank\>' ?'-':'+'<CR>=iblank<CR>
nnoremap yoDi :set diffopt<C-R>=&diffopt=~'\<icase\>' ?'-':'+'<CR>=icase<CR>
nnoremap yoDb :set diffopt<C-R>=&diffopt=~'\<iwhite\>' ?'-':'+'<CR>=iwhite<CR>
nnoremap yoDw :set diffopt<C-R>=&diffopt=~'\<iwhiteall\>'?'-':'+'<CR>=iwhiteall<CR>
nnoremap yoDZ :set diffopt<C-R>=&diffopt=~'\<iwhiteeol\>'?'-':'+'<CR>=iwhiteeol<CR>
nnoremap <expr> yoDB ':set diffopt'.(&diffopt=~'\<iblank\>' ?'-':'+').'=iblank<CR>'
nnoremap <expr> yoDi ':set diffopt'.(&diffopt=~'\<icase\>' ?'-':'+').'=icase<CR>'
nnoremap <expr> yoDb ':set diffopt'.(&diffopt=~'\<iwhite\>' ?'-':'+').'=iwhite<CR>'
nnoremap <expr> yoDw ':set diffopt'.(&diffopt=~'\<iwhiteall\>'?'-':'+').'=iwhiteall<CR>'
nnoremap <expr> yoDZ ':set diffopt'.(&diffopt=~'\<iwhiteeol\>'?'-':'+').'=iwhiteeol<CR>'
" Windows
" This could be smarter. E.g. Look if *any* window has 'diff' set and save them
" in a list before doing `:diffoff`; restore for all windows when doing
" `:diffthis`.
nnoremap <Space><Space>dw :windo diff<C-R>=&diff?'off':'this'<CR><CR>
" Current file.
" Se also |:DiffOrig|.
" TODO: Use a buffer?
" TODO: `--old-group-format "$(TODO)"`
" <https://gist.github.com/romainl/7198a63faffdadd741e4ae81ae6dd9e6>
nnoremap <silent> <Space><Space>dff :w !
\ diff -u --color=always %:S -
\ \| tail -n +3
\ \| less -FR
\ <CR>
nnoremap <silent> <Space><Space>dfw :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
""" Align operator
" Requires the `column` program (in `bsdextrautils` on Debian).
" See also |lion|.
" TODO: Does not support |count|, |quote|.
" TODO: When re-sourcing the vimrc, this overrides the previous |vim-lion|
" mappings.
xnoremap gl !column -t -o ' '<CR>
if has('eval')
nnoremap gl :set operatorfunc=<SID>gl<CR>g@
function! s:gl(...) abort
'[,']!column -t -o ' '
endfunction
endif
""" Normalize date to ISO 8601
" Requires the `date` program (in `coreutils` on Debian).
" 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
" Make |gF| support `filename:/search string/`.
"
" 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 trailing line number can't be found, which we
" mimic. |gF| also doesn't give an error (or any) message if the given line
" number is not present in the file (it goes to the closest one, i.e. the first
" or last line), so we use a "soft" |:echo| instead of "hard" |:echoerr| to
" tell the user if the search string was not found.
"
" [POSIX.1-2017]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ctags.html#tag_20_27_12
" TODO: I think the regex is not quite right, like it triggers even when the
" cursor is not on the filename. Maybe we need to put the |/\%>| in a group, or
" adjust the `col('.')-1`. I lost the test case, sorry.
" TODO: Clarify/expand separators. POSIX mandates tabs as separators for tag
" files, document that we use the |gF| rules instead, after we implement them
" completely (` line `). Also hardcode to allow : as separator, because
" ftplugin/perl.vim:/^set isfname/ adds : to the set of valid filenames
" 'isfname' (a global option!). Document this too.
" TODO: POSIX allows / and ? as pattern delimiters, we only allow /. Fix this
" and document.
" TODO: POSIX allows the anchors ^ and $ to be used independently. It looks
" like we do too, but it is not clear from the documentation.
" TODO: Also support `file:line:col`? Generalize the separator to conform to
" the |gF| rules, but change ` line ` to ` col(umn)? `.
" TODO: We are accruing features. Split into plugin? `vim-unobtrusive-gf`?
" TODO: The excessive string concatenation is done for readability, but it
" might be better (and faster) as comments? Those can get out of sync though...
if has('eval')
nnoremap <silent> gF :<C-U>call <SID>gf("gF")<CR>
nnoremap <silent> <C-W>F :<C-U>call <SID>gf("\<lt>C-W>F")<CR>
nnoremap <silent> <C-W>gF :<C-U>call <SID>gf("\<lt>C-W>gF")<CR>
let s:isfname = &isfname
function! s:gf(cmd) abort
let back = '\\\\'
let slash = '\\\/'
let dollar = '\$\/\@!'
let other = '[^\/$]'
let chr = '\%(' . join([back, slash, 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
" echo pat
let v:errmsg = ""
try
" See |myvimrc-isfname-bug|. Save the current 'isfname' and then set it
" to the one we set in our vimrc earlier (i.e. our actual preference).
let isfname = &isfname
let &isfname = s:isfname
let match = matchlist(getline('.'), pat)
silent! execute 'normal!' (v:count1 . a:cmd)
finally
" If the above `execute` triggered a change in 'isfname' through a loaded
" ftplugin, let that change stand. Otherwise revert our earlier override.
if &isfname ==# s:isfname
let &isfname = isfname
endif
endtry
if v:errmsg != ""
echohl Error | echomsg v:errmsg | echohl None
elseif !empty(match)
let start = match[1]
let str = match[2]
let end = match[3]
let pat = '\C' . '\m' . start . '\V' . escape(str, '\') . '\m' . end
call cursor(1, 1)
if search(pat, 'c')
normal! zz
else
echo "Can't 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 -nargs=+ -complete=shellcmd Cexpr
\ execute (empty(<q-bang>)?'cexpr':'cgetexpr') 'system(expandcmd(' escape(<q-args>, "'") '))'
""" Run `git ls` and preview commits on cursor move
" TODO: |fugitive|'s |Gclog| probably covers this use case. Remove?
" Requires |fugitive| and a `ls`/`lsa` Git alias.
command! -bar -nargs=0 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 -nargs=0 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' |
""" Diff
" See also |start-vimdiff|, |:DiffOrig|.
" TODO: This is unfinished.
if has('eval')
command! -nargs=* -complete=file Diff call s:diff(<q-args>)
function! s:diff(arglist) abort
" windo diffoff
" if a:0
" let args = map(
" \ flatten(map(
" \ copy(a:000),
" \ 'expand(v:val, 1, 1)'
" \ )),
" \ 'fnameescape(v:val)'
" \ )
" execute 'args' join(args)
if a:arglist
execute 'args' arglist
vertical all
windo diffthis
else
" let filetype = &filetype
" let swapfile = &swapfile
diffthis
aboveleft vertical new
diffthis
" let &filetype = filetype
" let &swapfile = swapfile
let &filetype = getbufvar('#', '&filetype')
let &swapfile = getbufvar('#', '&swapfile')
let &buftype = 'nofile'
let &bufhidden = 'wipe'
let &modifiable = 1 " Even `bh=wipe` doesn't forget the `noma` below.
execute 'file' 'diff://' . expand('#:p')
read ++edit #
1 delete _
let &modifiable = 0
wincmd p
endif
endfunction
endif
"" Auto commands
""" Options
"""" 'background'
" Vim likes to automatically reset |'background'| at inopportune moments (like
" at `$VIMRUNTIME/colors/default.vim:/set bg&/`).
if has('eval')
let s:background = &background
autocmd vimrc OptionSet background let &background = s:background
endif
"""" 'ttyscroll'
" *myvimrc-autocmd-ttyscroll*
" Unconditionally enable |'ttyscroll'| (by setting it to its default value
" `999`) if there are no vertical splits (so terminal scrolling can actually be
" used without downsides) and restore if there are vertical splits. Makes the
" most noticeable difference when doing |CTRL-U| |CTRL-D| in a Linux virtual
" terminal.
" TODO: When we set it to `999` we could store the current value in
" `s:ttyscrol` so that manual adjustments won't be lost.
if has('eval')
let s:ttyscroll = &ttyscroll
autocmd vimrc VimEnter,WinEnter *
\ let &ttyscroll = empty(filter(getwininfo(), 'v:val.wincol != 1'))
\ ? 999
\ : s:ttyscroll
endif
""" Save/load view
" Roughly as suggested in |:loadview|, load auto-saved view when opening
" buffer. Better (TODO: how?) than |last-position-jump|, |restore-cursor|. See
" also |'viewoptions'|.
" TODO: Use a (configurable?) `[nr]` argument to the `{mk,load}view` and
" reserve the use of the no argument version for the user.
" TODO: We used to also match on `Buf{Write,Read}` but that generated "E32: No
" file name" when e.g. discarding changes with `X` in the `vim-fugitive` `:Git`
" window.
autocmd vimrc BufWinLeave *
\ if !empty(expand('<afile>')) && empty(&buftype) |
\ mkview |
\ endif |
autocmd vimrc BufWinEnter *
\ if !empty(expand('<afile>')) && empty(&buftype) |
\ loadview |
\ endif |
""" Unclutter 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
""" Fixate terminal height
autocmd vimrc TerminalWinOpen *
\ set winfixheight |
\ 15wincmd _ |
""" QuickFix/Location list
"""" Open window automatically
" 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: These `vim-dispatch` issues might have been fixed?
" 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
""" Terminal folding
" If a line (like a shell prompt) starts with `│` it will define a fold start.
" TODO: More "shell integrations":
" - <https://wezterm.org/shell-integration.html>
" - <https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration>
" - OSC 133: Prompt.
" - <https://per.bothner.com/blog/2019/shell-integration-proposal/
" - <https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md>
" - OSC 7: Current directory.
" - <https://lacamb.re/blog/osc7_in_neovim_third_time.html>
autocmd vimrc TerminalWinOpen *
\ set foldlevel=0 |
\ set foldmethod=expr |
\ set foldexpr=getline(v:lnum)=~'^│'?'>1':'=' |
autocmd vimrc CursorMoved *
\ if &buftype ==# 'terminal' |
\ let &foldmethod = &foldmethod |
\ endif |
""" Find other Vim instance when swap file exists
" Only for Unix-likes. POSIX-compliant. Sends signal `USR1` which when received
" outputs a `BEL` to the terminal, hopefully making the terminal emulator mark
" the window as urgent, helping the user find it. Under X11 if `xdotool` is
" installed one alternative might be `!xdotool set_window --urgency 1
" $WINDOWID`. |swapinfo| was added in `8.1.0313` and |SigUSR1| in `8.2.0952`.
if has('eval') && executable('kill')
autocmd vimrc SwapExists *
\ let s:swapinfo = swapinfo(v:swapname) |
\ if s:swapinfo['host'] == hostname() |
\ call system('kill -USR1 ' . s:swapinfo['pid']) |
\ endif |
autocmd vimrc SigUSR1 * silent execute "!printf '\\a'" | silent redraw!
endif
"" Colors
" See |cterm-colors|, |gui-colors|.
" See |colortest.vim|, |hitest.vim|.
" TODO: If/when we break this out to a separate file/plugin, we might want to
" link to stuff like this:
" - <https://jeffkreeftmeijer.com/vim-16-color/>
" - <https://github.com/jeffkreeftmeijer/vim-dim>
" This creates problems, we should just make sure files opened with
" `vim.desktop` get the colors. It looks like `.desktop` files with
" `Terminal=true` makes the terminal source `~/.profile` but not `~/.shrc`
" (which makes sense in a way, it's `Terminal`, not `Shell`).
if $_ ==# '/usr/bin/xdg-open'
silent !. ~/.shrc.d/color.sh
" redraw!
endif
" 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
" `$VIMSRC/src/drawscreen.c:550` (at the bottom of the function
" `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'
" Emphasis levels, in ascending order:
"
" | Highlight | Use case | Example |
" | `Comment` | Non-highlighted (interface, menus) | `StatusLineNC` |
" | `Normal` | Non-highlighted (interface, menus) | `StatusLine` |
" | `Visual` | Highlighted (buffer text) | `Search` |
" | `cterm=reverse` | Highlighted (buffer text) | `IncSearch` |
" \ 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=DarkBlue ctermfg=NONE |
\ highlight IncSearch 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 |
""" No underline
" Remove all `cterm=underline` set by default in `$VIMRUNTIME/syntax/syncolor.vim`.
" `Underlined` is linked to by `htmlLink` and `mkdLink` by default and is too
" cluttered for my taste.
autocmd vimrc ColorScheme * nested
\ highlight Underlined cterm=NONE |
""" Wildmenu
" 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 |
""" Wildmenu
autocmd vimrc ColorScheme * nested
\ highlight! link WildMenu Search |
""" Popup menu
autocmd vimrc ColorScheme * nested
\ highlight Pmenu ctermbg=LightGray ctermfg=DarkGray |
\ highlight PmenuSel ctermbg=LightGray ctermfg=White |
\ highlight PmenuSbar ctermbg=DarkGray |
\ highlight PmenuThumb ctermbg=White |
""" Ignore
" See |'highlight'|. By default links to |NonText|.
autocmd vimrc ColorScheme * nested
\ highlight! link EndOfBuffer Ignore |
""" Non-Ignore
" By default links to |Ignore|.
autocmd vimrc ColorScheme * nested
\ highlight! link helpIgnore Comment |
\ highlight! link helpBacktick helpIgnore |
\ highlight! link helpBar helpIgnore |
\ highlight! link helpStar helpIgnore |
""" Non-document characters
" See |'highlight'|, |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
autocmd vimrc ColorScheme * nested
\ highlight! link NonText Special |
""" Document non-printables characters
" See |'highlight'|, |'listchars'| `tab`, `space`, `trail`, `nbsp`.
autocmd vimrc ColorScheme * nested
\ highlight! link SpecialKey Comment |
""" Document conceal replacement characters
autocmd vimrc ColorScheme * nested
\ highlight! link Conceal Identifier |
""" 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 |
" TODO: Filetype-specific customizations probably should trigger on some other
" event.
""" Markdown delimiters
autocmd vimrc ColorScheme * nested
\ highlight! link mkdDelimiter Comment |
\ highlight! link mkdCodeDelimiter Comment |
\ highlight! link mkdCodeStart Comment |
\ highlight! link mkdCodeEnd Comment |
""" 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')
""" |mapleader|
let g:mapleader = "\<Space>"
let g:localmapleader = "\<Space>"
""" 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
""" Interface
"""" `tpope/vim-flagship`
" GitAdd https://github.com/tpope/vim-flagship
"""" `chrisbra/NrrwRgn`
GitAdd https://github.com/chrisbra/NrrwRgn
let g:nrrw_topbot_leftright = 'belowright'
xmap <Space><Space>nr <Plug>NrrwrgnDo
""" 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
let g:vim_markdown_auto_insert_bullets = 0
let g:vim_markdown_new_list_item_indent = 0
" " 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
"""" `gpanders/vim-medieval`
GitAdd https://github.com/gpanders/vim-medieval
" Roughly as suggested in `vim-medieval/README.md:/Create a mapping/` (but
" not mentioned in |medieval.txt|...).
autocmd vimrc FileType markdown
\ nmap <buffer> <Space>! <Plug>(medieval-eval)
" TODO: Add `octave` (and `matlab`?). We probably need flags to prevent
" opening a GUI, does medieval support flags?
let g:medieval_langs = ['sh', 'bash', 'python=python3']
"""" `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
" Also search for `map[a-z]* \+\S*[][]` in this file.
" <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>
" See also `tpope/sleuth.vim`
" function! s:textwidth() abort
" return max(map(range(1, line('$')), 'len(getline(v:val))'))
" endfunction
" let g:textwidth = &textwidth
" nnoremap yoT :setlocal textwidth=<C-R>=&textwidth == g:textwidth ? <SID>textwidth() : g:textwidth<CR><CR>
"""" `tpope/vim-repeat`
" Does `vim-repeat` have to go at the beginning to activate integrations with
" other plugins (e.g. `vim-unimpaired`)?
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
"""" `chrisbra/unicode.vim`
" GitAdd https://github.com/chrisbra/unicode.vim
"""" `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
" TODO: The ones with `\%#` |cursor-position| does not work, probably because
" `switch.vim` tries to match it at some other position internally. Searching
" manually yields the expected matches though.
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\%(g\|global\)\? *\) \%(no\)\([a-z]\+\)\( \|$\)': '\1 \2\3',
\ '\(\<set\%(g\|global\)\? *\) \%(no\)\@!\([a-z]\+\)\( \|$\)': '\1 no\2\3',
\ '\(\<set\%(g\|global\)\? *.*\) \%(no\)\([a-z]*\%#[a-z]*\)\( \|$\)': '\1 \2\3',
\ '\(\<set\%(g\|global\)\? *.*\) \%(no\)\@!\([a-z]*\%#[a-z]*\)\( \|$\)': '\1 no\2\3',
\ }]
"""" `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
""" Visual mode
"""" `dahu/Severalections`
GitAdd https://github.com/dahu/Severalections
""" 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
"""" `chrisbra/NrrwRgn`
" GitAdd https://github.com/chrisbra/NrrwRgn
" TODO: I have not evaluated this yet. If it isn't to our liking there is
" also <https://github.com/chrisbra/NrrwRgn#similar-work>.
""" 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
""" Syntax
"""" `inkarkat/vim-SyntaxRange`
" NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
" GitAdd https://github.com/inkarkat/vim-SyntaxRange
"""" `ypcrts/securemodelines`
" GitAdd https://github.com/ypcrts/securemodelines
" TODO: Last updated 2019 as of this writing, can we be sure this is really
" more secure than the built-in sandbox? Besides, we currently disable
" modelines with `set modelines=0`.
" let g:secure_modelines_verbose = 1
""" Modelines
"""" `ypcrts/securemodelines`
" GitAdd https://github.com/ypcrts/securemodelines
" TODO: Last updated 2019 as of this writing, can we be sure this is really
" more secure than the built-in sandbox? Besides, we currently disable
" modelines with `set modelines=0`.
" let g:secure_modelines_verbose = 1
""" Environment interaction
"""" Built-in `netrw`
let g:netrw_home = '~/.cache/vim/netrw'
let g:netrw_banner = 0
let g:netrw_liststyle = 3 " Tree.
" 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, "/")')
" \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) .
" \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(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 " . v:val')) .
\ ' ' . join(map(s:wildignore_path, '"-o -path " . 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
autocmd vimrc FileType git set foldmethod=expr foldexpr=GitFoldexpr()
function! GitFoldexpr() abort
let line = getline(v:lnum)
if line =~# '^diff --git'
return '>1'
elseif line =~# '@@ [-+0-9, ]\+ @@'
return '>2'
endif
return '='
endfunction
" TODO: Add some `git log -L` (see man page) mapping.
"""" `samoshkin/vim-mergetool`
" GitAdd https://github.com/samoshkin/vim-mergetool
"""" `tpope/vim-rhubarb`
" GitHub extension for `tpope/vim-fugitive`. We mostly use it for |:GBrowse|.
GitAdd https://github.com/tpope/vim-rhubarb
"""" `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
" TODO: Put this in a QuickFix section?
" See also |dispatch-maps|.
" 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>
" 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>)
"""" `tpope/vim-eunuch`
GitAdd https://github.com/tpope/vim-eunuch
"""" `tpope/vim-projectionist`
GitAdd https://github.com/tpope/vim-projectionist
"""" `tpope/vim-vinegar`
" GitAdd https://github.com/tpope/vim-vinegar
""" 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? See |myvimrc-characters|.
" let g:termdebug_popup = 0
nnoremap <Space>dd :Termdebug<CR>
" `<Space>do` conflicts with our |do| ("diff obtain", |:diffget|)
" text-object.
" 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>.
""" LSP
" We have not decided on a LSP/linting plugin. Wishlist:
" - Compatible with at least Vim 8.
" - Not require dozens of other plugins to configure/make usable.
" Some things to check out, roughly in the order of looking like a good fit.
" - <https://github.com/dense-analysis/ale>
" - <https://github.com/prabirshrestha/vim-lsp>
" - <https://github.com/yegappan/lsp>
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` with the first two components of
" section words and `<cword>`.
"" File type overrides
" TODO: We want 'path' entries to be in priority order.
" TODO: It looks to me that this should be a global static default instead of a
" local dynamic override.
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`.
autocmd vimrc FileType *
\ setlocal statusline=%{Statusline()} |
" See also |scriptease| (which sets both 'keywordprg' and 'path', TODO but
" posssibly only in `vim` files, not `help` files).
autocmd vimrc FileType vim,help
\ execute "nnoremap <buffer> <Space>K :helpgrep <C-R><C-A><CR>" |
\ setlocal keywordprg=:help |
\ setlocal path=.,$VIMRUNTIME,$VIMSRC,$HOME/.vim,$HOME/.vim/pack/*/* |
\ if has('eval') |
\ execute 'setlocal' 'path+=' . fnamemodify($MYVIMRC, ':h') |
\ execute 'setlocal' 'path+=' . fnamemodify($MYVIMRC, ':h') . '/pack/*/*' |
\ endif |
\ setlocal path+=,
autocmd vimrc FileType man
\ setlocal textwidth=78 |
autocmd vimrc FileType sh
\ setlocal shiftwidth=2 |
\ if has('eval') |
\ execute 'setlocal' 'path=' . substitute($PATH, '[:;]', ',', 'g') |
\ endif |
" `path`s that start with `**` are great if you're in a project directory and
" want to find stuff like CMake's
" `_build/_deps/SOME_DEPENDENCY/include/SOME_PATH`, but not so great if you're
" in `$HOME`.
autocmd vimrc FileType c,cpp,lex,yacc,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=.,src,src/*,include,*/_deps/*/include |
autocmd vimrc FileType c,cpp,lex,yacc
\ if has('eval') && executable('uname') |
\ execute 'setlocal' 'path+=' . printf('/lib/modules/%s/build/include', trim(system('uname -r'))) |
\ endif |
\ setlocal path+=/usr/include,/usr/local/include |
autocmd vimrc FileType cpp
\ setlocal matchpairs+=<:> |
\ setlocal path+=/usr/include/c++/* |
autocmd vimrc FileType man
\ setlocal nolist nospell |
\ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\([-‐]\{2\}\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 |
" TODO: Might be nice to query some external command for the `path`.
autocmd vimrc FileType tex
\ setlocal path=.,,/usr/share/texlive/texmf-dist/tex/latex/*/ |
\ setlocal suffixesadd=.tex,.cls,.sty |
" 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 |
" If 'filetype' is never set, "universal" autocommand configuration will not be
" applied unless we explicitly trigger it.
doautocmd vimrc FileType *
" 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')
" In earlier Vim versions, these are the defaults only 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(getwininfo(),
\ 'getbufvar(v:val.bufnr, "&buftype") ==# "terminal"'
\ )) |
\ if s:newtermguicolors != &termguicolors |
\ execute 'set' (s:newtermguicolors ? '' : 'no') . 'termguicolors' |
\ endif |
endif
endif