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