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