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