Robert Cranston authored on 19/04/2026 22:22:29
Showing 1 changed files

... ...
@@ -3,7 +3,8 @@
3 3
 " TODO: Supply chain attacks are getting more common. We should use (mandate?)
4 4
 " commit hashes in `GitAdd`. Also, make sure to use a command format that
5 5
 " ignores tag/branch names (those can be named to look like hashes and are
6
-" mutable).
6
+" mutable). Maybe we deem some "publishers" worthy of trust, Tim Pope tags
7
+" releases of many of his plugins for instance.
7 8
 
8 9
 " TODO: Do we want to try to integrate with Debian? There seems to be at least
9 10
 " two ways vim-related files are installed:
... ...
@@ -18,6 +19,24 @@
18 19
 "   <https://vim-team.pages.debian.net/vim/> and the `dh_vim-addon` man page in
19 20
 "   the `dh-vim-addon` package contains some further details.
20 21
 
22
+" TODO: |unix| says
23
+"
24
+" > Temporary files (for filtering) are put in "/tmp".  If you want to place
25
+" > them somewhere else, set the environment variable $TMPDIR to the directory
26
+" > you prefer.
27
+"
28
+" and since we go to some effort to keep other intermediate files in
29
+" `~/.cache/vim` for privacy, we might want to create a shell alias that does
30
+" `alias vim='TMPDIR="$HOME/.cache/vim/tmp" vim'`, as well as making sure that
31
+" directory exists in shell startup files.
32
+"
33
+" Actually, I'm pretty sure we can do this from inside Vim (requires 'eval'
34
+" though), which might be cleaner (although some dotfiles for other programs
35
+" that do similar things do it in shell startup files). Do both?
36
+"
37
+" NOTE: This is an environment variable and affects child processes, including
38
+" ones run from the `:terminal`.
39
+
21 40
 """ Formatting
22 41
 
23 42
 " A |'textwidth'| of 79 is used throughout.
... ...
@@ -38,6 +57,7 @@
38 57
 " |$VIM_POSIX|.
39 58
 
40 59
 " This vimrc should work with all configurations of Vim. Manually tested with:
60
+"
41 61
 " - Versions: TODO: Whatever some old {Debian,Ubuntu,Fedora} ships.
42 62
 " - Features: small, huge (Debian `apt-get install vim-{tiny,gtk3}`)
43 63
 " - Locales: C, UTF-8 (`LC_ALL=C{,.UFT-8}`)
... ...
@@ -47,26 +67,34 @@
47 67
 " - Platforms: Unix-like
48 68
 
49 69
 " TODO: `man setfont` says:
70
+"
50 71
 " > Note: if a font has more than 256 glyphs, only 8 out of 16 colors can be
51 72
 " > used simultaneously. It can make console perception worse (loss of
52 73
 " > intensity and even some colors).
74
+"
53 75
 " The default font on my system has 512 glyphs (`showconsolefont -v`).
54 76
 
55 77
 " TODO: `man setfont` says, in section "CONSOLE MAPS":
78
+"
56 79
 " > Several mappings are involved in the path from user program output to
57 80
 " > console display.
81
+"
58 82
 " Might be worth reading up on that. If I already did, document.
59 83
 
60 84
 """ Features
61 85
 
62 86
 " |:version| says "tiny" features are always present and are therefore used in
63 87
 " favor other features whenever possible. "Tiny" features include:
88
+"
64 89
 " - |+multi_byte|
65 90
 " - |+mouse|
66 91
 " - |+tag_binary|
67 92
 " - |+user_commands|
68 93
 " - |+autocmd|
69 94
 " - |+localmap|
95
+"
96
+" TODO: What category features are placed in depends on Vim version. Look up
97
+" and create some table.
70 98
 
71 99
 " Note that trying to set (run-time, but not compile-time) unsupported options
72 100
 " is silently ignored, and so can be done without checking for support first
... ...
@@ -74,6 +102,21 @@
74 102
 " |:endif| is also silently ignored if |+eval| is not available. See
75 103
 " |no-eval-feature|.
76 104
 
105
+""" Patches
106
+
107
+" TODO: Instead of checking for patches we might want to standardize on
108
+" `exists()` instead since it is more descriptive and takes the compile-time
109
+" |+feature-list| into account (which would otherwise require
110
+" `has('patch-{patch}') && has('{feature}')`). The version/patch does indicate
111
+" how old the feature is and so how likely to be supported. Use
112
+" `exists('+option')` (not `exists('&option')`, see e.g. |missing-options|) and
113
+" `exists('##event')`
114
+
115
+" See |has-patch|.
116
+" |:helpgrep| |c_CTRL-R_CTRL-A| (mapped to `<Space>K` below).
117
+
118
+" - 8.1.0081
119
+
77 120
 """ Encoding
78 121
 
79 122
 " |'encoding'| is hard-coded to `utf-8`. However, only characters present in
... ...
@@ -84,6 +127,18 @@
84 127
 " - <https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/tty/vt/cp437.uni>
85 128
 " - `man showconsolefont`
86 129
 
130
+" One can find characters by looking at |digraph-table| in a lowest common
131
+" denominator terminal. Some characters tested to work (not all from Code Page
132
+" 437) *myvimrc-characters*:
133
+" - Rectangular: ■█▒░ (not ▌▐▓)
134
+" - Triangular: (not ►◄▲▼)
135
+" - Circular: ●•∙· (not ○☼)
136
+" - Other: ‼︎… (not ⌂♦☺︎☻)
137
+" - Arrows: ‹›«»←→↑↓ (not ↔↕)
138
+" - Box: │─├┤┼ (not ║═)
139
+" - Math: ∩×∆∅
140
+" - Greek: ΔΛλ
141
+
87 142
 """ Re-sourcing
88 143
 
89 144
 " |setglobal| is used where appropriate so that buffer/window-local options are
... ...
@@ -105,13 +160,73 @@
105 160
 " This includes mappings from popular plugins, for which the defaults should be
106 161
 " kept as far as possible.
107 162
 
108
-" |<Leader>| is hard-coded to <Space> so that mappings work without |+eval|.
109
-" Setting |mapleader| to a different value after the mappings have been defined
110
-" does not change the mappings, so it is not possible to "hot-swap" it for pair
111
-" programming anyway.
163
+" In this file, |<Leader>| is hard-coded to <Space> so that mappings work
164
+" without |+eval|. Setting |mapleader| to a different value after the mappings
165
+" have been defined does not change the mappings, so it is not possible to
166
+" "hot-swap" it for pair programming anyway. |mapleader| is still set though,
167
+" because some plugins expect it.
168
+
169
+""" Debugging
170
+
171
+" See |load-plugins|, |slow-start|.
172
+
173
+""" Novice
174
+" |myvimrc-novice|
175
+
176
+" The goal is to make it at least workable to pair program with a Vim novice
177
+" using this configuration.
178
+" From more heavy-handed to less:
179
+" - `$VIMRUNTIME/evim.vim`, |easy|, |evim-keys|, |i_CTRL-L|
180
+" - `$VIMRUNTIME/mswin.vim`
181
+" - |:behave|
182
+
183
+" TODO: Mark novice-unfriendly option settings as
184
+" |myvimrc-novice-unfriendly-$option|? (My original motivator for this was that
185
+" I thought setting 'hidden' was a bit dangerous, but it is set automatically
186
+" in easy mode!)
187
+
188
+"" Helpers
189
+
190
+""" Define and clear autocmd group
191
+" TODO: I seem to remember augroups being closed automatically at end of file,
192
+" in which case we could omit the `augroup END` and group name from our
193
+" `autocmd`s.
194
+augroup vimrc
195
+  autocmd!
196
+augroup END
197
+
198
+""" Functions
199
+if has('eval')
200
+
201
+  " See |has-patch|.
202
+  " TODO: After and including 7.4.237 `has("patch-{major}.{minor}.{patch}")`
203
+  " works and is nicer. If we never check for any version before that we might
204
+  " remove this.
205
+  function! s:has(major, minor, patch) abort
206
+    let version = 100 * major + minor
207
+    return v:version > version || (v:version == version && has('patch'.patch))
208
+  endfunction
209
+
210
+  " `$VIMSRC/src/option.h:/P_COMMA/`
211
+
212
+  " `$VIMSRC/src/option.h:/P_FLAGLIST/`
213
+
214
+endif
112 215
 
113 216
 "" Options
114 217
 
218
+" |:let-option|
219
+
220
+" Note that even options listed as local (only) have global variants. E.g.
221
+" 'fileencoding' is listed as "local to buffer" but 'fileencodings' says: "Note
222
+" that 'fileencodings' is not used for a new file, the global value of
223
+" 'fileencoding' is used instead.  You can set it with: `:setglobal
224
+" fenc=iso-8859-2`".
225
+
226
+" `$VIMSRC/src/optiondefs.h:/Options local to a window/`
227
+" `$VIMSRC/src/structs.h:/Options local to a window/`
228
+" `$VIMSRC/src/structs.h:/options that are local to a window/`
229
+
115 230
 " TODO: Use |setglobal| for more things? Note that for options with a non-empty
116 231
 " default local value, `setglobal` does nothing useful. Worse, for options with
117 232
 " only a (buffer or window) local value, `setglobal` does nothing, literally.
... ...
@@ -122,10 +237,11 @@
122 237
 
123 238
 " TODO: Look at |:options| and maybe follow the same grouping?
124 239
 
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.
127
-
128 240
 """ Reset
241
+" Undoes changes to global options made by any |system-vimrc| or interactively
242
+" (if re-sourced). The value of 'compatible' determines what defaults are
243
+" loaded, but 'nocompatible' is set automatically at startup when a user vimrc
244
+" file (this file!) is found |compatible-default|.
129 245
 setglobal all&
130 246
 
131 247
 """ Encoding
... ...
@@ -145,34 +261,51 @@ set backspace=indent,eol,start
145 261
 set virtualedit=block
146 262
 
147 263
 """ Modeline
148
-set nomodeline
264
+" 'modeline' is local to buffer, 'modelines' is global.
265
+" set nomodeline
266
+set modelines=0
149 267
 
150 268
 """ Navigation
151 269
 set nostartofline
270
+set sidescroll=1
271
+set sidescrolloff=1
272
+" set scrolloff=1 " Useful for |[[|.
273
+set display=lastline
152 274
 " <http://ftp.vim.org/pub/vim/patches/9.0/9.0.0640>: Cannot scroll by screen
153 275
 " line if a line wraps. Add the 'smoothscroll' option.
154 276
 if has('patch-9.0.0640')
155
-  set smoothscroll
277
+  set smoothscroll " TODO: Local to window.
156 278
 endif
157 279
 
158 280
 """ Windows
159 281
 " Put newly opened windows below and to the right.
282
+" Use |:aboveleft| to override.
160 283
 set splitbelow
161 284
 set splitright
162 285
 
163 286
 """ Interface
164 287
 set showcmd
288
+" TODO: Also look a bit at <https://github.com/tpope/vim-flagship>? Maybe
289
+" `flagship#tabcwds()` to summarize the tab working directory.
290
+" TODO: We could split the current `Statusline()` into
291
+" `Statusline{Left,Right}()` and have the new `Statusline()` join them with
292
+" 'fillchars', and `Ruler()` join them with `:`. Since the same functionality
293
+" is also used by 'titlestring' maybe name them something less statusline
294
+" centric? `Bufname(fill, right)`?
295
+" set ruler
296
+" set rulerformat=%=%(%{expand('%:t')}:%)%l
165 297
 set noruler
166 298
 set laststatus=1
167 299
 set showtabline=1
168
-set shortmess+=I
169
-set guioptions=cf " console dialogs, foreground (no fork())
170
-set numberwidth=1
300
+set shortmess+=I " See |:intro|.
301
+set guioptions=cf " Console dialogs, foreground (no fork())
302
+set numberwidth=1 " TODO: Local to window.
171 303
 
172 304
 """ Interface characters
305
+" See also |myvimrc-characters|.
173 306
 " If |'t_Co'| is empty (or set to 1) the default behavior of |'fillchars'|
174
-" `stl:`/`stlnc:` (`=`/`^`) will be used regardless of its setting. Other good
175
-" choices for |'listchars'| `fold:` is ` ` and `tab:` is: `→ `, `――>`, `├──`,
307
+" `stl`/`stlnc` (`^`/`=`) will be used regardless of its setting. Other good
308
+" choices for |'listchars'| `fold` is ` ` and `tab` is: `→ `, `――>`, `├──`,
176 309
 " `──┤`, `├─┤`.
