956923c00efce303e8b49d8966606ecc467a9aab
[profile.git] / .vimrc
1 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
2 " Multi-version vimrc compatible with version 4 and above.   vim6:set fdm=marker:
3 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
4
5 " Note that "if <condition> | call Something() | endif" syntax is unsupported
6 " in Vim 4 so we write all our functions out the long way.  It does work in
7 " autocommand definitions, however.
8
9 " Vim 4 complains if version isn't set in the configuration file.
10 version 4.0
11
12 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
13 " Handle options safe to use in version 4.  Vim 4 parses but ignores the
14 " "if version" syntax used later in this file so we don't use it.  No attempt
15 " is made to make this configuration compatible with Vim 3.
16 " Some of these settings should strictly be wrapped inside "if has()" blocks
17 " but that would cause them not to be ignored by Vim 4.
18 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
19 "{{{1
20 " No compatibility mode.
21 se nocp
22
23 " Tabstop 2.
24 se ts=2
25 " And use spaces not tabs.
26 se expandtab
27 " And << and >> indent by 2.
28 se sw=2
29 " Backspace deletes full tab width at the start of a line.
30 se smarttab
31
32 " Allow backspace to delete before start of line.
33 se bs=2
34
35 " Don't jump to the start of the line when using H, L etc.
36 se nosol
37
38 " Show the ruler.
39 se ruler
40 " Show partial commands in the ruler.
41 se showcmd
42 " And always show the status line.
43 se laststatus=2
44
45 " Use C indent style.
46 se cindent
47 se cinkeys=0{,0},0),:,!^F,o,O,e
48 se cinoptions=b1,c2
49
50 " GUI options.
51 se go=aglmr
52
53 " Don't be bugged by messages at the bottom of the screen.
54 se shm=aot
55
56 " Find as you type.
57 se incsearch
58
59 " Case-insensitive search.
60 se ignorecase
61 " But override by typing capitals.
62 se smartcase
63
64 " Look for ctags in home directory first.
65 se tags=~/.tags,./tags,tags
66
67 " Don't timeout waiting to interpet, eg, <ESC>OA as an escape code.
68 se ttimeoutlen=100
69
70 " Remember undo list for closed (but not wiped) buffers.
71 se hidden
72
73 " Use ^B to search backward when completing.
74 inoremap <C-b> <C-p>
75 " Use ^L to show matching completions but don't select one.
76 inoremap <C-l> <C-n><C-p>
77
78 " Swap jump keys.
79 nnoremap ' `
80 nnoremap ` '
81
82 " Select previous widnow.
83 nnoremap <C-w>^ <C-w>p
84 nnoremap <C-w><C-^> <C-w>p
85 "}}}1
86
87 " Find stuff.
88 if (has("win32") || has("win64")) && version >= "504"
89   se rtp=~/.vim,$VIMRUNTIME
90 endif
91
92 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
93 " Handle options only available in Vim 5 and above.
94 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
95 if version >= "500" "{{{1
96 version 5.0
97
98 " Tell Vim we use dark backgrounds in our terminals.
99 if ! has("gui_running")
100   se bg=dark
101 endif
102
103 " Allow mouse use in a terminal but only if it can work.
104 if has("xterm_clipboard")
105   se mouse=nvir
106 endif
107
108 " Update more quickly.  For use with sign highlighting as polling for
109 " CursorMove makes redrawing slow.
110 if has("signs")
111   se updatetime=500
112 endif
113
114 " Enable tab-completion prompting for commands.
115 if has("wildmenu")
116   se wildmenu
117   " Don't list object files when globbing files to load.
118   se wildignore+=*.o,*.obj
119   " So there's no need to assign them low priority.
120   se suffixes-=*.o,*.obj
121 endif
122
123 " Save sessions in UNIX format with / as file separator.  This is
124 " cross-platform.
125 if has("mksession")
126   se ssop+=unix,slash
127 endif
128
129 " How often do we need to use ^A/^X on octals?
130 se nf=hex
131
132 " Nuke any pre-existing autocommands.
133 if has("autocmd")
134   augroup Display
135   autocmd!
136   augroup Mode
137   autocmd!
138   if has("signs")
139     augroup Signs
140     autocmd!
141   endif
142   augroup StatusLine
143   autocmd!
144   augroup File
145   autocmd!
146   augroup END
147 endif
148
149 " Save the current window dimensions so we can restore them when we quit.
150 if ! exists("g:oldcols")
151   let g:oldcols=&columns
152 endif
153 if ! exists("g:oldlines")
154   let g:oldlines=&lines
155 endif
156
157 " More GUI options.  Add icon and tearoffs.
158 if has("gui")
159   se go+=i
160   se go+=t
161 endif
162
163 " Allow dynamic window resize even if we aren't in an xterm.
164 se t_WS=\e[8;%p1%d;%p2%dt
165
166 " Highlight search results.
167 if has("extra_search")
168   se hlsearch
169 endif
170
171 " Syntax highlighting.  New versions will use syn enable instead.
172 if version < "600"
173   syn on
174 endif
175
176 if has("user_commands")
177   " Catch typos.
178   command! W :w
179   command! Wq :wq
180   command! Wqa :wqa
181 endif
182
183 " Forget the Ex mode mapping.
184 map Q <NOP>
185
186 if has("autocmd")
187   " Position the compview plugin window.
188   au Display BufEnter -SearchResults- set buftype=nowrite | set nonumber | wincmd J
189 endif
190 endif "}}}1
191
192 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
193 " Handle options only available in Vim 5.2 and above.
194 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
195 if version >= "502" "{{{1
196 version 5.2
197
198 " Helper to initialise a variable.
199 fun! Prep_Var(var, value) "{{{2
200   if exists(a:var)
201     return
202   endif
203   exe "let " . a:var . "=" . a:value
204 endfun "}}}2
205
206 " Set up our variables.
207 fun! Iain_Vars() "{{{2
208   call Prep_Var("w:iainlist", 0)
209   call Prep_Var("b:iainhex", 0)
210   call Prep_Var("b:iainverbose", 0)
211   " Window Flags: (F)ocused, (I)nsert mode, Cursor (H)old.
212   call Prep_Var("b:iainstatus", "'Fih'")
213   call Prep_Var("g:iainextracolumnsnumber", "''")
214   call Prep_Var("g:iainextracolumnslist", "''")
215   call Prep_Var("b:iainalt", 0)
216   if has("signs")
217     call Prep_Var("g:marksigns", 0)
218     call Prep_Var("g:firstsign", 100)
219   endif
220   call Prep_Var("g:resizable", "''")
221 endfun "}}}2
222
223 " Show the window title.
224 fun! Show_TitleString() "{{{2
225   if bufname("") == ""
226     let l:ts1='Vim'
227   else
228     " Vim 5 doesn't have printf.
229     let l:ts1=bufnr("")
230     if l:ts1 < 10
231       let l:ts1=" " . l:ts1
232     endif
233     let l:ts1=l:ts1 . ": " . expand('%t')
234   endif
235   let l:ts1=l:ts1 . " (" .  getcwd() . ")"
236   if has("clientserver")
237     let l:ts1=l:ts1 . " " . v:servername
238   endif
239   return l:ts1
240 endfun "}}}2
241
242 " Toggle case-sensitivity.
243 fun! Invert_Case() "{{{2
244   let &ic = ! &ic
245 endfun "}}}2
246
247 " Can we resize this window?
248 fun! Can_Resize() "{{{2
249   call Iain_Vars()
250
251   if g:resizable == "0" || g:resizable == "1"
252     return g:resizable
253   endif
254
255   " Do we KNOW we can(not) resize?
256   if has("gui_running")
257     let g:resizable = 1
258   elseif $RESIZABLE == &term
259     let g:resizable = 1
260   elseif $RESIZABLE == "0"
261     let g:resizable = 0
262   else
263     " Assume we can.  Allow overriding.
264     let g:resizable = 1
265   endif
266   return g:resizable
267 endfun "}}}2
268
269 " Grow or shrink the window width.
270 fun! Resize_Columns(op, ...) "{{{2
271   if a:op == ""
272     return
273   endif
274
275   if ! Can_Resize()
276     return
277   endif
278
279   if a:0 == 0
280     " Vim 5 hardcodes the size of numbers column to 8.
281     if version >= "700" && has("linebreak")
282       let l:columns = &numberwidth
283     else
284       let l:columns = 8
285     endif
286   else
287     let l:columns = a:1
288   endif
289
290   exe "let l:resize=" . &columns . a:op . l:columns
291   let l:resize = "se columns=" . l:resize
292
293   " HACK: Inside screen there is an extra line for the status bar.  Vim
294   " manages the resize by sending an escape sequence to set the number of
295   " lines and number of columns in one action.  To do this it will first query
296   " the number of lines and then set <same number of lines> by <new number of
297   " columns>.  Because of the extra line for the status bar this results in
298   " the real terminal being shrunk by a line.  We ask for the terminal to grow
299   " by a line so it ends up actually being the same.
300   if &term =~ '^screen'
301     let l:resize = l:resize . " lines=" . (&lines + 1)
302   endif
303
304   exe l:resize
305 endfun "}}}2
306
307 " Grow or shrink the window height.
308 fun! Resize_Lines(op, lines) "{{{2
309   if a:op == ""
310     return
311   endif
312
313   if ! Can_Resize()
314     return
315   endif
316
317   exe "let l:resize=" . &lines . a:op . a:lines
318   if &term =~ '^screen'
319     let l:resize = l:resize + 1
320   endif
321   let l:resize = "se lines=" . l:resize
322
323   exe l:resize
324 endfun "}}}2
325
326 " Set extra columns depending on window status.
327 fun! Extra_Columns(extra, var, ...) "{{{2
328   " Vim 6 doesn't have winnr("$").  Determine which windows are open
329   " ourselves by using :windo to incremement a counter.  As Vim 5
330   " doesn't have :windo we require Vim 6 for this.
331   if v:version < "600"
332     return ""
333   endif
334   if ! has("windows")
335     return ""
336   endif
337
338   " Remember which window we're in.
339   let l:winnr = winnr()
340   let l:num_windows = 0
341   windo let l:num_windows = l:num_windows + 1
342   " Switch back to the window we were in.
343   exe l:winnr . "wincmd w"
344
345   call Iain_Vars()
346
347   if a:0 == 0
348     let l:condition = ""
349   else
350     let l:condition = a:1
351   endif
352
353   let l:n = 0
354   let l:i = 1
355   let l:windows = ""
356   while l:n < l:num_windows
357     " If window w exists then getwinvar(w, "&modified") will be 0 or 1.
358     if getwinvar(l:i, "&modified") =~ '^\d'
359       let l:n = l:n + 1
360
361       let l:val = 0
362       exe "if getwinvar(" . l:i . ", '" . a:var . "') " . l:condition . " | let l:val = 1 | endif"
363       if l:val
364         exe "let l:windows = '" . l:windows . ":" . l:i . "'"
365       endif
366     endif
367     let l:i = l:i + 1
368   endwhile
369
370   let l:extra = "g:iainextracolumns" . a:extra
371   exe "let l:val = " . l:extra
372   exe "let " . l:extra . " = '" . l:windows . "'"
373
374   if l:windows == l:val
375     return ""
376   endif
377
378   if l:windows == ""
379     return "-"
380   elseif l:val == ""
381     return "+"
382   endif
383 endfun "}}}2
384
385 " Toggle number display.
386 fun! Number(resize) "{{{2
387   call Iain_Vars()
388   let &number = ! &number
389
390   " Ensure we keep track of any extra columns even if we aren't resizing.
391   " This prevents confusion when number is set at startup.
392   let l:extra = Extra_Columns("number", "&number")
393
394   if a:resize
395     call Resize_Columns(l:extra)
396   endif
397 endfun "}}}2
398
399 " Restore window size.
400 if has("autocmd") && ! has("gui_running")
401   au Display VimLeave * if exists("g:oldcols") | call Resize_Columns("-", (&columns - g:oldcols)) | endif
402   au Display VimLeave * if exists("g:oldlines") | call Resize_Lines("-", (&lines - g:oldlines)) | endif
403 endif
404
405 " Map Makefile mode.
406 if has("autocmd")
407   au Mode BufEnter * if &ft == "make" | call MakeMode_map() | endif
408   au Mode BufLeave * if &ft == "make" | call MakeMode_unmap() | endif
409 endif
410
411 " Entering Make mode.
412 fun! MakeMode_map() "{{{2
413   call Iain_Vars()
414   let w:iainlist=1
415   call Cycle_List()
416   set ts=8
417   set noexpandtab
418 endfun "}}}2
419
420 " Leaving Make mode.
421 fun! MakeMode_unmap() "{{{2
422   call Cycle_List()
423   set ts=2
424   set expandtab
425 endfun "}}}2
426
427 " Function to create mappings with either a hardcoded \ or <Leader>.
428 fun! Mapping(keysequence, mapping, ...) "{{{2
429   if version < "600"
430     let l:args = "\\" . a:keysequence . " " . a:mapping . ":<CR>"
431   else
432     let l:args = "<silent> <Leader>" . a:keysequence . " " . a:mapping
433   endif
434   if a:0 == 0
435     " General mapping.
436     exec "map " . l:args
437   else
438     " Specific mapping(s).
439     let l:i = 1
440     while l:i <= a:0
441       exec "let l:map = a:" . l:i . " . \"map\""
442       exec l:map . " " . l:args
443       let l:i = l:i + 1
444     endwhile
445   endif
446 endfun "}}}2
447
448 " Use - and = to create underlines.
449 call Mapping("-", "yyp:s/./-/g<CR>:let @/=''<CR>")
450 call Mapping("=", "yyp:s/./=/g<CR>:let @/=''<CR>")
451
452 fun! Tab_Width(width) "{{{2
453   exec "set sw=" . a:width
454   exec "set ts=" . a:width
455 endfun "}}}2
456
457 " Set 2-column tabs with \2.
458 call Mapping("2", ":call Tab_Width(2)<CR>")
459 " Set 4-column tabs with \4.
460 call Mapping("4", ":call Tab_Width(4)<CR>")
461 " Set 8-column tabs with \8.
462 call Mapping("8", ":call Tab_Width(8)<CR>")
463 " Set 16-column tabs with \6.
464 call Mapping("6", ":call Tab_Width(16)<CR>")
465 " Set 32-column tabs with \3.
466 call Mapping("3", ":call Tab_Width(32)<CR>")
467 " Toggle paste mode with \p.
468 call Mapping("p", ":se paste!<CR>")
469 " Swap case-sensitivity with \c.
470 call Mapping("C", ":call Invert_Case()<CR>")
471 " Change number mode with \n.
472 call Mapping("n", ":call Number(1)<CR>")
473 " Expand or shrink window size with \> and \<.
474 call Mapping(">", ":call Resize_Columns('+')<CR>")
475 call Mapping("<", ":call Resize_Columns('-')<CR>")
476 " Clear search pattern with \/.
477 call Mapping("/", ":let @/=\"\"<CR>")
478 " Toggle alternate buffer name with \#.
479 call Mapping("#", ":call Cycle_Alt()<CR>")
480
481 " Set graphical window title.
482 if has("win32") || has("win64")
483   " Windows taskbar entries are probably too small to show full titles.
484   se titlestring=%t
485 else
486   se titlestring=%{Show_TitleString()}
487 endif
488
489 " Vim tip 99: What's the highlighting group under the cursor?
490 call Mapping("h", ":echo \"hi<\" . synIDattr(synID(line(\".\"),col(\".\"),1),\"name\") . '> trans<' . synIDattr(synID(line(\".\"),col(\".\"),0),\"name\") . \"> lo<\" . synIDattr(synIDtrans(synID(line(\".\"),col(\".\"),1)),\"name\") . \">\"<CR>")
491
492 fun! Uncluttered_Buffer() "{{{2
493   if exists("uncluttered_buffer")
494     if uncluttered_buffer == 1
495       return 1
496     endif
497   endif
498
499   if version >= "600"
500     if &buftype != ''
501       return 1
502     endif
503   endif
504
505   if &ft == 'perforce'
506     return 1
507   endif
508
509   if &ft == 'svn'
510     return 1
511   endif
512
513   if &ft == 'gitcommit'
514     return 1
515   endif
516
517   return 0
518 endfun "}}}2
519
520 fun! Startup_Resize() "{{{2
521   let l:columns = 0
522
523   " Resize for numbers.
524   if &number
525     if version >= "700" && has("linebreak")
526       let l:columns = &numberwidth
527     else
528       let l:columns = 8
529     endif
530   endif
531
532   " Resize for signs.
533   if has("signs")
534     if g:marksigns
535       if version >= "600"
536         let l:columns = l:columns + 2
537       endif
538     endif
539   endif
540
541   if g:oldcols < (80 + l:columns)
542     call Resize_Columns("+", l:columns)
543   endif
544 endfun "}}}2
545
546 " Change status bar colour when various things happen.
547 " Flags: H/h: Cursor held/moved.
548 "        F/f: Focus gained/lost.
549 "        I/i: Insert mode entered/left.
550 fun! Highlight_StatusLine(flag) "{{{2
551   if ! has("statusline")
552     return
553   endif
554   " Get current status.
555   call Iain_Vars()
556
557   " Change the status based on the flag.  XXX: Does Vim let us to do flags?
558   let l:ic = &ic
559   set ic
560   let b:iainstatus = substitute(b:iainstatus, a:flag, a:flag, "")
561   let &ic = l:ic
562
563   let l:normalcolour = "darkblue"
564   let l:editingcolour = "darkmagenta"
565   let l:replacecolour = "purple"
566   let l:warningcolour = "darkred"
567   let l:readonlycolour = "red"
568
569   if b:iainstatus =~# "I"
570     if v:insertmode == "r"
571       let l:editingcolour = l:replacecolour
572     endif
573   endif
574
575   " Default colour.
576   let l:colour = l:normalcolour
577   " Maybe override depending on status.
578   if b:iainstatus =~# "H"
579     if b:iainstatus =~# "I"
580       " Held in insert mode.  Add extra highlight if we don't have focus.
581       if b:iainstatus =~# "f"
582         let l:colour = l:warningcolour
583       else
584         let l:colour = l:editingcolour
585       endif
586     endif
587   else
588     if b:iainstatus =~# "I"
589       " Regular insert mode.
590       let l:colour = l:editingcolour
591     endif
592   endif
593
594   " Override again if readonly.
595   if l:colour != l:normalcolour
596     if getbufvar("", "&ro")
597       let l:colour = l:readonlycolour
598     endif
599   endif
600
601   let l:termcolour = Iain_Colour(l:colour)
602
603   exec "highlight StatusLine gui=none term=none cterm=none guifg=white guibg=" . l:colour . " ctermfg=white ctermbg=" . l:termcolour
604   exec "highlight User1 gui=bold term=bold cterm=bold guifg=white guibg=" . l:colour . " ctermfg=white ctermbg=" . l:termcolour
605 endfun "}}}2
606
607 fun! Iain_Colour(colour) "{{{2
608   if &t_Co == 88
609     if a:colour == "darkblue"
610       return 17
611     elseif a:colour == "darkmagenta"
612       return 33
613     elseif a:colour == "purple"
614       return 35
615     elseif a:colour == "darkred"
616       return 32
617     elseif a:colour == "red"
618       return 64
619     endif
620   elseif &t_Co == 256
621     if a:colour == "darkblue"
622       return 17
623     elseif a:colour == "darkmagenta"
624       return 90
625     elseif a:colour == "purple"
626       return 57
627     elseif a:colour == "darkred"
628       return 88
629     elseif a:colour == "red"
630       return 196
631     endif
632   else
633     " Colours which cterm*g doesn't recognise.
634     if a:colour == "purple"
635       return "magenta"
636     endif
637     return a:colour
638   endif
639 endfun "}}}2
640
641 if has("autocmd")
642   au StatusLine VimEnter * call Highlight_StatusLine("")
643
644   " Show numbers by default.
645   au Display VimEnter * if ! Uncluttered_Buffer() | call Number(0) | endif
646 endif
647 endif "}}}1
648
649 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
650 " Handle options only available in Vim 5.4 and above.
651 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
652 if version >= "504" "{{{1
653 version 5.4
654
655 " Reuse windows when using sbuffer.
656 se switchbuf=useopen
657
658 " Vim 5 requires a 'n setting for viminfo.
659 if ! &viminfo
660   se viminfo='100
661 endif
662
663 " Allow persistent variable saving for localvimrc.
664 se viminfo+=!
665
666 " Do we have Unicode?
667 fun! Has_Unicode() "{{{2
668   if ! has('multi_byte')
669     return 0
670   endif
671
672   if version < "602"
673     return 0
674   endif
675
676   if &tenc =~? '^u\(tf\|cs\)'
677     return 1
678   endif
679
680   if ! strlen(&tenc) && &enc =~? '^u\(tf\|cs\)'
681     return 1
682   endif
683
684   return 0
685 endfun "}}}2
686
687 " Helper for status line.
688 " Show file encoding
689 fun! Show_Encoding() "{{{2
690   if version < "600"
691     return ""
692   endif
693
694   let l:enc = &fenc
695   let l:symbol = ""
696   if l:enc == ""
697     let l:enc = &enc
698     if l:enc == ""
699       return ""
700     endif
701     if bufname("%") == ""
702       if Has_Unicode()
703         let l:symbol = '•'
704       else
705         let l:symbol = '*'
706       endif
707     endif
708   endif
709
710   if has("multi_byte")
711     if &bomb
712       if Has_Unicode()
713         let l:symbol = "☻"
714       else
715         let l:symbol = "@"
716       endif
717     endif
718   endif
719
720   " Don't return anything if the encoding is utf-8.
721   if l:enc == "utf-8"
722     if l:symbol == ""
723       return ""
724     endif
725   endif
726
727   return l:symbol . l:enc . ","
728 endfun "}}}2
729
730 " Helper for status line.
731 " Show space, underscore or dollar sign depending on list mode.
732 fun! Show_List() "{{{2
733   call Iain_Vars()
734   if w:iainlist == 0
735     " No list.
736     return ""
737   elseif Has_Unicode()
738     if w:iainlist == 1
739       " Just tabs.
740       return "»"
741     else
742       " Full list.
743       return "¶"
744     endif
745   else
746     if w:iainlist == 1
747       return "_"
748     else
749       return "\$"
750     endif
751   endif
752 endfun "}}}2
753
754 " Helper for status line.
755 " Show c or C to denote case-sensitivity.
756 fun! Show_Case() "{{{2
757   if &ic
758     return "c"
759   else
760     return "C"
761   endif
762 endfun "}}}2
763
764 " Helper for status line.
765 " Mark DOS buffers.
766 fun! Show_DOS() "{{{2
767   if &ff == "unix"
768     return ""
769   endif
770   return &ff . ","
771 endfun "}}}2
772
773 " Helper for status line.
774 " Show the size of the tabstop.
775 fun! Show_Tabstop() "{{{2
776   return &ts
777 endfun "}}}2
778
779 " Helper for status line.
780 " Show p when paste mode is on.
781 fun! Show_Paste() "{{{2
782   if &paste
783     return "p"
784   else
785     return ""
786   endif
787 endfun "}}}2
788
789 " Helper for status line.
790 " Show v when virtualedit mode is block, insert or onemore.
791 " Show V when virtualedit mode is all.
792 fun! Show_VirtualEdit() "{{{2
793   if ! has("virtualedit")
794     return ""
795   endif
796
797   if &ve == "all"
798     return "V"
799   elseif &ve != ''
800     return "v"
801   else
802     return ""
803   endif
804 endfun "}}}2
805
806 " Helper for status line.
807 " Show U when persistent undo is on.
808 " Show u when persistent undo is off but an undofile exists.
809 fun! Show_Undo() "{{{2
810   if ! exists("&undofile")
811     return ""
812   endif
813
814   if &undofile
815     return "U"
816   elseif filereadable(undofile(expand("%")))
817     return "u"
818   else
819     return ""
820   endif
821 endfun "}}}2
822
823 " Helper for status line.
824 " Show alternate buffer number and name.
825 fun! Show_Alt() "{{{2
826   let l:alt = bufnr("#")
827   if l:alt < 0 || l:alt == bufnr("") || ! b:iainalt
828     return ""
829   endif
830
831   return " " . l:alt . ": " . expand("#:t")
832 endfun "}}}2
833
834 " Helper for status line.
835 " Show scrollbind or cursorbind.
836 fun! Show_Bind() "{{{2
837   if has("cursorbind")
838     if &cursorbind
839       if Has_Unicode()
840         return "⇄"
841       else
842         return ">"
843       endif
844     elseif &scrollbind
845       if Has_Unicode()
846         return "⇅"
847       else
848         return "^"
849       endif
850     endif
851   endif
852   return ""
853 endfun "}}}2
854
855 " Helper for status line.
856 " Show marker if searchforward is unset.
857 fun! Show_SearchForward() "{{{2
858   if version >= "702"
859     if ! v:searchforward
860       if Has_Unicode()
861         return "∆"
862       else
863         return "^"
864       endif
865     endif
866   endif
867   return ""
868 endfun "}}}2
869
870 " Helper for status line.
871 " Show marks set in cursor line.
872 fun! Show_Marks() "{{{2
873   if ! exists("g:iainsigns")
874     return ""
875   endif
876
877   let l:marks = ""
878
879   let l:signs = g:iainsigns
880   let l:sign = ""
881   let l:cursorline = line(".")
882   while strlen(l:signs)
883     let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=>-][^ ]\+')
884     let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
885     let l:ascii = matchstr(l:sign, '^:.')
886     let l:mark = substitute(l:sign, '^\(:.\)*[.=>-]', "", "")
887     if strlen(l:ascii)
888       let l:ascii = substitute(l:ascii, '^:', "", "")
889     else
890       let l:ascii = l:mark
891     endif
892     let l:ascii = substitute(l:ascii, '"', '\\"', "")
893
894     if l:ascii == "o"
895       let l:line = "."
896     else
897       let l:line = "'" . l:ascii
898     endif
899
900     " Ignore cursor line which will always match.
901     if l:line != "."
902       if l:cursorline == line(l:line)
903         let l:marks = l:marks . l:mark
904       endif
905     endif
906
907     let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
908   endwhile
909
910   if l:marks == ""
911     return ""
912   else
913     return "M:" . l:marks . " "
914   endif
915 endfun "}}}2
916
917 " Helper for status lines.
918 " Show Space plugin command.
919 fun! Show_Space() "{{{2
920   if exists("*GetSpaceMovement")
921     let l:ret = GetSpaceMovement()
922     if l:ret != ""
923       if Has_Unicode()
924         let l:ret = "▭" . l:ret . Show_SearchForward()
925       else
926         let l:ret "[" . l:ret . Show_SearchForward() . "]"
927       endif
928     endif
929     return l:ret
930   else
931     return Show_SearchForward()
932   endif
933 endfun "}}}2
934
935 " Show the status line.
936 fun! Show_StatusLine() "{{{2
937   if ! has("statusline")
938     return
939   endif
940   call Iain_Vars()
941
942   " User{N} highlights %{N}*.
943   " Named highlight groups %#group% aren't available until Vim 7.
944   let l:normal = '%0*'
945   let l:bold = '%1*'
946
947   " sl1 contains left-aligned stuff.
948   " sl2 contains stuff shown only when verbose mode is enabled.
949   " sl3 contains right-aligned stuff.
950   let l:sl1='%2n\:\ %<' . l:bold . '%f' . l:normal . '\ [%{Show_Encoding()}%{Show_DOS()}%{Show_List()}%{Show_Bind()}%{Show_Case()}%{Show_Tabstop()}%{Show_Paste()}%{Show_VirtualEdit()}%{Show_Undo()}%Y%M%R%{Show_Space()}]%{Show_Alt()}\ '
951   let l:sl3='%{Show_Marks()}L:' . l:bold . '%4.6l' . l:normal . '/%-4.6L\ C:' . l:bold . '%3.6c%V' . l:normal . '\ \|\ %P'
952   let l:hexformat='%b'
953   if b:iainhex
954     let l:hexformat='0\x%02B'
955   endif
956   if b:iainverbose
957     let l:sl1=l:sl1 . v:version . '\ %='
958     let l:sl2=l:hexformat . '\ \|\ P:%4.6o\ '
959   else
960     let l:sl1=l:sl1 . '%='
961     let l:sl2=''
962   endif
963   exec "set statusline=" . l:sl1 . l:sl2 . l:sl3
964 endfun "}}}2
965
966 " Show the status line for the first time.
967 call Show_StatusLine()
968 endif "}}}1
969
970 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
971 " Handle options only available in Vim 6 and above.
972 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
973 if version >= "600" "{{{1
974 version 6.0
975
976 if has("win32") || has("win64")
977   se encoding=utf-8
978 endif
979
980 " Remember quickfix state.
981 if has("quickfix")
982   let g:quickfixing=0
983 endif
984
985 " Set indenting by filetype.
986 filetype indent on
987
988 " Less intrusive syntax highlighting.
989 if has("syntax")
990   " The :syntax enable command tries to source the syntax.vim runtime script.
991   " Parsing this .vimrc will fail if for some reason the runtime doesn't
992   " exist, as could be the case if the binary was installed with no support
993   " files.  GNU On Windows is one example of an incomplete installation.
994   try
995     syn enable
996   catch
997   endtry
998 endif
999
1000 " Set colours.
1001 if has("gui_running")
1002   if has("win32") || has("win64")
1003     exe "silent se guifont=DejaVu_Sans_Mono:h10:cANSI"
1004   else
1005     exe "silent se guifont=DejaVu\\ Sans\\ Mono\\ 10"
1006   endif
1007 endif
1008 if has("gui_running") || &t_Co > 16
1009   exe "silent colo iain"
1010 endif
1011
1012 " Ignore whitespace when diffing.
1013 if has("diff")
1014   se diffopt=filler,iwhite
1015 endif
1016
1017 if has("autocmd")
1018   if has("quickfix")
1019     " Remember that we are opening the quickfix window.
1020     au Mode BufWinEnter quickfix let g:quickfixing=1
1021     au Mode BufUnload * if &ft == "qf" | let g:quickfixing=0 | endif
1022   endif
1023
1024   " Allow in-place editing of crontabs.
1025   au Mode FileType crontab set backupcopy=yes
1026 endif
1027
1028 " Make * and # work the way you expect in visual mode.
1029 vnoremap * y/\V<C-R>=substitute(escape(@@,"/\\"),"\n","\\\\n","ge")<CR><CR>
1030 vnoremap # y?\V<C-R>=substitute(escape(@@,"?\\"),"\n","\\\\n","ge")<CR><CR>
1031
1032 " Set mark and update highlighting.
1033 if has("signs")
1034   au Signs BufReadPost * call <SID>Highlight_Signs()
1035   au Signs CursorHold * call <SID>Highlight_Signs()
1036 endif
1037
1038 " Helper to set buffer variable for a given sign.
1039 fun! <SID>Prep_Sign(sign) "{{{2
1040   if ! exists("b:sign" . a:sign) || ! g:marksigns
1041     exe "let b:sign" . a:sign . "=0"
1042    endif
1043 endfun "}}}2
1044
1045 fun! <SID>Place_Sign(number, line, old, name) "{{{2
1046   if a:line == a:old
1047     return a:old
1048   endif
1049
1050   exe "sign unplace " . (g:firstsign + a:number) . " buffer=" . bufnr("")
1051   " Don't place the sign if it would conflict with the last change sign.
1052   exe "sign place " . (g:firstsign + a:number) . " line=" . a:line . " name=" . a:name . " buffer=" . bufnr("")
1053   return a:line
1054 endfun "}}}2
1055
1056 fun! <SID>Highlight_Signs(...) "{{{2
1057   if ! has("signs") || ! g:marksigns || Uncluttered_Buffer()
1058     return
1059   endif
1060
1061   let l:signs = g:iainsigns
1062   let l:sign = ""
1063   let l:i = 0
1064   while strlen(l:signs)
1065     let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=>-][^ ]\+')
1066
1067     let l:name = substitute(l:sign, '[:.=>-].*', "", "")
1068     let l:var = tolower(l:name)
1069     let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
1070     let l:ascii = matchstr(l:sign, '^:.')
1071     let l:mark = substitute(l:sign, '^\(:.\)*[.=>-]', "", "")
1072     if strlen(l:ascii)
1073       let l:ascii = substitute(l:ascii, '^:', "", "")
1074     else
1075       let l:ascii = l:mark
1076     endif
1077     let l:ascii = substitute(l:ascii, '"', '\\"', "")
1078
1079     if l:ascii == "o"
1080       let l:line = "."
1081     else
1082       let l:line = "'" . l:ascii
1083     endif
1084
1085     call <SID>Prep_Sign(l:var)
1086     exe "let " . l:var . " = <SID>Place_Sign(" . l:i . ", line(\"" . l:line . "\"), b:sign" . l:var . ", \"Mark" . l:name . "\")"
1087     let l:i = l:i + 1
1088
1089     let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
1090   endwhile
1091 endfun "}}}2
1092
1093 " Toggle signs.
1094 fun! <SID>Cycle_Signs(resize) "{{{2
1095   if ! has("signs")
1096     return
1097   endif
1098   call Iain_Vars()
1099   let g:marksigns = ! g:marksigns
1100
1101   " Retrofit arrays on to Vim 6.
1102   if ! exists("g:iainsigns")
1103     " Signs are defined in g:iainsigns.  The syntax is as follows:
1104     "
1105     " Sign ::= Name (':' Mark)* Type Symbol
1106     " Type ::= '=' | '-' | '.'
1107     "
1108     " Signs with Type '=' will be highlighted with the MarkSign group.
1109     " Signs with Type '-' will be highlighted with the MarkLine group.
1110     " Signs with Type '.' will be highlighted with the MarkDot group.
1111     " Signs with Type '>' will be highlighted with the MarkArrow group.
1112     " Define the Mark where Symbol is not also the mark name, eg "']".
1113     let g:iainsigns = "Less=< Greater=> Left=( Right=) SquareLeft=[ SquareRight=] BraceLeft={ BraceRight=} a-a b-b c-c d-d e-e f-f A-A B-B C-C D-D E-E F-F"
1114     if Has_Unicode()
1115       let g:iainsigns = g:iainsigns . " Quote:\"=” Dash:'=’ Caret:^.ʌ Dot:..•"
1116       if version < "704"
1117         let g:iainsigns = g:iainsigns ." Cursor:o>▶"
1118       endif
1119     else
1120       let g:iainsigns = g:iainsigns . " Quote=\" Dash=' Caret.^ Dot:..*"
1121       if version < "704"
1122         let g:iainsigns = g:iainsigns ." Cursor>o"
1123       endif
1124     endif
1125   endif
1126
1127   if g:marksigns
1128     " Signs to highlight marks.
1129     " Syntax won't work properly in Vim 6.
1130     let l:signs = g:iainsigns
1131     let l:sign = ""
1132     while strlen(l:signs)
1133       let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=>-][^ ]\+')
1134
1135       let l:name = substitute(l:sign, '[:.=>-].*', "", "")
1136       let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
1137       let l:ascii = matchstr(l:sign, '^:.')
1138       let l:mark = substitute(l:sign, '^\(:.\)*[.=>-]', "", "")
1139       if strlen(l:ascii)
1140         let l:ascii = substitute(l:ascii, '^:', "", "")
1141         let l:ascii = matchstr(l:ascii, '^.')
1142       else
1143         let l:ascii = l:mark
1144       endif
1145       let l:ascii = substitute(l:ascii, '"', '\\"', "")
1146       let l:type = substitute(l:sign, '^:.', "", "")
1147       let l:type = matchstr(l:type, '^.')
1148
1149       let l:hl = ""
1150       if l:type == "="
1151         let l:hl = "texthl=MarkSign text="
1152       elseif l:type == "."
1153         let l:hl = "texthl=MarkDot text="
1154       elseif l:type == "-"
1155         let l:hl = "texthl=MarkLine text="
1156       elseif l:type == ">"
1157         let l:hl = "texthl=MarkArrow text="
1158       endif
1159
1160       exe "sign define Mark" . l:name . " " . l:hl . l:mark
1161
1162       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
1163     endwhile
1164
1165     if a:resize
1166       call Resize_Columns("+", 2)
1167     endif
1168     call <SID>Highlight_Signs()
1169   else
1170     let l:i = 0
1171     while l:i < 25
1172       exe "sign unplace " . (g:firstsign + l:i)
1173       let l:i = l:i + 1
1174     endwhile
1175
1176     let l:signs = g:iainsigns
1177     let l:sign = ""
1178     while strlen(l:signs)
1179       let l:sign = matchstr(l:signs, '^[A-Za-z]\+')
1180
1181       exe "sign undefine Mark" . l:sign
1182       call <SID>Prep_Sign(tolower(l:sign))
1183       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
1184     endwhile
1185
1186     if a:resize
1187       call Resize_Columns("-", 2)
1188     endif
1189   endif
1190 endfun "}}}2
1191
1192 " Change list mode.
1193 fun! Cycle_List() "{{{2
1194   " Pretty UTF-8 listchars.
1195   if Has_Unicode()
1196     let basic='tab:»·,trail:…,extends:«,precedes:»'
1197     let eol='eol:¶'
1198     if version >= "700"
1199       let basic=basic . ',nbsp:•'
1200     endif
1201   else
1202     let basic='tab:\\_,trail:_,extends:<,precedes:>'
1203     let eol='eol:$'
1204     if version >= "700"
1205       let basic=basic . ',nbsp:+'
1206     endif
1207   endif
1208   call Iain_Vars()
1209   let w:iainlist = w:iainlist + 1
1210   if w:iainlist > 2
1211     let w:iainlist = 0
1212   endif
1213   if w:iainlist == 0
1214     setlocal nolist
1215   elseif w:iainlist == 1
1216     exec "setlocal lcs=" . basic
1217     setlocal list
1218   else
1219     exec "setlocal lcs=" . basic . "," . eol
1220     setlocal list
1221   endif
1222
1223   call Resize_Columns(Extra_Columns("list", "iainlist", " == 2"), 1)
1224   call Extra_Whitespace_Match()
1225 endfun "}}}2
1226
1227 " Cycle between hex and decimal display of toolbar stuff.
1228 fun! Cycle_HexStatusLine() "{{{2
1229   call Iain_Vars()
1230   let b:iainhex = ! b:iainhex
1231   call Show_StatusLine()
1232 endfun "}}}2
1233
1234 " Cycle verbose display of toolbar stuff.
1235 fun! Cycle_VerboseStatusLine() "{{{2
1236   call Iain_Vars()
1237   let b:iainverbose = ! b:iainverbose
1238   call Show_StatusLine()
1239 endfun "}}}2
1240
1241 " Toggle quickfix window.
1242 fun! Cycle_Quickfix() "{{{2
1243   if ! has("quickfix")
1244     return
1245   endif
1246   if g:quickfixing == 1
1247     cclose
1248     let g:quickfixing=0
1249   else
1250     copen
1251   endif
1252 endfun "}}}2
1253
1254 " Toggle showing alternate buffer information.
1255 fun! Cycle_Alt() "{{{2
1256   call Iain_Vars()
1257   let b:iainalt = ! b:iainalt
1258   call Show_StatusLine()
1259 endfun "{{{2
1260
1261 " To be overridden later if applicable.
1262 fun! Extra_Whitespace_Match() "{{{2
1263   " NOP.
1264 endfun "}}}2
1265
1266 " Swap hex/decimal statusline with \x.
1267 call Mapping("x", ":call Cycle_HexStatusLine()<CR>")
1268 " Change statusline verbosity with \v.
1269 call Mapping("V", ":call Cycle_VerboseStatusLine()<CR>")
1270 " Cycle list styles with \l.
1271 call Mapping("l", ":call Cycle_List()<CR>")
1272 " Toggle tags with \t.
1273 call Mapping("t", ":Tlist<CR>")
1274 " Change foldmethod with \f.
1275 call Mapping("f", ":se foldenable!<CR>")
1276 " Toggle quickfix window with \q.
1277 call Mapping("q", ":call Cycle_Quickfix()<CR>")
1278 " Rerun filetype detection with \s.  The s is for syntax, as this will be
1279 " updated as a side-effect.
1280 call Mapping("S", ":filetype detect<CR>")
1281 " Toggle marks with \m.
1282 call Mapping("m", ":call <SID>Cycle_Signs(1)<CR>")
1283
1284 if has("autocmd")
1285   " Show signs by default.
1286   au Display VimEnter * call <SID>Cycle_Signs(0)
1287 endif
1288
1289 " move.
1290 nmap <A-u> <Plug>MoveLineHalfPageUp
1291 nmap <A-d> <Plug>MoveLineHalfPageDown
1292 vmap <A-u> <Plug>MoveBlockHalfPageUp
1293 vmap <A-d> <Plug>MoveBlockHalfPageDown
1294 endif "}}}1
1295
1296 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1297 " Handle options only available in Vim 7 and above.
1298 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1299 if version >= "700" "{{{1
1300 version 7.0
1301
1302 " Narrow buffer with \w.
1303 call Mapping("w", ":NarrowRegion<CR>", "n", "v")
1304 " Narrow window with \W.
1305 call Mapping("W", ":NarrowWindow<CR>", "n", "v")
1306
1307 " Helper to show tab name.
1308 fun! <SID>TabName(label, gui) "{{{2
1309   let l:label = a:label
1310   if l:label == ""
1311     let l:label = "No Name"
1312     if a:gui
1313       let l:label = "[" . l:label . "]"
1314     endif
1315   else
1316     let l:label = fnamemodify(l:label, ":t")
1317     if strlen(l:label) >= 18
1318       let l:label = l:label[0:17] . ".."
1319     endif
1320   endif
1321   return l:label
1322 endfun "}}}2
1323
1324 " Find out if any buffer was modified.
1325 fun! <SID>TabModified(buflist) "{{{2
1326   let l:i = 0
1327   while l:i < len(a:buflist)
1328     if getbufvar(a:buflist[l:i], "&modified") == 1
1329       return "+"
1330     endif
1331     let l:i = l:i + 1
1332   endwhile
1333   return ""
1334 endfun "}}}2
1335
1336 " Tab line.
1337 fun! Show_TabLine() "{{{2
1338   let l:s = "%#TabLineFill#Tabs:"
1339
1340   let l:i = 0
1341   while l:i < tabpagenr("$")
1342     let l:i = l:i + 1
1343     " Get the label.
1344     let l:buflist = tabpagebuflist(l:i)
1345     let l:winnr = tabpagewinnr(l:i)
1346     let l:n = tabpagewinnr(l:i, "$")
1347     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
1348     let l:modified = <SID>TabModified(l:buflist)
1349
1350     " Choose highlighting.
1351     if l:i == tabpagenr()
1352       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
1353     else
1354       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
1355     endif
1356   endwhile
1357
1358   " Padding.
1359   let l:s .= "%#TabLine#%T"
1360   return l:s
1361 endfun "}}}2
1362
1363 " Per tab label for the GUI.
1364 fun! Show_GUITabLine() "{{{2
1365   let l:buflist = tabpagebuflist(v:lnum)
1366   let l:winnr = tabpagewinnr(v:lnum)
1367   let l:s = tabpagewinnr(v:lnum, "$")
1368   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
1369   let l:modified = <SID>TabModified(l:buflist)
1370
1371   let l:s .= l:modified . " " . l:label
1372   return l:s
1373 endfun "}}}2
1374
1375 " Handle searching in a BufExplorer window.
1376 fun! <SID>BufExplorer_Search(n) "{{{2
1377   if a:n == 0
1378     let l:re = '^  *\d %'
1379   else
1380     let l:re = "^ *" . a:n
1381   endif
1382
1383   " Find matching line.
1384   let l:line = search(l:re, 'w')
1385   if ! l:line
1386     return
1387   endif
1388
1389   if a:n == 0
1390     return
1391   endif
1392
1393   " Peek ahead to the next matching line.
1394   let l:next = search(l:re, 'w')
1395
1396   " Select the buffer if the match is unambiguous.
1397   if l:next == l:line
1398     exe "normal \<CR>"
1399     return
1400   endif
1401
1402   " Go back.
1403   call cursor(l:line, 0)
1404 endfun! "}}}2
1405
1406 " Entering a BufExplorer window.
1407 fun! <SID>BufExplorer_Map() "{{{2
1408   for l:n in [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]
1409     exec "nnoremap <buffer> <silent>" . l:n . " :call <SID>BufExplorer_Search(" . l:n . ")<CR>"
1410   endfor
1411 endfun "}}}2
1412
1413 if has("windows")
1414   se tabline=%!Show_TabLine()
1415   se guitablabel=%!Show_GUITabLine()
1416 endif
1417
1418 if has("autocmd")
1419   au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1420   au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1421   au StatusLine FocusGained * call Highlight_StatusLine("F")
1422   au StatusLine FocusLost * call Highlight_StatusLine("f")
1423   au StatusLine InsertEnter * call Highlight_StatusLine("I")
1424   au StatusLine InsertChange * call Highlight_StatusLine("I")
1425   au StatusLine InsertLeave * call Highlight_StatusLine("i")
1426
1427   if has("signs")
1428     au Signs CursorHoldI * call <SID>Highlight_Signs()
1429     au Signs InsertEnter * call <SID>Highlight_Signs()
1430     au Signs InsertLeave * call <SID>Highlight_Signs()
1431   endif
1432
1433   au Mode BufEnter \[BufExplorer\] call <SID>BufExplorer_Map()
1434 endif
1435
1436 " Limit the size of the popup menu when completing.
1437 if has("insert_expand")
1438   se pumheight=20
1439 endif
1440
1441 " Make diffs vertical by default.
1442 if has("diff")
1443   se diffopt+=vertical
1444 endif
1445
1446 " Set size of numbers column.
1447 if has("linebreak")
1448   se numberwidth=5
1449 endif
1450
1451 " Add "previous tab" mapping as gb.
1452 map gb :tabprevious<CR>:<CR>
1453
1454 " Transparency.
1455 if has("gui_macvim")
1456   se transparency=15
1457 endif
1458
1459 " Yet more GUI options.  Add tabs.
1460 if has("gui")
1461   se go+=e
1462 endif
1463
1464 " Perforce.
1465 let g:p4EnableMenu=1
1466 let g:p4Presets='P4CONFIG'
1467
1468 " BufExplorer.
1469 let g:bufExplorerShowRelativePath=1
1470 let g:bufExplorerSplitOutPathName=0
1471
1472 " NERDcommenter.
1473 let g:NERDSpaceDelims=1
1474
1475 " localvimrc.
1476 let g:localvimrc_persistent=1
1477
1478 " Gitv.
1479 let g:Gitv_OpenHorizontal='auto'
1480 let g:Gitv_WipeAllOnClose=1
1481 endif "}}}1
1482
1483 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1484 " Handle options only available in Vim 7.2 and above.
1485 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1486 if version >= "702" "{{{1
1487 if has("autocmd")
1488   " http://vim.wikia.com/wiki/Highlight_unwanted_spaces
1489   augroup WhitespaceMatch
1490   autocmd!
1491   au Display BufWinEnter * call Extra_Whitespace_Match()
1492   au Display Syntax * call Extra_Whitespace_Match()
1493   au Display BufWinLeave * call clearmatches()
1494   augroup END
1495
1496   fun! Extra_Whitespace_Match() "{{{2
1497     " \s\+            <whitespace>
1498     "            $    <before end of line>
1499     "        \@<!     <unless preceded by>
1500     "     \%#         <cursor position, ie when typing>
1501     let l:pattern = '\s\+\%#\@<!$'
1502     " Don't match single space in first column of diff.
1503     if &ft =~# '^diff$\|git'
1504       "         \@!  <unless also matching>
1505       " \(^\s$\)     <a single whitespace>
1506       let l:pattern = '\(^\s$\)\@!' . l:pattern
1507     endif
1508
1509     let l:hl = 'ctermfg=red guifg=red'
1510     if ! &list
1511       " Underline if we aren't using listchars.
1512       let l:hl = l:hl . ' cterm=underline gui=underline'
1513     endif
1514     highlight clear ExtraWhitespace
1515     exe "highlight ExtraWhitespace " . l:hl
1516     if exists('w:whitespace_match_number')
1517       try
1518         call matchdelete(w:whitespace_match_number)
1519       catch
1520       endtry
1521       call matchadd('ExtraWhitespace', l:pattern, 10, w:whitespace_match_number)
1522     else
1523       let w:whitespace_match_number = matchadd('ExtraWhitespace', l:pattern)
1524     endif
1525   endfun "}}}2
1526
1527   call Extra_Whitespace_Match()
1528 endif
1529
1530 endif "}}}1
1531
1532 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1533 " Handle options only available in Vim 7.3 and above.
1534 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1535 if version >= "703" "{{{1
1536 version 7.3
1537
1538 " Toggle persistent undo with \u.
1539 call Mapping("u", ":call <SID>Cycle_Undo()<CR>")
1540 " Remove persistent undo file with \U.
1541 call Mapping("U", ":call <SID>Clear_Undo()<CR>")
1542
1543 " Toggle gundo window with \g.
1544 call Mapping("g", ":call gundo#GundoToggle()<CR>")
1545
1546 " Use a persistent undo file if it exists.
1547 fun! <SID>Check_Undo() "{{{2
1548   if filereadable(undofile(expand("%")))
1549     setlocal undofile
1550   endif
1551 endfun "}}}2
1552
1553 " Toggle persistent undo for this buffer.
1554 fun! <SID>Cycle_Undo() "{{{2
1555   if has("persistent_undo")
1556     let &undofile = ! &undofile
1557   endif
1558 endfun "}}}2
1559
1560 " Remove the persistent undo file for this buffer.
1561 fun! <SID>Clear_Undo() "{{{2
1562   if ! has("persistent_undo")
1563     return
1564   endif
1565
1566   setlocal noundofile
1567
1568   let l:f = expand("%")
1569   if l:f == ""
1570     return
1571   endif
1572
1573   let l:u = undofile(l:f)
1574   if l:u == ""
1575     return
1576   endif
1577
1578   if ! filereadable(l:u) || ! filewritable(l:u)
1579     return
1580   endif
1581
1582   call delete(l:u)
1583 endfun "}}}2
1584
1585 " Toggle ColorColumn at cursor position.
1586 fun! <SID>Cycle_ColorColumn() "{{{2
1587   if ! has("syntax")
1588     return
1589   endif
1590
1591   let l:cc = &colorcolumn
1592   let l:column = col(".")
1593   let l:re = ",*\\<" . l:column . "\\>"
1594   if l:cc =~# l:re
1595     let l:cc = substitute(l:cc, l:re, "", "g")
1596   else
1597     let l:cc = l:cc . "," . l:column
1598   endif
1599   let &colorcolumn = substitute(l:cc, "^,*", "", "")
1600 endfun "}}}2
1601
1602 if has("syntax")
1603   " Enable showing ColorColumn at cursor position with \CC.
1604   call Mapping("CC", ":call <SID>Cycle_ColorColumn()<CR>")
1605   " Remove last shown ColorColumn with \Cc.
1606   call Mapping("Cc", ":let &colorcolumn=substitute(&colorcolumn, \",*[0-9]*$\", \"\", \"\")<CR>")
1607   " Remove all ColorColumns with \Cx.
1608   call Mapping("Cx", ":se colorcolumn=<CR>")
1609 endif
1610
1611 " Use persistent undo if available.
1612 if has("autocmd")
1613   if has("persistent_undo")
1614     au File BufReadPost * call <SID>Check_Undo()
1615   endif
1616
1617   if has("cursorbind")
1618     au Display WinEnter * if &diff | se cursorbind | endif
1619   endif
1620 endif
1621
1622 " Mapping to reload the gundo window.
1623 if has("autocmd")
1624   au Mode BufEnter * if &ft == "gundo" | try | nnoremap <silent> <buffer> <unique> r :call gundo#GundoToggle()<CR>:call gundo#GundoToggle()<CR> | catch | endtry | endif
1625 endif
1626
1627 endif "}}}1
1628 "
1629 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1630 " Handle options only available in Vim 7.4 and above.
1631 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1632 if version >= "704" "{{{1
1633 version 7.4
1634
1635 if has("syntax")
1636   se cursorline
1637 endif
1638
1639 endif "}}}1
1640
1641 " Resize after startup.
1642 if version >= "500" "{{{1
1643 if has("autocmd")
1644   au Display VimEnter * call Startup_Resize()
1645 endif
1646 endif "}}}1