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