Robert Cranston authored on 23/05/2025 18:29:50
Showing 1 changed files

... ...
@@ -1,26 +1,62 @@
1 1
 "" My |vimrc|
2 2
 
3
-" A |'textwidth'| of 79 is used throughout.
3
+" TODO: Supply chain attacks are getting more common. We should use (mandate?)
4
+" commit hashes in `GitAdd`. Also, make sure to use a command format that
5
+" ignores tag/branch names (those can be named to look like hashes and are
6
+" mutable).
7
+
8
+" TODO: Do we want to try to integrate with Debian? There seems to be at least
9
+" two ways vim-related files are installed:
10
+" - Purely auxilliary files as part of some other package: Files are installed
11
+"   to `/usr/share/vim/addons` which are referenced by files installed to
12
+"   `/usr/share/vim/registry`. `vim-addons` from the `vim-addon-manager` can be
13
+"   used to (presumably) symlink them into a path that is listed in
14
+"   'runtimepath'.
15
+" - As a standalone `vim-${addon}` package: Files are installed to
16
+"   `/usr/share/vim-${addon}`, presumably symlinked into a `start` or `opt`
17
+"   'packpath' during package installation.
18
+"   <https://vim-team.pages.debian.net/vim/> and the `dh_vim-addon` man page in
19
+"   the `dh-vim-addon` package contains some further details.
4 20
 
5
-""" Comments
21
+""" Formatting
22
+
23
+" A |'textwidth'| of 79 is used throughout.
6 24
 
7 25
 " Comments are written in Vim's help |notation|, see |help-writing|. They can
8
-" be highlighted with https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-comment.
26
+" be highlighted with
27
+" <https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-comment>.
9 28
 
10 29
 " Section headings are not written in the help |notation|, but are instead
11 30
 " indicated with multiple contiguous comment characters. They can form folds
12
-" with https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold.
31
+" with <https://git.rcrnstn.net/rcrnstn/vim-unobtrusive-fold>.
13 32
 
14 33
 """ Compatibility
15 34
 
35
+" TODO: Test with `nvi`, a "bug-for-bug compatible" clone of the original BSD
36
+" `vi`.
37
+" TODO: Test with `VIM_POSIX=1 "$vim"` (for different `$vim`s?). See
38
+" |$VIM_POSIX|.
39
+
16 40
 " This vimrc should work with all configurations of Vim. Manually tested with:
17
-" - Features: tiny, huge (Debian `apt-get install vim-{tiny,gtk3}`)
41
+" - Versions: TODO: Whatever some old {Debian,Ubuntu,Fedora} ships.
42
+" - Features: small, huge (Debian `apt-get install vim-{tiny,gtk3}`)
18 43
 " - Locales: C, UTF-8 (`LC_ALL=C{,.UFT-8}`)
19 44
 " - Colors: 1, 2, 8, 16, 256, termguicolors (`--cmd "set {t_Co=$colors,tgc}"`)
20 45
 " - UI: TUI, GUI (`{,g}vim`)
21 46
 " - Terminals: GUI, VTE, Linux, tmux with the correct `Ss` `terminal-override`
22 47
 " - Platforms: Unix-like
23 48
 
49
+" TODO: `man setfont` says:
50
+" > Note: if a font has more than 256 glyphs, only 8 out of 16 colors can be
51
+" > used simultaneously. It can make console perception worse (loss of
52
+" > intensity and even some colors).
53
+" The default font on my system has 512 glyphs (`showconsolefont -v`).
54
+
55
+" TODO: `man setfont` says, in section "CONSOLE MAPS":
56
+" > Several mappings are involved in the path from user program output to
57
+" > console display.
58
+" Might be worth reading up on that. If I already did, document.
59
+
24 60
 """ Features
25 61
 
26 62
 " |:version| says "tiny" features are always present and are therefore used in
... ...
@@ -35,15 +71,17 @@
35 71
 " Note that trying to set (run-time, but not compile-time) unsupported options
36 72
 " is silently ignored, and so can be done without checking for support first
37 73
 " (which is good, since that requires |+eval|). Everything between |:if| and
38
-" |:endif| is also silently ignored if |+eval| is not available.
74
+" |:endif| is also silently ignored if |+eval| is not available. See
75
+" |no-eval-feature|.
39 76
 
40 77
 """ Encoding
41 78
 
42 79
 " |'encoding'| is hard-coded to `utf-8`. However, only characters present in
43 80
 " Code Page 437 should be used in the interface, to ensure font support on most
44
-" terminals (in particular, the Linux console). See
45
-" - https://en.wikipedia.org/wiki/Code_page_437
46
-" - https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/vt/cp437.uni
81
+" terminals (in particular, the Linux console, via `CHARMAP` in
82
+" `/etc/default/console-setup`). See
83
+" - <https://en.wikipedia.org/wiki/Code_page_437>
84
+" - <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/vt/cp437.uni>
47 85
 " - `man showconsolefont`
48 86
 
49 87
 """ Re-sourcing
... ...
@@ -73,11 +111,22 @@
73 111
 " programming anyway.
74 112
 
75 113
 "" Options
114
+
76 115
 " TODO: Use |setglobal| for more things? Note that for options with a non-empty
77
-" default local value, `setglobal` does nothing useful.
116
+" default local value, `setglobal` does nothing useful. Worse, for options with
117
+" only a (buffer or window) local value, `setglobal` does nothing, literally.
118
+" Is that a problem, should we even set local values here? Maybe identifying
119
+" them and getting rid of them is a good idea?
120
+
121
+" TODO: Maybe source |defaults.vim|? Probably not, but add some documentation?
122
+
123
+" TODO: Look at |:options| and maybe follow the same grouping?
124
+
125
+" NOTE that |OptionSet| was added in
126
+" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0081> and may not be available.
78 127
 
79 128
 """ Reset
80
-" set all&
129
+setglobal all&
81 130
 
82 131
 """ Encoding
83 132
 " Force Vim's internal encoding to a Unicode encoding.
... ...
@@ -95,48 +144,144 @@ set clipboard^=unnamedplus
95 144
 set backspace=indent,eol,start
96 145
 set virtualedit=block
97 146
 
147
+""" Modeline
148
+set nomodeline
149
+
150
+""" Navigation
151
+set nostartofline
152
+" <http://ftp.vim.org/pub/vim/patches/9.0/9.0.0640>: Cannot scroll by screen
153
+" line if a line wraps. Add the 'smoothscroll' option.
154
+if has('patch-9.0.0640')
155
+  set smoothscroll
156
+endif
157
+
98 158
 """ Windows
99 159
 " Put newly opened windows below and to the right.
100 160
 set splitbelow
101 161
 set splitright
102 162
 
103
-""" Interface clutter
104
-set noruler
163
+""" Interface
105 164
 set showcmd
165
+set noruler
166
+set laststatus=1
167
+set showtabline=1
106 168
 set shortmess+=I
107
-set guioptions=cf
169
+set guioptions=cf " console dialogs, foreground (no fork())
170
+set numberwidth=1
108 171
 
109 172
 """ Interface characters
110 173
 " If |'t_Co'| is empty (or set to 1) the default behavior of |'fillchars'|
111 174
 " `stl:`/`stlnc:` (`=`/`^`) will be used regardless of its setting. Other good
112 175
 " choices for |'listchars'| `fold:` is ` ` and `tab:` is: `→ `, `――>`, `├──`,
113 176
 " `──┤`, `├─┤`.
177
+" TODO: `:help 'fillchars'` says "for `stl` and `stlnc` only single-byte values
178
+" are supported". Test the current (non-ASCII) values against older versions of
179
+" Vim. See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.2569>.
180
+" TODO: If Vim cannot tell appart |hl-StatusLine| and |hl-StatusLineNC| (e.g.
181
+" because |hl-StatusLine| is a |hl-link|), (ordinary) spaces and `fillchars`
182
+" `stl` characters for the statusline of the focused window will be replaced
183
+" with `^`. Note that this includes the single character under the `fillchars`
184
+" `vert`, which cannot be set with |'statusline'|.
185
+set linespace=-1
114 186
 set list
115 187
 set linebreak
116 188
 set breakindent
117 189
 set breakindentopt=sbr,shift:2
118
-set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff:\ |
119
-set listchars=tab:├\ ┤,trail:•,extends:›,precedes:‹,nbsp:·
120
-set showbreak=»\ |
190
+set showbreak=» 
191
+set fillchars=stl:─,stlnc:─,vert:│,fold:─,diff: 
192
+" set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff: 
193
+set listchars=tab:├─,trail:•,extends:›,precedes:‹,nbsp:·
194
+" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0759>: Showing two characters for
195
+" tab is limited. Allow for a third character for "tab:" in 'listchars'.
196
+if has('patch-8.1.0759')
197
+  " ab	c
198
+  " set listchars+=tab:├\ ┤
199
+  set listchars+=tab:│\ │
200
+endif
201
+" TODO: `%f` still shows `[No Name]`, is there a way to remove that?
202
+set statusline=%(%f\ %)
203
+if has('eval')
204
+  " TODO: This works poorly with plugins that have windows with their own
205
+  " statusbar, e.g. |undotree.txt|.
206
+  " set statusline=%(%{expand('%:.s?^/??')}\ %)
207
+  " `fillchar_status` function in `src/screen.c:4649` of Vim source.
208
+  " TODO: Try to use some other non-standard space? Search for "\<SPACE\>" in
209
+  " |digraphs|.
210
+  " set fillchars+=stl:\ ,stlnc: 
211
+  set fillchars+=stl: ,stlnc: 
212
+  " set fillchars+=stl:┘,stlnc:┘
213
+  " TODO: Standardize on global functions? Or |autoload|s (but that would break
214
+  " our "single file" policy)?
215
+  " function! s:statusline() abort
216
+  function! Statusline() abort
217
+    " TODO: Make this expansion relative to the window-local cwd? Also do other
218
+    " substitutions, like `$HOME` to `~`, the expanded `$VIMRUMTIME` to the
219
+    " string `$VIMRUNTIME`, etc. We used to have `s?^/??`, why?
220
+    " TODO: Harmonize with `titlestring`.
221
+    let l:title = !empty(&l:buftype) ? &l:buftype : expand('%:~:.')
222
+    if &l:buftype =~# 'help\|terminal'
223
+      let l:title .= ':' . expand('%:t')
224
+    elseif &l:buftype ==# 'quickfix' && exists('w:quickfix_title')
225
+      let l:title .= ':' . w:quickfix_title
226
+    endif
227
+    if !empty(l:title)
228
+      let l:title .= ' '
229
+    endif
230
+    " NOTE: `matchstr` looks for the _first_ match.
231
+    " TODO: This is slow. Cache the `matchstr` result?
232
+    let l:fill = matchstr(&fillchars, '\(^\|,\)stl:\zs[^,]*')
233
+    let l:pad  = winwidth(0) - strwidth(l:title)
234
+    return l:title . repeat(l:fill, l:pad)
235
+  endfunction
236
+  " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.1347>: Cannot easily get the
237
+  " script ID. Support expand('<SID>').
238
+  " if has('patch-8.2.1347')
239
+  "   let &statusline = '%{'.expandcmd('<SID>statusline()').'}'
240
+  " else
241
+    let &statusline = '%{Statusline()}'
242
+  "   function! g:Statusline() abort
243
+  "     return s:statusline()
244
+  "   endfunction
245
+  " endif
246
+endif
121 247
 