177 310
 " TODO: `:help 'fillchars'` says "for `stl` and `stlnc` only single-byte values
178 311
 " are supported". Test the current (non-ASCII) values against older versions of
... ...
@@ -180,69 +313,130 @@ set numberwidth=1
180 313
 " TODO: If Vim cannot tell appart |hl-StatusLine| and |hl-StatusLineNC| (e.g.
181 314
 " because |hl-StatusLine| is a |hl-link|), (ordinary) spaces and `fillchars`
182 315
 " `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'|.
316
+" with `^` (i.e. the default `fillchars` `stl`). Note that this includes the
317
+" single character under the `fillchars` `vert`, which cannot be set with
318
+" |'statusline'|.
185 319
 set linespace=-1
186
-set list
187
-set linebreak
188
-set breakindent
189
-set breakindentopt=sbr,shift:2
190
-set showbreak=» 
191
-set fillchars=stl:─,stlnc:─,vert:│,fold:─,diff: 
192
-" set fillchars=stl:_,stlnc:_,vert:│,fold:─,diff: 
320
+set list " TODO: Local to window.
321
+set linebreak " TODO: Local to window.
322
+set breakindent " TODO: Local to window.
323
+set breakindentopt=sbr,shift:2 " TODO: Local to window.
324
+set showbreak=»  " TODO: Local to window (or global).
325
+set fillchars=diff: ,stl:─,stlnc:─,vert:│,fold:─
326
+" set fillchars=diff: ,stl:_,stlnc:_,vert:│,fold:─
193 327
 set listchars=tab:├─,trail:•,extends:›,precedes:‹,nbsp:·
194 328
 " <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0759>: Showing two characters for
195 329
 " tab is limited. Allow for a third character for "tab:" in 'listchars'.
196 330
 if has('patch-8.1.0759')
197
-  " ab	c
198
-  " set listchars+=tab:├\ ┤
199
-  set listchars+=tab:│\ │
331
+  " set listchars+=tab:├─┤
332
+  " set listchars+=tab:├ ┤
333
+  set listchars+=tab:│ │
200 334
 endif
201 335
 " TODO: `%f` still shows `[No Name]`, is there a way to remove that?
202
-set statusline=%(%f\ %)
336
+set statusline=%(%f %) " TODO: Local to window (or global).
203 337
 if has('eval')
204 338
   " TODO: This works poorly with plugins that have windows with their own
205 339
   " statusbar, e.g. |undotree.txt|.
206
-  " set statusline=%(%{expand('%:.s?^/??')}\ %)
340
+  " set statusline=%(%{expand('%:.s?^/??')} %)
207 341
   " `fillchar_status` function in `src/screen.c:4649` of Vim source.
208 342
   " TODO: Try to use some other non-standard space? Search for "\<SPACE\>" in
209 343
   " |digraphs|.
210
-  " set fillchars+=stl:\ ,stlnc: 
344
+  " set fillchars+=stl: ,stlnc: 
211 345
   set fillchars+=stl: ,stlnc: 
212 346
   " set fillchars+=stl:┘,stlnc:┘
213 347
   " TODO: Standardize on global functions? Or |autoload|s (but that would break
214 348
   " our "single file" policy)?
215 349
   " function! s:statusline() abort
350
+  function! s:opt(opt, key) abort
351
+      return matchstr(a:opt, '.*\(^\|,\)' . key . ':\zs[^,]*')
352
+      return split(a:opt, )
353
+  endfunction
354
+  function! s:expand() abort
355
+  endfunction
216 356
   function! Statusline() abort
357
+    " TODO: The global CWD, `getcwd(-1)`, might be useful. Also indicate
358
+    " `haslocaldir()` somehow?
217 359
     " TODO: Make this expansion relative to the window-local cwd? Also do other
218 360
     " substitutions, like `$HOME` to `~`, the expanded `$VIMRUMTIME` to the
219 361
     " string `$VIMRUNTIME`, etc. We used to have `s?^/??`, why?
220 362
     " 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
363
+    " TODO: Generalize `&filetype`, `&buftype` and the matched `bufname()`
364
+    " `<type>://` somehow?
365
+    if &filetype ==# 'man'
366
+      let title = &filetype . ':' . expand('%:t')
367
+    " elseif &buftype =~# 'nofile\|nowrite'
368
+    "   let title = &filetype
369
+    elseif &buftype ==# 'help'
370
+      let title = &buftype . ':' . expand('%:t:s?.txt$??')
371
+    elseif &buftype ==# 'terminal'
372
+      " TODO: We sometimes want to use some variation of `expand('%')`, e.g.
373
+      " when using the |terminal-debugger|.
374
+      " TODO: 'statusline' is not re-evaluated when |term_gettitle()| changes,
375
+      " can we do something like `let &statusline = &statusline` in some
376
+      " |autocmd| (perhaps one that triggers when the terminal content
377
+      " changes)? Worst case |CursorMoved|.
378
+      let title = &buftype . ':' . substitute(term_gettitle(bufnr()), '[^:]*:', '', '')
379
+    " TODO: Change the `&&` into nested `if`? Note that it has different
380
+    " semantics because of the `if`/`elseif`/`else` chain.
381
+    elseif &buftype ==# 'quickfix' && !empty(get(w:, 'quickfix_title'))
382
+      " Remove leading colon (Ex commands) and trailing parenthesis (e.g.
383
+      " |dispatch| job number).
384
+      let title = w:quickfix_title
385
+      let title = substitute(title, '^:', '', '')
386
+      let title = substitute(title, '\s*([^)]\+)\s*$', '', '')
387
+      let title = &buftype . ':' . title
388
+    else
389
+      let title = expand('%')
390
+      " fugitive:///home/rcrnstn/repo/.git//hash/dir/file.ext
391
+      " fugitive:///home/rcrnstn/repo/.git//hash/dir/file.ext
392
+      " TODO: |split()| on `:` (info), `://` (fugitive) and `#` (info), do
393
+      " processing, and then `join(filter(parts, '!empty(v:val)'), ':')`.
394
+      " Replace names of the form `<type>://<path>/.<dot>//<obj>` with
395
+      " `<type>:<obj>` where any leading 40 character hex string (hash) in
396
+      " `<obj>` is truncated to 7 characters. (Yes, this was designed for
397
+      " |fugitive|.)
398
+      let parts = matchlist(expand('%'),
399
+      \ '^\%(\([^:]\+\)://\)\?\%(\(.*\)//\)\?\(.*\)'
400
+      \ )
401
+      if !empty(parts)
402
+        let [type, prefix, path] = parts[1:3]
403
+        if !empty(prefix)
404
+          while fnamemodify(prefix, ':t')[:0] ==# '.'
405
+            let prefix = fnamemodify(prefix, ':h')
406
+          endwhile
407
+          let prefix = fnamemodify(prefix . '/', ':~:.:h:t:s?^\.$??')
408
+        endif
409
+        let path = substitute(path,
410
+        \   '^\([0-9a-fA-F]\{7\}\)[0-9a-fA-F]\{33\}\(/.*\|$\)', '\1\2', ''
411
+        \ )
412
+        let title = join(filter([type, prefix, path], '!empty(v:val)'), ':')
413
+      endif
226 414
     endif
227
-    if !empty(l:title)
228
-      let l:title .= ' '
415
+    if !empty(title)
416
+      let title = substitute(title, ' *$', '', '') . ' '
229 417
     endif
418
+    let title = substitute(title, ' ',  ' ', 'g')
230 419
     " NOTE: `matchstr` looks for the _first_ match.
231 420
     " 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)
421
+    let fillchar = matchstr(&fillchars, '\(^\|,\)stl:\zs[^,]*')
422
+    let pad  = winwidth(0) - strdisplaywidth(title)
423
+    return title . repeat(fillchar, pad)
235 424
   endfunction
236 425
   " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.1347>: Cannot easily get the
237 426
   " script ID. Support expand('<SID>').
238 427
   " if has('patch-8.2.1347')
239 428
   "   let &statusline = '%{'.expandcmd('<SID>statusline()').'}'
240 429
   " else
241
-    let &statusline = '%{Statusline()}'
430
+    set statusline=%{Statusline()} " TODO: Local to window (or global).
242 431
   "   function! g:Statusline() abort
243 432
   "     return s:statusline()
244 433
   "   endfunction
245 434
   " endif
435
+  " TODO: This doesn't seem to do the trick.
436
+  autocmd vimrc CursorMoved *
437
+  \ if &buftype ==# 'terminal' |
438
+  \   let &statusline = &statusline |
439
+  \ endif |
246 440
 endif
247 441
 
248 442
 """ Colors
... ...
@@ -270,41 +464,71 @@ set belloff=error
270 464
 
271 465
 """ Title
272 466
 set title
467
+set titlelen=0
273 468
 " set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{pathshorten(expand('%:.:s?^/??'))}%)
274 469
 " TODO: Break out into `Title()` function and harmonize with `statusline`.
470
+" TODO: Ideas from `tpope/vim-flagship`: `hostname()` and `v:servername`.
275 471
 set titlestring=vi:%{fnamemodify(getcwd(),':~:t:s?^$?/?')}%(:%<%{expand('%:.:s?^/??')}%)
276 472
 set titleold=
277 473
 
474
+function! s:cwdname() abort
475
+  return fnamemodify(getcwd(), ':~:t:s?^$?/?')
476
+endfunction
477
+
478
+function! s:bufname() abort
479
+  return expand('%:.:s?^/??')
480
+  return pathshorten(expand('%:.:s?^/??'))
481
+endfunction
482
+
278 483
 """ Tabs
279 484
 " When reading files written by others, assume default `tabstop=8`.
280 485
 " When Writing files, use 4 space indents.
281
-set shiftwidth=4
486
+set shiftwidth=4 " TODO: Local to buffer.
282 487
 set shiftround
283
-set softtabstop=-1
284
-set expandtab
488
+set softtabstop=-1 " TODO: Local to buffer.
489
+set expandtab " TODO: Local to buffer.
285 490
 
286 491
 """ Mouse
492
+" |scroll-mouse-wheel| is generally useful, the rest for |myvimrc-novice|.
287 493
 set mouse=a
494
+set mousemodel=popup
495
+set selectmode+=mouse
496
+
497
+""" Novice
498
+set keymodel=startsel,stopsel
499
+set selectmode+=key
500
+set whichwrap+=<,>,[,]
288 501
 
289 502
 """ Command-line
503
+" See also Readline's `menu-complete`, documented in `bash(1)`.
290 504
 set wildmenu
291 505
 set wildmode=longest:full,full
292 506
 " See also |'suffixes'|.
293
-set wildignore+=_*
507
+" Source control.
508
+" set wildignore+=_*
294 509
 set wildignore+=.git
295
-set wildignore+=UPSTREAMS,FORKS
510
+" Programming language specific.
511
+set wildignore+=__pycache__,.venv,*.egg-info
512
+set wildignore+=node_modules
296 513
 " 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_*
514
+set wildignore+=$HOME/projects/UPSTREAMS
515
+set wildignore+=$HOME/.vim/pack
516
+set wildignore+=$HOME/.config/vim/pack
517
+set wildignore+=$HOME/.config/nvim/pack
518
+set wildignore+=$HOME/.cache
519
+set wildignore+=$HOME/.local/lib
520
+set wildignore+=$HOME/.local/share/man
521
+set wildignore+=$HOME/.local/share/tldr
522
+set wildignore+=$HOME/.mozilla/firefox
523
+set wildignore+=$HOME/.ansible
524
+set wildignore+=$HOME/.vagrant
525
+set wildignore+=$HOME/.local/pipx
526
+set wildignore+=$HOME/.cargo/register
527
+set wildignore+=$HOME/.cargo
528
+set wildignore+=$HOME/.npm
529
+set wildignore+=$HOME/.wine/dosdevices
530
+set wildignore+=$HOME/.wine/drive_*
531
+set wildignore+=$HOME/snap
308 532
 " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.4325>: 'wildmenu' only shows few
309 533
 " matches. Add the "pum" option: use a popup menu to show the matches.
310 534
 if has('patch-8.2.4325')
... ...
@@ -316,10 +540,19 @@ set incsearch
316 540
 set shortmess-=S
317 541
 
