aboutsummaryrefslogtreecommitdiff
path: root/.vim/vimrc
blob: cb9b9029f839675d1fec24a94525a99b2ea7e569 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
"------------Setup-------------"

mapclear                                 " Clear all mappings.
packadd! matchit                         " Add match tag pairs package.
let skip_defaults_vim=1                  " Do not load defaults if vimrc is missing.


"------------General------------"

let mapleader = "\<space>"               " Set default map leader.
let php_htmlInStrings = 1                " Highlight HTML in PHP.

set ruler                                " Show the cursor position all the time.
set nowrap                               " Do not wrap lines.
set nonumber                             " Set line numbers.
set hlsearch                             " Enable search.
set incsearch                            " Set incremental search.
set showmatch                            " Briefly show matching tags.
set nocompatible                         " Use Vim defaults.
set splitbelow                           " Open horizontal splits below.
set splitright                           " Open vertical splits to the right.
set cursorline                           " Set cursor line highlight.
set notimeout                            " Wait indefinitely for complete key combinations.
set ttimeout                             " Prevent pressing <Esc> twice.
set nostartofline                        " Do not move cursor to line start on buffer switch.
set showcmd                              " Show key presses in status line.
set wildmenu                             " Show tab completions menu.
set nojoinspaces                         " Insert one space after a '.', '?' and '!' with a join command.
set path+=**                             " Search subfolders.
set display=lastline                     " @@@ which indicates remaining line is not displayed.

set hidden                               " Set hidden buffers.
set nobackup                             " No write backups.
set noswapfile                           " Disable swap files.
set nowritebackup                        " No overwrite backups.
set autoread                             " Auto read file on external change.
set autowrite                            " Write if modified.
set autowriteall                         " Write if modified on buffer change.
set autoindent                           " Copy indent from current line to new line.
set ignorecase                           " Ignore case on search.
set smartcase                            " Search by case smartly.
set nolazyredraw                         " Disable lazy redraw on screen when using macros.
set ttyfast                              " Assume fast terminal.
set undofile                             " Enable undofile.
set viminfo+=n~/.vim/viminfo             " Set viminfo file path.
set undodir=~/.vim/undodir               " Set undofile directory.

set mouse=a                              " Enable mouse.
set shortmess+=I                         " Disable startup message.
set shortmess-=S                         " Count number of search result matches.
set showtabline=0                        " Disable tab bar.
set updatetime=1500                      " Set duration for cursor hold event.
set synmaxcol=500                        " Maximum column in which to search for syntax items.
set fillchars=                           " Set split window margin fill to none.
set laststatus=0                         " Disable status bar.
set linespace=3                          " Set line spaces.
set guiheadroom=0                        " Disable headroom on window maximize.
set history=50                           " Keep 50 lines of command line history.
set clipboard=unnamed                    " Use clipboard as default register.
set backspace=indent,eol,start           " Enable backspacing.
set formatoptions-=t                     " Do not auto wrap text when typing.
set complete=.,w,b,u                     " Set our desired autocompletion match pattern.
set encoding=utf-8                       " Set UTF-8 encoding.
set scrolloff=3                          " Set vertical scroll headroom.
set sidescroll=3                         " Set horizontal column scroll.
set sidescrolloff=10                     " Set horizontal scroll headroom.
set foldcolumn=2                         " Set fold column width to 2.

set tabstop=2 softtabstop=0 shiftwidth=2 smarttab expandtab       " Set spaces as default.
set listchars=eol,tab:>·,trail:~,extends:>,precedes:<,space:␣   " Set hidden character identifiers.


"----------------Visuals----------------"

syntax enable                            " Enable syntax highlighting.
colorscheme fluid                        " Set color scheme.


"---------------Functions---------------"

" Ansible Check
function! AnsibleCheck()
  :exe 'Notify(''ansible-playbook --syntax-check ' . expand('%') . ' 2>&1'')' | :e
endfunction