122 248
 """ Colors
249
+" May be overritten later by Vim for terminals with |t_RB|.
123 250
 set background=dark
124
-if has('gui_running')
125
-  set t_Co=16777216
126
-endif
127
-if 16 <= &t_Co && &t_Co <= 256 && !&termguicolors
251
+set guioptions+=d
252
+if &t_Co > 16
128 253
   set t_Co=16
254
+  " <https://github.com/neovim/neovim/issues/11974#issuecomment-1658464993>
255
+  if has('nvim')
256
+    lua ffi = require "ffi" ffi.cdef "int t_colors" ffi.C.t_colors = 16
257
+  endif
258
+endif
259
+set notermguicolors
260
+" <https://github.com/termstandard/colors#truecolor-detection>
261
+if empty($COLORTERM) && !has('vcon')
262
+  set notermguicolors
129 263
 endif
264
+if has('gui_running')
265
+  set termguicolors
266
+endif
267
+
268
+""" Bell
269
+set belloff=error
130 270
 
131 271
 """ Title
132 272
 set title
133
-set titlestring=vim:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:~:.'))}%)
273
+" set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:.:s?^/??'))}%)
274
+" TODO: Break out into `Title()` function and harmonize with `statusline`.
275
+set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{expand('%:.:s?^/??')}%)
276
+set titleold=
134 277
 
135 278
 """ Tabs
136
-set expandtab
137
-set shiftround
279
+" When reading files written by others, assume default `tabstop=8`.
280
+" When Writing files, use 4 space indents.
138 281
 set shiftwidth=4
282
+set shiftround
139 283
 set softtabstop=-1
284
+set expandtab
140 285
 
141 286
 """ Mouse
142 287
 set mouse=a
... ...
@@ -144,9 +289,25 @@ set mouse=a
144 289
 """ Command-line
145 290
 set wildmenu
146 291
 set wildmode=longest:full,full
147
-set wildignore=_*,.git,.cache,.vagrant,.ansible,.npm,node_modules,__pycache__,.venv,*.egg-info,pipx,snap
292
+" See also |'suffixes'|.
293
+set wildignore+=_*
294
+set wildignore+=.git
295
+set wildignore+=UPSTREAMS,FORKS
296
+" Relative to `$HOME`.
297
+set wildignore+=*/.vim/pack,*/.config/vim/pack,*/.config/nvim/pack
298
+set wildignore+=*/.cache,
299
+set wildignore+=*/.mozilla/firefox
300
+set wildignore+=*/.local/lib,*/.local/share/man
301
+set wildignore+=*/.vagrant,*/.ansible
302
+set wildignore+=*/.local/pipx,__pycache__,.venv,*.egg-info
303
+set wildignore+=*/.cargo
304
+set wildignore+=*/.npm,node_modules
305
+set wildignore+=*/.local/share/tldr
306
+set wildignore+=*/snap
307
+set wildignore+=*/.wine/dosdevices,*/.wine/drive_*
308
+" <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325>: 'wildmenu' only shows few
309
+" matches. Add the "pum" option: use a popup menu to show the matches.
148 310
 if has('patch-8.2.4325')
149
-  " See http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325.
150 311
   set wildoptions+=pum
151 312
 endif
152 313
 
... ...
@@ -163,8 +324,9 @@ set ttimeoutlen=100
163 324
 """ Diffs
164 325
 set diffopt+=vertical
165 326
 set diffopt+=foldcolumn:0
327
+" <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360>: Using an external diff
328
+" program is slow and inflexible. Include the xdiff library. Use it by default.
166 329
 if has('patch-8.1.0360')
167
-  " See http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360.
168 330
   set diffopt+=internal
169 331
   set diffopt+=algorithm:histogram
170 332
   set diffopt+=indent-heuristic
... ...
@@ -173,29 +335,72 @@ endif
173 335
 """ Formatting
174 336
 " See |auto-format|, |format-comments|, and |fo-table|.
175 337
 set textwidth=79
176
-set winwidth=80
338
+" set winwidth=80
177 339
 " set colorcolumn=+1
178 340
 set autoindent
179 341
 set nojoinspaces
342
+" Don't autowrap text, enable comment formatting with |gq|, recognize lists,
343
+" remove comment leader when joining.
180 344
 set formatoptions-=t
181
-set formatoptions+=q
345
+" set formatoptions+=q " TODO: This is the default?
182 346
 set formatoptions+=n
183 347
 set formatoptions+=j
184
-set nowrap
348
+set nowrap " See also |breakindent|, |breakindentopt|, |showbreak| set above.
349
+" A custom 'formatprg' produces nicer results but is harder to replicate for
350
+" others and places undue burden on documentation contributors. Having simple
351
+" format rules is more important than slightly prettier formatting.
352
+" TODO: At least make the expressions valid (we're lacking spaces, no?).
353
+" if executable('par')
354
+"   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e'])
355
+"   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e', 'j'])
356
+" elseif executable('fmt')
357
+"   let &formatprg = 'fmt' . '-w' . &textwidth '-g' . &textwidth
358
+" endif
185 359
 
186 360
 """ Comments
187
-set commentstring=
361
+" set commentstring=#%s
188 362
 
189 363
 """ Folds
190 364
 set foldlevelstart=999
191 365
 set foldtext=substitute(getline(v:foldstart),'\\t',repeat('\ ',&ts),'g').'\ '
192 366
 
193 367
 """ Spelling
194
-set spell
368
+" set spell
195 369
 set spelllang=en_us
196
-" `thesaurus/en_us.txt` downloaded from URL documented in |'thesaurus'|:
197
-" https://github.com/vim/vim/issues/629#issuecomment-443293282.
198 370
 set thesaurus=~/.vim/thesaurus/en_us.txt
371
+" TODO: We can probably do something better/cleaner for the thesaurus on our
372
+" own. In particular, publicly available, clearly licensed, version controlled,
373
+" code to generate the vim thesaurus from primary sources.
374
+" The current `~/.vim/thesaurus/en_us.txt` is downloaded from the URL
375
+" documented in |'thesaurus'|:
376
+" <https://github.com/vim/vim/issues/629#issuecomment-443293282>. This zip file
377
+" contains a patch to <https://www.openoffice.org/lingucomponent/MyThes-1.zip>
378
+" and the results of running the patched code on the included files, as well as
379
+" the licenses. `MyThes-1.zip` is linked from
380
+" <https://www.openoffice.org/lingucomponent/thesaurus.html> and seems to be
381
+" some version of <https://github.com/hunspell/mythes>. MyThes states in its
382
+" readme that it is based on WordNet 2.0. However, the latest version as of
383
+" this writing is 3.1. When generating a Vim version, it helps to have a
384
+" visualization to guide the heuristics that will probably be needed. Searching
385
+" <https://wordnet.princeton.edu/related-projects> for "thesaurus" gives
386
+" several projects. <https://wordvis.com> looks good (try e.g. "completion").
387
+" Another search hit,
388
+" <https://www2.seas.gwu.edu/~simhaweb/software/jword/index.html>, states that
389
+" "WordNet's vocabulary is smaller than other "word" databases", so we might
390
+" want to use other sources as well, e.g. Roget's Thesaurus.
391
+"
392
+" WordNet
393
+" - <https://wordnet.princeton.edu/download/current-version>
394
+" - <https://wordnetcode.princeton.edu/wn3.1.dict.tar.gz>
395
+" Data hosted on Project Gutenberg
396
+" - <https://www.gutenberg.org/ebooks/3202>  (2002) Moby Thesaurus List
397
+" - <https://www.gutenberg.org/ebooks/10681> (2004) Roget's Thesaurus of English Words and Phrases
398
+" - <https://www.gutenberg.org/ebooks/22>    (1991) Roget's Thesaurus
399
+" - <https://www.gutenberg.org/ebooks/38390> (2011) A Dictionary of English Synonymes [...]
400
+" - <https://www.gutenberg.org/ebooks/51155> (2016) A Complete Dictionary of Synonyms and Antonyms
401
+" For Swedish, there is
402
+" - <https://folkets-lexikon.csc.kth.se/synlex.html>
403
+" - <https://spraakbanken.gu.se/en/resources/saldo>
199 404
 
200 405
 """ Views
201 406
 set viewoptions-=options
... ...
@@ -205,18 +410,38 @@ set viewoptions+=unix
205 410
 """ Files
206 411
 set swapfile
207 412
 set writebackup
413
+set backupcopy=yes
208 414
 set undofile
209 415
 set directory=~/.cache/vim/swap//
210 416
 set backupdir=~/.cache/vim/backup//
211 417
 set undodir=~/.cache/vim/undo//
212 418
 set viewdir=~/.cache/vim/view//
213 419
 set viminfofile=~/.cache/vim/viminfo
420
+if has('nvim')
421
+  set shadafile=
422
+endif
423
+
424
+""" Conceal
425
+set conceallevel=2
426
+set concealcursor=nc
427
+
428
+""" Platform
429
+set shellslash
430
+
431
+""" External tools
432
+" Not POSIX: `-H` (suggested in 'grepprg'), `-I`.
433
+set grepprg=grep\ -nHI
434
+
435
+""" Quickfix
436
+set switchbuf=useopen
214 437
 
215 438
 "" Mappings
439
+" TODO: Categorize into map modes. Use the nonspecific |:map| (|mapmode-nvo|)
440
+" and |:map!| (|mapmode-ic|) more often?
216 441
 
217 442
 """ Escape
218 443
 " Overwrites the default |i_CTRL-C|, |v_CTRL-C|. See
219
-" https://vim.fandom.com/wiki/Avoid_the_escape_key.
444
+" <https://vim.fandom.com/wiki/Avoid_the_escape_key>.
220 445
 inoremap <C-C> <Esc>
221 446
 xnoremap <C-C> <Esc>
222 447
 
... ...
@@ -230,31 +455,77 @@ tnoremap <C-J> <C-W>j
230 455
 tnoremap <C-K> <C-W>k
231 456
 tnoremap <C-L> <C-W>l
232 457
 
