aboutsummaryrefslogtreecommitdiff
path: root/vim/vimrc
blob: 1a4c916d65c22b36e98b9da59b87f962d0c2418a (plain) (blame)
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
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
" Don't make any effort to be compatible with vi, use more sensible settings
set nocompatible

" Use UTF-8 by default wherever possible, including in this file
if has('multi_byte')
  set encoding=utf-8
  scriptencoding utf-8
endif

" Load configuration files from ~/.vim/config or its analogue, before Pathogen
" loads all its directories into 'runtimepath'
runtime! config/*.vim

" If our version isn't ancient and Pathogen is available, call it to load all
" the plugins in .vim/bundle; these are saved as submodules
if v:version >= 701
  silent! call pathogen#infect()
  silent! call pathogen#helptags()
endif

" Load plugins for file types
if has('autocmd')
  filetype plugin on
endif

" Options dependent on the syntax feature
if has('syntax')

  " Use syntax highlighting with 100 lines of context
  silent! syntax enable
  silent! syntax sync minlines=100

  " Use my custom color scheme if possible, otherwise I'm happy with whatever
  " the default is, and it usually cares about my background
  set background=dark
  silent! colorscheme sahara
endif

" Use all ancestors of current directory for :find
if has('file_in_path')
  set path=**
endif

" Command-line based features
if has('cmdline_info')

  " Show my current position in the status bar
  set ruler
  " Show the keystrokes being entered in the screen
  set showcmd

  " Show the mode we're using if not normal mode (e.g. --INSERT--)
  set showmode
endif

" Don't try to complete strings from included files, just use the strings in
" the open buffers; I'll open the file if I want to complete from it
set complete-=i

" Try Mac line-endings if UNIX or DOS don't make sense; this has never
" happened to me but who knows, it might one day
set fileformats+=mac

" Don't join lines with two spaces at the end of sentences; I don't two-space,
" despite the noble Steve Losh's exhortations
set nojoinspaces

" Don't jump my screen around when I join lines, keep my cursor in the same
" place; this is done by dropping a mark first and then immediately returning
" to it; note that it wipes out your z mark, if you happen to use it
nnoremap J mzJ`z

" If we can, add j to the format options to get rid of comment leaders when
" joining lines
if v:version > 703 || v:version == 703 && has('patch541')
  set formatoptions+=j
endif

"
" Quick way to toggle flags in 'formatoptions' that I often want to change;
" specifically:
"
" a - Automatically format paragraphs, reapplying the wrap on every text
"     insertion or deletion; sometimes I want this and sometimes I
"     don't, it particularly varies when typing prose in Markdown that
"     includes headings and code
" c - Automatically wrap comments at 'textwidth' (which I allow the filetypes
"     to set for me)
" t - Automatically wrap text at 'textwidth' (as above)
"
" So I just have to type e.g. \a to toggle the auto-format flag on and off;
" very handy
"
if has('eval')
  function! ToggleFormatFlag(flag)
    let l:operation = (&formatoptions =~ a:flag) ? '-=' : '+='
    silent! exec 'setlocal formatoptions' . l:operation . a:flag
    setlocal formatoptions?
  endfunction
  nnoremap <silent> <leader>a :<C-U>call ToggleFormatFlag('a')<CR>
  nnoremap <silent> <leader>c :<C-U>call ToggleFormatFlag('c')<CR>
  nnoremap <silent> <leader>t :<C-U>call ToggleFormatFlag('t')<CR>
endif

" Strip trailing whitespace with \x
if has('eval')
  function! StripTrailingWhitespace()
    let l:search = @/
    %substitute/\s\+$//e
    let @/ = l:search
    nohlsearch
  endfunction
  nnoremap <silent> <leader>x :<C-U>call StripTrailingWhitespace()<CR>
endif

" Keep plenty of command and search history, because disk space is cheap
set history=2000

" Don't show whitespace characters or end-of-line characters visually by
" default, but make \l toggle between them
set nolist
nnoremap <leader>l :setlocal list!<CR>

" Try to run the version of matchit.vim included in the distribution, if there
" is one; extends % to match more than it does by default
silent! runtime macros/matchit.vim

" Match all forms of brackets in pairs (including angle brackets)
set matchpairs=(:),{:},[:],<:>

" Don't show the Vim startup message, I have registered Vim and donated to
" Uganda
set shortmess+=I

" Let me backspace over pretty much anything, even if it's not text I inserted
" in the current session
set backspace=indent,eol,start

" Don't use modelines at all, they're apparently potential security problems
" and I've never used them anyway
set nomodeline

" Don't assume a number with a leading zero is octal; it's far more likely a
" zero-padded decimal, so increment and decrement with ^A and ^X on that basis
set nrformats-=octal

" Always tell me the number of lines changed by a command
set report=0

" Always use forward slashes, I very seldom need to use Vim on Windows for
" more than scratch space anyway
set shellslash

" Don't show line numbers by default, but \n toggles them
set nonumber
nnoremap <leader>n :setlocal number!<CR>

" Start paste mode with F10 to prevent console Vim from confusing a swathe of
" pre-formatted pasted text with actual keyboard input, and thereby attempting
" to indent it inappropriately. If unimpaired.vim is available, it's generally
" nicer to use yo or yO.
set nopaste
set pastetoggle=<F10>

" If the Vim buffer for a file doesn't have any changes and Vim detects the
" file has been altered, quietly update it
set autoread

" Save a file automatically if I change buffers or perform operations with the
" argument list; this is particularly helpful for me as I don't use 'hidden'
set autowrite

" Allow the cursor to get to the top or bottom of the screen before scrolling
" vertically, but set a reasonably wide gutter for scrolling horizontally; no
" particular reason, just suits me better
set scrolloff=0
set sidescrolloff=16

" Configure spell checking features, if available
if has('spell')

  " Don't check spelling by default, but bind \s to toggle this
  set nospell
  nnoremap <leader>s :setlocal spell!<CR>

  " Use New Zealand English for spelling by default (it's almost identical
  " to British English), but bind \u to switch to US English and \z to
  " switch back
  set spelllang=en_nz
  nnoremap <leader>u :setlocal spelllang=en_us<CR>
  nnoremap <leader>z :setlocal spelllang=en_nz<CR>
endif

" Don't keep .viminfo information for files in temporary directories or shared
" memory filesystems; this is because they're used as scratch spaces for tools
" like sudoedit(8) and pass(1) and hence could present a security problem
if has('viminfo') && has('autocmd')
  augroup viminfoskip
    autocmd!
    silent! autocmd BufNewFile,BufReadPre
        \ /tmp/*,$TMPDIR/*,$TMP/*,$TEMP/*,*/shm/*
        \ setlocal viminfo=
  augroup END
endif

" Preserve the flags for a pattern when repeating a substitution with &; I don't
" really understand why this isn't a default, but there it is
nnoremap & :&&<CR>
vnoremap & :&&<CR>

" Don't bother about checking whether Escape is being used as a means to enter
" a Meta-key combination, just register Escape immediately
set noesckeys

" Don't bother drawing the screen while executing macros or other automated or
" scripted processes, just draw the screen as it is when the operation
" completes
set lazyredraw

" Improve redrawing smoothness by assuming that my terminal is reasonably
" fast
set ttyfast

" Never use any kind of bell, visual or not
set visualbell t_vb=

" Require less than one second between keys for mappings to work correctly
set timeout
set timeoutlen=1000

" Require less than a twentieth of a second between keys for key codes to work
" correctly; I don't use Escape as a meta key anyway
set ttimeout
set ttimeoutlen=50

" Tolerate typos like :Wq, :Q, or :Qa and do what I mean, including any
" arguments or modifiers; I fat-finger these commands a lot because I type
" them so rapidly, and they don't correspond to any other commands I use
if has('user_commands')
  command! -bang -complete=file -nargs=? E e<bang> <args>
  command! -bang -complete=file -nargs=? W w<bang> <args>
  command! -bang -complete=file -nargs=? WQ wq<bang> <args>
  command! -bang -complete=file -nargs=? Wq wq<bang> <args>
  command! -bang Q q<bang>
  command! -bang Qa qa<bang>
  command! -bang QA qa<bang>
  command! -bang Wa wa<bang>
  command! -bang WA wa<bang>
endif

" When in visual block mode, let me move the cursor anywhere in the buffer;
" don't restrict me only to regions with text
if has('virtualedit')
  set virtualedit+=block
endif

" Configuration for the command completion feature; rather than merely cycling
" through possible completions with Tab, show them above the command line
if has('wildmenu')

  " Use the wild menu, both completing and showing all possible completions
  " with a single Tab press, just as I've configured Bash to do
  set wildmenu
  set wildmode=longest:list

  " Don't complete certain files that I'm not likely to want to manipulate
  " from within Vim:
  if has('wildignore')
    set wildignore+=*.a,*.o
    set wildignore+=*.bmp,*.gif,*.ico,*.jpg,*.png
    set wildignore+=.DS_Store,.git,.hg,.svn
    set wildignore+=*~,*.swp,*.tmp
  endif

  " Complete files without case sensitivity, if the option is available
  if exists('&wildignorecase')
    set wildignorecase
  endif
endif

" Configuration for window features
if has('windows')

  " Show the status in a distinct bar above the command line only if there's
  " more than one window on the screen or in the current tab
  set laststatus=1

  " Don't resize windows we're not splitting (Tmux-like; think Mondrian)
  set noequalalways

  " New split windows appear below or to the right of the existing window,
  " not above or to the left per the default
  set splitbelow
  if has('vertsplit')
    set splitright
  endif

  " Only show the tab bar if there's more than one tab
  if exists('&showtabline')
    set showtabline=1
  endif

  " Get rid of visually noisy folding characters
  if has('folding')
    let &fillchars = 'diff: ,fold: ,vert: '
  endif
endif

" Use the tilde as an operator with motions, rather than just swapping the
" case of the character under the cursor
set tildeop

" When wrapping text, if a line is so long that not all of it can be shown on
" the screen, show as much as possible anyway; by default Vim fills the left
" column with @ symbols instead, which I don't find very helpful
set display=lastline

" Don't wrap by default, but use \w to toggle it on or off quickly
set nowrap
nnoremap <leader>w :set wrap!<CR>

" Clearly show when the start or end of the row does not correspond to the
" start and end of the line
set listchars+=precedes:<,extends:>

" Don't write the output of :make to the terminal
set shellpipe=>

" When wrapping, j and k should move by screen row, and not to the same
" column number in the previous logical line, which feels very clumsy and is
" seldom particularly helpful; you can use n| to jump to the nth column in a
" line anyway if you need to
nnoremap j gj
nnoremap k gk

" Break lines at word boundaries if possible and not simply at the last
" character that will fit on the screen, preceding the next line with three
" periods to make it obvious that it's a continuation of the previous line
if has('linebreak')
  set linebreak
  set showbreak=...
  if v:version > 704 || v:version == 704 && has('patch338')
    set breakindent
  endif

  " Bind \b to turn off linebreak and toggle the showbreak characters on and
  " off for convenience of copypasting multiple lines from terminal emulators.
  if has('eval')
    function! ToggleBreak()
      if &linebreak
        set nolinebreak
        set showbreak=
        if v:version > 704 || v:version == 704 && has('patch338')
          set nobreakindent
        endif
      else
        set linebreak
        set showbreak=...
        if v:version > 704 || v:version == 704 && has('patch338')
          set breakindent
        endif
      endif
    endfunction
    nnoremap <silent> <leader>b :<C-U>call ToggleBreak()<CR>
  endif
endif

" I really like ZZ and ZQ, so I wrote a couple more mappings; ZW forces a
" write of the current buffer, but doesn't quit, and ZA forces a write of all
" buffers but doesn't quit
nnoremap ZW :w!<CR>
nnoremap ZA :wa!<CR>

" Change and delete with C and D both cut off the remainder of the line from
" the cursor, but Y yanks the whole line, which is inconsistent (and can be
" done with yy anyway); this fixes it so it only yanks the rest of the line
nnoremap Y y$

" Allow jumping between windows and tabs to find an open instance of a given
" buffer with :sbuffer.
if v:version >= 701
  set switchbuf=useopen,usetab
else
  set switchbuf=useopen
endif

" Fedora's default environment adds a few auto commands that I don't like,
" including the 'return to previous position in buffer' one; fortunately
" they're nice enough to group the commands, so I can just clear them
if has('autocmd')
  augroup fedora
    autocmd!
  augroup END
endif

" When opening a large file, take some measures to keep things loading quickly
if has('eval') && has('autocmd')

  " Threshold is 10 MiB
  let g:bigfilesize = 10 * 1024 * 1024

  " Declare function for turning off slow options
  function! BigFileMeasures()
    let l:file = expand('<afile>')
    if getfsize(l:file) > g:bigfilesize
      setlocal nobackup
      setlocal nowritebackup
      setlocal noswapfile
      if has('persistent_undo')
        setlocal noundofile
      endif
      if exists('&synmaxcol')
        setlocal synmaxcol=256
      endif
    endif
  endfunction

  " Define autocmd for calling to check filesize
  augroup bigfilesize
    autocmd!
    autocmd BufReadPre * call BigFileMeasures()
  augroup end
endif