318 542
 """ Timing
319
-set lazyredraw
320 543
 set notimeout
544
+
545
+""" Terminal
321 546
 set ttimeout
322 547
 set ttimeoutlen=100
548
+set ttyfast
549
+set lazyredraw
550
+" A |'ttyscroll'| of 0 is beneficial on local terminals (especially reduces
551
+" flickering on Linux VT), but might be worse on slow remote connections. Set
552
+" |'writedelay'| to a small value (like 1), and maybe |'redrawtime'| to a very
553
+" large value (like 20000), to see what difference this option makes. See also
554
+" |myvimrc-autocmd-ttyscroll|.
555
+set ttyscroll=0
323 556
 
324 557
 """ Diffs
325 558
 set diffopt+=vertical
... ...
@@ -327,47 +560,49 @@ set diffopt+=foldcolumn:0
327 560
 " <http://ftp.vim.org/pub/vim/patches/8.1/8.1.0360>: Using an external diff
328 561
 " program is slow and inflexible. Include the xdiff library. Use it by default.
329 562
 if has('patch-8.1.0360')
330
-  set diffopt+=internal
563
+  " set diffopt+=internal
331 564
   set diffopt+=algorithm:histogram
332 565
   set diffopt+=indent-heuristic
333 566
 endif
334 567
 
335 568
 """ Formatting
336
-" See |auto-format|, |format-comments|, and |fo-table|.
337
-set textwidth=79
569
+" See |formatting|, |auto-format|, |format-comments|, and |fo-table|.
570
+set textwidth=79 " TODO: Local to buffer.
338 571
 " set winwidth=80
339
-" set colorcolumn=+1
340
-set autoindent
572
+" set colorcolumn=+1 " TODO: Local to window.
573
+set autoindent " TODO: Local to buffer.
341 574
 set nojoinspaces
342
-" Don't autowrap text, enable comment formatting with |gq|, recognize lists,
343
-" remove comment leader when joining.
344
-set formatoptions-=t
345
-" set formatoptions+=q " TODO: This is the default?
575
+" Don't autowrap text (non-comments), recognize lists, remove comment leader
576
+" when joining.
577
+set formatoptions-=t " TODO: Local to buffer.
346 578
 set formatoptions+=n
347 579
 set formatoptions+=j
348
-set nowrap " See also |breakindent|, |breakindentopt|, |showbreak| set above.
580
+" See also |breakindent|, |breakindentopt|, |showbreak| set above.
581
+set nowrap " TODO: Local to window.
349 582
 " A custom 'formatprg' produces nicer results but is harder to replicate for
350 583
 " others and places undue burden on documentation contributors. Having simple
351 584
 " format rules is more important than slightly prettier formatting.
352 585
 " TODO: At least make the expressions valid (we're lacking spaces, no?).
586
+" TODO: Local to buffer (or global).
353 587
 " if executable('par')
354 588
 "   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e'])
355 589
 "   let &formatprg = join(['par', 'T'.&tabstop, 'w'.&textwidth, 'e', 'j'])
356 590
 " elseif executable('fmt')
357
-"   let &formatprg = 'fmt' . '-w' . &textwidth '-g' . &textwidth
591
+"   let &formatprg = join(['fmt', '-w'.&textwidth, '-g'.&textwidth])
358 592
 " endif
359 593
 
360 594
 """ Comments
361
-" set commentstring=#%s
595
+" set commentstring=#%s " TODO: Local to buffer.
362 596
 
363 597
 """ Folds
364 598
 set foldlevelstart=999
365
-set foldtext=substitute(getline(v:foldstart),'\\t',repeat('\ ',&ts),'g').'\ '
599
+" TODO: Local to window.
600
+set foldtext=substitute(getline(v:foldstart),'\\t',repeat(' ',&ts),'g').' '
366 601
 
367 602
 """ Spelling
368 603
 " set spell
369
-set spelllang=en_us
370
-set thesaurus=~/.vim/thesaurus/en_us.txt
604
+set spelllang=en_us " TODO: Local to buffer.
605
+set thesaurus=~/.vim/thesaurus/en_us.txt " TODO: Local to buffer (or global).
371 606
 " TODO: We can probably do something better/cleaner for the thesaurus on our
372 607
 " own. In particular, publicly available, clearly licensed, version controlled,
373 608
 " code to generate the vim thesaurus from primary sources.
... ...
@@ -401,36 +636,65 @@ set thesaurus=~/.vim/thesaurus/en_us.txt
401 636
 " For Swedish, there is
402 637
 " - <https://folkets-lexikon.csc.kth.se/synlex.html>
403 638
 " - <https://spraakbanken.gu.se/en/resources/saldo>
639
+"
640
+" Other assorted resources:
641
+" - <https://github.com/dahu/vimdictive>
642
+" - <https://dict.org>
404 643
 
405 644
 """ Views
645
+" TODO: Per the documentation `curdir` is only supposed to save the
646
+" window-local directory as set by |:lcd|, which I wouldn't mind so much and
647
+" might even make use of. But currently it is being set apparently without my
648
+" involvement (perhaps by some plugin, probably |netrw|) far too often, and
649
+" since we do |:loadview| on every opened file this gets annoying fast.
406 650
 set viewoptions-=options
651
+set viewoptions-=curdir
407 652
 set viewoptions+=slash
408 653
 set viewoptions+=unix
409 654
 
410 655
 """ Files
411
-set swapfile
656
+set swapfile " TODO: Local to buffer.
412 657
 set writebackup
413
-set backupcopy=yes
414
-set undofile
658
+set backupcopy=yes " TODO: Local to buffer (or global).
659
+set undofile " TODO: Local to buffer.
415 660
 set directory=~/.cache/vim/swap//
416 661
 set backupdir=~/.cache/vim/backup//
417 662
 set undodir=~/.cache/vim/undo//
418 663
 set viewdir=~/.cache/vim/view//
419 664
 set viminfofile=~/.cache/vim/viminfo
665
+if has('eval')
666
+  let $TMPDIR = $HOME . '/.cache/vim/tmp'
667
+  call mkdir($TMPDIR, 'p')
668
+endif
420 669
 if has('nvim')
421 670
   set shadafile=
422 671
 endif
423 672
 
424 673
 """ Conceal
425
-set conceallevel=2
426
-set concealcursor=nc
674
+set conceallevel=2 " TODO: Local to window.
675
+set concealcursor=n " TODO: Local to window.
427 676
 
428 677
 """ Platform
429 678
 set shellslash
430 679
 
680
+""" Filenames
681
+" I generally allow everything (except control codes) in filenames on the
682
+" filesystem. However, only media files (photos or videos) tend to take
683
+" advantage of that, to be more descriptive/preserve some upstream name. Files
684
+" I will want Vim to be able to cross-reference will be text (code or notes)
685
+" with more constrained names. Disallowing some punctuation makes things like
686
+" |gf| more useful.
687
+" NOTE: This is a global option, but some ftplugins (Perl) change it anyway.
688
+" `:grep -R 'isf\(name\)\?' /usr/share/vim/vim82/ftplugin/`
689
+" *myvimrc-isfname-bug*
690
+set isfname-=, " Common file separator.
691
+set isfname-=; " Common file separator.
692
+set isfname-=: " Common file separator (e.g. when using |gf|).
693
+set isfname-=# " URL fragment separator.
694
+
431 695
 """ External tools
432 696
 " Not POSIX: `-H` (suggested in 'grepprg'), `-I`.
433
-set grepprg=grep\ -nHI
697
+set grepprg=grep\ -nHI " TODO: Local to buffer (or global).
434 698
 
435 699
 """ Quickfix
436 700
 set switchbuf=useopen
... ...
@@ -439,13 +703,23 @@ set switchbuf=useopen
439 703
 " TODO: Categorize into map modes. Use the nonspecific |:map| (|mapmode-nvo|)
440 704
 " and |:map!| (|mapmode-ic|) more often?
441 705
 
706
+""" Mapleader
707
+" Prefill command line with query to discover mapleader mappings.
708
+nnoremap <Space>?        :verbose nmap <lt>Space>
709
+nnoremap <Space><Space>? :verbose nmap <lt>Space><lt>Space>
710
+
442 711
 """ Escape
443 712
 " Overwrites the default |i_CTRL-C|, |v_CTRL-C|. See
444 713
 " <https://vim.fandom.com/wiki/Avoid_the_escape_key>.
445 714
 inoremap <C-C> <Esc>
446 715
 xnoremap <C-C> <Esc>
447 716
 
717
+""" Novice
718
+" We 
719
+
448 720
 """ Windows
721
+
722
+"""" Focus
449 723
 nnoremap <C-H> <C-W>h
450 724
 nnoremap <C-J> <C-W>j
451 725
 nnoremap <C-K> <C-W>k
... ...
@@ -455,28 +729,84 @@ tnoremap <C-J> <C-W>j
455 729
 tnoremap <C-K> <C-W>k
456 730
 tnoremap <C-L> <C-W>l
457 731
 
732
+"""" Move
733
+if has('eval')
734
+  function! s:winmove(dir) abort
735
+    let prefix =
736
+    \ dir ~=# '[hj]' ? 'leftabove' :
737
+    \ dir ~=# '[kl]' ? 'belowright'
738
+    winnr(a:dir)
739
+  endfunction
740
+endif
741
+
742
+"""" Empty vertical split
743
+" See also |CTRL-W_n|, which does |:new|.
744
+nnoremap <C-W>N :vnew<CR>
745
+
746
+"""" Resize
747
+" Resize height to number of lines in buffer.
748
+nnoremap <expr> <C-W>? line('$')."<C-W>_"
749
+
458 750
 """ Clear and redraw
459 751
 " <C-L> is overridden above, so use a <Leader> mapping.
460 752
 nnoremap <Space><C-L> <C-L>
461 753
 
462 754
 """ Movement
463 755
 " Up down dispaly lines (unless a count is given).
756
+" TODO: Mappings like these that extend builtin functionality (identify them
757
+" and put them in the same place) could be made more formally feature complete
758
+" by doing the same thing for any aliases (listed in `:help j` etc). If the
759
+" functinonality is implemented in other modes (insert and the various visual
760
+" modes) then that should probably be extended too. Document this general
761
+" principle.
464 762
 nnoremap <expr> j v:count ? 'j' : 'gj'
465 763
 nnoremap <expr> k v:count ? 'k' : 'gk'
466 764
 