233
-""" Buffers
234
-nnoremap <Space><Space>bb :ls<CR>:b<Space>
235
-nnoremap <Space><Space>bs :ls<CR>:sb<Space>
236
-nnoremap <Space><Space>bv :ls<CR>:vertical sb<Space>
458
+""" Clear and redraw
459
+" <C-L> is overridden above, so use a <Leader> mapping.
460
+nnoremap <Space><C-L> <C-L>
461
+
462
+""" Movement
463
+" Up down dispaly lines (unless a count is given).
464
+nnoremap <expr> j v:count ? 'j' : 'gj'
465
+nnoremap <expr> k v:count ? 'k' : 'gk'
466
+
467
+" End of pair opened at end of current line.
468
+" TODO: These are overridden by `matchit`.
469
+nnoremap <silent> g% :<C-U>norm!  $%<CR>
470
+onoremap <silent> g% :<C-U>norm!  $%<CR>
471
+xnoremap <silent> g% :<C-U>norm! v$%<CR>
472
+
473
+""" Scrolling
474
+" Put paragraph containing cursor line at the top of the window.
475
+" TODO: Preserve jump list somehow?
476
+nnoremap zg {jzt<C-O>
477
+
478
+""" Visual mode repeat
479
+" See also `vim-visualrepeat`.
480
+xnoremap . :normal! .<CR>
481
+
482
+""" Clipboard
483
+" Yank file and line number of cursor.
484
+nnoremap <silent> <Space>yy :let @+ = expand('%:p') . ':' . line('.')<CR>
237 485
 
238 486
 """ `$MYVIMRC`
239 487
 nnoremap <silent> <Space><Space>ve :edit   $MYVIMRC<CR>
240 488
 nnoremap <silent> <Space><Space>vs :source $MYVIMRC<CR>
241 489
 
490
+""" Keyword
491
+" nnoremap K :silent execute "normal! K" \| redraw!<CR>
492
+" nnoremap <silent> K :terminal ++close <C-R>=&keywordprg<CR> <cword><CR>
493
+" TODO: vnoremap
494
+" TODO: `set keywordprg=:help`
495
+
242 496
 """ Help
497
+" TODO: Make this filetype dependent? Could use |:grep| or |fugitive|'s
498
+" |:Ggrep|. On the other hand, there are other built-in mappings that does
499
+" keyword search in a codebase.
500
+" TODO: Here we use `g` as prefix. Do we do that in other places? Should we not
501
+" use <Leader> (i.e. <Space>)?
243 502
 nnoremap <silent> gK  :helpgrep \<<C-R><C-W>\><CR>
244 503
 xnoremap <silent> gK y:helpgrep <C-R>"<CR>
245 504
 
246 505
 """ Run
506
+" TODO: Standardize where the output goes.
247 507
 
248
-" File.
508
+" File (with output in pager).
249 509
 nnoremap <silent> <Space><Space>% :!%:p:S \| less -FR<CR>
250 510
 nnoremap <silent> <Space><Space># :!#:p:S \| less -FR<CR>
251 511
 
252
-" Command.
512
+" Command (with output in new window).
253 513
 nnoremap <Space><Space>! :new \| .!
254 514
 
515
+""" Quickfix
516
+
517
+"""" Toggle Quickfix window
518
+" TODO: Do similar for location list?
519
+" TODO: Make the |botright| global with some |autocmd|?
520
+nnoremap <expr> <Space><Space>q
521
+\ empty(filter(range(1,winnr('$')),'getwinvar(v:val,"&buftype")==#"quickfix"'))
522
+\ ? ':botright copen<CR>'
523
+\ : ':botright cclose<CR>'
524
+
255 525
 """ Make
256 526
 " TODO: |dispatch| provides default mappings, try to emulate them?
257 527
 " TODO: Should these be <silent> as well?
528
+" TODO: Use the |terminal-debugger| instead of a make target?
258 529
 nnoremap <Space><Space>m% :!make %:r:S \| less -FR<CR>
259 530
 nnoremap <Space><Space>m# :!make #:r:S \| less -FR<CR>
260 531
 nnoremap <Space><Space>mm :!make       \| less -FR<CR>
... ...
@@ -288,11 +559,17 @@ nnoremap Y y$
288 559
 """" Don't include newline in Visual mode `$`.
289 560
 xnoremap $ $h
290 561
 
291
-"""" Visual mode paste doesn't clobber unnamed register
292
-xnoremap p pgvy
562
+"""" Visual mode put that doesn't clobber unnamed register
563
+" See also <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4242>.
564
+xnoremap P pgvy
565
+
566
+""" Visual mode
293 567
 
294 568
 """" Visually select last pasted text
295 569
 " TODO: Make a text object as well?
570
+" TODO: I use this relatively often, but it clobbers the built in |gp|. I never
571
+" use that, but it seems useful, so maybe I should? Find another natural
572
+" mapping?
296 573
 " Analogous with how |gv| visually selects last visually selected text. Default
297 574
 " to always using ordinary Visual mode. Linewise and blockwise with |+eval|
298 575
 " support.
... ...
@@ -304,13 +581,34 @@ endif
304 581
 """" Restrict Visual mode substitutions to the selected text
305 582
 xnoremap <Space>s :s/\%V
306 583
 
584
+"""" Visual movement
585
+xnoremap <C-h> hoho
586
+xnoremap <C-j> jojo
587
+xnoremap <C-k> koko
588
+xnoremap <C-l> lolo
589
+
590
+""" Scrolling
591
+" Arrow keys scroll. Useful when 'mouse' is empty and the terminal sends arrow
592
+" keys when scrolling with the mouse.
593
+noremap <Up>    <C-Y>
594
+noremap <Down>  <C-E>
595
+noremap <Left>  zh
596
+noremap <Right> zl
597
+
307 598
 """ Mouse
308 599
 " As suggested in |scroll-mouse-wheel|, scroll only one line.
309
-noremap <MouseUp>   <C-E>
310
-noremap <MouseDown> <C-Y>
600
+noremap <ScrollWheelUp>     <C-Y>
601
+noremap <ScrollWheelDown>   <C-E>
602
+noremap <C-ScrollWheelUp>   zh
603
+noremap <C-ScrollWheelDown> zl
604
+noremap <ScrollWheelLeft>   zh
605
+noremap <ScrollWheelRight>  zl
311 606
 
312 607
 " Toggle folds.
313
-noremap <RightMouse> <LeftMouse>za
608
+noremap <RightMouse>   <LeftMouse>za
609
+noremap <2-RightMouse> <LeftMouse>za
610
+noremap <3-RightMouse> <LeftMouse>za
611
+noremap <4-RightMouse> <LeftMouse>za
314 612
 
315 613
 """ Command-line
316 614
 " Take already written text into account when searching history.
... ...
@@ -333,9 +631,29 @@ endif
333 631
 """ Diffs
334 632
 
335 633
 " Current file.
336
-nnoremap <silent> <Space><Space>dd :w !diff --color=always -u %:S - \| less -FR<CR>
634
+" Se also |:DiffOrig|.
635
+" TODO: Use a buffer?
636
+" <https://gist.github.com/romainl/7198a63faffdadd741e4ae81ae6dd9e6>
637
+nnoremap <silent> <Space><Space>dd :w !
638
+\ diff -u --color=always %:S -
639
+\ \| tail -n +3
640
+\ \| less -FR
641
+\ <CR>
642
+nnoremap <silent> <Space><Space>dw :w !
643
+\ diff -u %:S -
644
+\ \| tail -n +3
645
+\ \| wdiff -d -n
646
+\   -w "$([ "$(tput colors)" -ge 16 ] && tput setaf  9 \|\| { tput bold; tput setaf 1; })"
647
+\   -y "$([ "$(tput colors)" -ge 16 ] && tput setaf 10 \|\| { tput bold; tput setaf 2; })"
648
+\   -x "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })"
649
+\   -z "$([ "$(tput colors)" -ge 16 ] && tput setaf 15 \|\| { tput bold; tput setaf 7; })"
650
+\ \| less -FR
651
+\ <CR>
652
+" Requires `vim-fugitive`.
653
+nmap <silent> <Space><Space>dg :Gdiffsplit<CR>
337 654
 
338 655
 " Analogous with |dp| |do| in Normal mode.
656
+" TODO: Is adding a `diffupdate` at the end useful?
339 657
 nnoremap <silent> <Space>dpp :.diffput<CR>
340 658
 nnoremap <silent> <Space>doo :.diffget<CR>
341 659
 xnoremap <silent> <Space>dp  :diffput<CR>
... ...
@@ -365,6 +683,7 @@ nnoremap zV zMzv
365 683
 
366 684
 " Focus next/previous fold. Overwrites default move to start/end of
367 685
 " next/previous fold.
686
+" TODO: |c_CTRL-R_=| requires |+eval|?
368 687
 nnoremap <silent> zj m<zjzvm>gvzc'>zv
369 688
 nnoremap <silent> zk zvzckVzvV:<C-R>=prevnonblank(line('.'))<CR><CR>zvzcVoVzv
370 689
 
... ...
@@ -399,33 +718,125 @@ if has('eval')
399 718
   endfunction
400 719
 endif
401 720
 
721
+""" Normalize date to ISO 8601
722
+" See |:visual_example|.
723
+" See also |abolish-coercion|.
724
+" This is hacky but works without |+eval|.
725
+xnoremap crd <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date +'\%Y-\%m-\%d' -f -<CR>kJJ
726
+
727
+""" Go to string in file under cursor
728
+
729
+" The built-in |gF|, and related |CTRL-W_F|, |CTRL-W_gF|, commands extend |gf|
730
+" by also parsing trailing `:{lineno}` (specifically, any non-filename
731
+" character optionally surrounded by whitespace, or the literal string
732
+" ` line `, followed by a decimal number). This corresponds to common output of
733
+" compilers/interpreters/linters. It also happens to roughly correspond to
734
+" _one_ of the common (or, for [POSIX.1-2017][], allowed) outputs of `ctags`.
735
+" It does not however allow the _other_ format: search strings. Let's fix that.
736
+"
737
+" Search strings are very useful when you're not sure what version of the file
738
+" someone else might have, so it's hard to give an accurate line number, but
739
+" the chance is high that a search string will yield the correct location. It
740
+" also conveys more information to someone not wanting to _follow_ the
741
+" reference right now than a line number would.
742
+"
743
+" Vim actually allows _any_ Ex command in tag files (subject to |'exrc'| and
744
+" |'secure'|, see |tag-security|), not just line numbers and search strings,
745
+" see |tags-file-format|. The mapping below only accepts what amounts to
746
+" possibly anchored non-regex search strings, for three reasons: 1) security,
747
+" 2) implementation simplicity, 3) it is what [POSIX.1-2017][] `ctags` / `ex` /
748
+" `vi` supports.
749
+"
750
+" It is important that we lean on the built-in mappings as much as possible
751
+" since they include functionality based on <count>, |'isfname'|, |'path'|,
752
+" |'suffixesadd'|, and |'includeexpr'|, special handling of escaped spaces and
753
+" trailing punctuation, as well as home directory and environment variable
754
+" expansion (|expandcmd|) that would be hard to re-implement, see |gf|. Note
755
+" that the built-in mappings only trigger when the cursor is on or before the
756
+" _filename_, not on the address. |gF| falls back to |gf| functionality without
757
+" giving an error message if a traling line number can't be found, which we
758
+" mimic.
759
+"
760
+" [POSIX.1-2017]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ctags.html#tag_20_27_12
761
+
762
+" TODO: Also support `file:line:col`?
763
+
764
+if has('eval')
765
+  nnoremap gF      :<C-U>call <SID>gf("gF")<CR>
766
+  nnoremap <C-W>F  :<C-U>call <SID>gf("\<lt>C-W>F")<CR>
767
+  nnoremap <C-W>gF :<C-U>call <SID>gf("\<lt>C-W>gF")<CR>
768
+  function! s:gf(cmd) abort
769
+    let back   = '\\\\'
770
+    let fwd    = '\\\/'
771
+    let dollar = '\$\/\@!'
772
+    let other  = '[^\/$]'
773
+    let chr    = '\%(' . join([back, fwd, dollar, other], '\|') . '\)'
774
+    let str    = '\(' . chr . '\+\)'
775
+    let start  = '\(\^\?\)'
776
+    let end    = '\(\$\?\)'
777
+    let addr   = '\/' . start . str . end . '\/'
778
+    let after  = '\%>' . (col('.')-1) . 'c'
779
+    let file   = '[[:fname:]]'
780
+    let sep    = '[[:space:]]*[^[:fname:][:digit:]/][[:space:]]*'
781
+    let pat    = '\m' . after . file . sep . addr
782
+    let match  = matchlist(getline('.'), pat)
783
+    execute 'normal!' (v:count1 . a:cmd)
784
+    if !empty(match)
785
+      let start = match[1]
786
+      let str   = match[2]
787
+      let end   = match[3]
788
+      let pat   = '\C' . '\m' . start . '\V' . str . '\m' . end
789
+      call cursor(1, 1)
790
+      if search(pat, 'c') == 0
791
+        echo "Could not find search string:" (start . str . end)
792
+      endif
793
+    endif
794
+  endfunction
795
+endif
796
+
797
+"" Commands
798
+
799
+""" Fill quickfix with output from system command
800
+" TODO: |<q-args>| does not seem to escape quotes, so things like `Cexpr echo
801
+" 'hello'` does not work. Probably passing it to a function so that we get a
802
+" argument variable to call |shellescape| on is required?
803
+" TODO: How does this compare to |dispatch|?
804
+command! -bang -complete=shellcmd -nargs=+ Cexpr
805
+\ execute (empty(<q-bang>)?'cexpr':'cgetexpr') 'system(expandcmd(' escape(<q-args>, "'") '))'
806
+
807
+""" Run `git ls` and preview commits on cursor move
808
+" Requires `vim-fugitive` and a `ls`/`lsa` Git alias.
809
+command! -bar Gls
810
+\ Git ls |
811
+\ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
812
+\ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
813
+\ execute 'autocmd vimrc BufUnload <buffer> pclose' |
814
+command! -bar Glsa
815
+\ Git lsa |
816
+\ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
817
+\ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
818
+\ execute 'autocmd vimrc BufUnload <buffer> pclose' |
819
+
402 820
 "" Auto commands
403 821
 " Make sure to not define any |autocmd|s before this!
404 822
 augroup vimrc
405 823
   autocmd!
406 824
 augroup END
407 825
 
408
-""" Open the QuickFix/Location list window
409
-" See
410
-" - https://github.com/tpope/vim-dispatch/issues/145
411
-" - https://github.com/tpope/vim-dispatch/issues/254
412
-" - https://github.com/tpope/vim-dispatch/issues/310
413
-" autocmd vimrc QuickFixCmdPost  *{make,{,vim}grep}* nested botright cwindow
414
-" autocmd vimrc QuickFixCmdPost *l{make,{,vim}grep}* nested botright lwindow
826
+""" Hacks for options that Vim likes to reset
415 827
 
416
-""" Highlight all searches
417
-" |'incsearch'| only highlights the first match.
418
-autocmd vimrc CmdlineEnter /,\? let s:hlsearch =  &hlsearch | set hlsearch
419
-autocmd vimrc CmdlineLeave /,\? let  &hlsearch = s:hlsearch
828
+" `$VIMRUNTIME/colors/default.vim`
829
+autocmd vimrc OptionSet background set background=dark
420 830
 
421 831
 """ Save/load view
422
-" As suggested in |:loadview|, load auto-saved view when opening buffer. Better
423
-" than |last-position-jump|, |restore-cursor|.
424
-autocmd vimrc BufWinEnter *
832
+" Roughly as suggested in |:loadview|, load auto-saved view when opening
833
+" buffer. Better than |last-position-jump|, |restore-cursor|. See also
834
+" |'viewoptions'|.
835
+autocmd vimrc BufWinEnter,BufRead *
425 836
 \ if !empty(expand('<afile>')) && empty(&buftype) |
426 837
 \   loadview |
427 838
 \ endif |
428
-autocmd vimrc BufWinLeave *
839
+autocmd vimrc BufWinLeave,BufWrite *
429 840
 \ if !empty(expand('<afile>')) && empty(&buftype) |
430 841
 \   mkview |
431 842
 \ endif |
... ...
@@ -433,75 +844,223 @@ autocmd vimrc BufWinLeave *
433 844
 """ Don't show extra things in special buffers
434 845
 " TODO: This needs to be moved to after the plugins for it to work in e.g.
435 846
 " fugitive?
436
-autocmd vimrc WinEnter,TerminalWinOpen *
437
-\ if &buftype !=# '' |
438
-\   silent setlocal nolist nospell |
439
-\ endif
847
+if !has('nvim')
848
+  autocmd vimrc BufReadPost,TerminalWinOpen *
849
+  \ if !empty(&buftype) |
850
+  \   silent setlocal nolist nospell |
851
+  \ endif
852
+endif
853
+
854
+""" QuickFix/Location list
855
+
856
+"""" Open window
857
+" See
858
+" - <https://github.com/tpope/vim-dispatch/issues/145>
859
+" - <https://github.com/tpope/vim-dispatch/issues/254>
860
+" - <https://github.com/tpope/vim-dispatch/issues/310>
861
+" TODO: Maybe this can be fixed by switching back to the previous window after
862
+" opening the quickfix window? Make sure to only switch to the previous if we
863
+" actually opened the window.
864
+" autocmd vimrc QuickFixCmdPost [^l]* nested botright cwindow
865
+" autocmd vimrc QuickFixCmdPost   l*  nested botright lwindow
866
+" autocmd vimrc QuickFixCmdPost  {{make,{,vim}grep{,add}},c{,get,add}{expr,file,buffer}} nested botright cwindow
867
+" autocmd vimrc QuickFixCmdPost {l{make,{,vim}grep{,add}},l{,get,add}{expr,file,buffer}} nested botright lwindow
868
+
869
+"""" Conceal column numbers
870
+autocmd vimrc BufReadPost quickfix
871
+\ setlocal conceallevel=2 concealcursor=nvic nonumber |
872
+\ syntax match qfColumnNr / col \d\+/ containedin=qfLineNr transparent conceal |
873
+
874
+""" Highlight all searches
875
+" |'incsearch'| only highlights the first match.
876
+if has('eval')
877
+  autocmd vimrc CmdlineEnter /,\? let s:hlsearch =  &hlsearch | set hlsearch
878
+  autocmd vimrc CmdlineLeave /,\? let  &hlsearch = s:hlsearch
879
+endif
440 880
 
441 881
 "" Colors
442 882
 " See |cterm-colors|, |gui-colors|.
443 883
 
444
-""" Overrides
445
-" Transparent background, greyscale interface. Sensible errors/warnings,
884
+silent !. ~/.shrc.d/color.sh
885
+" redraw!
886
+
887
+" TODO: Document that |autocmd| is available in "tiny" (i.e. always) but
888
+" |+syntax| requires "normal", so doing it the way we're doing it makes sure it
889
+" works everywhere. This is especially important for interface highlights
890
+" (|listchars|).
891
+
892
+" TODO: This is getting ridiculous. |:syntax-on| suggests we can just use
893
+" |:highlight| outside any |autocmd|s and it will work. Look into this.
894
+
895
+" TODO: Support `has('gui_running')` and |'termguicolors'|. Look into e.g.
896
+" |g:terminal_ansi_colors|.
897
+
898
+""" General
899
+" Transparent background, grayscale interface. Sensible errors/warnings,
446 900
 " spellchecking, diffs, comments, and todos. See |:hi-normal| and
447 901
 " |:hi-normal-cterm|.
448 902
 
449 903
 if !has('gui_running')
450
-  autocmd vimrc VimEnter,ColorScheme *
904
+  autocmd vimrc ColorScheme * nested
451 905
   \ highlight! Normal guibg=NONE |
452 906
 endif
453 907
 
454
-" TODO: Look at all in |'highlight'|.
455
-autocmd vimrc VimEnter,ColorScheme *
456
-\ highlight! Normal           term=NONE cterm=NONE gui=NONE ctermbg=NONE                    ctermfg=White                    |
457
-\ highlight! Comment          term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey                     |
458
-\ highlight! Todo             term=bold cterm=bold gui=bold ctermbg=NONE       guibg=NONE   ctermfg=White                    |
459
-\ highlight! LineNr           term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
460
-\ highlight! FoldColumn       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
461
-\ highlight! SignColumn       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
462
-\ highlight! VertSplit        term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
463
-\ highlight! StatusLine       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=White     guifg=White    |
464
-\ highlight! StatusLineNC     term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
465
-\ highlight! StatusLineTerm   term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=White     guifg=White    |
466
-\ highlight! StatusLineTermNC term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
467
-\ highlight! TabLine          term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
468
-\ highlight! TabLineFill      term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Grey      guifg=Grey     |
469
-\ highlight! TabLineSel       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=White     guifg=White    |
470
-\ highlight! EndOfBuffer      term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=Black     guifg=Black    |
471
-\ highlight! Error            term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=DarkRed   guifg=Red      |
472
-\ highlight! ErrorMsg         term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=DarkRed   guifg=Red      |
473
-\ highlight! WarningMsg       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=DarkRed   guifg=Red      |
474
-\ highlight! SpellBad         term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=LightRed  guifg=LightRed |
475
-\ highlight! SpellLocal       term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=LightRed  guifg=LightRed |
476
-\ highlight! SpellRare        term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=LightRed  guifg=LightRed |
477
-\ highlight! SpellCap         term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=LightRed  guifg=LightRed |
478
-\ highlight! DiffAdd          term=NONE cterm=NONE gui=NONE ctermbg=DarkGreen  guibg=Green  ctermfg=Black     guifg=Black    |
479
-\ highlight! DiffDelete       term=NONE cterm=NONE gui=NONE ctermbg=DarkRed    guibg=Red    ctermfg=Black     guifg=Black    |
480
-\ highlight! DiffChange       term=NONE cterm=NONE gui=NONE ctermbg=DarkBlue   guibg=Blue   ctermfg=Black     guifg=Black    |
481
-\ highlight! DiffText         term=NONE cterm=NONE gui=NONE ctermbg=DarkYellow guibg=Yellow ctermfg=Black     guifg=Black    |
482
-\ highlight! diffAdded        term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=DarkGreen guifg=Green    |
483
-\ highlight! diffRemoved      term=NONE cterm=NONE gui=NONE ctermbg=NONE       guibg=NONE   ctermfg=DarkRed   guifg=Red      |
484
-
485
-""" |'listchars'|
486
-autocmd vimrc VimEnter,ColorScheme *
487
-\ highlight! link SpecialKey Special |
488
-\ highlight! link NonText    Special |
489
-
490
-""" Folds
491
-autocmd vimrc VimEnter,ColorScheme *
492
-\ highlight! link Folded Comment |
908
+" TODO: Look at all in |'highlight'| (in particular |hl-Search|) and |highlight-default|.
909
+" TODO: This could be done by setting |'highlight'| instead of monkying around
910
+" with highlight groups. Unclear if better.
911
+" TODO: For all chromatic colors, use `Light*`.
912
+" TODO: Remove all `White` except `Normal` from this list and link them to `Normal`?
913
+" TODO: Remove all `Gray` except `Comment` from this list and link them to `Comment`?
914
+" NOTE: When |hl-StatusLine| is a |:hi-link| Vim cannot determine if it's equal
915
+" to |hl-StatusLineNC| and uses "^^^". Same for `StatusLineTerm{,NC}`. See
916
+" `src/drawscreen.c:550` (at the bottom of the funtion `win_redr_status`) in
917
+" the Vim source.
918
+" TODO: Since the Linux console cannot use `DarkGray` as a background, consider
919
+" using any other `Dark*` color (e.g. `DarkYellow`) as (non-`reverse`) `Visual`
920
+" `ctermbg` with `ctermfg=NONE`. NOTE: This requires that we standardize on
921
+" `__color_set_uniform_diff_low`. `__color_set_uniform_diff_high` works (in
922
+" fact is required) for `cterm=reverse ctermfg=NONE ctermbg=NONE`.
923
+" TODO: Why do we need the `term=NONE`? Is this tested ever? Is it used in
924
+" `vim.tiny`?
925
+
926
+" TODO: Vim requests the background color from the terinal with the escape
927
+" sequence |t_RB| and sets |'background'| when it gets the response
928
+" (|v:termrbgresp|). That response may come after |vimrc| has completed, so if
929
+" you want to do |:colorscheme| do it in a `autocmd vimrc OptionSet
930
+" background`.
931
+
932
+" autocmd vimrc ColorScheme * nested
933
+" \ highlight Normal font='Monospace Regular 10'
934
+
935
+" \ set background=dark | runtime syntax/syncolor.vim |
936
+autocmd vimrc ColorScheme * nested
937
+\ highlight Normal           term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
938
+\ highlight Comment          term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
939
+\ highlight Todo             term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=White      |
940
+\ highlight Error            term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
941
+\ highlight SpellBad         term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
942
+\ highlight SpellOther       term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
943
+\ highlight Visual           term=NONE   cterm=NONE   gui=NONE              ctermbg=LightGray   ctermfg=NONE       |
944
+\ highlight Search           term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkYellow  ctermfg=NONE       |
945
+\ highlight DiffAdd          term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkGreen   ctermfg=NONE       |
946
+\ highlight DiffDelete       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkRed     ctermfg=NONE       |
947
+\ highlight DiffChange       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkBlue    ctermfg=NONE       |
948
+\ highlight DiffText         term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkYellow  ctermfg=NONE       |
949
+\ highlight diffAdded        term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightGreen |
950
+\ highlight diffRemoved      term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
951
+\ highlight StatusLine       term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
952
+\ highlight StatusLineTerm   term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
953
+\ highlight StatusLineNC     term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
954
+\ highlight StatusLineTermNC term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=DarkGray   |
955
+\ highlight Ignore           term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=Black      |
956
+" \ highlight DiffAdd          term=NONE   cterm=NONE   gui=NONE              ctermbg=LightGreen  ctermfg=Black      |
957
+" \ highlight DiffDelete       term=NONE   cterm=NONE   gui=NONE              ctermbg=LightRed    ctermfg=Black      |
958
+" \ highlight DiffChange       term=NONE   cterm=NONE   gui=NONE              ctermbg=LightBlue   ctermfg=Black      |
959
+" \ highlight DiffText         term=NONE   cterm=NONE   gui=NONE              ctermbg=LightYellow ctermfg=Black      |
960
+
961
+""" No bold
962
+" Remove all `cterm=bold` set by default in `$VIMRUNTIME/syntax/syncolor.vim`.
963
+" The Linux virtual console does typically not have a bold font.
964
+autocmd vimrc ColorScheme * nested
965
+\ highlight Identifier cterm=NONE ctermfg=LightCyan |
966
+
967
+""" Debug
968
+autocmd vimrc ColorScheme * nested
969
+\ highlight debugPC         term=reverse cterm=NONE gui=NONE guibg=DarkBlue ctermbg=DarkBlue guifg=NONE     ctermfg=NONE     |
970
+\ highlight debugBreakpoint term=NONE    cterm=NONE gui=NONE guibg=NONE     ctermbg=NONE     guifg=LightRed ctermfg=LightRed |
971
+
972
+" set highlight-=s:StatusLine
973
+" set highlight-=S:StatusLineNC
974
+" set highlight-=z:StatusLineTerm
975
+" set highlight-=Z:StatusLineTermNC
976
+" set highlight+=s:Normal,z:Normal,S:Comment,Z:Comment
977
+
978
+autocmd vimrc ColorScheme * nested
979
+\ highlight! link TabLineSel     Normal |
980
+\ highlight! link ToolbarButton  Comment |
981
+" \ highlight! link StatusLine     Normal |
982
+" \ highlight! link StatusLineTerm Normal |
983
+
984
+""" Interface
985
+autocmd vimrc ColorScheme * nested
986
+\ highlight! link TabLine          Comment |
987
+\ highlight! link TabLineFill      Comment |
988
+\ highlight! link ToolbarLine      Comment |
989
+\ highlight! link VertSplit        Comment |
990
+\ highlight! link LineNr           Comment |
991
+\ highlight! link Folded           Comment |
992
+\ highlight! link FoldColumn       Comment |
993
+\ highlight! link SignColumn       Comment |
994
+" \ highlight! link StatusLineNC     Comment |
995
+" \ highlight! link StatusLineTermNC Comment |
996
+
997
+""" Errors/warnings
998
+autocmd vimrc ColorScheme * nested
999
+\ highlight! link ErrorMsg   Error |
1000
+\ highlight! link WarningMsg Error |
1001
+
1002
+""" Spell
1003
+autocmd vimrc ColorScheme * nested
1004
+\ highlight! link SpellCap   SpellOther |
1005
+\ highlight! link SpellRare  SpellOther |
1006
+\ highlight! link SpellLocal SpellOther |
1007
+
1008
+""" Visual
1009
+autocmd vimrc ColorScheme * nested
1010
+\ highlight! link VisualNOS    Visual |
1011
+\ highlight! link ColorColumn  Visual |
1012
+\ highlight! link CursorColumn Visual |
1013
+\ highlight! link CursorLine   Visual |
1014
+\ highlight! link CursorLineNr Visual |
1015
+
1016
+""" Popup menu
1017
+" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
1018
+autocmd vimrc ColorScheme * nested
1019
+\ highlight Pmenu     ctermbg=LightGray ctermfg=DarkGray |
1020
+\ highlight PmenuSel  ctermbg=LightGray ctermfg=White    |
1021
+\ highlight PmenuSbar ctermbg=DarkGray                   |
1022
+
1023
+""" Non-document characters
1024
+" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
1025
+autocmd vimrc ColorScheme * nested
1026
+\ highlight! link NonText     Special |
1027
+\ highlight! link EndOfBuffer Ignore  |
1028
+
1029
+""" Document non-printables characters
1030
+" See |'listchars'| `tab`, `space`, `trail`, `nbsp`.
1031
+autocmd vimrc ColorScheme * nested
1032
+\ highlight! link SpecialKey Comment |
1033
+
1034
+""" Document concealed characters
1035
+" See |'listchars'| `conceal`.
1036
+autocmd vimrc ColorScheme * nested
1037
+\ highlight! link Conceal Ignore |
493 1038
 
494 1039
 """ Vim comments
495
-autocmd vimrc VimEnter,ColorScheme *
1040
+autocmd vimrc ColorScheme * nested
496 1041
 \ highlight! link vimCommentString vimComment |
497 1042
 \ highlight! link vimCommentTitle  vimComment |
498 1043
 
1044
+""" Apply
1045
+" TODO: Move `syntax enable` to someplace before this?
1046
+" TODO: `doautocmd vimrc ColorScheme` worked for everything except when using
1047
+" Vim as `$MANPAGER`. Not sure if this is a problem with `vimrc` or
1048
+" `.vim/ftplugin/man.vim`. We don't always `has('eval')` though.
1049
+" echom &background
1050
+" if has('eval')
1051
+"   colorscheme default
1052
+" endif
1053
+" echom &background
1054
+doautocmd vimrc ColorScheme
1055
+" autocmd vimrc VimEnter  *               nested doautocmd vimrc ColorScheme
1056
+" autocmd vimrc OptionSet background,t_Co nested doautocmd vimrc ColorScheme
1057
+
499 1058
 "" Plugins
500 1059
 
501 1060
 if has('eval')
502 1061
 
503 1062
   """ GitAdd
504
-  " https://git.rcrnstn.net/rcrnstn/vim-gitadd
1063
+  " <https://git.rcrnstn.net/rcrnstn/vim-gitadd>
505 1064
 
506 1065
   " Make sure to not enable |:syntax| and |:filetype| until all plugins that
507 1066
   " interact with them have been added! See |:packadd|.
... ...
@@ -536,24 +1095,72 @@ if has('eval')
536 1095
 
537 1096
   " See |ft-man-plugin|.
538 1097
   let g:ft_man_folding_enable = 1
539
-  runtime ftplugin/man.vim
540
-  setglobal keywordprg=:Man
541 1098
 
542
-  """" `sheerun/vim-polyglot`
543
-  GitAdd https://github.com/sheerun/vim-polyglot
1099
+  " TODO: Should be easy to create a |'foldexpr'| that's better than the
1100
+  " built-in `foldmethod=indent`.
1101
+  " function s:manfold() abort
1102
+  "   foldlevel()
1103
+  " endfunction
1104
+
1105
+  " We're using our own |:ManHelp| instead.
1106
+  " runtime ftplugin/man.vim
1107
+  " setglobal keywordprg=:Man
1108
+
1109
+  """" Built-in `asm`
1110
+
1111
+  " See |ft-asm-syntax|.
1112
+  let g:filetype_i = 'asm'
1113
+
1114
+  """" `tpope/vim-markdown`
1115
+  " GitAdd https://github.com/tpope/vim-markdown
1116
+
1117
+  """" `preservim/vim-markdown`
1118
+  GitAdd https://github.com/preservim/vim-markdown
544 1119
 
545 1120
   let g:vim_markdown_no_default_key_mappings = 1
1121
+  let g:vim_markdown_toc_autofit = 1
1122
+  let g:vim_markdown_math = 1
1123
+  let g:vim_markdown_frontmatter = 1
1124
+  let g:vim_markdown_no_extensions_in_markdown = 1
1125
+
1126
+  " " Defaults.
1127
+  " " |vim-markdown-fenced-code-block-languages|
1128
+  " let g:vim_markdown_fenced_languages = [
1129
+  " \   "c++=cpp",
1130
+  " \   "viml=vim",
1131
+  " \   "bash=sh",
1132
+  " \   "ini=dosini",
1133
+  " \ ]
1134
+  " " Additions.
1135
+  " call add(g:vim_markdown_fenced_languages, [
1136
+  " \   "diff",
1137
+  " \ ])
1138
+
1139
+
1140
+  " <https://github.com/preservim/vim-markdown/issues/232>
1141
+  " let g:vim_markdown_new_list_item_indent = 0
1142
+  " let g:vim_markdown_auto_insert_bullets = 0
1143
+
1144
+  """" `vim-pandoc/vim-pandoc-syntax`
1145
+  " GitAdd https://github.com/vim-pandoc/vim-pandoc-syntax
1146
+
1147
+  " Roughly as recommended in the readme.
1148
+  " autocmd vimrc BufNewFile,BufFilePre,BufRead *.md set filetype=markdown.pandoc
1149
+
1150
+  """" `sheerun/vim-polyglot`
1151
+  GitAdd https://github.com/sheerun/vim-polyglot
546 1152
 
547 1153
   let g:polyglot_disabled = [
548 1154
   \   'sensible',
549 1155
   \   'autoindent',
1156
+  \   'markdown',
550 1157
   \ ]
551 1158
 
552 1159
   """" `tpope/vim-sleuth`
553 1160
   GitAdd https://github.com/tpope/vim-sleuth
554 1161
 
555 1162
   """" `tpope/vim-apathy`
556
-  GitAdd https://github.com/tpope/vim-apathy
1163
+  " GitAdd https://github.com/tpope/vim-apathy
557 1164
 
558 1165
   """" `tpope/vim-scriptease`
559 1166
   GitAdd https://github.com/tpope/vim-scriptease
... ...
@@ -570,6 +1177,12 @@ if has('eval')
570 1177
   " \   'ext':    '.md',
571 1178
   " \ }]
572 1179
 
1180
+  """" `mhinz/vim-rfc`
1181
+  GitAdd https://github.com/mhinz/vim-rfc
1182
+
1183
+  """" `HiPhish/info.vim`
1184
+  GitAdd https://gitlab.com/HiPhish/info.vim
1185
+
573 1186
   """ Normal mode
574 1187
 
575 1188
   """" Built-in `matchit`
... ...
@@ -579,9 +1192,20 @@ if has('eval')
579 1192
   """" `tpope/vim-unimpaired`
580 1193
   GitAdd https://github.com/tpope/vim-unimpaired
581 1194
 
1195
+  " <https://github.com/tpope/vim-unimpaired/issues?q=conceal>
1196
+  " <https://github.com/tpope/vim-unimpaired/issues/105>
1197
+  " <https://github.com/tpope/vim-unimpaired/pull/152>
1198
+  nnoremap yoe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 2 : 0<CR><CR>
1199
+  nnoremap [oe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 0 : &conceallevel - 1<CR><CR>
1200
+  nnoremap ]oe :setlocal conceallevel=<C-R>=&conceallevel == 2 ? 2 : &conceallevel + 1<CR><CR>
1201
+
582 1202
   """" `tpope/vim-repeat`
583 1203
   GitAdd https://github.com/tpope/vim-repeat
584 1204
 
1205
+  """" `inkarkat/vim-visualrepeat`
1206
+  " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
1207
+  GitAdd https://github.com/inkarkat/vim-visualrepeat
1208
+
585 1209
   """" `tpope/vim-characterize`
586 1210
   GitAdd https://github.com/tpope/vim-characterize
587 1211
 
... ...
@@ -596,26 +1220,56 @@ if has('eval')
596 1220
   map           g# <Plug>(asterisk-g#)
597 1221
   map <silent>  z* <Plug>(asterisk-z*): set hlsearch<CR>
598 1222
   map <silent>  z# <Plug>(asterisk-z#): set hlsearch<CR>
599
-  map <silent> zg* <Plug>(asterisk-gz*):set hlsearch<CR>
600
-  map <silent> zg# <Plug>(asterisk-gz#):set hlsearch<CR>
1223
+  map <silent> gz* <Plug>(asterisk-gz*):set hlsearch<CR>
1224
+  map <silent> gz# <Plug>(asterisk-gz#):set hlsearch<CR>
601 1225
 
602 1226
   """" `AndrewRadev/splitjoin.vim`
603 1227
   GitAdd https://github.com/AndrewRadev/splitjoin.vim
604 1228
 
1229
+  " TODO: According to |splitjoin_align| this requires either of the Tabular or
1230
+  " Align plugins. We currently prefer vim-lion. Create a pull request?
1231
+  " let g:splitjoin_align = 1
1232
+
605 1233
   """" `AndrewRadev/switch.vim`
606 1234
   GitAdd https://github.com/AndrewRadev/switch.vim
607 1235
 
608 1236
   let g:switch_custom_definitions = [{
609 1237
   \   '\<0\>': '1',
610 1238
   \   '\<1\>': '0',
611
-  \   '\(\w*\)TRUE\(\w*\)': '\1FALSE\2',
612
-  \   '\(\w*\)True\(\w*\)': '\1False\2',
613
-  \   '\(\w*\)true\(\w*\)': '\1false\2',
1239
+  \   '\<OFF\>': 'ON',
1240
+  \   '\<Off\>': 'On',
1241
+  \   '\<off\>': 'on',
1242
+  \   '\<ON\>': 'OFF',
1243
+  \   '\<On\>': 'Off',
1244
+  \   '\<on\>': 'off',
1245
+  \   '\<NO\>': 'YES',
1246
+  \   '\<No\>': 'Yes',
1247
+  \   '\<no\>': 'yes',
1248
+  \   '\<YES\>': 'NO',
1249
+  \   '\<Yes\>': 'No',
1250
+  \   '\<yes\>': 'no',
614 1251
   \   '\(\w*\)FALSE\(\w*\)': '\1TRUE\2',
615 1252
   \   '\(\w*\)False\(\w*\)': '\1True\2',
616 1253
   \   '\(\w*\)false\(\w*\)': '\1true\2',
1254
+  \   '\(\w*\)TRUE\(\w*\)': '\1FALSE\2',
1255
+  \   '\(\w*\)True\(\w*\)': '\1False\2',
1256
+  \   '\(\w*\)true\(\w*\)': '\1false\2',
1257
+  \   '\<\(set *\)no\([a-z]\+\)\>=\@!': '\1\2',
1258
+  \   '\<\(set *\)\([a-z]\+\)\>=\@!':   '\1no\2',
617 1259
   \ }]
618 1260
 
1261
+  """" `terryma/vim-smooth-scroll`
1262
+  " GitAdd https://github.com/terryma/vim-smooth-scroll
1263
+
1264
+  " Kind of useful when pair programming to give some indication of navigation,
1265
+  " mostly annoying when not.
1266
+
1267
+  " Roughly as suggested in the readme.
1268
+  " noremap <silent> <C-U> :call smooth_scroll#up(  &scroll*1, 20, &scroll/4)<CR>
1269
+  " noremap <silent> <C-D> :call smooth_scroll#down(&scroll*1, 20, &scroll/4)<CR>
1270
+  " noremap <silent> <C-B> :call smooth_scroll#up(  &scroll*2, 20, &scroll/2)<CR>
1271
+  " noremap <silent> <C-F> :call smooth_scroll#down(&scroll*2, 20, &scroll/2)<CR>
1272
+
619 1273
   """ Insert mode
620 1274
 
621 1275
   """" `tpope/vim-endwise`
... ...
@@ -624,6 +1278,14 @@ if has('eval')
624 1278
   """" `jiangmiao/auto-pairs`
625 1279
   GitAdd https://github.com/jiangmiao/auto-pairs
626 1280
 
1281
+  " TODO: Look at "Swedish Character Conflict" in the documentation.
1282
+
1283
+  " Disable meta mappings.
1284
+  let g:AutoPairsShortcutToggle     = ''
1285
+  let g:AutoPairsShortcutFastWrap   = ''
1286
+  let g:AutoPairsShortcutJump       = ''
1287
+  let g:AutoPairsShortcutBackInsert = ''
1288
+
627 1289
   " Don't jump around too much. See |autopairs-options|.
628 1290
   let g:AutoPairsCenterLine = 0
629 1291
   let g:AutoPairsMultilineClose = 0
... ...
@@ -631,7 +1293,7 @@ if has('eval')
631 1293
   """ Command-line mode
632 1294
 
633 1295
   """" `tpope/vim-rsi`
634
-  GitAdd https://github.com/tpope/vim-rsi
1296
+  " GitAdd https://github.com/tpope/vim-rsi
635 1297
 
636 1298
   """" `tpope/vim-abolish`
637 1299
   GitAdd https://github.com/tpope/vim-abolish
... ...
@@ -659,6 +1321,15 @@ if has('eval')
659 1321
   """" `wellle/targets.vim`
660 1322
   GitAdd https://github.com/wellle/targets.vim
661 1323
 
1324
+  " `targets` just pairs up quotes from the beginning of line, which is often
1325
+  " not what we want (especially in shell scripts).
1326
+  xnoremap i" i"
1327
+  xnoremap i' i'
1328
+  xnoremap i` i`
1329
+  onoremap i" i"
1330
+  onoremap i' i'
1331
+  onoremap i` i`
1332
+
662 1333
   """" `bkad/CamelCaseMotion`
663 1334
   GitAdd https://github.com/bkad/CamelCaseMotion
664 1335
 
... ...
@@ -675,7 +1346,7 @@ if has('eval')
675 1346
   GitAdd https://github.com/kana/vim-textobj-user
676 1347
 
677 1348
   " All later plugins in the "Motions / text objects" category depend on this
678
-  " plugin. See https://github.com/kana/vim-textobj-user/wiki.
1349
+  " plugin. See <https://github.com/kana/vim-textobj-user/wiki>.
679 1350
 
680 1351
   """" `kana/vim-textobj-entire`
681 1352
   GitAdd https://github.com/kana/vim-textobj-entire
... ...
@@ -715,17 +1386,17 @@ if has('eval')
715 1386
   """ Colors
716 1387
 
717 1388
   """" `gruvbox-community/gruvbox`
1389
+  " TODO: This is a stopgap untill we make a Vim colorscheme from
1390
+  " <https://notes/rcrnstn/colors.md>.
718 1391
   GitAdd https://github.com/gruvbox-community/gruvbox
719 1392
 
720 1393
   let g:gruvbox_contrast_dark = 'hard'
721 1394
   let g:gruvbox_invert_selection = 0
722 1395
 
723
-  " Earlier settings indicate whether we want a color scheme not based on
724
-  " terminal colors. '|termguicolors|' is reset further down if not supported.
725
-  if &t_Co >= 256
726
-    set termguicolors
727
-    colorscheme gruvbox
728
-  endif
1396
+  autocmd vimrc OptionSet termguicolors nested
1397
+  \ execute 'colorscheme' &termguicolors ? 'gruvbox' : 'default' |
1398
+
1399
+  doautocmd OptionSet termguicolors
729 1400
 
730 1401
   """ Windows
731 1402
 
... ...
@@ -741,8 +1412,10 @@ if has('eval')
741 1412
   set foldtext=unobtrusive_fold#text()
742 1413
 
743 1414
   " As suggested in |unobtrusive-fold-example|.
744
-  autocmd vimrc FileType *        UnobtrusiveFoldComment
745
-  autocmd vimrc FileType markdown UnobtrusiveFoldChar #
1415
+  " autocmd vimrc FileType *        UnobtrusiveFoldComment
1416
+  " autocmd vimrc FileType markdown UnobtrusiveFoldChar #
1417
+
1418
+  let g:vim_markdown_folding_disabled = 1
746 1419
 
747 1420
   """ Undo
748 1421
 
... ...
@@ -757,30 +1430,79 @@ if has('eval')
757 1430
   """ QuickFix
758 1431
 
759 1432
   """" Built-in `cfilter`
760
-
761 1433
   packadd! cfilter
762 1434
 
1435
+  """" `romainl/vim-qf`
1436
+  " GitAdd https://github.com/romainl/vim-qf
1437
+
1438
+  " let g:qf_mapping_ack_style = 1
1439
+  " let g:qf_shorten_path = 1
1440
+
1441
+  " TODO: Check if this causes problems, see the "Open the QuickFix/Location
1442
+  " list window" section.
1443
+  " let g:qf_auto_open_quickfix = 0
1444
+
1445
+  """ Spell
1446
+
1447
+  """" `inkarkat/vim-SpellCheck`
1448
+  " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
1449
+  " GitAdd https://github.com/inkarkat/vim-SpellCheck
1450
+
763 1451
   """ Modelines
764 1452
 
765 1453
   """" `ypcrts/securemodelines`
766
-  GitAdd https://github.com/ypcrts/securemodelines
1454
+  " GitAdd https://github.com/ypcrts/securemodelines
1455
+  " TODO: Last updated 2019 as of writing, can we be sure is this really more
1456
+  " secure than the built-in sandbox? Besides, we don't use modelines much
1457
+  " anyway.
1458
+
1459
+  " let g:secure_modelines_verbose = 1
767 1460
 
768 1461
   """ Environment interaction
769 1462
 
770 1463
   """" Built-in `netrw`
771 1464
 
1465
+  let g:netrw_home = '~/.cache/vim/netrw'
1466
+  let g:netrw_banner = 0
1467
+
772 1468
   " Netrw versions (roughly) 162h to 170 break `gx`. Never download the remote
773 1469
   " file to a temporary. See
774
-  " - https://github.com/vim/vim/issues/1386
775
-  " - https://github.com/vim/vim/issues/4738
776
-  " - https://github.com/vim/vim/pull/7188
1470
+  " - <https://github.com/vim/vim/issues/1386>
1471
+  " - <https://github.com/vim/vim/issues/4738>
1472
+  " - <https://github.com/vim/vim/pull/7188>
777 1473
   let g:netrw_nogx = 1
778 1474
   nnoremap <silent> gx  :call netrw#BrowseX(netrw#GX(), 0)<CR>
779 1475
   xnoremap <silent> gx y:call netrw#BrowseX(@",         0)<CR>
780 1476
 
1477
+  """" `bogado/file-line`
1478
+  GitAdd https://github.com/bogado/file-line
1479
+
781 1480
   """" `ctrlpvim/ctrlp.vim`
782 1481
   GitAdd https://github.com/ctrlpvim/ctrlp.vim
783 1482
 
1483
+  " <https://github.com/kien/ctrlp.vim/issues/337>
1484
+  " <https://github.com/ctrlpvim/ctrlp.vim/pull/316>
1485
+  " <https://github.com/ctrlpvim/ctrlp.vim/issues/450>
1486
+  " NOTE: Highly dependent on non-documented ctrlp internals.
1487
+  function! s:ctrlp_syntax() abort
1488
+    execute 'autocmd vimrc OptionSet cursorline'
1489
+    \  'if winnr() == ' winnr() ' && &cursorline |'
1490
+    \  '  set nocursorline |'
1491
+    \  'endif |'
1492
+    syntax     region CtrlPLine      start="^"   end="$"
1493
+    syntax     region CtrlPLineSel   start="\%#" end="$"
1494
+    highlight! link   CtrlPLine      Comment
1495
+    highlight! link   CtrlPLineSel   Normal
1496
+    " TODO: `&term ==# 'linux'` does not do `underline`.
1497
+    highlight         CtrlPPrtCursor term=underline cterm=underline
1498
+  endfunction
1499
+  " We need to define the `Syntax` `autocmd` after `ctrlp` has been loaded, but
1500
+  " also when we reload the `vimrc`.
1501
+  " TODO: This still does not work when reloading the `vimrc`.
1502
+  autocmd vimrc VimEnter *
1503
+  \ autocmd vimrc Syntax ctrlp call s:ctrlp_syntax()
1504
+  autocmd vimrc Syntax ctrlp call s:ctrlp_syntax()
1505
+
784 1506
   let g:ctrlp_working_path_mode = ''
785 1507
   let g:ctrlp_match_current_file = 1
786 1508
   let g:ctrlp_follow_symlinks = 2
... ...
@@ -791,33 +1513,76 @@ if has('eval')
791 1513
   let g:ctrlp_use_readdir = 0 " Respect 'wildignore'.
792 1514
   let g:ctrlp_max_files = 0 " Default 10000.
793 1515
   let g:ctrlp_max_depth = 40 " Default 40.
1516
+  let g:ctrlp_match_window = 'max:20' " Default 'max:10'
794 1517
   " let g:ctrlp_user_command_async = 1
795 1518
   if has('unix')
796 1519
     " TODO: Set `grepprg` to something similar, that skips things in
797 1520
     " 'wildignore'.
798
-    let g:ctrlp_user_command = 'find' .
799
-    \ (g:ctrlp_follow_symlinks ? ' -L' : '') .
1521
+    let s:wildignore      = split(&wildignore, ',')
1522
+    let s:wildignore_name = filter(copy(s:wildignore), '!count(v:val, "/")')
1523
+    let s:wildignore_path = filter(copy(s:wildignore), ' count(v:val, "/")')
1524
+
1525
+    let g:ctrlp_user_command =
1526
+    \ 'find' .
1527
+    \ (!g:ctrlp_follow_symlinks ? '' : ' -L') .
800 1528
     \ ' %s' .
1529
+    \ ' -mount' .
801 1530
     \ ' -maxdepth ' . g:ctrlp_max_depth .
802 1531
     \ ' \( -false' .
803 1532
     \ (g:ctrlp_show_hidden ? '' : ' -o -name ".*"') .
804
-    \ ' ' .
805
-    \ join(map(split(&wildignore, ','), '"-o -name " . shellescape(v:val)')) .
1533
+    \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) .
1534
+    \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(v:val)')) .
806 1535
     \ ' \) -prune -o' .