" Typography Format
function! TypographyFormat()
  :silent! %s/\(^\|\s\|\w\)\zs--\ze\($\|\s\|\w\)//g | silent! %s/\(^\|\s\|\w\)\zs---\ze\($\|\s\|\w\)/—/g
  :silent! %s/ '//g | silent! %s/' /’ /g | :silent! %s/^'/‘/g | silent! %s/'$/’/g
  :silent! %s/ "//g | silent! %s/" /” /g | :silent! %s/^"/“/g | silent! %s/"$/”/g
  :silent! %s/\S\@='\S@!//g | :silent! %s/\S\@<='\S\@=/’/g
  :silent! %s/\S\@="\S@!//g | :silent! %s/\S\@<="\S\@=/”/g
endfunction


"---------------Shortcuts---------------"

" Edit shortcuts
nmap <leader>ev :tabedit ~/.vim/vimrc<cr>
nmap <leader>eh :tabedit ~/.vim/post-save-hook<cr>

" Show key mappings
nmap <leader>mn :nmap<cr>
nmap <leader>mv :vmap<cr>
nmap <leader>mi :imap<cr>
nmap <leader>mc :command<cr>

" Search documentation under cursor
nmap <leader>ds :exe ':term ++hidden ++close recoll -q ' . '' . expand('<cword>') . ''<cr>
nmap <leader>dt :exe ':term dict -h localhost -d dict-moby-thesaurus-latest ' . expand('<cword>')<cr>

" Search for file containing word under cursor
nmap <silent> <leader>ag :Ag <C-R><C-W><cr>

" View function documentation
nmap <leader>dp :call fzf#run({'options': ['--preview', 'echo doc {} \| psysh \| fold --spaces --width 80'], 'source': "psysh-doc", 'sink': ':term psysh-doc', 'down': '50%'})<cr>

" Jump to line
nmap <leader>jl :norm yaW<cr> \| :Jump<cr>

" Load and save sessions
nmap <leader>sl :source ~/.vim/sessions/session.vim \| :source ~/.vim/vimrc<cr>:Notify('printf "Last saved session loaded."')<cr>
nmap <leader>ss :silent! exe "!~/.vim/hooks/pre-session-save" \| :mksession! ~/.vim/sessions/session.vim \| :redraw!<cr>:Notify('printf "Current session saved."')<cr>

" Toggle Spell Check
nmap <leader>sp :set spell!<cr>

" Sort lines by length
vnoremap <leader>sn !perl -e 'print sort { length($a) <=> length($b) } <>'<cr>

" Switch between tabs and spaces
nmap <leader>ses :set tabstop=2 softtabstop=0 shiftwidth=2 smarttab expandtab<cr>
nmap <leader>set :set tabstop=2 softtabstop=0 shiftwidth=2 smarttab noexpandtab<cr>

" Close buffer and window
nmap <leader>qq :bd<cr>
nmap <leader>qa :silent! %bd!\|e#\|bd#<cr>
nmap <leader>qw <C-w>c<cr>

" Re-indent entire file
nmap <leader>re gg=G<C-o><C-o>

" Reset all settings and source configuration.
nmap <leader>ra :set all& \| :source ~/.vim/vimrc \| :packloadall \|:e<cr>:Notify('printf "Settings cleared and reloaded."')<cr>

" Remove trailing whitespace
nmap <leader>rs :%s/\s\+$//e

" Dump output of command to new buffer
nmap <leader>rr :enew \| .!<space>

" Remove duplicate lines
vnoremap <leader>rd !awk '\!visited[$0]++'<cr>

" Toggle color column
nmap <leader>cv :exe "set colorcolumn=" . (&colorcolumn == "" ? "80" : "")<cr>

" Toggle cursor column
nmap <leader>cx :set cursorcolumn!<cr>

" Transliterate special characters to ascii
nmap <leader>ce :silent! %s/–/--/g<cr> \| :silent! %s//---/g<cr> \| my \| :%!iconv -f utf-8 -t ascii//translit<cr>'y

" Use typographic characters
nmap <leader>cl :call TypographyFormat()<cr>

" Toggle line numbers
nmap <leader>cn :set number!<cr>
nmap <leader>cr :set relativenumber!<cr>

" Move line up or down
nmap <leader>ck ddkkpk<cr>
nmap <leader>cj ddpk<cr>

" Justify columns
vnoremap <leader>ct !column -t -o' '<cr>

" Fold text
vnoremap <leader>cf <S-J><S-v> \| !fold --spaces --width<space>80

