Bash 4 stuff.
[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 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
17 "{{{1
18 " No compatibility mode.
19 se nocp
20
21 " Find stuff.
22 if has("win32") || has("win64")
23   se rtp=~/.vim,$VIMRUNTIME
24 endif
25
26 " Tabstop 2.
27 se ts=2
28 " And use spaces not tabs.
29 se expandtab
30 " And << and >> indent by 2.
31 se sw=2
32 " Backspace deletes full tab width at the start of a line.
33 se smarttab
34
35 " Allow backspace to delete before start of line.
36 se bs=2
37
38 " Don't jump to the start of the line when using H, L etc.
39 se nosol
40
41 " Show the ruler.
42 se ruler
43 " Show partial commands in the ruler.
44 se showcmd
45 " And always show the status line.
46 se laststatus=2
47
48 " Use C indent style.
49 se cindent
50 se cinkeys=0{,0},0),:,!^F,o,O,e
51 se cinoptions=b1,c2
52
53 " GUI options.
54 se go=aglmr
55
56 " Don't be bugged by messages at the bottom of the screen.
57 se shm=aot
58
59 " Find as you type.
60 se incsearch
61
62 " Case-insensitive search.
63 se ignorecase
64 " But override by typing capitals.
65 se smartcase
66
67 " Look for ctags in home directory first.
68 se tags=~/.tags,./tags,tags
69
70 " Don't timeout waiting to interpet, eg, <ESC>OA as an escape code.
71 se ttimeoutlen=100
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 noremap ' `
80 noremap ` '
81 "}}}1
82
83 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
84 " Handle options only available in Vim 5 and above.
85 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
86 if version >= "500" "{{{1
87 version 5.0
88
89 " Tell Vim we use dark backgrounds in our terminals.
90 if ! has("gui_running")
91   se bg=dark
92 endif
93
94 " Allow mouse use in a terminal but only if it can work.
95 if has("xterm_clipboard")
96   se mouse=nvir
97 endif
98
99 " Update more quickly.  For use with sign highlighting as polling for
100 " CursorMove makes redrawing slow.
101 if has("signs")
102   se updatetime=500
103 endif
104
105 " Enable tab-completion prompting for commands.
106 se wildmenu
107 " Don't list object files when globbing files to load.
108 se wildignore+=*.o,*.obj
109 " So there's no need to assign them low priority.
110 se suffixes-=*.o,*.obj
111
112 " Save sessions in UNIX format with / as file separator.  This is
113 " cross-platform.
114 se ssop+=unix,slash
115
116 " How often do we need to use ^A/^X on octals?
117 se nf=hex
118
119 " Nuke any pre-existing autocommands.
120 augroup Display
121 autocmd!
122 augroup Mode
123 autocmd!
124 if has("signs")
125   augroup Signs
126   autocmd!
127 endif
128 augroup StatusLine
129 autocmd!
130 augroup END
131
132 " Save the current window dimensions so we can restore them when we quit.
133 if ! exists("g:oldcols")
134   let g:oldcols=&columns
135 endif
136 if ! exists("g:oldlines")
137   let g:oldlines=&lines
138 endif
139
140 " More GUI options.  Add icon and tearoffs.
141 se go+=i
142 se go+=t
143
144 " Allow dynamic window resize even if we aren't in an xterm.
145 se t_WS=\e[8;%p1%d;%p2%dt
146
147 " Highlight search results.
148 se hlsearch
149
150 " Set graphical window title.
151 if has("win32") || has("win64")
152   " Windows taskbar entries are probably too small to show full titles.
153   se titlestring=%t
154 else
155   se titlestring=%{Show_TitleString()}
156 endif
157
158 " Syntax highlighting.  New versions will use syn enable instead.
159 if version < "600"
160   syn on
161 endif
162
163 " Catch typos.
164 command! W :w
165 command! Wq :wq
166 command! Wqa :wqa
167
168 " Helper to initialise a variable.
169 fun! Prep_Var(var, value) "{{{2
170   if exists(a:var)
171     return
172   endif
173   exe "let " . a:var . "=" . a:value
174 endfun "}}}2
175
176 " Set up our variables.
177 fun! Iain_Vars() "{{{2
178   call Prep_Var("w:iainlist", 0)
179   call Prep_Var("b:iainhex", 0)
180   call Prep_Var("b:iainverbose", 0)
181   " Window Flags: (F)ocused, (I)nsert mode, Cursor (H)old.
182   call Prep_Var("b:iainstatus", "'Fih'")
183   call Prep_Var("g:iainextracolumnsnumber", "''")
184   call Prep_Var("g:iainextracolumnslist", "''")
185   call Prep_Var("b:iaincul", 0)
186   if has("signs")
187     call Prep_Var("g:marksigns", 0)
188     call Prep_Var("g:firstsign", 100)
189   endif
190   call Prep_Var("g:resizable", "''")
191 endfun "}}}2
192
193 " Helper for status line.
194 " Show space, underscore or dollar sign depending on list mode.
195 fun! Show_List() "{{{2
196   call Iain_Vars()
197   if w:iainlist == 0
198     " No list.
199     return " "
200   elseif <SID>Has_Unicode()
201     if w:iainlist == 1
202       " Just tabs.
203       return "»"
204     else
205       " Full list.
206       return "¶"
207     endif
208   else
209     if w:iainlist == 1
210       return "_"
211     else
212       return "\$"
213     endif
214   endif
215 endfun "}}}2
216
217 " Helper for status line.
218 " Show c or C to denote case-sensitivity.
219 fun! Show_Case() "{{{2
220   if &ic
221     return "c"
222   else
223     return "C"
224   endif
225 endfun "}}}2
226
227 " Helper for status line.
228 " Show the size of the tabstop.
229 fun! Show_Tabstop() "{{{2
230   return &ts
231 endfun "}}}2
232
233 " Helper for status line.
234 " Show p when paste mode is on.
235 fun! Show_Paste() "{{{2
236   if &paste
237     return "p"
238   else
239     return ""
240   endif
241 endfun "}}}2
242
243 " Show the window title.
244 fun! Show_TitleString() "{{{2
245   if bufname("") == ""
246     let l:ts1='Vim'
247   else
248     " Vim 5 doesn't have printf.
249     let l:ts1=bufnr("")
250     if l:ts1 < 10
251       let l:ts1=" " . l:ts1
252     endif
253     let l:ts1=l:ts1 . ": " . expand('%t')
254   endif
255   let l:ts1=l:ts1 . " (" .  getcwd() . ")"
256   if has("clientserver")
257     let l:ts1=l:ts1 . " " . v:servername
258   endif
259   return l:ts1
260 endfun "}}}2
261
262 " Show the status line.
263 fun! Show_StatusLine() "{{{2
264   call Iain_Vars()
265   let l:sl1='%2n\:\ %<%1*%f%0*\ [%{Show_List()}%{Show_Case()}%{Show_Tabstop()}%{Show_Paste()}%Y%M%R]\ '
266   let l:sl3='L:%1*%4.6l%0*/%-4.6L\ C:%1*%3.6c%0*\ \|\ %P'
267   let l:hexformat='%b'
268   if b:iainhex
269     let l:hexformat='0\x%02B'
270   endif
271   if b:iainverbose
272     let l:sl1=l:sl1 . v:version . '\ %='
273     let l:sl2=l:hexformat . '\ \|\ P:%4.6o\ '
274   else
275     let l:sl1=l:sl1 . '%='
276     let l:sl2=''
277   endif
278   exec "set statusline=" . l:sl1 . l:sl2 . l:sl3
279 endfun "}}}2
280
281 " Toggle case-sensitivity.
282 fun! Invert_Case() "{{{2
283   let &ic = ! &ic
284 endfun "}}}2
285
286 " Can we resize this window?
287 fun! Can_Resize() "{{{2
288   call Iain_Vars()
289
290   if g:resizable == "0" || g:resizable == "1"
291     return g:resizable
292   endif
293
294   " Do we KNOW we can(not) resize?
295   if has("gui_running")
296     let g:resizable = 1
297   elseif $RESIZABLE == &term
298     let g:resizable = 1
299   elseif $RESIZABLE == "0"
300     let g:resizable = 0
301   else
302     " Assume we can.  Allow overriding.
303     let g:resizable = 1
304   endif
305   return g:resizable
306 endfun "}}}2
307
308 " Grow or shrink the window width.
309 fun! Resize_Columns(op, ...) "{{{2
310   if a:op == ""
311     return
312   endif
313
314   if ! Can_Resize()
315     return
316   endif
317
318   if a:0 == 0
319     " Vim 5 hardcodes the size of numbers column to 8.
320     if version >= "700"
321       let l:columns = &numberwidth
322     else
323       let l:columns = 8
324     endif
325   else
326     let l:columns = a:1
327   endif
328
329   exe "let l:resize=" . &columns . a:op . l:columns
330   let l:resize = "se columns=" . l:resize
331
332   " HACK: Inside screen there is an extra line for the status bar.  Vim
333   " manages the resize by sending an escape sequence to set the number of
334   " lines and number of columns in one action.  To do this it will first query
335   " the number of lines and then set <same number of lines> by <new number of
336   " columns>.  Because of the extra line for the status bar this results in
337   " the real terminal being shrunk by a line.  We ask for the terminal to grow
338   " by a line so it ends up actually being the same.
339   if &term =~ '^screen'
340     let l:resize = l:resize . " lines=" . (&lines + 1)
341   endif
342
343   exe l:resize
344 endfun "}}}2
345
346 " Grow or shrink the window height.
347 fun! Resize_Lines(op, lines) "{{{2
348   if a:op == ""
349     return
350   endif
351
352   if ! Can_Resize()
353     return
354   endif
355
356   exe "let l:resize=" . &lines . a:op . a:lines
357   if &term =~ '^screen'
358     let l:resize = l:resize + 1
359   endif
360   let l:resize = "se lines=" . l:resize
361
362   exe l:resize
363 endfun "}}}2
364
365 " Set extra columns depending on window status.
366 fun! Extra_Columns(extra, var, ...) "{{{2
367   " Vim 6 doesn't have winnr("$").  Determine which windows are open
368   " ourselves by using :windo to incremement a counter.  As Vim 5 
369   " doesn't have :windo we require Vim 6 for this.
370   if v:version < "600"
371     return ""
372   endif
373
374   " Remember which window we're in.
375   let l:winnr = winnr()
376   let l:num_windows = 0
377   windo let l:num_windows = l:num_windows + 1
378   " Switch back to the window we were in.
379   exe l:winnr . "wincmd w"
380
381   call Iain_Vars()
382
383   if a:0 == 0
384     let l:condition = ""
385   else
386     let l:condition = a:1
387   endif
388
389   let l:n = 0
390   let l:i = 1
391   let l:windows = ""
392   while l:n < l:num_windows
393     " If window w exists then getwinvar(w, "&modified") will be 0 or 1.
394     if getwinvar(l:i, "&modified") =~ '^\d'
395       let l:n = l:n + 1
396
397       let l:val = 0
398       exe "if getwinvar(" . l:i . ", '" . a:var . "') " . l:condition . " | let l:val = 1 | endif"
399       if l:val
400         exe "let l:windows = '" . l:windows . ":" . l:i . "'"
401       endif
402     endif
403     let l:i = l:i + 1
404   endwhile
405
406   let l:extra = "g:iainextracolumns" . a:extra
407   exe "let l:val = " . l:extra
408   exe "let " . l:extra . " = '" . l:windows . "'"
409
410   if l:windows == l:val
411     return ""
412   endif
413
414   if l:windows == ""
415     return "-"
416   elseif l:val == ""
417     return "+"
418   endif
419 endfun "}}}2
420
421 " Toggle number display.
422 fun! Number(resize) "{{{2
423   call Iain_Vars()
424   let &number = ! &number
425
426   " Ensure we keep track of any extra columns even if we aren't resizing.
427   " This prevents confusion when number is set at startup.
428   let l:extra = Extra_Columns("number", "&number")
429
430   if a:resize
431     call Resize_Columns(l:extra)
432   endif
433 endfun "}}}2
434
435 " Restore window size.
436 if ! has("gui_running")
437   au Display VimLeave * if exists("g:oldcols") | call Resize_Columns("-", (&columns - g:oldcols)) | endif
438   au Display VimLeave * if exists("g:oldlines") | call Resize_Lines("-", (&lines - g:oldlines)) | endif
439 endif
440
441 " Map Makefile mode.
442 au Mode BufEnter * if &ft == "make" | call MakeMode_map() | endif
443 au Mode BufLeave * if &ft == "make" | call MakeMode_unmap() | endif
444
445 " Entering Make mode.
446 fun! MakeMode_map() "{{{2
447   call Iain_Vars()
448   let w:iainlist=1
449   call Cycle_List()
450   set ts=8
451   set noexpandtab
452 endfun "}}}2
453
454 " Leaving Make mode.
455 fun! MakeMode_unmap() "{{{2
456   call Cycle_List()
457   set ts=2
458   set expandtab
459 endfun "}}}2
460
461 " Show the status line for the first time.
462 call Show_StatusLine()
463
464 " Function to create mappings with either a hardcoded \ or <Leader>.
465 fun! Mapping(keysequence,mapping) "{{{2
466   if version < "600"
467     exec "map \\" . a:keysequence . " " . a:mapping
468   else
469     exec "map <Leader>" . a:keysequence . " " . a:mapping
470   endif
471 endfun "}}}2
472
473 " Use - and = to create underlines.
474 call Mapping("-", "yyp:s/./-/g<RETURN>:let @/=''<RETURN>:<RETURN>")
475 call Mapping("=", "yyp:s/./=/g<RETURN>:let @/=''<RETURN>:<RETURN>")
476
477 " Change to ts=2 with \2.
478 call Mapping("2", ":se ts=2<CR>:<CR>")
479 " Change to ts=4 with \4.
480 call Mapping("4", ":se ts=4<CR>:<CR>")
481 " Change to ts=8 with \8.
482 call Mapping("8", ":se ts=8<CR>:<CR>")
483 " Change to ts=16 with \6.
484 call Mapping("6", ":se ts=16<CR>:<CR>")
485 " Change to ts=32 with \3.
486 call Mapping("3", ":se ts=32<CR>:<CR>")
487 " Toggle paste mode with \p.
488 call Mapping("p", ":se paste!<CR>:<CR>")
489 " Swap case-sensitivity with \c.
490 call Mapping("C", ":call Invert_Case()<CR>:<CR>")
491 " Change number mode with \n.
492 call Mapping("n", ":call Number(1)<CR>:<CR>")
493 " Expand or shrink window size with \> and \<.
494 call Mapping(">", ":call Resize_Columns('+')<CR>:<CR>")
495 call Mapping("<", ":call Resize_Columns('-')<CR>:<CR>")
496 " Clear search pattern with \/.
497 call Mapping("/", ":let @/=\"\"<CR>:<CR>")
498
499 " Forget the Ex mode mapping.
500 map Q <NOP>
501
502 " Vim tip 99: What's the highlighting group under the cursor?
503 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>")
504
505 fun! Uncluttered_Buffer() "{{{2
506   if exists("uncluttered_buffer")
507     if uncluttered_buffer == 1
508       return 1
509     endif
510   endif
511
512   if version >= "600"
513     if &buftype != ''
514       return 1
515     endif
516   endif
517
518   if &ft == 'perforce'
519     return 1
520   endif
521
522   if &ft == 'svn'
523     return 1
524   endif
525
526   if &ft == 'gitcommit'
527     return 1
528   endif
529
530   return 0
531 endfun "}}}2
532
533 fun! Startup_Resize() "{{{2
534   let l:columns = 0
535
536   " Resize for numbers.
537   if &number
538     if version >= "700"
539       let l:columns = &numberwidth
540     else
541       let l:columns = 8
542     endif
543   endif
544
545   " Resize for signs.
546   if has("signs")
547     if g:marksigns
548       if version >= "600"
549         let l:columns = l:columns + 2
550       endif
551     endif
552   endif
553
554   if g:oldcols < (80 + l:columns)
555     call Resize_Columns("+", l:columns)
556   endif
557 endfun "}}}2
558
559 " Change status bar colour when various things happen.
560 " Flags: H/h: Cursor held/moved.
561 "        F/f: Focus gained/lost.
562 "        I/i: Insert mode entered/left.
563 fun! Highlight_StatusLine(flag) "{{{2
564   " Get current status.
565   call Iain_Vars()
566
567   " Change the status based on the flag.  XXX: Does Vim let us to do flags?
568   let l:ic = &ic
569   set ic
570   let b:iainstatus = substitute(b:iainstatus, a:flag, a:flag, "")
571   let &ic = l:ic
572
573   let l:normalcolour = "darkblue"
574   let l:editingcolour = "darkmagenta"
575   let l:warningcolour = "darkred"
576   let l:readonlycolour = "red"
577
578   " Default colour.
579   let l:colour = l:normalcolour
580   " Maybe override depending on status.
581   if b:iainstatus =~# "H"
582     if b:iainstatus =~# "I"
583       " Held in insert mode.  Add extra highlight if we don't have focus.
584       if b:iainstatus =~# "f"
585         let l:colour = l:warningcolour
586       else
587         let l:colour = l:editingcolour
588       endif
589     endif
590   else
591     if b:iainstatus =~# "I"
592       " Regular insert mode.
593       let l:colour = l:editingcolour
594     endif
595   endif
596
597   " Override again if readonly.
598   if l:colour != l:normalcolour
599     if getbufvar("", "&ro")
600       let l:colour = l:readonlycolour
601     endif
602   endif
603
604   let l:termcolour = Iain_Colour(l:colour)
605
606   exec "highlight StatusLine gui=none term=none cterm=none guifg=white guibg=" . l:colour . " ctermfg=white ctermbg=" . l:termcolour
607   exec "highlight User1 gui=bold term=bold cterm=bold guifg=white guibg=" . l:colour . " ctermfg=white ctermbg=" . l:termcolour
608 endfun "}}}2
609
610 fun! Iain_Colour(colour) "{{{2
611   if &t_Co == 88
612     if a:colour == "darkblue"
613       return 17
614     elseif a:colour == "darkmagenta"
615       return 33
616     elseif a:colour == "darkred"
617       return 32
618     elseif a:colour == "red"
619       return 64
620     endif
621   elseif &t_Co == 256
622     if a:colour == "darkblue"
623       return 17
624     elseif a:colour == "darkmagenta"
625       return 90
626     elseif a:colour == "darkred"
627       return 88
628     elseif a:colour == "red"
629       return 196
630     endif
631   else
632     return a:colour
633   endif
634 endfun "}}}2
635
636 au StatusLine VimEnter * call Highlight_StatusLine("")
637
638 " Show numbers by default.
639 au Display VimEnter * if ! Uncluttered_Buffer() | call Number(0) | endif
640
641 " Position the compview plugin window.
642 au Display BufEnter -SearchResults- set buftype=nowrite | set nonumber | wincmd J
643 endif "}}}1
644
645 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
646 " Handle options only available in Vim 6 and above.
647 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
648 if version >= "600" "{{{1
649 version 6.0
650
651 if has("gui_win32")
652   se encoding=utf-8
653 endif
654
655 " Remember quickfix state.
656 let g:quickfixing=0
657
658 " Set indenting by filetype.
659 filetype indent on
660
661 " Less intrusive syntax highlighting.
662 syn enable
663
664 " Set colours.
665 if has("gui_running")
666   if has("win32") || has("win64")
667     exe "silent se guifont=DejaVu_Sans_Mono:h10:cANSI"
668   else
669     exe "silent se guifont=DejaVu\\ Sans\\ Mono\\ 10"
670   endif
671 endif
672 if has("gui_running") || &t_Co > 16
673   exe "silent colo iain"
674 endif
675
676 " Ignore whitespace when diffing.
677 se diffopt=filler,iwhite
678
679 " Expand window when doing a vertical diff.
680 if &diff
681   if &columns < 161
682     let &columns = &columns * 2
683   endif
684 endif
685
686 " Remember that we are opening the quickfix window.
687 au Mode BufWinEnter quickfix let g:quickfixing=1
688 au Mode BufUnload * if &ft == "qf" | let g:quickfixing=0 | endif
689
690 " Allow in-place editing of crontabs.
691 au Mode FileType crontab set backupcopy=yes
692
693 " Make * and # work the way you expect in visual mode.
694 vnoremap * y/\V<C-R>=substitute(escape(@@,"/\\"),"\n","\\\\n","ge")<CR><CR>
695 vnoremap # y?\V<C-R>=substitute(escape(@@,"?\\"),"\n","\\\\n","ge")<CR><CR>
696
697 " Set mark and update highlighting.
698 if has("signs")
699   au Signs BufReadPost * call <SID>Highlight_Signs()
700   au Signs CursorHold * call <SID>Highlight_Signs()
701 endif
702
703 " Helper to set buffer variable for a given sign.
704 fun! <SID>Prep_Sign(sign) "{{{2
705   if ! exists("b:sign" . a:sign) || ! g:marksigns
706     exe "let b:sign" . a:sign . "=0"
707    endif
708 endfun "}}}2
709
710 fun! <SID>Place_Sign(number, line, old, name) "{{{2
711   if a:line == a:old
712     return a:old
713   endif
714
715   exe "sign unplace " . (g:firstsign + a:number) . " buffer=" . bufnr("")
716   " Don't place the sign if it would conflict with the last change sign.
717   exe "sign place " . (g:firstsign + a:number) . " line=" . a:line . " name=" . a:name . " buffer=" . bufnr("")
718   return a:line
719 endfun "}}}2
720
721 fun! <SID>Highlight_Signs(...) "{{{2
722   if ! has("signs") || ! g:marksigns || Uncluttered_Buffer()
723     return
724   endif
725
726   let l:signs = g:iainsigns
727   let l:sign = ""
728   let l:i = 0
729   while strlen(l:signs)
730     let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
731
732     let l:name = substitute(l:sign, '[:.=-].*', "", "")
733     let l:var = tolower(l:name)
734     let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
735     let l:ascii = matchstr(l:sign, '^:.')
736     let l:mark = substitute(l:sign, '^\(:.\)*[.=-]', "", "")
737     if strlen(l:ascii)
738       let l:ascii = substitute(l:ascii, '^:', "", "")
739     else
740       let l:ascii = l:mark
741     endif
742     let l:ascii = substitute(l:ascii, '"', '\\"', "")
743
744     call <SID>Prep_Sign(l:var)
745     exe "let " . l:var . " = <SID>Place_Sign(" . l:i . ", line(\"'" . l:ascii . "\"), b:sign" . l:var . ", \"Mark" . l:name . "\")"
746     let l:i = l:i + 1
747
748     let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
749   endwhile
750 endfun "}}}2
751
752 " Toggle signs.
753 fun! <SID>Cycle_Signs(resize) "{{{2
754   if ! has("signs")
755     return
756   endif
757   call Iain_Vars()
758   let g:marksigns = ! g:marksigns
759
760   " Retrofit arrays on to Vim 6.
761   if ! exists("g:iainsigns")
762     " Signs are defined in g:iainsigns.  The syntax is as follows:
763     "
764     " Sign ::= Name (':' Mark)* Type Symbol
765     " Type ::= '=' | '-' | '.'
766     "
767     " Signs with Type '=' will be highlighted with the MarkSign group.
768     " Signs with Type '-' will be highlighted with the MarkLine group.
769     " Signs with Type '.' will be highlighted with the MarkDot group.
770     " Define the Mark where Symbol is not also the mark name, eg "']".
771     if <SID>Has_Unicode()
772       let g:iainsigns = "Dash:'=’ Dot:..• Quote:\"=” Caret:^.ʌ"
773     else
774       let g:iainsigns = "Dash=' Dot:..* Quote=\" Caret.^"
775     endif
776     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"
777   endif
778
779   if g:marksigns
780     " Signs to highlight marks.
781     " Syntax won't work properly in Vim 6.
782     let l:signs = g:iainsigns
783     let l:sign = ""
784     while strlen(l:signs)
785       let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
786
787       let l:sign = substitute(l:sign, ':.', "", "")
788       let l:sign = substitute(l:sign, '=', " texthl=MarkSign text=", "")
789       let l:sign = substitute(l:sign, '\.', " texthl=MarkDot text=", "")
790       let l:sign = substitute(l:sign, '-', " texthl=MarkLine linehl=MarkLine text=", "")
791
792       exe "sign define Mark" . l:sign
793
794       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
795     endwhile
796
797     if a:resize
798       call Resize_Columns("+", 2)
799     endif
800     call <SID>Highlight_Signs()
801   else
802     let l:i = 0
803     while l:i < 25
804       exe "sign unplace " . (g:firstsign + l:i)
805       let l:i = l:i + 1
806     endwhile
807
808     let l:signs = g:iainsigns
809     let l:sign = ""
810     while strlen(l:signs)
811       let l:sign = matchstr(l:signs, '^[A-Za-z]\+')
812
813       exe "sign undefine Mark" . l:sign
814       call <SID>Prep_Sign(tolower(l:sign))
815       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
816     endwhile
817
818     if a:resize
819       call Resize_Columns("-", 2)
820     endif
821   endif
822 endfun "}}}2
823
824 " Do we have Unicode?
825 fun! <SID>Has_Unicode() "{{{2
826   if ! has('multi_byte')
827     return 0
828   endif
829
830   if version < "602"
831     return 0
832   endif
833
834   if &tenc =~? '^u\(tf\|cs\)'
835     return 1
836   endif
837
838   if ! strlen(&tenc) && &enc =~? '^u\(tf\|cs\)'
839     return 1
840   endif
841
842   return 0
843 endfun "}}}2
844
845 " Change list mode.
846 fun! Cycle_List() "{{{2
847   " Pretty UTF-8 listchars.
848   if <SID>Has_Unicode()
849     let basic='tab:»·,trail:…,extends:«,precedes:»'
850     let eol='eol:¶'
851     if version >= "700"
852       let basic=basic . ',nbsp:•'
853     endif
854   else
855     let basic='tab:\\_,trail:_,extends:<,precedes:>'
856     let eol='eol:$'
857     if version >= "700"
858       let basic=basic . ',nbsp:+'
859     endif
860   endif
861   call Iain_Vars()
862   let w:iainlist = w:iainlist + 1
863   if w:iainlist > 2
864     let w:iainlist = 0
865   endif
866   if w:iainlist == 0
867     setlocal nolist
868   elseif w:iainlist == 1
869     exec "setlocal lcs=" . basic
870     setlocal list
871   else
872     exec "setlocal lcs=" . basic . "," . eol
873     setlocal list
874   endif
875
876   call Resize_Columns(Extra_Columns("list", "iainlist", " == 2"), 1)
877 endfun "}}}2
878
879 " Cycle between hex and decimal display of toolbar stuff.
880 fun! Cycle_HexStatusLine() "{{{2
881   call Iain_Vars()
882   let b:iainhex = ! b:iainhex
883   call Show_StatusLine()
884 endfun "}}}2
885
886 " Cycle verbose display of toolbar stuff.
887 fun! Cycle_VerboseStatusLine() "{{{2
888   call Iain_Vars()
889   let b:iainverbose = ! b:iainverbose
890   call Show_StatusLine()
891 endfun "}}}2
892
893 " Toggle quickfix window.
894 fun! Cycle_Quickfix() "{{{2
895   if g:quickfixing == 1
896     cclose
897     let g:quickfixing=0
898   else
899     copen
900   endif
901 endfun "}}}2
902
903 " Swap hex/decimal statusline with \x.
904 call Mapping("x", ":call Cycle_HexStatusLine()<CR>:<CR>")
905 " Change statusline verbosity with \v.
906 call Mapping("V", ":call Cycle_VerboseStatusLine()<CR>:<CR>")
907 " Cycle list styles with \l.
908 call Mapping("l", ":call Cycle_List()<CR>:<CR>")
909 " Toggle tags with \t.
910 call Mapping("t", ":Tlist<CR>")
911 " Change foldmethod with \f.
912 call Mapping("f", ":se foldenable!<CR>:<CR>")
913 " Toggle quickfix window with \q.
914 call Mapping("q", ":call Cycle_Quickfix()<CR>:<CR>")
915 " Rerun filetype detection with \s.  The s is for syntax, as this will be
916 " updated as a side-effect.
917 call Mapping("S", ":filetype detect<CR>:<CR>")
918 " Toggle marks with \m.
919 call Mapping("m", ":call <SID>Cycle_Signs(1)<CR>:<CR>")
920
921 " Show signs by default.
922 au Display VimEnter * call <SID>Cycle_Signs(0)
923 endif "}}}1
924
925 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
926 " Handle options only available in Vim 7 and above.
927 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
928 if version >= "700" "{{{1
929 version 7.0
930
931 " Helper to show tab name.
932 fun! <SID>TabName(label, gui) "{{{2
933   let l:label = a:label
934   if l:label == ""
935     let l:label = "No Name"
936     if a:gui
937       let l:label = "[" . l:label . "]"
938     endif
939   else
940     let l:label = fnamemodify(l:label, ":t")
941     if strlen(l:label) >= 18
942       let l:label = l:label[0:17] . ".."
943     endif
944   endif
945   return l:label
946 endfun "}}}2
947
948 " Find out if any buffer was modified.
949 fun! <SID>TabModified(buflist) "{{{2
950   let l:i = 0
951   while l:i < len(a:buflist)
952     if getbufvar(a:buflist[l:i], "&modified") == 1
953       return "+"
954     endif
955     let l:i = l:i + 1
956   endwhile
957   return ""
958 endfun "}}}2
959
960 " Tab line.
961 fun! Show_TabLine() "{{{2
962   let l:s = "%#TabLineFill#Tabs:"
963
964   let l:i = 0
965   while l:i < tabpagenr("$")
966     let l:i = l:i + 1
967     " Get the label.
968     let l:buflist = tabpagebuflist(l:i)
969     let l:winnr = tabpagewinnr(l:i)
970     let l:n = tabpagewinnr(l:i, "$")
971     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
972     let l:modified = <SID>TabModified(l:buflist)
973
974     " Choose highlighting.
975     if l:i == tabpagenr()
976       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
977     else
978       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
979     endif
980   endwhile
981
982   " Padding.
983   let l:s .= "%#TabLine#%T"
984   return l:s
985 endfun "}}}2
986
987 " Per tab label for the GUI.
988 fun! Show_GUITabLine() "{{{2
989   let l:buflist = tabpagebuflist(v:lnum)
990   let l:winnr = tabpagewinnr(v:lnum)
991   let l:s = tabpagewinnr(v:lnum, "$")
992   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
993   let l:modified = <SID>TabModified(l:buflist)
994
995   let l:s .= l:modified . " " . l:label
996   return l:s
997 endfun "}}}2
998
999 " Toggle highlighting cursor line when focus changes.
1000 fun! <SID>ToggleCursorLine() "{{{2
1001   call Iain_Vars()
1002
1003   if b:iainstatus =~# "f" && b:iainstatus =~# "H" && b:iainstatus =~# "I"
1004     " Focus lost while held in insert mode.
1005     let b:iaincul = getbufvar("", "&cursorline")
1006     setlocal cursorline
1007   elseif ! b:iaincul
1008     setlocal nocursorline
1009   endif
1010 endfun "}}}2
1011
1012 se tabline=%!Show_TabLine()
1013 se guitablabel=%!Show_GUITabLine()
1014
1015 au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1016 au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1017 au StatusLine FocusGained * call Highlight_StatusLine("F")
1018 au StatusLine FocusLost * call Highlight_StatusLine("f")
1019 au StatusLine InsertEnter * call Highlight_StatusLine("I")
1020 au StatusLine InsertLeave * call Highlight_StatusLine("i")
1021
1022 au Display FocusGained,FocusLost * call <SID>ToggleCursorLine()
1023
1024 if has("signs")
1025   au Signs InsertEnter * call <SID>Highlight_Signs()
1026   au Signs InsertLeave * call <SID>Highlight_Signs()
1027 endif
1028
1029 " Limit the size of the popup menu when completing.
1030 se pumheight=20
1031
1032 " Make diffs vertical by default.
1033 se diffopt+=vertical
1034
1035 " Set size of numbers column.
1036 se numberwidth=5
1037
1038 " Add "previous tab" mapping as gb.
1039 map gb :tabprevious<CR>:<CR>
1040
1041 " Transparency.
1042 if has("gui_macvim")
1043   se transparency=15
1044 endif 
1045
1046 " Yet more GUI options.  Add tabs.
1047 se go+=e
1048
1049 " Perforce.
1050 let g:p4EnableMenu=1
1051 let g:p4Presets='P4CONFIG'
1052
1053 " BufExplorer.
1054 let g:bufExplorerShowRelativePath=1
1055 let g:bufExplorerSplitOutPathName=0
1056 endif "}}}1
1057
1058 " Resize after startup.
1059 if version >= "500" "{{{1
1060 au Display VimEnter * call Startup_Resize()
1061 endif "}}}1