807
-    \ ' -type f' .
1536
+    \ ' -type f -print' .
808 1537
     \ ' 2> /dev/null' .
809
-    \ (g:ctrlp_max_files ? ' | head -n ' . g:ctrlp_max_files : '')
1538
+    \ (!g:ctrlp_max_files ? '' : ' | head -n ' . g:ctrlp_max_files)
1539
+
1540
+
1541
+    " \ ' -type d -exec test -d {}/.git \; -prune -o' .
810 1542
     " \ ' -exec grep -Il . {} +' .
811 1543
     " \ ' \(' .
812 1544
     " \ (g:ctrlp_follow_symlinks == 2 ? ' -o -type l' : '') .
813 1545
     " \ ' \)' .
1546
+
1547
+    " function! s:ctrl_find_prefix(prefix, list) abort
1548
+    "   return map(copy(a:list), '["' . a:prefix . '", shellescape(v:val)]')
1549
+    " endfunction
1550
+    " function! s:ctrl_find_join(join, list) abort
1551
+    "   return ['\('] + eval(join(a:list, '+["' . a:join . '"]+')) + ['\)']
1552
+    " endfunction
1553
+    " let g:ctrlp_user_command = join(
1554
+    " \   ['find', (!g:ctrlp_follow_symlinks ? '' : '-L'), '%s'] +
1555
+    " \   ['-maxdepth', g:ctrlp_max_depth] +
1556
+    " \   s:ctrl_find_join('-o',
1557
+    " \     s:ctrl_find_prefix('-name', g:ctrlp_show_hidden ? [] : ['.*']) +
1558
+    " \     s:ctrl_find_prefix('-name', s:wildignore_name) +
1559
+    " \     s:ctrl_find_prefix('-path', s:wildignore_path)
1560
+    " \   ) + ['-prune', '-o'] +
1561
+    " \   ['-type', 'f', '-print'] +
1562
+    " \   ['2>', '/dev/null'] +
1563
+    " \   (!g:ctrlp_max_files ? [] : ['|', 'head', '-n', g:ctrlp_max_files])
1564
+    " \ )
1565
+
814 1566
   endif