" Go to scratchpad of specified filetype
noremap <leader>cs :w !cat > $HOME/.cache/vim-scratchpad<cr>:e +setf\ <space>$HOME/.cache/vim-scratchpad<C-left><left>

" File open mappings
nmap <Tab> :Buffers<cr>
nmap <leader>ov :Lines<cr>
nmap <leader>ob :BLines<cr>
nmap <leader>ol :Locate<space>
nmap <leader>ot :exe '!$TERMINAL -cd ' . expand('%:p:h') . ' > /dev/null 2>&1 &'<cr><cr>
nmap <leader>of :call fzf#run({'options': [], 'source': "cat $FZF_FILE_MARKS", 'sink': 'e', 'window': { 'xoffset': 0, 'yoffset': 1, 'width': 1, 'height': 0.5 }})<cr><down>
nmap <leader>od :call fzf#run({'options': ['--preview', 'ls {}'], 'source': "cut -d' ' -f3 $FZF_DIRECTORY_MARKS", 'sink': 'cd', 'window': { 'xoffset': 0, 'yoffset': 1, 'width': 1, 'height': 0.5 }})<cr><down>
nmap <leader>oo :call fzf#run({'options': ['--preview', 'highlight -O ansi --force {}'], 'source': 'rg --files --hidden \|\| find . -type f -printf "%P\n"', 'sink': 'e', 'window': { 'xoffset': 0, 'yoffset': 1, 'width': 1, 'height': 0.5 }})<cr><down>
nmap <leader>oa :call fzf#run({'options': ['--preview', 'ls {}'], 'source': "find $HOME -type d -maxdepth 6", 'sink': 'cd', 'window': { 'xoffset': 0, 'yoffset': 1, 'width': 1, 'height': 0.5 }})<cr><down>

" Mappings for nnn
nmap <leader>nm :NnnPicker<cr>
nmap <leader>nn :NnnPicker '%:p:h'<cr>

" Exit incremental search
nmap <Esc><Esc> :nohl<cr>

" Disable Ex Mode
nnoremap Q <Nop>

" Split window mappings
nmap <Bslash> :vsplit<cr>
nmap <C-Bslash> :split<cr>
nmap <C-j> :resize +5<cr>
nmap <C-k> :resize -5<cr>
nmap <C-h> :vertical resize +5<cr>
nmap <C-l> :vertical resize -5<cr>

" Inverse Tabs
inoremap <S-Tab> <C-d>

" Retain visual selection when tabbing
vnoremap < <gv
vnoremap > >gv

" Prevent cursor from jumping in visual select context https://ddrscott.github.io/blog/2016/yank-without-jank/
vnoremap <expr>y "my\"" . v:register . "y`y"


"------------------Snippets-------------------"

nnoremap ,awk         :-1read $HOME/.vim/snippets/skeleton.awk<cr>
nnoremap ,nix-shell   :-1read $HOME/.vim/snippets/shell.nix<cr>2jf"a
nnoremap ,nix-module  :-1read $HOME/.vim/snippets/module.nix<cr>4jf"a
nnoremap ,nix-package :-1read $HOME/.vim/snippets/package.nix<cr>3jf"a
nnoremap ,html        :-1read $HOME/.vim/snippets/skeleton.html<cr>3jwf>a


"---------------Plugin Settings---------------"

let g:gundo_prefer_python3=1                                                                " Use python3 to restore gundo functionality.
let g:netrw_banner=0                                                                        " Disable netrw banner.
let g:nnn#command = 'nnn -H'                                                                " Override default command.
let g:nnn#set_default_mappings = 0                                                          " Disable default mappings.
let g:nnn#layout = 'new'                                                                    " Opens the nnn window in a split.
let g:nnn#layout = { 'left': '~20%' }                                                       " Left 20% of the window.
let g:fzf_layout = { 'window': { 'xoffset': 0, 'yoffset': 1, 'width': 1, 'height': 0.5 } }  " Set fzf window layout,


"-------------------Scripts-------------------"