765
+" When moving to the next/previous '{'/'}' in the first column (function
766
+" body/struct definition start/end), make visible the matching '}'/'{'
767
+" (function body/struct definition end/start) and paragraph containing '{'
768
+" (function prototype/struct name and preceeding comments). A prefix of 'g'
769
+" aligns the paragraph containing '{' to the top of the window.
770
+" TODO: Keep jumps somehow? `:keepjumps normal!`?
771
+" TODO: |]]| says "[count] sections forward or to the next '{' in the first
772
+" column". |section| says "a section begins after a form-feed (<C-L>) in the
773
+" first column and [...]". We completely ignore the form-feed aspect. It's not
774
+" commonly seen in code, but the GNU Coding Standards recommends them
775
+" <https://www.gnu.org/prep/standards/standards.html#index-formfeed>.
776
+nnoremap  ]] ]]%%m'vipo<Esc>''
777
+nnoremap g]] ]]%%m'vipozt<Esc>''
778
+nnoremap  [[ [[%%m'vipo<Esc>''
779
+nnoremap g[[ [[%%m'vipozt<Esc>''
780
+nnoremap  ][ ][m'%vipo<Esc>''
781
+nnoremap g][ ][m'%vipozt<Esc>''
782
+nnoremap  [] []m'%vipo<Esc>''
783
+nnoremap g[] []m'%vipozt<Esc>''
784
+
785
+""" Search and edit file
786
+" See also |ctrlp|.
787
+nnoremap <C-P> :edit **/**<Left>
788
+
789
+""" Visual line insert and append
790
+" TODO: This breaks text object that start with `A` or `I`. Ironically, those
791
+" two characters specifically are prefixes in `wellle/targets.vim`.
792
+" xnoremap <expr> A mode() !=# 'V' ? 'A' : ':normal A'
793
+" xnoremap <expr> I mode() !=# 'V' ? 'I' : ':normal I'
794
+
467 795
 " End of pair opened at end of current line.
468
-" TODO: These are overridden by `matchit`.
796
+" TODO: These are overridden by `matchit`, use `<Space>%` instead?
469 797
 nnoremap <silent> g% :<C-U>norm!  $%<CR>
470 798
 onoremap <silent> g% :<C-U>norm!  $%<CR>
471 799
 xnoremap <silent> g% :<C-U>norm! v$%<CR>
472 800
 
473 801
 """ Scrolling
474
-" Put paragraph containing cursor line at the top of the window.
802
+" Put paragraph containing cursor line at the top/bottom of the window.
475 803
 " TODO: Preserve jump list somehow?
476
-nnoremap zg {jzt<C-O>
804
+" TODO: If |+eval|, also account for |scrolloff|?
805
+nnoremap z{ {jzt<C-O>
806
+nnoremap z} }kzb<C-O>
477 807
 
478 808
 """ Visual mode repeat
479
-" See also `vim-visualrepeat`.
809
+" See also `visualrepeat`.
480 810
 xnoremap . :normal! .<CR>
481 811
 
482 812
 """ Clipboard
... ...
@@ -484,7 +814,7 @@ xnoremap . :normal! .<CR>
484 814
 nnoremap <silent> <Space>yy :let @+ = expand('%:p') . ':' . line('.')<CR>
485 815
 
486 816
 """ `$MYVIMRC`
487
-nnoremap <silent> <Space><Space>ve :edit   $MYVIMRC<CR>
817
+nnoremap <silent> <Space><Space>ve :edit   $MYVIMRC<CR>:lcd %:h<CR>
488 818
 nnoremap <silent> <Space><Space>vs :source $MYVIMRC<CR>
489 819
 
490 820
 """ Keyword
... ...
@@ -499,6 +829,7 @@ nnoremap <silent> <Space><Space>vs :source $MYVIMRC<CR>
499 829
 " keyword search in a codebase.
500 830
 " TODO: Here we use `g` as prefix. Do we do that in other places? Should we not
501 831
 " use <Leader> (i.e. <Space>)?
832
+" TODO: We do have a `<Space>K` `FileType vim,help` mapping.
502 833
 nnoremap <silent> gK  :helpgrep \<<C-R><C-W>\><CR>
503 834
 xnoremap <silent> gK y:helpgrep <C-R>"<CR>
504 835
 
... ...
@@ -514,13 +845,25 @@ nnoremap <Space><Space>! :new \| .!
514 845
 
515 846
 """ Quickfix
516 847
 
848
+"""" Go to first/last valid entry
849
+" |:cfirst|, |:clast|, |[Q|, and |]Q| (the last ones being
850
+" `vim-unimpaired` mappings) go to the first/last entry regardless of whether
851
+" it is |quickfix-valid| (includes a file name). I prefer to go to the
852
+" first/last entry that includes a file name (even if I was already
853
+" before/after that entry).
854
+nnoremap [Q :cfirst \| silent! execute "cnext\|cprev"<CR>
855
+nnoremap ]Q :clast  \| silent! execute "cprev\|cnext"<CR>
856
+
517 857
 """" Toggle Quickfix window
518 858
 " TODO: Do similar for location list?
519
-" TODO: Make the |botright| global with some |autocmd|?
859
+" TODO: Make the |botright| global with some |autocmd|? Is it implied by our
860
+" `set split{below,right}`?
520 861
 nnoremap <expr> <Space><Space>q
521
-\ empty(filter(range(1,winnr('$')),'getwinvar(v:val,"&buftype")==#"quickfix"'))
522
-\ ? ':botright copen<CR>'
523
-\ : ':botright cclose<CR>'
862
+\ empty(filter(getwininfo(),
863
+\   'getbufvar(v:val.bufnr, "&buftype") ==# "quickfix"'
864
+\ ))
865
+\   ? ':botright copen<CR>'
866
+\   : ':botright cclose<CR>'
524 867
 
525 868
 """ Make
526 869
 " TODO: |dispatch| provides default mappings, try to emulate them?
... ...
@@ -557,6 +900,10 @@ nnoremap <silent> ZQ :quit<CR>
557 900
 nnoremap Y y$
558 901
 
559 902
 """" Don't include newline in Visual mode `$`.
903
+" TODO: Do you just want `set selection=old`? Nope, the builtin `matchit`
904
+" doesn't work correctly with `selection=old`, this is probably a bug though
905
+" and might get fixed.
906
+" set selection=old
560 907
 xnoremap $ $h
561 908
 
562 909
 """" Visual mode put that doesn't clobber unnamed register
... ...
@@ -582,38 +929,70 @@ endif
582 929
 xnoremap <Space>s :s/\%V
583 930
 
584 931
 """" 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
932
+xnoremap <C-H> hoho
933
+xnoremap <C-J> jojo
934
+xnoremap <C-K> koko
935
+xnoremap <C-L> lolo
597 936
 
598 937
 """ Mouse
599
-" As suggested in |scroll-mouse-wheel|, scroll only one line.
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
606
-
607
-" Toggle folds.
608
-noremap <RightMouse>   <LeftMouse>za
938
+
939
+"""" Scroll vertically by single lines
940
+" As suggested in |scroll-mouse-wheel|.
941
+nnoremap <ScrollWheelUp>        <C-Y>
942
+xnoremap <ScrollWheelUp>        <C-Y>
943
+inoremap <ScrollWheelUp>   <C-O><C-Y>
944
+nnoremap <ScrollWheelDown>      <C-E>
945
+xnoremap <ScrollWheelDown>      <C-E>
946
+inoremap <ScrollWheelDown> <C-O><C-E>
947
+
948
+"""" Scroll horizontally by single columns with <C-Scrollwheel>
949
+nnoremap <C-ScrollWheelUp>        zh
950
+xnoremap <C-ScrollWheelUp>        zh
951
+inoremap <C-ScrollWheelUp>   <C-O>zh
952
+nnoremap <C-ScrollWheelDown>      zl
953
+xnoremap <C-ScrollWheelDown>      zl
954
+inoremap <C-ScrollWheelDown> <C-O>zl
955
+nnoremap <ScrollWheelLeft>        zh
956
+xnoremap <ScrollWheelLeft>        zh
957
+inoremap <ScrollWheelLeft>   <C-O>zh
958
+nnoremap <ScrollWheelRight>       zl
959
+xnoremap <ScrollWheelRight>       zl
960
+inoremap <ScrollWheelRight>  <C-O>zl
961
+
962
+"""" Toggle folds with <2-RightMouse>
963
+" noremap   <RightMouse> <LeftMouse>za
609 964
 noremap <2-RightMouse> <LeftMouse>za
610
-noremap <3-RightMouse> <LeftMouse>za
611
-noremap <4-RightMouse> <LeftMouse>za
965
+" noremap <3-RightMouse> <LeftMouse>za
966
+" noremap <4-RightMouse> <LeftMouse>za
612 967
 
613 968
 """ Command-line
969
+
614 970
 " Take already written text into account when searching history.
615 971
 cnoremap <C-P> <Up>
616 972
 cnoremap <C-N> <Down>
973
+" Try not to interfere with |'wildmenu'|.
974
+if has('eval')
975
+  cnoremap <expr> <C-P> wildmenumode() ? "\<C-P>" : "\<Up>"
976
+  cnoremap <expr> <C-N> wildmenumode() ? "\<C-N>" : "\<Down>"
977
+endif
978
+
979
+""" Wildmenu
980
+
981
+" <Left> and <Right> moves the cursor, not the completion selection. As
982
+" suggested in 'wildmenu'.
983
+cnoremap <Left>  <Space><BS><Left>
984
+cnoremap <Right> <Space><BS><Right>
985
+
986
+""" Terminal
987
+
988
+" TODO: Call a function that:
989
+" - Find (the first) buffer with `&buftype ==# 'terminal'`
990
+"   - If it doesn't have window, create one and make it focused
991
+"   - Switch to the terminal buffer
992
+" - If none, do `:terminal`
993
+" NOTE: The proceedure described above is more or less `:Start` from
994
+" `vim-dispatch`.
995
+nnoremap <Space><Space>t :terminal<CR>
617 996
 
618 997
 """ Macros
619 998
 
... ...
@@ -630,16 +1009,42 @@ endif
630 1009
 
631 1010
 """ Diffs
632 1011
 
1012
+" Toggle 'diffopt' ignores
1013
+" See also |unimpaired|'s |yod|. Mapping suffix based on the `diff` flags.
1014
+" TODO: `&diffopt=~'iwhite'` will match if `&diffopt` contains e.g.
1015
+" `iwhiteall`, use `'\(^\|,\)iwhite\(,\|$\)'` instead. Introduce a helper
1016
+" function that does the wrapping. Update: We're trying out word boundaries.
1017
+" TODO: Maybe even introduce a helper that does the toggling. Look at
1018
+" `vim-unimpaired` implementation?
1019
+nnoremap yoDB :set diffopt<C-R>=&diffopt=~'\<iblank\>'   ?'-':'+'<CR>=iblank<CR>
1020
+nnoremap yoDi :set diffopt<C-R>=&diffopt=~'\<icase\>'    ?'-':'+'<CR>=icase<CR>
1021
+nnoremap yoDb :set diffopt<C-R>=&diffopt=~'\<iwhite\>'   ?'-':'+'<CR>=iwhite<CR>
1022
+nnoremap yoDw :set diffopt<C-R>=&diffopt=~'\<iwhiteall\>'?'-':'+'<CR>=iwhiteall<CR>
1023
+nnoremap yoDZ :set diffopt<C-R>=&diffopt=~'\<iwhiteeol\>'?'-':'+'<CR>=iwhiteeol<CR>
1024
+
1025
+nnoremap <expr> yoDB ':set diffopt'.(&diffopt=~'\<iblank\>'   ?'-':'+').'=iblank<CR>'
1026
+nnoremap <expr> yoDi ':set diffopt'.(&diffopt=~'\<icase\>'    ?'-':'+').'=icase<CR>'
1027
+nnoremap <expr> yoDb ':set diffopt'.(&diffopt=~'\<iwhite\>'   ?'-':'+').'=iwhite<CR>'
1028
+nnoremap <expr> yoDw ':set diffopt'.(&diffopt=~'\<iwhiteall\>'?'-':'+').'=iwhiteall<CR>'
1029
+nnoremap <expr> yoDZ ':set diffopt'.(&diffopt=~'\<iwhiteeol\>'?'-':'+').'=iwhiteeol<CR>'
1030
+
1031
+" Windows
1032
+" This could be smarter. E.g. Look if *any* window has 'diff' set and save them
1033
+" in a list before doing `:diffoff`; restore for all windows when doing
1034
+" `:diffthis`.
1035
+nnoremap <Space><Space>dw :windo diff<C-R>=&diff?'off':'this'<CR><CR>
1036
+
633 1037
 " Current file.
634 1038
 " Se also |:DiffOrig|.
635 1039
 " TODO: Use a buffer?
1040
+" TODO: `--old-group-format "$(TODO)"`
636 1041
 " <https://gist.github.com/romainl/7198a63faffdadd741e4ae81ae6dd9e6>
637
-nnoremap <silent> <Space><Space>dd :w !
1042
+nnoremap <silent> <Space><Space>dff :w !
638 1043
 \ diff -u --color=always %:S -
639 1044
 \ \| tail -n +3
640 1045
 \ \| less -FR
641 1046
 \ <CR>
642
-nnoremap <silent> <Space><Space>dw :w !
1047
+nnoremap <silent> <Space><Space>dfw :w !
643 1048
 \ diff -u %:S -
644 1049
 \ \| tail -n +3
645 1050
 \ \| wdiff -d -n
... ...
@@ -718,7 +1123,22 @@ if has('eval')
718 1123
   endfunction
719 1124
 endif
720 1125
 
1126
+""" Align operator
1127
+" Requires the `column` program (in `bsdextrautils` on Debian).
1128
+" See also |lion|.
1129
+" TODO: Does not support |count|, |quote|.
1130
+" TODO: When re-sourcing the vimrc, this overrides the previous |vim-lion|
1131
+" mappings.
1132
+xnoremap gl !column -t -o ' '<CR>
1133
+if has('eval')
1134
+  nnoremap gl :set operatorfunc=<SID>gl<CR>g@
1135
+  function! s:gl(...) abort
1136
+    '[,']!column -t -o ' '
1137
+  endfunction
1138
+endif
1139
+
721 1140
 """ Normalize date to ISO 8601
1141
+" Requires the `date` program (in `coreutils` on Debian).
722 1142
 " See |:visual_example|.
723 1143
 " See also |abolish-coercion|.
724 1144
 " This is hacky but works without |+eval|.
... ...
@@ -726,6 +1146,8 @@ xnoremap crd <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date +'\%Y-\%m-\%d' -f -<CR>kJJ
726 1146
 
727 1147
 """ Go to string in file under cursor
728 1148
 
1149
+" Make |gF| support `filename:/search string/`.
1150
+"
729 1151
 " The built-in |gF|, and related |CTRL-W_F|, |CTRL-W_gF|, commands extend |gf|
730 1152
 " by also parsing trailing `:{lineno}` (specifically, any non-filename
731 1153
 " character optionally surrounded by whitespace, or the literal string
... ...
@@ -754,23 +1176,49 @@ xnoremap crd <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date +'\%Y-\%m-\%d' -f -<CR>kJJ
754 1176
 " expansion (|expandcmd|) that would be hard to re-implement, see |gf|. Note
755 1177
 " that the built-in mappings only trigger when the cursor is on or before the
756 1178
 " _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.
1179
+" giving an error message if a trailing line number can't be found, which we
1180
+" mimic. |gF| also doesn't give an error (or any) message if the given line
1181
+" number is not present in the file (it goes to the closest one, i.e. the first
1182
+" or last line), so we use a "soft" |:echo| instead of "hard" |:echoerr| to
1183
+" tell the user if the search string was not found.
759 1184
 "
760 1185
 " [POSIX.1-2017]: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/ctags.html#tag_20_27_12
761 1186
 
762
-" TODO: Also support `file:line:col`?
1187
+" TODO: I think the regex is not quite right, like it triggers even when the
1188
+" cursor is not on the filename. Maybe we need to put the |/\%>| in a group, or
1189
+" adjust the `col('.')-1`. I lost the test case, sorry.
1190
+
1191
+" TODO: Clarify/expand separators. POSIX mandates tabs as separators for tag
1192
+" files, document that we use the |gF| rules instead, after we implement them
1193
+" completely (` line `). Also hardcode to allow : as separator, because
1194
+" ftplugin/perl.vim:/^set isfname/ adds : to the set of valid filenames
1195
+" 'isfname' (a global option!). Document this too.
1196
+
1197
+" TODO: POSIX allows / and ? as pattern delimiters, we only allow /. Fix this
1198
+" and document.
1199
+
1200
+" TODO: POSIX allows the anchors ^ and $ to be used independently. It looks
1201
+" like we do too, but it is not clear from the documentation.
1202
+
1203
+" TODO: Also support `file:line:col`? Generalize the separator to conform to
1204
+" the |gF| rules, but change ` line ` to ` col(umn)? `.
1205
+
1206
+" TODO: We are accruing features. Split into plugin? `vim-unobtrusive-gf`?
1207
+
1208
+" TODO: The excessive string concatenation is done for readability, but it
1209
+" might be better (and faster) as comments? Those can get out of sync though...
763 1210
 
764 1211
 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>
1212
+  nnoremap <silent> gF      :<C-U>call <SID>gf("gF")<CR>
1213
+  nnoremap <silent> <C-W>F  :<C-U>call <SID>gf("\<lt>C-W>F")<CR>
1214
+  nnoremap <silent> <C-W>gF :<C-U>call <SID>gf("\<lt>C-W>gF")<CR>
1215
+  let s:isfname = &isfname
768 1216
   function! s:gf(cmd) abort
769 1217
     let back   = '\\\\'
770
-    let fwd    = '\\\/'
1218
+    let slash  = '\\\/'
771 1219
     let dollar = '\$\/\@!'
772 1220
     let other  = '[^\/$]'
773
-    let chr    = '\%(' . join([back, fwd, dollar, other], '\|') . '\)'
1221
+    let chr    = '\%(' . join([back, slash, dollar, other], '\|') . '\)'
774 1222
     let str    = '\(' . chr . '\+\)'
775 1223
     let start  = '\(\^\?\)'
776 1224
     let end    = '\(\$\?\)'
... ...
@@ -779,16 +1227,34 @@ if has('eval')
779 1227
     let file   = '[[:fname:]]'
780 1228
     let sep    = '[[:space:]]*[^[:fname:][:digit:]/][[:space:]]*'
781 1229
     let pat    = '\m' . after . file . sep . addr
782
-    let match  = matchlist(getline('.'), pat)
783
-    execute 'normal!' (v:count1 . a:cmd)
784
-    if !empty(match)
1230
+    " echo pat
1231
+    let v:errmsg = ""
1232
+    try
1233
+      " See |myvimrc-isfname-bug|. Save the current 'isfname' and then set it
1234
+      " to the one we set in our vimrc earlier (i.e. our actual preference).
1235
+      let isfname  = &isfname
1236
+      let &isfname = s:isfname
1237
+      let match  = matchlist(getline('.'), pat)
1238
+      silent! execute 'normal!' (v:count1 . a:cmd)
1239
+    finally
1240
+      " If the above `execute` triggered a change in 'isfname' through a loaded
1241
+      " ftplugin, let that change stand. Otherwise revert our earlier override.
1242
+      if &isfname ==# s:isfname
1243
+        let &isfname = isfname
1244
+      endif
1245
+    endtry
1246
+    if v:errmsg != ""
1247
+      echohl Error | echomsg v:errmsg | echohl None
1248
+    elseif !empty(match)
785 1249
       let start = match[1]
786 1250
       let str   = match[2]
787 1251
       let end   = match[3]
788
-      let pat   = '\C' . '\m' . start . '\V' . str . '\m' . end
1252
+      let pat   = '\C' . '\m' . start . '\V' . escape(str, '\') . '\m' . end
789 1253
       call cursor(1, 1)
790
-      if search(pat, 'c') == 0
791
-        echo "Could not find search string:" (start . str . end)
1254
+      if search(pat, 'c')
1255
+        normal! zz
1256
+      else
1257
+        echo "Can't find search string /" . start . str . end . "/"
792 1258
       endif
793 1259
     endif
794 1260
   endfunction
... ...
@@ -799,65 +1265,137 @@ endif
799 1265
 """ Fill quickfix with output from system command
800 1266
 " TODO: |<q-args>| does not seem to escape quotes, so things like `Cexpr echo
801 1267
 " 'hello'` does not work. Probably passing it to a function so that we get a
802
-" argument variable to call |shellescape| on is required?
1268
+" argument variable to call |shellescape()| on is required?
803 1269
 " TODO: How does this compare to |dispatch|?
804
-command! -bang -complete=shellcmd -nargs=+ Cexpr
1270
+command! -bang -nargs=+ -complete=shellcmd Cexpr
805 1271
 \ execute (empty(<q-bang>)?'cexpr':'cgetexpr') 'system(expandcmd(' escape(<q-args>, "'") '))'
806 1272
 
807 1273
 """ Run `git ls` and preview commits on cursor move
808
-" Requires `vim-fugitive` and a `ls`/`lsa` Git alias.
809
-command! -bar Gls
1274
+" TODO: |fugitive|'s |Gclog| probably covers this use case. Remove?
1275
+" Requires |fugitive| and a `ls`/`lsa` Git alias.
1276
+command! -bar -nargs=0 Gls
810 1277
 \ Git ls |
811 1278
 \ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
812 1279
 \ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
813 1280
 \ execute 'autocmd vimrc BufUnload <buffer> pclose' |
814
-command! -bar Glsa
1281
+command! -bar -nargs=0 Glsa
815 1282
 \ Git lsa |
816 1283
 \ execute 'nmap <silent> <buffer> j j:silent vert Gpedit <cword><CR><C-W>=' |
817 1284
 \ execute 'nmap <silent> <buffer> k k:silent vert Gpedit <cword><CR><C-W>=' |
818 1285
 \ execute 'autocmd vimrc BufUnload <buffer> pclose' |
819 1286
 
1287
+""" Diff
1288
+" See also |start-vimdiff|, |:DiffOrig|.
1289
+" TODO: This is unfinished.
1290
+if has('eval')
1291
+  command! -nargs=* -complete=file Diff call s:diff(<q-args>)
1292
+  function! s:diff(arglist) abort
1293
+    " windo diffoff
1294
+    " if a:0
1295
+    "   let args = map(
1296
+    "   \   flatten(map(
1297
+    "   \     copy(a:000),
1298
+    "   \     'expand(v:val, 1, 1)'
1299
+    "   \   )),
1300
+    "   \   'fnameescape(v:val)'
1301
+    "   \ )
1302
+    "   execute 'args' join(args)
1303
+    if a:arglist
1304
+      execute 'args' arglist
1305
+      vertical all
1306
+      windo diffthis
1307
+    else
1308
+      " let filetype    = &filetype
1309
+      " let swapfile    = &swapfile
1310
+      diffthis
1311
+      aboveleft vertical new
1312
+      diffthis
1313
+      " let &filetype   = filetype
1314
+      " let &swapfile   = swapfile
1315
+      let &filetype   = getbufvar('#', '&filetype')
1316
+      let &swapfile   = getbufvar('#', '&swapfile')
1317
+      let &buftype    = 'nofile'
1318
+      let &bufhidden  = 'wipe'
1319
+      let &modifiable = 1 " Even `bh=wipe` doesn't forget the `noma` below.
1320
+      execute 'file' 'diff://' . expand('#:p')
1321
+      read ++edit #
1322
+      1 delete _
1323
+      let &modifiable = 0
1324
+      wincmd p
1325
+    endif
1326
+  endfunction
1327
+endif
1328
+
820 1329
 "" Auto commands
821
-" Make sure to not define any |autocmd|s before this!
822
-augroup vimrc
823
-  autocmd!
824
-augroup END
825 1330
 
826
-""" Hacks for options that Vim likes to reset
1331
+""" Options
827 1332
 
828
-" `$VIMRUNTIME/colors/default.vim`
829
-autocmd vimrc OptionSet background set background=dark
1333
+"""" 'background'
1334
+" Vim likes to automatically reset |'background'| at inopportune moments (like
1335
+" at `$VIMRUNTIME/colors/default.vim:/set bg&/`).
1336
+if has('eval')
1337
+  let s:background = &background
1338
+  autocmd vimrc OptionSet background let &background = s:background
1339
+endif
1340
+
1341
+"""" 'ttyscroll'
1342
+" *myvimrc-autocmd-ttyscroll*
1343
+" Unconditionally enable |'ttyscroll'| (by setting it to its default value
1344
+" `999`) if there are no vertical splits (so terminal scrolling can actually be
1345
+" used without downsides) and restore if there are vertical splits. Makes the
1346
+" most noticeable difference when doing |CTRL-U| |CTRL-D| in a Linux virtual
1347
+" terminal.
1348
+" TODO: When we set it to `999` we could store the current value in
1349
+" `s:ttyscrol` so that manual adjustments won't be lost.
1350
+if has('eval')
1351
+  let s:ttyscroll = &ttyscroll
1352
+  autocmd vimrc VimEnter,WinEnter *
1353
+  \ let &ttyscroll = empty(filter(getwininfo(), 'v:val.wincol != 1'))
1354
+  \   ? 999
1355
+  \   : s:ttyscroll
1356
+endif
830 1357
 
831 1358
 """ Save/load view
832 1359
 " 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 *
1360
+" buffer. Better (TODO: how?) than |last-position-jump|, |restore-cursor|. See
1361
+" also |'viewoptions'|.
1362
+" TODO: Use a (configurable?) `[nr]` argument to the `{mk,load}view` and
1363
+" reserve the use of the no argument version for the user.
1364
+" TODO: We used to also match on `Buf{Write,Read}` but that generated "E32: No
1365
+" file name" when e.g. discarding changes with `X` in the `vim-fugitive` `:Git`
1366
+" window.
1367
+autocmd vimrc BufWinLeave *
836 1368
 \ if !empty(expand('<afile>')) && empty(&buftype) |
837
-\   loadview |
1369
+\   mkview |
838 1370
 \ endif |
839
-autocmd vimrc BufWinLeave,BufWrite *
1371
+autocmd vimrc BufWinEnter *
840 1372
 \ if !empty(expand('<afile>')) && empty(&buftype) |
841
-\   mkview |
1373
+\   loadview |
842 1374
 \ endif |
843 1375
 
844
-""" Don't show extra things in special buffers
1376
+""" Unclutter special buffers
845 1377
 " TODO: This needs to be moved to after the plugins for it to work in e.g.
846 1378
 " fugitive?
847 1379
 if !has('nvim')
848 1380
   autocmd vimrc BufReadPost,TerminalWinOpen *
849 1381
   \ if !empty(&buftype) |
850 1382
   \   silent setlocal nolist nospell |
851
-  \ endif
1383
+  \ endif |
852 1384
 endif
853 1385
 
1386
+""" Fixate terminal height
1387
+autocmd vimrc TerminalWinOpen *
1388
+\ set winfixheight |
1389
+\ 15wincmd _ |
1390
+
854 1391
 """ QuickFix/Location list
855 1392
 
856
-"""" Open window
1393
+"""" Open window automatically
857 1394
 " See
858 1395
 " - <https://github.com/tpope/vim-dispatch/issues/145>
859 1396
 " - <https://github.com/tpope/vim-dispatch/issues/254>
860 1397
 " - <https://github.com/tpope/vim-dispatch/issues/310>
1398
+" TODO: These `vim-dispatch` issues might have been fixed?
861 1399
 " TODO: Maybe this can be fixed by switching back to the previous window after
862 1400
 " opening the quickfix window? Make sure to only switch to the previous if we
863 1401
 " actually opened the window.
... ...
@@ -878,11 +1416,57 @@ if has('eval')
878 1416
   autocmd vimrc CmdlineLeave /,\? let  &hlsearch = s:hlsearch
879 1417
 endif
880 1418
 
1419
+""" Terminal folding
1420
+" If a line (like a shell prompt) starts with `│` it will define a fold start.
1421
+" TODO: More "shell integrations":
1422
+" - <https://wezterm.org/shell-integration.html>
1423
+" - <https://learn.microsoft.com/en-us/windows/terminal/tutorials/shell-integration>
1424
+"   - OSC 133: Prompt.
1425
+"     - <https://per.bothner.com/blog/2019/shell-integration-proposal/
1426
+"     - <https://gitlab.freedesktop.org/Per_Bothner/specifications/blob/master/proposals/semantic-prompts.md>
1427
+"   - OSC 7: Current directory.
1428
+"     - <https://lacamb.re/blog/osc7_in_neovim_third_time.html>
1429
+autocmd vimrc TerminalWinOpen *
1430
+\ set foldlevel=0 |
1431
+\ set foldmethod=expr |
1432
+\ set foldexpr=getline(v:lnum)=~'^│'?'>1':'=' |
1433
+autocmd vimrc CursorMoved *
1434
+\ if &buftype ==# 'terminal' |
1435
+\   let &foldmethod = &foldmethod |
1436
+\ endif |
1437
+
1438
+""" Find other Vim instance when swap file exists
1439
+" Only for Unix-likes. POSIX-compliant. Sends signal `USR1` which when received
1440
+" outputs a `BEL` to the terminal, hopefully making the terminal emulator mark
1441
+" the window as urgent, helping the user find it. Under X11 if `xdotool` is
1442
+" installed one alternative might be `!xdotool set_window --urgency 1
1443
+" $WINDOWID`. |swapinfo| was added in `8.1.0313` and |SigUSR1| in `8.2.0952`.
1444
+if has('eval') && executable('kill')
1445
+  autocmd vimrc SwapExists *
1446
+  \ let s:swapinfo = swapinfo(v:swapname) |
1447
+  \ if s:swapinfo['host'] == hostname() |
1448
+  \   call system('kill -USR1 ' . s:swapinfo['pid']) |
1449
+  \ endif |
1450
+  autocmd vimrc SigUSR1 * silent execute "!printf '\\a'" | silent redraw!
1451
+endif
1452
+
881 1453
 "" Colors
882 1454
 " See |cterm-colors|, |gui-colors|.
883
-
884
-silent !. ~/.shrc.d/color.sh
885
-" redraw!
1455
+" See |colortest.vim|, |hitest.vim|.
1456
+
1457
+" TODO: If/when we break this out to a separate file/plugin, we might want to
1458
+" link to stuff like this:
1459
+" - <https://jeffkreeftmeijer.com/vim-16-color/>
1460
+" - <https://github.com/jeffkreeftmeijer/vim-dim>
1461
+
1462
+" This creates problems, we should just make sure files opened with
1463
+" `vim.desktop` get the colors. It looks like `.desktop` files with
1464
+" `Terminal=true` makes the terminal source `~/.profile` but not `~/.shrc`
1465
+" (which makes sense in a way, it's `Terminal`, not `Shell`).
1466
+if $_ ==# '/usr/bin/xdg-open'
1467
+  silent !. ~/.shrc.d/color.sh
1468
+  " redraw!
1469
+endif
886 1470
 
887 1471
 " TODO: Document that |autocmd| is available in "tiny" (i.e. always) but
888 1472
 " |+syntax| requires "normal", so doing it the way we're doing it makes sure it
... ...
@@ -913,8 +1497,8 @@ endif
913 1497
 " TODO: Remove all `Gray` except `Comment` from this list and link them to `Comment`?
914 1498
 " NOTE: When |hl-StatusLine| is a |:hi-link| Vim cannot determine if it's equal
915 1499
 " 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.
1500
+" `$VIMSRC/src/drawscreen.c:550` (at the bottom of the function
1501
+" `win_redr_status`) in the Vim source.
918 1502
 " TODO: Since the Linux console cannot use `DarkGray` as a background, consider
919 1503
 " using any other `Dark*` color (e.g. `DarkYellow`) as (non-`reverse`) `Visual`
920 1504
 " `ctermbg` with `ctermfg=NONE`. NOTE: This requires that we standardize on
... ...
@@ -932,6 +1516,14 @@ endif
932 1516
 " autocmd vimrc ColorScheme * nested
933 1517
 " \ highlight Normal font='Monospace Regular 10'
934 1518
 
1519
+" Emphasis levels, in ascending order:
1520
+"
1521
+" | Highlight       | Use case                           | Example        |
1522
+" | `Comment`       | Non-highlighted (interface, menus) | `StatusLineNC` |
1523
+" | `Normal`        | Non-highlighted (interface, menus) | `StatusLine`   |
1524
+" | `Visual`        | Highlighted     (buffer text)      | `Search`       |
1525
+" | `cterm=reverse` | Highlighted     (buffer text)      | `IncSearch`    |
1526
+
935 1527
 " \ set background=dark | runtime syntax/syncolor.vim |
936 1528
 autocmd vimrc ColorScheme * nested
937 1529
 \ highlight Normal           term=NONE   cterm=NONE   gui=NONE              ctermbg=NONE        ctermfg=White      |
... ...
@@ -941,7 +1533,8 @@ autocmd vimrc ColorScheme * nested
941 1533
 \ highlight SpellBad         term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
942 1534
 \ highlight SpellOther       term=NONE   cterm=NONE   gui=NONE   guibg=NONE ctermbg=NONE        ctermfg=LightRed   |
943 1535
 \ 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       |
1536
+\ highlight Search           term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkBlue    ctermfg=NONE       |
1537
+\ highlight IncSearch        term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkYellow  ctermfg=NONE       |
945 1538
 \ highlight DiffAdd          term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkGreen   ctermfg=NONE       |
946 1539
 \ highlight DiffDelete       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkRed     ctermfg=NONE       |
947 1540
 \ highlight DiffChange       term=NONE   cterm=NONE   gui=NONE              ctermbg=DarkBlue    ctermfg=NONE       |
... ...
@@ -964,10 +1557,14 @@ autocmd vimrc ColorScheme * nested
964 1557
 autocmd vimrc ColorScheme * nested
965 1558
 \ highlight Identifier cterm=NONE ctermfg=LightCyan |
966 1559
 
967
-""" Debug
1560
+""" No underline
1561
+" Remove all `cterm=underline` set by default in `$VIMRUNTIME/syntax/syncolor.vim`.
1562
+" `Underlined` is linked to by `htmlLink` and `mkdLink` by default and is too
1563
+" cluttered for my taste.
968 1564
 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 |
1565
+\ highlight Underlined cterm=NONE |
1566
+
1567
+""" Wildmenu
971 1568
 
972 1569
 " set highlight-=s:StatusLine
973 1570
 " set highlight-=S:StatusLineNC
... ...
@@ -1013,28 +1610,58 @@ autocmd vimrc ColorScheme * nested
1013 1610
 \ highlight! link CursorLine   Visual |
1014 1611
 \ highlight! link CursorLineNr Visual |
1015 1612
 
1613
+""" Wildmenu
1614
+autocmd vimrc ColorScheme * nested
1615
+\ highlight! link WildMenu Search |
1616
+
1016 1617
 """ Popup menu
1017
-" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
1018 1618
 autocmd vimrc ColorScheme * nested
1019
-\ highlight Pmenu     ctermbg=LightGray ctermfg=DarkGray |
1020
-\ highlight PmenuSel  ctermbg=LightGray ctermfg=White    |
1021
-\ highlight PmenuSbar ctermbg=DarkGray                   |
1619
+\ highlight Pmenu      ctermbg=LightGray ctermfg=DarkGray |
1620
+\ highlight PmenuSel   ctermbg=LightGray ctermfg=White    |
1621
+\ highlight PmenuSbar  ctermbg=DarkGray                   |
1622
+\ highlight PmenuThumb ctermbg=White                      |
1623
+
1624
+""" Ignore
1625
+" See |'highlight'|. By default links to |NonText|.
1626
+autocmd vimrc ColorScheme * nested
1627
+\ highlight! link EndOfBuffer Ignore |
1628
+
1629
+""" Non-Ignore
1630
+" By default links to |Ignore|.
1631
+autocmd vimrc ColorScheme * nested
1632
+\ highlight! link helpIgnore   Comment    |
1633
+\ highlight! link helpBacktick helpIgnore |
1634
+\ highlight! link helpBar      helpIgnore |
1635
+\ highlight! link helpStar     helpIgnore |
1022 1636
 
1023 1637
 """ Non-document characters
1024
-" See |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
1638
+" See |'highlight'|, |'showbreak'|, |'listchars'| `extends` `precedes` `eol`.
1025 1639
 autocmd vimrc ColorScheme * nested
1026
-\ highlight! link NonText     Special |
1027
-\ highlight! link EndOfBuffer Ignore  |
1640
+\ highlight! link NonText Special |
1028 1641
 
1029 1642
 """ Document non-printables characters
1030
-" See |'listchars'| `tab`, `space`, `trail`, `nbsp`.
1643
+" See |'highlight'|, |'listchars'| `tab`, `space`, `trail`, `nbsp`.
1031 1644
 autocmd vimrc ColorScheme * nested
1032 1645
 \ highlight! link SpecialKey Comment |
1033 1646
 
1034
-""" Document concealed characters
1035
-" See |'listchars'| `conceal`.
1647
+""" Document conceal replacement characters
1648
+autocmd vimrc ColorScheme * nested
1649
+\ highlight! link Conceal Identifier |
1650
+
1651
+""" Debug
1652
+autocmd vimrc ColorScheme * nested
1653
+\ highlight debugPC         term=reverse cterm=NONE gui=NONE guibg=DarkBlue ctermbg=DarkBlue guifg=NONE     ctermfg=NONE     |
1654
+\ highlight debugBreakpoint term=NONE    cterm=NONE gui=NONE guibg=NONE     ctermbg=NONE     guifg=LightRed ctermfg=LightRed |
1655
+
1656
+" TODO: Filetype-specific customizations probably should trigger on some other
1657
+" event.
1658
+
1659
+""" Markdown delimiters
1036 1660
 autocmd vimrc ColorScheme * nested
1037
-\ highlight! link Conceal Ignore |
1661
+\ highlight! link mkdDelimiter     Comment |
1662
+\ highlight! link mkdCodeDelimiter Comment |
1663
+\ highlight! link mkdCodeStart     Comment |
1664
+\ highlight! link mkdCodeEnd       Comment |
1038 1665
 
1039 1666
 """ Vim comments
1040 1667
 autocmd vimrc ColorScheme * nested
... ...
@@ -1059,6 +1686,10 @@ doautocmd vimrc ColorScheme
1059 1686
 
1060 1687
 if has('eval')
1061 1688
 
1689
+  """ |mapleader|
1690
+  let g:mapleader      = "\<Space>"
1691
+  let g:localmapleader = "\<Space>"
1692
+
1062 1693
   """ GitAdd
1063 1694
   " <https://git.rcrnstn.net/rcrnstn/vim-gitadd>
1064 1695
 
... ...
@@ -1079,6 +1710,18 @@ if has('eval')
1079 1710
     endif
1080 1711
   endfunction
1081 1712
 
1713
+  """ Interface
1714
+
1715
+  """" `tpope/vim-flagship`
1716
+  " GitAdd https://github.com/tpope/vim-flagship
1717
+
1718
+  """" `chrisbra/NrrwRgn`
1719
+  GitAdd https://github.com/chrisbra/NrrwRgn
1720
+
1721
+  let g:nrrw_topbot_leftright = 'belowright'
1722
+
1723
+  xmap <Space><Space>nr <Plug>NrrwrgnDo
1724
+
1082 1725
   """ File type
1083 1726
 
1084 1727
   """" Built-in `vim`
... ...
@@ -1122,6 +1765,8 @@ if has('eval')
1122 1765
   let g:vim_markdown_math = 1
1123 1766
   let g:vim_markdown_frontmatter = 1
1124 1767
   let g:vim_markdown_no_extensions_in_markdown = 1
1768
+  let g:vim_markdown_auto_insert_bullets = 0
1769
+  let g:vim_markdown_new_list_item_indent = 0
1125 1770
 
1126 1771
   " " Defaults.
1127 1772
   " " |vim-markdown-fenced-code-block-languages|
... ...
@@ -1147,6 +1792,18 @@ if has('eval')
1147 1792
   " Roughly as recommended in the readme.
1148 1793
   " autocmd vimrc BufNewFile,BufFilePre,BufRead *.md set filetype=markdown.pandoc
1149 1794
 
1795
+  """" `gpanders/vim-medieval`
1796
+  GitAdd https://github.com/gpanders/vim-medieval
1797
+
1798
+  " Roughly as suggested in `vim-medieval/README.md:/Create a mapping/` (but
1799
+  " not mentioned in |medieval.txt|...).
1800
+  autocmd vimrc FileType markdown
1801
+  \ nmap <buffer> <Space>! <Plug>(medieval-eval)
1802
+
1803
+  " TODO: Add `octave` (and `matlab`?). We probably need flags to prevent
1804
+  " opening a GUI, does medieval support flags?
1805
+  let g:medieval_langs = ['sh', 'bash', 'python=python3']
1806
+
1150 1807
   """" `sheerun/vim-polyglot`
1151 1808
   GitAdd https://github.com/sheerun/vim-polyglot
1152 1809
 
... ...
@@ -1192,6 +1849,8 @@ if has('eval')
1192 1849
   """" `tpope/vim-unimpaired`
1193 1850
   GitAdd https://github.com/tpope/vim-unimpaired
1194 1851
 
1852
+  " Also search for `map[a-z]* \+\S*[][]` in this file.
1853
+
1195 1854
   " <https://github.com/tpope/vim-unimpaired/issues?q=conceal>
1196 1855
   " <https://github.com/tpope/vim-unimpaired/issues/105>
1197 1856
   " <https://github.com/tpope/vim-unimpaired/pull/152>
... ...
@@ -1199,7 +1858,16 @@ if has('eval')
1199 1858
   nnoremap [oe :setlocal conceallevel=<C-R>=&conceallevel == 0 ? 0 : &conceallevel - 1<CR><CR>
1200 1859
   nnoremap ]oe :setlocal conceallevel=<C-R>=&conceallevel == 2 ? 2 : &conceallevel + 1<CR><CR>
1201 1860
 
1861
+  " See also `tpope/sleuth.vim`
1862
+  " function! s:textwidth() abort
1863
+  "   return max(map(range(1, line('$')), 'len(getline(v:val))'))
1864
+  " endfunction
1865
+  " let g:textwidth = &textwidth
1866
+  " nnoremap yoT :setlocal textwidth=<C-R>=&textwidth == g:textwidth ? <SID>textwidth() : g:textwidth<CR><CR>
1867
+
1202 1868
   """" `tpope/vim-repeat`
1869
+  " Does `vim-repeat` have to go at the beginning to activate integrations with
1870
+  " other plugins (e.g. `vim-unimpaired`)?
1203 1871
   GitAdd https://github.com/tpope/vim-repeat
1204 1872
 
1205 1873
   """" `inkarkat/vim-visualrepeat`
... ...
@@ -1209,6 +1877,9 @@ if has('eval')
1209 1877
   """" `tpope/vim-characterize`
1210 1878
   GitAdd https://github.com/tpope/vim-characterize
1211 1879
 
1880
+  """" `chrisbra/unicode.vim`
1881
+  " GitAdd https://github.com/chrisbra/unicode.vim
1882
+
1212 1883
   """" `haya14busa/vim-asterisk`
1213 1884
   GitAdd https://github.com/haya14busa/vim-asterisk
1214 1885
 
... ...
@@ -1233,6 +1904,9 @@ if has('eval')
1233 1904
   """" `AndrewRadev/switch.vim`
1234 1905
   GitAdd https://github.com/AndrewRadev/switch.vim
1235 1906
 
1907
+  " TODO: The ones with `\%#` |cursor-position| does not work, probably because
1908
+  " `switch.vim` tries to match it at some other position internally. Searching
1909
+  " manually yields the expected matches though.
1236 1910
   let g:switch_custom_definitions = [{
1237 1911
   \   '\<0\>': '1',
1238 1912
   \   '\<1\>': '0',
... ...
@@ -1254,8 +1928,10 @@ if has('eval')
1254 1928
   \   '\(\w*\)TRUE\(\w*\)': '\1FALSE\2',
1255 1929
   \   '\(\w*\)True\(\w*\)': '\1False\2',
1256 1930
   \   '\(\w*\)true\(\w*\)': '\1false\2',
1257
-  \   '\<\(set *\)no\([a-z]\+\)\>=\@!': '\1\2',
1258
-  \   '\<\(set *\)\([a-z]\+\)\>=\@!':   '\1no\2',
1931
+  \   '\(\<set\%(g\|global\)\? *\) \%(no\)\([a-z]\+\)\( \|$\)':    '\1 \2\3',
1932
+  \   '\(\<set\%(g\|global\)\? *\) \%(no\)\@!\([a-z]\+\)\( \|$\)': '\1 no\2\3',
1933
+  \   '\(\<set\%(g\|global\)\? *.*\) \%(no\)\([a-z]*\%#[a-z]*\)\( \|$\)':    '\1 \2\3',
1934
+  \   '\(\<set\%(g\|global\)\? *.*\) \%(no\)\@!\([a-z]*\%#[a-z]*\)\( \|$\)': '\1 no\2\3',
1259 1935
   \ }]
1260 1936
 
1261 1937
   """" `terryma/vim-smooth-scroll`
... ...
@@ -1298,6 +1974,11 @@ if has('eval')
1298 1974
   """" `tpope/vim-abolish`
1299 1975
   GitAdd https://github.com/tpope/vim-abolish
1300 1976
 
1977
+  """ Visual mode
1978
+
1979
+  """" `dahu/Severalections`
1980
+  GitAdd https://github.com/dahu/Severalections
1981
+
1301 1982
   """ Operators
1302 1983
 
1303 1984
   """" `tpope/vim-surround`
... ...
@@ -1403,6 +2084,11 @@ if has('eval')
1403 2084
   """" `moll/vim-bbye`
1404 2085
   GitAdd https://github.com/moll/vim-bbye
1405 2086
 
2087
+  """" `chrisbra/NrrwRgn`
2088
+  " GitAdd https://github.com/chrisbra/NrrwRgn
2089
+  " TODO: I have not evaluated this yet. If it isn't to our liking there is
2090
+  " also <https://github.com/chrisbra/NrrwRgn#similar-work>.
2091
+
1406 2092
   """ Folds
1407 2093
 
1408 2094
   """" `rcrnstn/vim-unobtrusive-fold`
... ...
@@ -1448,13 +2134,27 @@ if has('eval')
1448 2134
   " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
1449 2135
   " GitAdd https://github.com/inkarkat/vim-SpellCheck
1450 2136
 
2137
+  """ Syntax
2138
+
2139
+  """" `inkarkat/vim-SyntaxRange`
2140
+  " NOTE: Requires <https://github.com/inkarkat/vim-ingo-library>
2141
+  " GitAdd https://github.com/inkarkat/vim-SyntaxRange
2142
+
2143
+  """" `ypcrts/securemodelines`
2144
+  " GitAdd https://github.com/ypcrts/securemodelines
2145
+  " TODO: Last updated 2019 as of this writing, can we be sure this is really
2146
+  " more secure than the built-in sandbox? Besides, we currently disable
2147
+  " modelines with `set modelines=0`.
2148
+
2149
+  " let g:secure_modelines_verbose = 1
2150
+
1451 2151
   """ Modelines
1452 2152
 
1453 2153
   """" `ypcrts/securemodelines`
1454 2154
   " 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.
2155
+  " TODO: Last updated 2019 as of this writing, can we be sure this is really
2156
+  " more secure than the built-in sandbox? Besides, we currently disable
2157
+  " modelines with `set modelines=0`.
1458 2158
 
1459 2159
   " let g:secure_modelines_verbose = 1
1460 2160
 
... ...
@@ -1462,8 +2162,9 @@ if has('eval')
1462 2162
 
1463 2163
   """" Built-in `netrw`
1464 2164
 
1465
-  let g:netrw_home = '~/.cache/vim/netrw'
1466
-  let g:netrw_banner = 0
2165
+  let g:netrw_home      = '~/.cache/vim/netrw'
2166
+  let g:netrw_banner    = 0
2167
+  let g:netrw_liststyle = 3 " Tree.
1467 2168
 
1468 2169
   " Netrw versions (roughly) 162h to 170 break `gx`. Never download the remote
1469 2170
   " file to a temporary. See
... ...
@@ -1522,6 +2223,8 @@ if has('eval')
1522 2223
     let s:wildignore_name = filter(copy(s:wildignore), '!count(v:val, "/")')
1523 2224
     let s:wildignore_path = filter(copy(s:wildignore), ' count(v:val, "/")')
1524 2225
 
2226
+    " \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) .
2227
+    " \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(v:val)')) .
1525 2228
     let g:ctrlp_user_command =
1526 2229
     \ 'find' .
1527 2230
     \ (!g:ctrlp_follow_symlinks ? '' : ' -L') .
... ...
@@ -1530,8 +2233,8 @@ if has('eval')
1530 2233
     \ ' -maxdepth ' . g:ctrlp_max_depth .
1531 2234
     \ ' \( -false' .
1532 2235
     \ (g:ctrlp_show_hidden ? '' : ' -o -name ".*"') .
1533
-    \ ' ' . join(map(s:wildignore_name, '"-o -name " . shellescape(v:val)')) .
1534
-    \ ' ' . join(map(s:wildignore_path, '"-o -path " . shellescape(v:val)')) .
2236
+    \ ' ' . join(map(s:wildignore_name, '"-o -name " . v:val')) .
2237
+    \ ' ' . join(map(s:wildignore_path, '"-o -path " . v:val')) .
1535 2238
     \ ' \) -prune -o' .
1536 2239
     \ ' -type f -print' .
1537 2240
     \ ' 2> /dev/null' .
... ...
@@ -1575,14 +2278,32 @@ if has('eval')
1575 2278
   """" `tpope/vim-fugitive`
1576 2279
   GitAdd https://github.com/tpope/vim-fugitive
1577 2280
 
1578
-  autocmd vimrc FileType fugitiveblame call fugitive#MapJumps()
2281
+  " autocmd vimrc FileType fugitiveblame call fugitive#MapJumps()
1579 2282
 
1580 2283
   " http://vimcasts.org/episodes/fugitive-vim-browsing-the-git-object-database/
1581 2284
   " TODO: Do we want `bufhidden=wipe`?
1582 2285
   autocmd vimrc BufReadPost fugitive://* setlocal bufhidden=delete
1583 2286
 
2287
+  autocmd vimrc FileType git set foldmethod=expr foldexpr=GitFoldexpr()
2288
+  function! GitFoldexpr() abort
2289
+    let line = getline(v:lnum)
2290
+    if line =~# '^diff --git'
2291
+      return '>1'
2292
+    elseif line =~# '@@ [-+0-9, ]\+ @@'
2293
+      return '>2'
2294
+    endif
2295
+    return '='
2296
+  endfunction
2297
+
1584 2298
   " TODO: Add some `git log -L` (see man page) mapping.
1585 2299
 
2300
+  """" `samoshkin/vim-mergetool`
2301
+  " GitAdd https://github.com/samoshkin/vim-mergetool
2302
+
2303
+  """" `tpope/vim-rhubarb`
2304
+  " GitHub extension for `tpope/vim-fugitive`. We mostly use it for |:GBrowse|.
2305
+  GitAdd https://github.com/tpope/vim-rhubarb
2306
+
1586 2307
   """" `tommcdo/vim-fugitive-blame-ext`
1587 2308
   GitAdd https://github.com/tommcdo/vim-fugitive-blame-ext
1588 2309
 
... ...
@@ -1592,6 +2313,16 @@ if has('eval')
1592 2313
   """" `tpope/vim-dispatch`
1593 2314
   GitAdd https://github.com/tpope/vim-dispatch
1594 2315
 
2316
+  " TODO: Put this in a QuickFix section?
2317
+
2318
+  " See also |dispatch-maps|.
2319
+  " TODO: Stick to the default mappings.
2320
+  nnoremap <Space><Space>m% :Make %:r:S<CR>
2321
+  nnoremap <Space><Space>m# :Make #:r:S<CR>
2322
+  nnoremap <Space><Space>mm :Make<CR>
2323
+  nnoremap <Space><Space>ma :Make all<CR>
2324
+  nnoremap <Space><Space>mt :Make test<CR>
2325
+
1595 2326
   " https://github.com/tpope/vim-dispatch/issues/203
1596 2327
   function! s:focus_start_set() abort
1597 2328
     if get(b:, 'start_local', 1)
... ...
@@ -1642,21 +2373,15 @@ if has('eval')
1642 2373
   command! -bang -nargs=* -range=-1 -complete=customlist,dispatch#command_complete FocusStart
1643 2374
   \ call s:focus_start(<bang>0, <q-args>)
1644 2375
 
1645
-  " TODO: Put this in a QuickFix section?
1646
-
1647
-  " TODO: Stick to the default mappings.
1648
-  nnoremap <Space><Space>m% :Make %:r:S<CR>
1649
-  nnoremap <Space><Space>m# :Make #:r:S<CR>
1650
-  nnoremap <Space><Space>mm :Make<CR>
1651
-  nnoremap <Space><Space>ma :Make all<CR>
1652
-  nnoremap <Space><Space>mt :Make test<CR>
1653
-
1654 2376
   """" `tpope/vim-eunuch`
1655 2377
   GitAdd https://github.com/tpope/vim-eunuch
1656 2378
 
1657 2379
   """" `tpope/vim-projectionist`
1658 2380
   GitAdd https://github.com/tpope/vim-projectionist
1659 2381
 
2382
+  """" `tpope/vim-vinegar`
2383
+  " GitAdd https://github.com/tpope/vim-vinegar
2384
+
1660 2385
   """ Debugging
1661 2386
 
1662 2387
   """" Built-in `termdebug`
... ...
@@ -1666,20 +2391,23 @@ if has('eval')
1666 2391
   " TODO: Add mappings.
1667 2392
   " TODO: Remove |:Winbar|.
1668 2393
   " TODO: Do some |termdebug-customizing|, especially |termdebug_shortcuts|.
1669
-  " TODO: Add some signs? ■♦←↑→↓›»•·
2394
+  " TODO: Add some signs? See |myvimrc-characters|.
2395
+
1670 2396
   " let g:termdebug_popup = 0
1671 2397
 
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>
2398
+  nnoremap <Space>dd :Termdebug<CR>
2399
+
2400
+  " `<Space>do` conflicts with our |do| ("diff obtain", |:diffget|)
2401
+  " text-object.
2402
+  " nnoremap <Space>db :Break<CR>
2403
+  " nnoremap <Space>dB :Clear<CR>
2404
+  " nnoremap <Space>di :Step<CR>
2405
+  " nnoremap <Space>do :Over<CR>
2406
+  " nnoremap <Space>df :Finish<CR>
2407
+  " nnoremap <Space>dr :Run<CR>
2408
+  " nnoremap <Space>da :Arguments<CR>
2409
+  " nnoremap <Space>ds :Stop<CR>
2410
+  " nnoremap <Space>dc :Continue<CR>
1683 2411
   " nnoremap <Space>de :Evaluate<CR>
1684 2412
 
1685 2413
   " nnoremap <Space>dg :Gdb<CR>
... ...
@@ -1705,6 +2433,16 @@ if has('eval')
1705 2433
   " Common DeBugGer Protocol (DBGP) client. See
1706 2434
   " <https://en.wikipedia.org/wiki/DBGp>.
1707 2435
 
2436
+  """ LSP
2437
+
2438
+  " We have not decided on a LSP/linting plugin. Wishlist:
2439
+  " - Compatible with at least Vim 8.
2440
+  " - Not require dozens of other plugins to configure/make usable.
2441
+  " Some things to check out, roughly in the order of looking like a good fit.
2442
+  " - <https://github.com/dense-analysis/ale>
2443
+  " - <https://github.com/prabirshrestha/vim-lsp>
2444
+  " - <https://github.com/yegappan/lsp>
2445
+
1708 2446
 endif " has('eval')
1709 2447
 
1710 2448
 "" Syntax and file type
... ...
@@ -1752,7 +2490,7 @@ if has('eval')
1752 2490
     silent execute 'setlocal' 'filetype=' . a:filetype
1753 2491
     silent setlocal readonly nomodifiable nomodified
1754 2492
     silent setlocal buftype=help
1755
-    silent let &shellredir = old_shellredir
2493
+    " silent let &shellredir = old_shellredir
1756 2494
   endfunction
1757 2495
 endif
1758 2496
 
... ...
@@ -1766,40 +2504,66 @@ command! -nargs=1 OctaveHelp
1766 2504
 \ call s:help(['octave', '--eval', 'help("%s")'], <q-args>, 'octave')
1767 2505
 
1768 2506
 " 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>`.
2507
+" `ManHelp git-config` and then `/^ {7}\zs` with the first two components of
2508
+" section words and `<cword>`.
1771 2509
 
1772 2510
 "" File type overrides
1773 2511
 
2512
+" TODO: We want 'path' entries to be in priority order.
2513
+
2514
+" TODO: It looks to me that this should be a global static default instead of a
2515
+" local dynamic override.
1774 2516
 autocmd vimrc FileType *
1775 2517
 \ setlocal keywordprg=:ManHelp |
1776 2518
 
1777 2519
 " TODO: This needs work. We globally override `fillchars` `stl`/`stlnc` and
1778 2520
 " `statusline` but don't take into account file type plugins setting their own
1779 2521
 " `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
2522
+autocmd vimrc FileType *
1786 2523
 \ setlocal statusline=%{Statusline()} |
1787 2524
 
1788
-autocmd vimrc FileType vim
2525
+" See also |scriptease| (which sets both 'keywordprg' and 'path', TODO but
2526
+" posssibly only in `vim` files, not `help` files).
2527
+autocmd vimrc FileType vim,help
2528
+\ execute "nnoremap <buffer> <Space>K :helpgrep <C-R><C-A><CR>" |
1789 2529
 \ setlocal keywordprg=:help |
2530
+\ setlocal path=.,$VIMRUNTIME,$VIMSRC,$HOME/.vim,$HOME/.vim/pack/*/* |
2531
+\ if has('eval') |
2532
+\   execute 'setlocal' 'path+=' . fnamemodify($MYVIMRC, ':h') |
2533
+\   execute 'setlocal' 'path+=' . fnamemodify($MYVIMRC, ':h') . '/pack/*/*' |
2534
+\ endif |
2535
+\ setlocal path+=,
2536
+
2537
+autocmd vimrc FileType man
2538
+\ setlocal textwidth=78 |
1790 2539
 
1791 2540
 autocmd vimrc FileType sh
1792 2541
 \ setlocal shiftwidth=2 |
2542
+\ if has('eval') |
2543
+\   execute 'setlocal' 'path=' . substitute($PATH, '[:;]', ',', 'g') |
2544
+\ endif |
1793 2545
 
1794
-autocmd vimrc FileType c,cpp,glsl
2546
+" `path`s that start with `**` are great if you're in a project directory and
2547
+" want to find stuff like CMake's
2548
+" `_build/_deps/SOME_DEPENDENCY/include/SOME_PATH`, but not so great if you're
2549
+" in `$HOME`.
2550
+autocmd vimrc FileType c,cpp,lex,yacc,glsl
1795 2551
 \ setlocal commentstring=//\ %s |
1796
-\ setlocal matchpairs=(:),{:},[:],<:> |
2552
+\ setlocal matchpairs=(:),{:},[:] |
1797 2553
 \ 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 |
2554
+\ setlocal path=.,src,src/*,include,*/_deps/*/include |
2555
+autocmd vimrc FileType c,cpp,lex,yacc
2556
+\ if has('eval') && executable('uname') |
2557
+\   execute 'setlocal' 'path+=' . printf('/lib/modules/%s/build/include', trim(system('uname -r'))) |
2558
+\ endif |
2559
+\ setlocal path+=/usr/include,/usr/local/include |
2560
+autocmd vimrc FileType cpp
2561
+\ setlocal matchpairs+=<:> |
2562
+\ setlocal path+=/usr/include/c++/* |
1799 2563
 
1800 2564
 autocmd vimrc FileType man
1801 2565
 \ setlocal nolist nospell |
1802
-\ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\(--\S\+\, \)\?\zs-' |
2566
+\ execute 'nnoremap <buffer> <Space>/ /^ \{4,\}\([-‐]\{2\}\S\+\, \+\)\?\zs[-‐]' |
1803 2567
 
1804 2568
 autocmd vimrc FileType dot
1805 2569
 \ setlocal commentstring=//\ %s |
... ...
@@ -1817,6 +2581,11 @@ autocmd vimrc FileType python
1817 2581
 autocmd vimrc FileType octave
1818 2582
 \ setlocal keywordprg=:OctaveHelp |
1819 2583
 
2584
+" TODO: Might be nice to query some external command for the `path`.
2585
+autocmd vimrc FileType tex
2586
+\ setlocal path=.,,/usr/share/texlive/texmf-dist/tex/latex/*/ |
2587
+\ setlocal suffixesadd=.tex,.cls,.sty |
2588
+
1820 2589
 " Don't insert comment leader after |i_<CR>|, |o|, or |O|.
1821 2590
 autocmd vimrc FileType *
1822 2591
 \ setlocal formatoptions-=r formatoptions-=o |
... ...
@@ -1828,6 +2597,10 @@ autocmd vimrc FileType *
1828 2597
 \   setlocal omnifunc=syntaxcomplete#Complete |
1829 2598
 \ endif |
1830 2599
 
2600
+" If 'filetype' is never set, "universal" autocommand configuration will not be
2601
+" applied unless we explicitly trigger it.
2602
+doautocmd vimrc FileType *
2603
+
1831 2604
 " TODO: Add a match for `\<TODO\>` (and `\<NOTE\>`?) unconditionally for all
1832 2605
 " file types.
1833 2606
 
... ...
@@ -1874,7 +2647,7 @@ endif
1874 2647
 " See |xterm-true-color|.
1875 2648
 
1876 2649
 if has('termguicolors') && !has('nvim')
1877
-  " These are the defaults if `$TERM` is `xterm`.
2650
+  " In earlier Vim versions, these are the defaults only if `$TERM` is `xterm`.
1878 2651
   let &t_8f = "\033[38;2;%lu;%lu;%lum"
1879 2652
   let &t_8b = "\033[48;2;%lu;%lu;%lum"
1880 2653
   " <http://ftp.vim.org/pub/vim/patches/8.2/8.2.3516>: Terminal window does not
... ...
@@ -1887,8 +2660,8 @@ if has('termguicolors') && !has('nvim')
1887 2660
     autocmd vimrc TerminalOpen,WinEnter *
1888 2661
     \ let s:newtermguicolors =
1889 2662
     \   s:termguicolors &&
1890
-    \   empty(filter(range(1, bufnr('$')),
1891
-    \     'getbufvar(v:val, "&buftype") ==# "terminal"'
2663
+    \   empty(filter(getwininfo(),
2664
+    \     'getbufvar(v:val.bufnr, "&buftype") ==# "terminal"'
1892 2665
     \   )) |
1893 2666
     \ if s:newtermguicolors != &termguicolors |
1894 2667
     \   execute 'set' (s:newtermguicolors ? '' : 'no') . 'termguicolors' |