815 1567
 
1568
+  """" `mhinz/vim-tree`
1569
+  " GitAdd https://github.com/mhinz/vim-tree
1570
+
1571
+  " As suggesteed in the readme.
1572
+  " autocmd vimrc FileType tree
1573
+  " \ setlocal foldmethod=expr
1574
+
816 1575
   """" `tpope/vim-fugitive`
817 1576
   GitAdd https://github.com/tpope/vim-fugitive
818 1577
 
819 1578
   autocmd vimrc FileType fugitiveblame call fugitive#MapJumps()
820 1579
 
1580
+  " http://vimcasts.org/episodes/fugitive-vim-browsing-the-git-object-database/
1581
+  " TODO: Do we want `bufhidden=wipe`?
1582
+  autocmd vimrc BufReadPost fugitive://* setlocal bufhidden=delete
1583
+
1584
+  " TODO: Add some `git log -L` (see man page) mapping.
1585
+
821 1586
   """" `tommcdo/vim-fugitive-blame-ext`
822 1587
   GitAdd https://github.com/tommcdo/vim-fugitive-blame-ext
823 1588
 
... ...
@@ -827,6 +1592,58 @@ if has('eval')
827 1592
   """" `tpope/vim-dispatch`
828 1593
   GitAdd https://github.com/tpope/vim-dispatch