" https://vi.stackexchange.com/questions/14300/vim-how-to-send-entire-line-to-a-buffer-of-type-terminal
function s:repl(start, end, language)
  let g:terminal_buffer = get(g:, 'terminal_buffer', -1)
  if g:terminal_buffer == -1 || !bufexists(g:terminal_buffer)
    terminal ++rows=10
    let g:terminal_buffer = bufnr('')
    call term_sendkeys(g:terminal_buffer, a:language . "; exit" . "\<cr>")
    wincmd p
  elseif bufwinnr(g:terminal_buffer) == -1
    exe 'sbuffer ' . g:terminal_buffer
    wincmd p
  endif
  call term_sendkeys(g:terminal_buffer, join(getline(a:start, a:end), "\<cr>") . " " . "\<cr>")
endfunction

" Jump to line and column in the format 123:13
function s:cursor(selection)
  wincmd p
  let g:cursor_request = split(a:selection, ":")
  call cursor(g:cursor_request[0], g:cursor_request[1])
endfunction

" Notify
function s:notify(command)
  call popup_notification(systemlist(a:command), { 'pos': 'topright', 'col': 9999, 'time' : 600000, 'highlight': 'Normal' })
endfunction


"-------------------Commands-------------------"

command! -nargs=? -range Jump   call s:cursor(@*)
command! -nargs=? -range REPL   call s:repl(<line1>, <line2>, <f-args>)
command! -nargs=1 -range Notify call s:notify(<args>)
command! Term term ++noclose


"----------------Autorun----------------"

