Reuse windows when using sbuffer.
[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 " Reuse windows when using sbuffer.
618 se switchbuf=useopen
619
620 " Do we have Unicode?
621 fun! Has_Unicode() "{{{2
622   if ! has('multi_byte')
623     return 0
624   endif
625
626   if version < "602"
627     return 0
628   endif
629
630   if &tenc =~? '^u\(tf\|cs\)'
631     return 1
632   endif
633
634   if ! strlen(&tenc) && &enc =~? '^u\(tf\|cs\)'
635     return 1
636   endif
637
638   return 0
639 endfun "}}}2
640
641 " Helper for status line.
642 " Show space, underscore or dollar sign depending on list mode.
643 fun! Show_List() "{{{2
644   call Iain_Vars()
645   if w:iainlist == 0
646     " No list.
647     return " "
648   elseif Has_Unicode()
649     if w:iainlist == 1
650       " Just tabs.
651       return "»"
652     else
653       " Full list.
654       return "¶"
655     endif
656   else
657     if w:iainlist == 1
658       return "_"
659     else
660       return "\$"
661     endif
662   endif
663 endfun "}}}2
664
665 " Helper for status line.
666 " Show c or C to denote case-sensitivity.
667 fun! Show_Case() "{{{2
668   if &ic
669     return "c"
670   else
671     return "C"
672   endif
673 endfun "}}}2
674
675 " Helper for status line.
676 " Show the size of the tabstop.
677 fun! Show_Tabstop() "{{{2
678   return &ts
679 endfun "}}}2
680
681 " Helper for status line.
682 " Show p when paste mode is on.
683 fun! Show_Paste() "{{{2
684   if &paste
685     return "p"
686   else
687     return ""
688   endif
689 endfun "}}}2
690
691 " Helper for status line.
692 " Show v when virtualedit mode is block, insert or onemore.
693 " Show V when virtualedit mode is all.
694 fun! Show_VirtualEdit() "{{{2
695   if ! has("virtualedit")
696     return ""
697   endif
698
699   if &ve == "all"
700     return "V"
701   elseif &ve != ''
702     return "v"
703   else
704     return ""
705   endif
706 endfun "}}}2
707
708 " Helper for status line.
709 " Show U when persistent undo is on.
710 " Show u when persistent undo is off but an undofile exists.
711 fun! Show_Undo() "{{{2
712   if ! exists("&undofile")
713     return ""
714   endif
715
716   if &undofile
717     return "U"
718   elseif filereadable(undofile(expand("%")))
719     return "u"
720   else
721     return ""
722   endif
723 endfun "}}}2
724
725 " Helper for status line.
726 " Show alternate buffer number and name.
727 fun! Show_Alt() "{{{2
728   let l:alt = bufnr("#")
729   if l:alt < 0 || l:alt == bufnr("") || ! b:iainalt
730     return ""
731   endif
732
733   return " " . l:alt . ": " . expand("#:t")
734 endfun "}}}2
735
736 " Helper for status line.
737 " Show scrollbind or cursorbind.
738 fun! Show_Bind() "{{{2
739   if has("cursorbind")
740     if &cursorbind
741       if Has_Unicode()
742         return "⇄"
743       else
744         return ">"
745       endif
746     elseif &scrollbind
747       if Has_Unicode()
748         return "⇅"
749       else
750         return "^"
751       endif
752     endif
753   endif
754   return ""
755 endfun "}}}2
756
757 " Show the status line.
758 fun! Show_StatusLine() "{{{2
759   if ! has("statusline")
760     return
761   endif
762   call Iain_Vars()
763   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()}\ '
764   let l:sl3='L:%1*%4.6l%0*/%-4.6L\ C:%1*%3.6c%V%0*\ \|\ %P'
765   let l:hexformat='%b'
766   if b:iainhex
767     let l:hexformat='0\x%02B'
768   endif
769   if b:iainverbose
770     let l:sl1=l:sl1 . v:version . '\ %='
771     let l:sl2=l:hexformat . '\ \|\ P:%4.6o\ '
772   else
773     let l:sl1=l:sl1 . '%='
774     let l:sl2=''
775   endif
776   exec "set statusline=" . l:sl1 . l:sl2 . l:sl3
777 endfun "}}}2
778
779 " Show the status line for the first time.
780 call Show_StatusLine()
781 endif "}}}1
782
783 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
784 " Handle options only available in Vim 6 and above.
785 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
786 if version >= "600" "{{{1
787 version 6.0
788
789 if has("gui_win32")
790   se encoding=utf-8
791 endif
792
793 " Remember quickfix state.
794 if has("quickfix")
795   let g:quickfixing=0
796 endif
797
798 " Set indenting by filetype.
799 filetype indent on
800
801 " Less intrusive syntax highlighting.
802 if has("syntax")
803   syn enable
804 endif
805
806 " Set colours.
807 if has("gui_running")
808   if has("win32") || has("win64")
809     exe "silent se guifont=DejaVu_Sans_Mono:h10:cANSI"
810   else
811     exe "silent se guifont=DejaVu\\ Sans\\ Mono\\ 10"
812   endif
813 endif
814 if has("gui_running") || &t_Co > 16
815   exe "silent colo iain"
816 endif
817
818 " Ignore whitespace when diffing.
819 if has("diff")
820   se diffopt=filler,iwhite
821 endif
822
823 if has("autocmd")
824   if has("quickfix")
825     " Remember that we are opening the quickfix window.
826     au Mode BufWinEnter quickfix let g:quickfixing=1
827     au Mode BufUnload * if &ft == "qf" | let g:quickfixing=0 | endif
828   endif
829
830   " Allow in-place editing of crontabs.
831   au Mode FileType crontab set backupcopy=yes
832 endif
833
834 " Make * and # work the way you expect in visual mode.
835 vnoremap * y/\V<C-R>=substitute(escape(@@,"/\\"),"\n","\\\\n","ge")<CR><CR>
836 vnoremap # y?\V<C-R>=substitute(escape(@@,"?\\"),"\n","\\\\n","ge")<CR><CR>
837
838 " Set mark and update highlighting.
839 if has("signs")
840   au Signs BufReadPost * call <SID>Highlight_Signs()
841   au Signs CursorHold * call <SID>Highlight_Signs()
842 endif
843
844 " Helper to set buffer variable for a given sign.
845 fun! <SID>Prep_Sign(sign) "{{{2
846   if ! exists("b:sign" . a:sign) || ! g:marksigns
847     exe "let b:sign" . a:sign . "=0"
848    endif
849 endfun "}}}2
850
851 fun! <SID>Place_Sign(number, line, old, name) "{{{2
852   if a:line == a:old
853     return a:old
854   endif
855
856   exe "sign unplace " . (g:firstsign + a:number) . " buffer=" . bufnr("")
857   " Don't place the sign if it would conflict with the last change sign.
858   exe "sign place " . (g:firstsign + a:number) . " line=" . a:line . " name=" . a:name . " buffer=" . bufnr("")
859   return a:line
860 endfun "}}}2
861
862 fun! <SID>Highlight_Signs(...) "{{{2
863   if ! has("signs") || ! g:marksigns || Uncluttered_Buffer()
864     return
865   endif
866
867   let l:signs = g:iainsigns
868   let l:sign = ""
869   let l:i = 0
870   while strlen(l:signs)
871     let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
872
873     let l:name = substitute(l:sign, '[:.=-].*', "", "")
874     let l:var = tolower(l:name)
875     let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
876     let l:ascii = matchstr(l:sign, '^:.')
877     let l:mark = substitute(l:sign, '^\(:.\)*[.=-]', "", "")
878     if strlen(l:ascii)
879       let l:ascii = substitute(l:ascii, '^:', "", "")
880     else
881       let l:ascii = l:mark
882     endif
883     let l:ascii = substitute(l:ascii, '"', '\\"', "")
884
885     call <SID>Prep_Sign(l:var)
886     exe "let " . l:var . " = <SID>Place_Sign(" . l:i . ", line(\"'" . l:ascii . "\"), b:sign" . l:var . ", \"Mark" . l:name . "\")"
887     let l:i = l:i + 1
888
889     let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
890   endwhile
891 endfun "}}}2
892
893 " Toggle signs.
894 fun! <SID>Cycle_Signs(resize) "{{{2
895   if ! has("signs")
896     return
897   endif
898   call Iain_Vars()
899   let g:marksigns = ! g:marksigns
900
901   " Retrofit arrays on to Vim 6.
902   if ! exists("g:iainsigns")
903     " Signs are defined in g:iainsigns.  The syntax is as follows:
904     "
905     " Sign ::= Name (':' Mark)* Type Symbol
906     " Type ::= '=' | '-' | '.'
907     "
908     " Signs with Type '=' will be highlighted with the MarkSign group.
909     " Signs with Type '-' will be highlighted with the MarkLine group.
910     " Signs with Type '.' will be highlighted with the MarkDot group.
911     " Define the Mark where Symbol is not also the mark name, eg "']".
912     if Has_Unicode()
913       let g:iainsigns = "Dash:'=’ Dot:..• Quote:\"=” Caret:^.ʌ"
914     else
915       let g:iainsigns = "Dash=' Dot:..* Quote=\" Caret.^"
916     endif
917     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"
918   endif
919
920   if g:marksigns
921     " Signs to highlight marks.
922     " Syntax won't work properly in Vim 6.
923     let l:signs = g:iainsigns
924     let l:sign = ""
925     while strlen(l:signs)
926       let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
927
928       let l:sign = substitute(l:sign, ':.', "", "")
929       let l:sign = substitute(l:sign, '=', " texthl=MarkSign text=", "")
930       let l:sign = substitute(l:sign, '\.', " texthl=MarkDot text=", "")
931       let l:sign = substitute(l:sign, '-', " texthl=MarkLine linehl=MarkLine text=", "")
932
933       exe "sign define Mark" . l:sign
934
935       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
936     endwhile
937
938     if a:resize
939       call Resize_Columns("+", 2)
940     endif
941     call <SID>Highlight_Signs()
942   else
943     let l:i = 0
944     while l:i < 25
945       exe "sign unplace " . (g:firstsign + l:i)
946       let l:i = l:i + 1
947     endwhile
948
949     let l:signs = g:iainsigns
950     let l:sign = ""
951     while strlen(l:signs)
952       let l:sign = matchstr(l:signs, '^[A-Za-z]\+')
953
954       exe "sign undefine Mark" . l:sign
955       call <SID>Prep_Sign(tolower(l:sign))
956       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
957     endwhile
958
959     if a:resize
960       call Resize_Columns("-", 2)
961     endif
962   endif
963 endfun "}}}2
964
965 " Change list mode.
966 fun! Cycle_List() "{{{2
967   " Pretty UTF-8 listchars.
968   if Has_Unicode()
969     let basic='tab:»·,trail:…,extends:«,precedes:»'
970     let eol='eol:¶'
971     if version >= "700"
972       let basic=basic . ',nbsp:•'
973     endif
974   else
975     let basic='tab:\\_,trail:_,extends:<,precedes:>'
976     let eol='eol:$'
977     if version >= "700"
978       let basic=basic . ',nbsp:+'
979     endif
980   endif
981   call Iain_Vars()
982   let w:iainlist = w:iainlist + 1
983   if w:iainlist > 2
984     let w:iainlist = 0
985   endif
986   if w:iainlist == 0
987     setlocal nolist
988   elseif w:iainlist == 1
989     exec "setlocal lcs=" . basic
990     setlocal list
991   else
992     exec "setlocal lcs=" . basic . "," . eol
993     setlocal list
994   endif
995
996   call Resize_Columns(Extra_Columns("list", "iainlist", " == 2"), 1)
997   call Extra_Whitespace_Match()
998 endfun "}}}2
999
1000 " Cycle between hex and decimal display of toolbar stuff.
1001 fun! Cycle_HexStatusLine() "{{{2
1002   call Iain_Vars()
1003   let b:iainhex = ! b:iainhex
1004   call Show_StatusLine()
1005 endfun "}}}2
1006
1007 " Cycle verbose display of toolbar stuff.
1008 fun! Cycle_VerboseStatusLine() "{{{2
1009   call Iain_Vars()
1010   let b:iainverbose = ! b:iainverbose
1011   call Show_StatusLine()
1012 endfun "}}}2
1013
1014 " Toggle quickfix window.
1015 fun! Cycle_Quickfix() "{{{2
1016   if ! has("quickfix")
1017     return
1018   endif
1019   if g:quickfixing == 1
1020     cclose
1021     let g:quickfixing=0
1022   else
1023     copen
1024   endif
1025 endfun "}}}2
1026
1027 " Toggle showing alternate buffer information.
1028 fun! Cycle_Alt() "{{{2
1029   call Iain_Vars()
1030   let b:iainalt = ! b:iainalt
1031   call Show_StatusLine()
1032 endfun "{{{2
1033
1034 " To be overridden later if applicable.
1035 fun! Extra_Whitespace_Match() "{{{2
1036   " NOP.
1037 endfun "}}}2
1038
1039 " Swap hex/decimal statusline with \x.
1040 call Mapping("x", ":call Cycle_HexStatusLine()<CR>:<CR>")
1041 " Change statusline verbosity with \v.
1042 call Mapping("V", ":call Cycle_VerboseStatusLine()<CR>:<CR>")
1043 " Cycle list styles with \l.
1044 call Mapping("l", ":call Cycle_List()<CR>:<CR>")
1045 " Toggle tags with \t.
1046 call Mapping("t", ":Tlist<CR>")
1047 " Change foldmethod with \f.
1048 call Mapping("f", ":se foldenable!<CR>:<CR>")
1049 " Toggle quickfix window with \q.
1050 call Mapping("q", ":call Cycle_Quickfix()<CR>:<CR>")
1051 " Rerun filetype detection with \s.  The s is for syntax, as this will be
1052 " updated as a side-effect.
1053 call Mapping("S", ":filetype detect<CR>:<CR>")
1054 " Toggle marks with \m.
1055 call Mapping("m", ":call <SID>Cycle_Signs(1)<CR>:<CR>")
1056
1057 if has("autocmd")
1058   " Show signs by default.
1059   au Display VimEnter * call <SID>Cycle_Signs(0)
1060 endif
1061 endif "}}}1
1062
1063 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1064 " Handle options only available in Vim 7 and above.
1065 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1066 if version >= "700" "{{{1
1067 version 7.0
1068
1069 " Helper to show tab name.
1070 fun! <SID>TabName(label, gui) "{{{2
1071   let l:label = a:label
1072   if l:label == ""
1073     let l:label = "No Name"
1074     if a:gui
1075       let l:label = "[" . l:label . "]"
1076     endif
1077   else
1078     let l:label = fnamemodify(l:label, ":t")
1079     if strlen(l:label) >= 18
1080       let l:label = l:label[0:17] . ".."
1081     endif
1082   endif
1083   return l:label
1084 endfun "}}}2
1085
1086 " Find out if any buffer was modified.
1087 fun! <SID>TabModified(buflist) "{{{2
1088   let l:i = 0
1089   while l:i < len(a:buflist)
1090     if getbufvar(a:buflist[l:i], "&modified") == 1
1091       return "+"
1092     endif
1093     let l:i = l:i + 1
1094   endwhile
1095   return ""
1096 endfun "}}}2
1097
1098 " Tab line.
1099 fun! Show_TabLine() "{{{2
1100   let l:s = "%#TabLineFill#Tabs:"
1101
1102   let l:i = 0
1103   while l:i < tabpagenr("$")
1104     let l:i = l:i + 1
1105     " Get the label.
1106     let l:buflist = tabpagebuflist(l:i)
1107     let l:winnr = tabpagewinnr(l:i)
1108     let l:n = tabpagewinnr(l:i, "$")
1109     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
1110     let l:modified = <SID>TabModified(l:buflist)
1111
1112     " Choose highlighting.
1113     if l:i == tabpagenr()
1114       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
1115     else
1116       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
1117     endif
1118   endwhile
1119
1120   " Padding.
1121   let l:s .= "%#TabLine#%T"
1122   return l:s
1123 endfun "}}}2
1124
1125 " Per tab label for the GUI.
1126 fun! Show_GUITabLine() "{{{2
1127   let l:buflist = tabpagebuflist(v:lnum)
1128   let l:winnr = tabpagewinnr(v:lnum)
1129   let l:s = tabpagewinnr(v:lnum, "$")
1130   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
1131   let l:modified = <SID>TabModified(l:buflist)
1132
1133   let l:s .= l:modified . " " . l:label
1134   return l:s
1135 endfun "}}}2
1136
1137 " Toggle highlighting cursor line when focus changes.
1138 fun! <SID>ToggleCursorLine() "{{{2
1139   call Iain_Vars()
1140
1141   if b:iainstatus =~# "H" && b:iainstatus =~# "I"
1142     " We are held in insert mode.
1143     if b:iainstatus =~# "f"
1144       " And focus was lost.
1145       let b:iaincul = getbufvar("", "&cursorline")
1146       setlocal cursorline
1147     elseif ! b:iaincul
1148       setlocal nocursorline
1149     endif
1150   endif
1151 endfun "}}}2
1152
1153 " Handle searching in a BufExplorer window.
1154 fun! <SID>BufExplorer_Search(n) "{{{2
1155   if a:n == 0
1156     let l:re = '^  *\d %'
1157   else
1158     let l:re = "^ *" . a:n
1159   endif
1160
1161   " Find matching line.
1162   let l:line = search(l:re, 'w')
1163   if ! l:line
1164     return
1165   endif
1166
1167   if a:n == 0
1168     return
1169   endif
1170
1171   " Peek ahead to the next matching line.
1172   let l:next = search(l:re, 'w')
1173
1174   " Select the buffer if the match is unambiguous.
1175   if l:next == l:line
1176     exe "normal \<CR>"
1177     return
1178   endif
1179
1180   " Go back.
1181   call cursor(l:line, 0)
1182 endfun! "}}}2
1183
1184 " Entering a BufExplorer window.
1185 fun! <SID>BufExplorer_Map() "{{{2
1186   for l:n in [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]
1187     exec "nnoremap <buffer> <silent>" . l:n . " :call <SID>BufExplorer_Search(" . l:n . ")<CR>"
1188   endfor
1189 endfun "}}}2
1190
1191 if has("windows")
1192   se tabline=%!Show_TabLine()
1193   se guitablabel=%!Show_GUITabLine()
1194 endif
1195
1196 if has("autocmd")
1197   au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1198   au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1199   au StatusLine FocusGained * call Highlight_StatusLine("F")
1200   au StatusLine FocusLost * call Highlight_StatusLine("f")
1201   au StatusLine InsertEnter * call Highlight_StatusLine("I")
1202   au StatusLine InsertLeave * call Highlight_StatusLine("i")
1203
1204   if has("syntax")
1205     au Display FocusGained,FocusLost * call <SID>ToggleCursorLine()
1206   endif
1207
1208   if has("signs")
1209     au Signs InsertEnter * call <SID>Highlight_Signs()
1210     au Signs InsertLeave * call <SID>Highlight_Signs()
1211   endif
1212
1213   au Mode BufEnter \[BufExplorer\] call <SID>BufExplorer_Map()
1214 endif
1215
1216 " Limit the size of the popup menu when completing.
1217 if has("insert_expand")
1218   se pumheight=20
1219 endif
1220
1221 " Make diffs vertical by default.
1222 if has("diff")
1223   se diffopt+=vertical
1224 endif
1225
1226 " Set size of numbers column.
1227 if has("linebreak")
1228   se numberwidth=5
1229 endif
1230
1231 " Add "previous tab" mapping as gb.
1232 map gb :tabprevious<CR>:<CR>
1233
1234 " Transparency.
1235 if has("gui_macvim")
1236   se transparency=15
1237 endif 
1238
1239 " Yet more GUI options.  Add tabs.
1240 if has("gui")
1241   se go+=e
1242 endif
1243
1244 " Perforce.
1245 let g:p4EnableMenu=1
1246 let g:p4Presets='P4CONFIG'
1247
1248 " BufExplorer.
1249 let g:bufExplorerShowRelativePath=1
1250 let g:bufExplorerSplitOutPathName=0
1251
1252 " NERDcommenter.
1253 let g:NERDSpaceDelims=1
1254 endif "}}}1
1255
1256 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1257 " Handle options only available in Vim 7.2 and above.
1258 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1259 if version >= "702" "{{{1
1260 if has("autocmd")
1261   " http://vim.wikia.com/wiki/Highlight_unwanted_spaces
1262   augroup WhitespaceMatch
1263   autocmd!
1264   au Display BufWinEnter * call Extra_Whitespace_Match()
1265   au Display Syntax * call Extra_Whitespace_Match()
1266   au Display BufWinLeave * call clearmatches()
1267   augroup END
1268
1269   fun! Extra_Whitespace_Match() "{{{2
1270     " \s\+            <whitespace>
1271     "            $    <before end of line>
1272     "        \@<!     <unless preceded by>
1273     "     \%#         <cursor position, ie when typing>
1274     let l:pattern = '\s\+\%#\@<!$'
1275     " Don't match single space in first column of diff.
1276     if &ft =~# '^diff$\|git'
1277       "         \@!  <unless also matching>
1278       " \(^\s$\)     <a single whitespace>
1279       let l:pattern = '\(^\s$\)\@!' . l:pattern
1280     endif
1281
1282     let l:hl = 'ctermfg=red guifg=red'
1283     if ! &list
1284       " Underline if we aren't using listchars.
1285       let l:hl = l:hl . ' cterm=underline gui=underline'
1286     endif
1287     highlight clear ExtraWhitespace
1288     exe "highlight ExtraWhitespace " . l:hl
1289     if exists('w:whitespace_match_number')
1290       try
1291         call matchdelete(w:whitespace_match_number)
1292       catch
1293       endtry
1294       call matchadd('ExtraWhitespace', l:pattern, 10, w:whitespace_match_number)
1295     else
1296       let w:whitespace_match_number = matchadd('ExtraWhitespace', l:pattern)
1297     endif
1298   endfun "}}}2
1299
1300   call Extra_Whitespace_Match()
1301 endif
1302
1303 endif "}}}1
1304
1305 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1306 " Handle options only available in Vim 7.3 and above.
1307 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1308 if version >= "703" "{{{1
1309 version 7.3
1310
1311 " Toggle persistent undo with \u.
1312 call Mapping("u", ":call <SID>Cycle_Undo()<CR>:<CR>")
1313 " Remove persistent undo file with \U.
1314 call Mapping("U", ":call <SID>Clear_Undo()<CR>:<CR>")
1315
1316 " Use a persistent undo file if it exists.
1317 fun! <SID>Check_Undo() "{{{2
1318   if filereadable(undofile(expand("%")))
1319     setlocal undofile
1320   endif
1321 endfun "}}}2
1322
1323 " Toggle persistent undo for this buffer.
1324 fun! <SID>Cycle_Undo() "{{{2
1325   if has("persistent_undo")
1326     let &undofile = ! &undofile
1327   endif
1328 endfun "}}}2
1329
1330 " Remove the persistent undo file for this buffer.
1331 fun! <SID>Clear_Undo() "{{{2
1332   if ! has("persistent_undo")
1333     return
1334   endif
1335
1336   setlocal noundofile
1337
1338   let l:f = expand("%")
1339   if l:f == ""
1340     return
1341   endif
1342
1343   let l:u = undofile(l:f)
1344   if l:u == ""
1345     return
1346   endif
1347
1348   if ! filereadable(l:u) || ! filewritable(l:u)
1349     return
1350   endif
1351
1352   call delete(l:u)
1353 endfun "}}}2
1354
1355 " Toggle ColorColumn at cursor position.
1356 fun! <SID>Cycle_ColorColumn() "{{{2
1357   if ! has("syntax")
1358     return
1359   endif
1360
1361   let l:cc = &colorcolumn
1362   let l:column = col(".")
1363   let l:re = ",*\\<" . l:column . "\\>"
1364   if l:cc =~# l:re
1365     let l:cc = substitute(l:cc, l:re, "", "g")
1366   else
1367     let l:cc = l:cc . "," . l:column
1368   endif
1369   let &colorcolumn = substitute(l:cc, "^,*", "", "")
1370 endfun "}}}2
1371
1372 if has("syntax")
1373   " Enable showing ColorColumn at cursor position with \CC.
1374   call Mapping("CC", ":call <SID>Cycle_ColorColumn()<CR>:<CR>")
1375   " Remove last shown ColorColumn with \Cc.
1376   call Mapping("Cc", ":let &colorcolumn=substitute(&colorcolumn, \",*[0-9]*$\", \"\", \"\")<CR>:<CR>")
1377   " Remove all ColorColumns with \Cx.
1378   call Mapping("Cx", ":se colorcolumn=<CR>:<CR>")
1379 endif
1380
1381 " Use persistent undo if available.
1382 if has("autocmd")
1383   if has("persistent_undo")
1384     au File BufReadPost * call <SID>Check_Undo()
1385   endif
1386
1387   if has("cursorbind")
1388     au Display WinEnter * if &diff | se cursorbind | endif
1389   endif
1390 endif
1391 endif "}}}1
1392
1393 " Resize after startup.
1394 if version >= "500" "{{{1
1395 if has("autocmd")
1396   au Display VimEnter * call Startup_Resize()
1397 endif
1398 endif "}}}1