829 1594
 
1595
+  " https://github.com/tpope/vim-dispatch/issues/203
1596
+  function! s:focus_start_set() abort
1597
+    if get(b:, 'start_local', 1)
1598
+      let b:start_local = get(b:, 'start')
1599
+    endif
1600
+    let b:start = s:start
1601
+  endfunction
1602
+  function! s:focus_start_unset() abort
1603
+    if type(get(b:, 'start_local')) == type('')
1604
+      let b:start = b:start_local
1605
+    else
1606
+      unlet! b:start
1607
+    endif
1608
+    unlet! b:start_local
1609
+  endfunction
1610
+  function! s:focus_start(bang, command) abort
1611
+    if !empty(a:command)
1612
+      let s:start = a:command
1613
+      augroup vimrc_dispatch_start
1614
+        autocmd!
1615
+      augroup END
1616
+      silent bufdo call s:focus_start_set()
1617
+      augroup vimrc_dispatch_start
1618
+        autocmd BufEnter * call s:focus_start_set()
1619
+      augroup END
1620
+      echo 'Set global default to :Start' s:start
1621
+    elseif a:bang
1622
+      unlet! s:start
1623
+      augroup vimrc_dispatch_start
1624
+        autocmd!
1625
+      augroup END
1626
+      silent bufdo call s:focus_start_unset()
1627
+      if type(get(b:, 'start')) == type('')
1628
+        echo 'Reverted default to :Start' b:start
1629
+      else
1630
+        echo 'Reverted default to :Start'
1631
+      endif
1632
+    else
1633
+      if type(get(s:, 'start')) == type('')
1634
+        echo 'Global focus is :Start' s:start
1635
+      elseif type(get(b:, 'start')) == type('')
1636
+        echo 'Buffer default is :Start' b:start
1637
+      else
1638
+        echo 'Global default is :Start'
1639
+      endif
1640
+    endif
1641
+  endfunction
1642
+  command! -bang -nargs=* -range=-1 -complete=customlist,dispatch#command_complete FocusStart
1643
+  \ call s:focus_start(<bang>0, <q-args>)
1644
+
1645
+  " TODO: Put this in a QuickFix section?
1646
+
830 1647
   " TODO: Stick to the default mappings.