augroup AutoCommands

  " Clear auto commands.
  autocmd!

  " Source reloads.
  autocmd BufWritePost .vimrc,vimrc source % | Notify('printf "Configuration sourced."')

  " Linting file type post write commands.
  autocmd FileType markdown         autocmd! BufWritePost <buffer> :only | :term ++rows=10 sh -c "cat % | vale --ext .md"
  autocmd FileType scheme           autocmd! BufWritePost <buffer> exe 'Notify(''guile -s ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType css              autocmd! BufWritePost <buffer> exe 'Notify(''prettier --write --parser css ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType html             autocmd! BufWritePost <buffer> exe 'Notify(''prettier --write --parser html ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType python           autocmd! BufWritePost <buffer> exe 'Notify(''ruff --no-cache ' . expand('%') . ' 2>&1 && black ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType nim              autocmd! BufWritePost <buffer> exe 'Notify(''nimpretty ' . expand('%') . ' 2>&1 && printf "Nim OK: ' . expand('%') . '"'')' | :e
  autocmd FileType rust             autocmd! BufWritePost <buffer> exe 'Notify(''rustfmt ' . expand('%') . ' 2>&1 && printf "rustfmt OK: ' . expand('%') . '"'')' | :e
  autocmd FileType json             autocmd! BufWritePost <buffer> exe 'Notify(''jsonlint -i ' . expand('%') . ' 2>&1 && printf "JSON OK: ' . expand('%') . '"'')' | :e
  autocmd FileType ruby             autocmd! BufWritePost <buffer> exe 'Notify(''rubocop --fix-layout ' . expand('%') . ' 2>&1 && rubocop ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType javascript       autocmd! BufWritePost <buffer> exe 'Notify(''eslint --fix ' . expand('%') . ' 2>&1 && printf "JavaScript OK: '. expand('%') . '"'')' | :e
  autocmd FileType elixir           autocmd! BufWritePost <buffer> exe 'Notify(''mix format ' . expand('%') . ' 2>&1 && printf "Elixir Format OK: ' . expand('%') . '"'')' | :e
  autocmd FileType haskell          autocmd! BufWritePost <buffer> exe 'Notify(''hlint ' . expand('%') . ' 2>&1 && brittany --write-mode inplace ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType bash,sh          autocmd! BufWritePost <buffer> exe 'Notify(''shellcheck -x --exclude=SC1090,SC1091 ' . expand('%') . ' 2>&1 && printf "Shellcheck OK: ' . expand('%') . '"'')'
  autocmd FileType xml,xslt,rng,xsd autocmd! BufWritePost <buffer> exe 'Notify(''xmllint --pretty 1 ' . expand('%') . ' --output ' . expand('%') . ' 2>&1 && printf "XML OK: ' . expand('%') . '"'')' | :e
  autocmd FileType go               autocmd! BufWritePost <buffer> exe 'Notify(''gofmt -w -s -e ' . expand('%') . ' 2>&1 && go vet ' . expand('%') . ' 2>&1 && printf "Go Format OK: ' . expand('%') . '"'')' | :e
  autocmd FileType nix              autocmd! BufWritePost <buffer> exe 'Notify(''nix-linter ' . expand('%') . ' 2>&1 && printf "Nix Lint OK: ' . expand('%') . '"' . ' && nixfmt ' . expand('%') . ' 2>&1' . ''')' | :e
  autocmd FileType php              autocmd! BufWritePost <buffer> exe 'Notify(''phpcbf ' . expand('%') . ' 2>&1 && phpstan --no-progress --no-ansi --no-interaction analyze --level max ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType tex              autocmd! BufWritePost <buffer> exe 'Notify(''latexindent ' . expand('%') . ' 2>&1 && printf "LaTeX OK: ' . expand('%') . '"'')' | :e | :only | :term ++close ++rows=10 latex-compile %
  autocmd FileType bindzone         autocmd! BufWritePost <buffer> exe 'Notify(''file="' . expand('%') . '" && named-checkzone "$(head --lines=1 "$file" | cut --delimiter=" " --fields=2 | perl -ple "chop")" $file'')' | :e
  autocmd FileType awk              autocmd! BufWritePost <buffer> exe 'Notify(''awk -g -f ' . expand('%') . ' 2>&1 && awk -o- -f ' . expand('%') . ' | sponge ' . expand('%') . ' && printf "AWK OK: ' . expand('%') . '"'')' | :e
  autocmd FileType yaml             autocmd! BufWritePost <buffer> exe 'Notify(''yaml round-trip --indent 2 --save ' . expand('%') . ' 2>&1 && yamllint -s ' . expand('%') . ' 2>&1 && printf "YAML OK: ' . expand('%') . '"'')' | :e
  autocmd FileType typescript       autocmd! BufWritePost <buffer> exe 'Notify(''deno fmt ' . expand('%') . ' 2>&1 && NO_COLOR=true deno lint ' . expand('%') . ' 2>&1'')' | :e | :only | :term ++rows=10 deno run --allow-all --location https://example.com/ %
  autocmd FileType c                autocmd! BufWritePost <buffer> exe 'Notify(''clang-format -i ' . expand('%') . ' 2>&1 && printf "Clang Format OK: ' . expand('%') . '\n"' . ' && gcc -Wall -Wpedantic -Werror -fsyntax-only ' . expand('%') . ' 2>&1'')' | :e
  autocmd FileType sql              autocmd! BufWritePost <buffer> exe 'Notify(''sqlint ' . expand('%') . ' 2>&1 && pg_format --type-case 2 --inplace ' . expand('%') . ' 2>&1 && sqlfluff lint --exclude-rules L003,L016 --dialect postgres ' . expand('%') . ' 2>&1 && printf "SQL OK: ' . expand('%') . '"'')' | :e

  " Linting extension post write commands.
  autocmd BufWritePost $HOME/.config/chromexup/config.ini exe 'Notify(''chromexup 2>&1'')'
  autocmd BufWritePost rc.lua                             exe 'Notify(''awesome -k 2>&1'')'
  autocmd BufWritePost quotes,*.fortune                   exe 'Notify(''strfile ' . expand('%') . ''')'
  autocmd BufWritePost *.doas                             exe 'Notify(''doas -C ' . expand('%') . ' 2>&1 && printf "doas OK: ' . expand('%') . '"'')'
  autocmd BufWritePost Xresources                         exe 'Notify(''xrdb ~/.config/X11/Xresources ' . '2>&1 && printf "Reloading Xresources: ' . expand('%') . '"'')'
  autocmd BufWritePost Makefile                           exe 'Notify(''make --dry-run --warn-undefined-variables ' . '2>&1 && printf "\nMake OK: ' . expand('%') . '"'')'
  autocmd BufWritePost *.nft                              exe 'Notify(''doas nft --check --file ' . expand('%') . ' 2>&1 && printf "nftables OK: ' . expand('%') . '"'')'
  autocmd BufWritePost *.desktop                          exe 'Notify(''desktop-file-validate ' . expand('%') . ' 2>&1 && printf "Desktop File OK: ' . expand('%') . '"'')'
  autocmd BufWritePost *.service                          exe 'Notify(''systemd-analyze verify --user ' . expand('%') . ' 2>&1 && printf "Systemd Service File OK: ' . expand('%') . '"'')'

  " File type function under cursor lookups.
  autocmd FileType go     noremap <buffer> <leader>df :exe ':term ++rows=10 go doc ' . expand('<cexpr>')<cr>
  autocmd FileType elixir noremap <buffer> <leader>df :exe ':term ++rows=10 sh -c "echo ''h(' . expand('<cexpr>') . ')'' \| iex"'<cr>

  " REPL commands.
  autocmd FileType bash       noremap <buffer> <leader>cc :REPL bash -x<cr>
  autocmd FileType elixir     noremap <buffer> <leader>cc :REPL iex<cr>
  autocmd FileType go         noremap <buffer> <leader>cc :REPL gore<cr>
  autocmd FileType javascript noremap <buffer> <leader>cc :REPL node<cr>
  autocmd FileType lua        noremap <buffer> <leader>cc :REPL lua<cr>
  autocmd FileType nix        noremap <buffer> <leader>cc :REPL nix repl<cr>
  autocmd FileType perl       noremap <buffer> <leader>cc :REPL perl -de0<cr>
  autocmd FileType php        noremap <buffer> <leader>cc :REPL psysh<cr>
  autocmd FileType python     noremap <buffer> <leader>cc :REPL python<cr>
  autocmd FileType rust       noremap <buffer> <leader>cc :REPL evcxr<cr>
  autocmd FileType scheme     noremap <buffer> <leader>cc :REPL guile<cr>
  autocmd FileType sh         noremap <buffer> <leader>cc :REPL dash -x<cr>
  autocmd FileType typescript noremap <buffer> <leader>cc :REPL deno<cr>
  autocmd FileType awk        noremap <buffer> <leader>cc :term ++rows=10 ++close awk -f %<cr>

  " Format using visual select + gq.
  autocmd FileType nix             set formatprg=nixfmt
  autocmd FileType sh              set formatprg=shfmt\ -
  autocmd FileType lua             set formatprg=lua-format
  autocmd FileType perl            set formatprg=perltidy\ -
  autocmd FileType typescriptreact set formatprg=deno\ fmt\ -
  autocmd FileType typescript      set formatprg=deno\ fmt\ -
  autocmd FileType elixir          set formatprg=mix\ format\ -
  autocmd FileType c               set formatprg=clang-format\ -
  autocmd FileType python          set formatprg=black\ --quiet\ -
  autocmd FileType scheme          set formatprg=emacs-batch-indent\ scheme
  autocmd FileType css             set formatprg=prettier\ --parser\ css\ --stdin-filepath\ %
  autocmd FileType html            set formatprg=prettier\ --parser\ html\ --stdin-filepath\ %
  autocmd FileType markdown        set formatprg=prettier\ --parser\ markdown\ --stdin-filepath\ %
  autocmd FileType javascript      set formatprg=swc\ compile\ --filename\ %\ \|\ tail\ --lines\ +2
  autocmd FileType ruby            set formatprg=rubocop\ --autocorrect\ --stderr\ --stdin\ %\ 2>\ \/dev\/null

  " Format by extension using visual select + gq
  autocmd BufRead,BufNewFile *.mathml.xml set formatprg=latexmlmath\ -

  " Set file types by extension
  autocmd BufRead,BufNewFile *.nims       set filetype=nim
  autocmd BufRead,BufNewFile *.rasi       set filetype=css
  autocmd BufRead,BufNewFile *.doas       set filetype=conf
  autocmd BufRead,BufNewFile *.nft        set filetype=nftables
  autocmd BufRead,BufNewFile *.blade.php  set filetype=php

  " Clear notification on cursor movement.
  autocmd CursorMoved * silent! call popup_clear()

  " Automatically remove trailing white space on save.
  autocmd BufWritePre * %s/\s\+$//e

  " Automatically save file on insert and idle.
  autocmd InsertLeave,CursorHold * silent! write
    \| silent! exe "!~/.vim/hooks/post-save > /dev/null 2>&1 &"
    \| :echo expand('%:t') '[filetype=' . &filetype . ']'

augroup END