831 1648
   nnoremap <Space><Space>m% :Make %:r:S<CR>
832 1649
   nnoremap <Space><Space>m# :Make #:r:S<CR>
... ...
@@ -842,42 +1659,167 @@ if has('eval')
842 1659
 
843 1660
   """ Debugging
844 1661
 
1662
+  """" Built-in `termdebug`
1663
+  " See |terminal-debug|.
1664
+
1665
+  packadd! termdebug
1666
+  " TODO: Add mappings.
1667
+  " TODO: Remove |:Winbar|.
1668
+  " TODO: Do some |termdebug-customizing|, especially |termdebug_shortcuts|.
1669
+  " TODO: Add some signs? ■♦←↑→↓›»•·
1670
+  " let g:termdebug_popup = 0
1671
+
1672
+  nnoremap <Space>dd :Termdebug
1673
+
1674
+  nnoremap <Space>db :Break<CR>
1675
+  nnoremap <Space>dB :Clear<CR>
1676
+  nnoremap <Space>di :Step<CR>
1677
+  nnoremap <Space>do :Over<CR>
1678
+  nnoremap <Space>df :Finish<CR>
1679
+  nnoremap <Space>dr :Run<CR>
1680
+  nnoremap <Space>da :Arguments<CR>
1681
+  nnoremap <Space>ds :Stop<CR>
1682
+  nnoremap <Space>dc :Continue<CR>
1683
+  " nnoremap <Space>de :Evaluate<CR>
1684
+
1685
+  " nnoremap <Space>dg :Gdb<CR>
1686
+  " nnoremap <Space>ds :Source<CR>
1687
+  " nnoremap <Space>da :Asm<CR>
1688
+
1689
+  " nnoremap <Space>dw :Winbar<CR>
1690
+
845 1691
   """" `puremourning/vimspector`
846 1692
   " GitAdd https://github.com/puremourning/vimspector
847 1693
 
848 1694
   " Debug Adapter Protocol (DAP) client. See
849
-  " https://microsoft.github.io/debug-adapter-protocol/.
1695
+  " - <https://microsoft.github.io/debug-adapter-protocol/>
1696
+  " - <https://sourceware.org/gdb/current/onlinedocs/gdb.html/Debugger-Adapter-Protocol.html>
1697
+
1698
+  " <https://github.com/mfussenegger/nvim-dap/wiki/Debug-Adapter-installation>
850 1699
 
851 1700
   """" `vim-vdebug/vdebug`
852 1701
   " GitAdd https://github.com/vim-vdebug/vdebug
853 1702
 
1703
+  " Supports PHP, Python, Ruby, Perl, Tcl and NodeJS.
1704
+
854 1705
   " Common DeBugGer Protocol (DBGP) client. See
855
-  " https://en.wikipedia.org/wiki/DBGp.
1706
+  " <https://en.wikipedia.org/wiki/DBGp>.
856 1707
 
857
-endif "" has('eval')
1708
+endif " has('eval')
858 1709
 
859 1710
 "" Syntax and file type
1711
+if has('gui_running')
1712
+  " See |'background'|.
1713
+  " TODO: Causes the GUI cursor to be misplaced?
1714
+  " gui
1715
+endif
860 1716
 if has('eval')
861
-  syntax enable
862 1717
   filetype plugin indent on
1718
+  syntax enable
1719
+endif
1720
+
1721
+"" File type detection
1722
+" See |new-filetype|.
1723
+
1724
+if has('eval')
1725
+
1726
+  autocmd! filetypedetect BufRead,BufNewFile *.Xresources setf xdefaults
1727
+  autocmd! filetypedetect BufRead,BufNewFile *.gdb*init   setf gdb
1728
+  autocmd! filetypedetect BufRead,BufNewFile *.asy        setf cpp
1729
+  autocmd! filetypedetect BufRead,BufNewFile *.gvpr       setf c
1730
+
1731
+endif
1732
+
1733
+"" Language specific |help|
1734
+
1735
+if has('eval')
1736
+  function! s:help(cmd, arg, filetype) abort
1737
+    for i in range(len(a:cmd))
1738
+      let a:cmd[i] = join(
1739
+      \   map(split(a:cmd[i], '%s', 1), 'shellescape(v:val)'),
1740
+      \   shellescape(a:arg)
1741
+      \ )
1742
+    endfor
1743
+    silent help
1744
+    silent let old_shellredir = &shellredir
1745
+    silent let &shellredir    = '>'
1746
+    silent setlocal buftype=nofile bufhidden=delete noswapfile
1747
+    silent setlocal noreadonly modifiable
1748
+    silent execute 'file' a:arg
1749
+    silent keepjumps normal! ggdG
1750
+    silent execute 'read' '!' join(a:cmd)
1751
+    silent keepjumps normal! ggdd
1752
+    silent execute 'setlocal' 'filetype=' . a:filetype
1753
+    silent setlocal readonly nomodifiable nomodified
1754
+    silent setlocal buftype=help
1755
+    silent let &shellredir = old_shellredir
1756
+  endfunction
863 1757
 endif
864 1758
 
1759
+command! -nargs=1 -complete=shellcmd ManHelp
1760
+\ call s:help(['man', '%s'], <q-args>, 'man')
1761
+
1762
+command! -nargs=1 PythonHelp
1763
+\ call s:help(['python3', '-m', 'pydoc', '%s'], <q-args>, 'python')
1764
+
1765
+command! -nargs=1 OctaveHelp
1766
+\ call s:help(['octave', '--eval', 'help("%s")'], <q-args>, 'octave')
1767
+
1768
+" TODO: Would be cool to define one for `filetype` `gitconfig` that does
1769
+" `ManHelp git-config` and then `/^ {7}\zs` whith the first two components of
1770
+" setion words and `<cowrd>`.
1771
+
865 1772
 "" File type overrides
866 1773
 
1774
+autocmd vimrc FileType *
1775
+\ setlocal keywordprg=:ManHelp |
1776
+
1777
+" TODO: This needs work. We globally override `fillchars` `stl`/`stlnc` and
1778
+" `statusline` but don't take into account file type plugins setting their own
1779
+" `statusline`.
1780
+" TODO: `w:quickfix_title` is not always defined (e.g. when openging the
1781
+" quickfix list when it has not been populated). Guard the printing in some
1782
+" way?
1783
+autocmd vimrc FileType qf
1784
+\ setlocal statusline=%{Statusline()} |
1785
+autocmd vimrc FileType help
1786
+\ setlocal statusline=%{Statusline()} |
1787
+
867 1788
 autocmd vimrc FileType vim
868
-\ setlocal keywordprg=:help formatoptions-=r
1789
+\ setlocal keywordprg=:help |
1790
+
1791
+autocmd vimrc FileType sh
1792
+\ setlocal shiftwidth=2 |
1793
+
1794
+autocmd vimrc FileType c,cpp,glsl
1795
+\ setlocal commentstring=//\ %s |
1796
+\ setlocal matchpairs=(:),{:},[:],<:> |
1797
+\ setlocal cinkeys-=0# cinoptions=L0,l1,g0,N-s,E-s,t0,c0,C1,(s,u0,W1s,m1,j1,J1,N999,*999 |
1798
+\ setlocal path=.,**/include,**/src,/usr/include,/usr/local/include,/usr/include/c++/11 |
869 1799
 
870
-autocmd vimrc FileType c,cpp
871
-\ setlocal commentstring=//\ %s
1800
+autocmd vimrc FileType man
1801
+\ setlocal nolist nospell |
1802
+\ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\(--\S\+\, \)\?\zs-' |
872 1803
 
873 1804
 autocmd vimrc FileType dot
874
-\ setlocal commentstring=//\ %s
1805
+\ setlocal commentstring=//\ %s |
1806
+
1807
+autocmd vimrc FileType gitcommit
1808
+\ setlocal nolist spell |
875 1809
 
876 1810
 autocmd vimrc FileType markdown
877
-\ setlocal complete+=kspell
1811
+\ setlocal spell complete+=kspell |
1812
+" \ setlocal formatoptions-=q |
878 1813
 
879
-autocmd vimrc FileType man
880
-\ setlocal nolist nospell
1814
+autocmd vimrc FileType python
1815
+\ setlocal keywordprg=:PythonHelp |
1816
+
1817
+autocmd vimrc FileType octave
1818
+\ setlocal keywordprg=:OctaveHelp |
1819
+
1820
+" Don't insert comment leader after |i_<CR>|, |o|, or |O|.
1821
+autocmd vimrc FileType *
1822
+\ setlocal formatoptions-=r formatoptions-=o |
881 1823
 
882 1824
 " As suggested in |ft-syntax-omni|, use syntax completion if no other
883 1825
 " completion has been defined.
... ...
@@ -886,6 +1828,9 @@ autocmd vimrc FileType *
886 1828
 \   setlocal omnifunc=syntaxcomplete#Complete |
887 1829
 \ endif |
888 1830
 
1831
+" TODO: Add a match for `\<TODO\>` (and `\<NOTE\>`?) unconditionally for all
1832
+" file types.
1833
+
889 1834
 "" Terminal overrides
890 1835
 " See |terminal-options|.
891 1836
 
... ...
@@ -895,42 +1840,50 @@ autocmd vimrc FileType *
895 1840
 
896 1841
 if has('cursorshape')
897 1842
   set noshowmode
898
-  let &t_vi = ''
899
-  let &t_ve = "\<Esc>[?25h"
1843
+  " Cursor visible/invisible
1844
+  " On Linux the following is the default, which messes with our cursor
1845
+  " shape:
1846
+  " - `t_ve = "\033[?25h\033[?0c"`
1847
+  " - `t_vi = "\033[?25l\033[?1c"`
1848
+  " See
1849
+  " - <https://vt100.net/docs/vt510-rm/DECTCEM>
1850
+  " - `console_codes(4)`
1851
+  let &t_ve = "\033[?25h"
1852
+  let &t_vi = "\033[?25l"
900 1853
   " if $TERM =~? '^xterm\(-\|$\)'
901 1854
     " See
902
-    " - https://vt100.net/docs/vt510-rm/DECSCUSR
903
-    " - http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
904
-    let &t_EI = "\<Esc>[1 q"
905
-    let &t_SI = "\<Esc>[5 q"
906
-    let &t_SR = "\<Esc>[3 q"
907
-    let &t_SH = "\<Esc>[%p1%d q"
1855
+    " - <https://vt100.net/docs/vt510-rm/DECSCUSR>
1856
+    " - `:helpgrep t_SH`
1857
+    let &t_EI = "\033[1 q"
1858
+    let &t_SI = "\033[5 q"
1859
+    let &t_SR = "\033[3 q"
1860
+    let &t_SH = "\033[%p1%d q"
908 1861
   " endif
909 1862
   if $TERM =~? '^linux\(-\|$\)'
910 1863
     " See
911
-    " - https://www.kernel.org/doc/Documentation/admin-guide/vga-softcursor.rst
912
-    let &t_EI = "\<Esc>[?8c"
913
-    let &t_SI = "\<Esc>[?2c"
914
-    let &t_SR = "\<Esc>[?2c"
915
-    let &t_SH = "\<Esc>[?%?%p1%{3}%<%t%{8}%e%{2}%;%dc"
1864
+    " - <https://www.kernel.org/doc/Documentation/admin-guide/vga-softcursor.rst>
1865
+    " - `console_codes(4)`
1866
+    let &t_EI = "\033[?6c"
1867
+    let &t_SI = "\033[?2c"
1868
+    let &t_SR = "\033[?2c"
1869
+    let &t_SH = "\033[?%?%p1%{3}%<%t%{6}%e%{2}%;%dc"
916 1870
   endif
917 1871
 endif
918 1872
 
919 1873
 """ True-color
920 1874
 " See |xterm-true-color|.
921 1875
 
922
-if has('termguicolors')
923
-  " See https://github.com/termstandard/colors#truecolor-detection.
924
-  if empty($COLORTERM) && !has('vcon')
925
-    set notermguicolors
926
-  endif
1876
+if has('termguicolors') && !has('nvim')
927 1877
   " These are the defaults if `$TERM` is `xterm`.
928
-  let &t_8f = "\<Esc>[38;2;%lu;%lu;%lum"
929
-  let &t_8b = "\<Esc>[48;2;%lu;%lu;%lum"
930
-  " Terminal window does not have transparent background when 'termguicolors'
931
-  " is used. See http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516.
1878
+  let &t_8f = "\033[38;2;%lu;%lu;%lum"
1879
+  let &t_8b = "\033[48;2;%lu;%lu;%lum"
1880
+  " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516>: Terminal window does not
1881
+  " have transparent background when 'termguicolors' is used. Fix the
1882
+  " background color.
932 1883
   if !has('patch-8.2.3516')
933 1884
     let s:termguicolors = &termguicolors
1885
+    autocmd vimrc OptionSet termguicolors
1886
+    \ let s:termguicolors = &termguicolors
934 1887
     autocmd vimrc TerminalOpen,WinEnter *
935 1888
     \ let s:newtermguicolors =
936 1889
     \   s:termguicolors &&