Sign precedence.
[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 nnoremap ' `
80 nnoremap ` '
81
82 " Select previous widnow.
83 nnoremap <C-w>^ <C-w>p
84 nnoremap <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("win32") || has("win64")
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   " The :syntax enable command tries to source the syntax.vim runtime script.
814   " Parsing this .vimrc will fail if for some reason the runtime doesn't
815   " exist, as could be the case if the binary was installed with no support
816   " files.  GNU On Windows is one example of an incomplete installation.
817   try
818     syn enable
819   catch
820   endtry
821 endif
822
823 " Set colours.
824 if has("gui_running")
825   if has("win32") || has("win64")
826     exe "silent se guifont=DejaVu_Sans_Mono:h10:cANSI"
827   else
828     exe "silent se guifont=DejaVu\\ Sans\\ Mono\\ 10"
829   endif
830 endif
831 if has("gui_running") || &t_Co > 16
832   exe "silent colo iain"
833 endif
834
835 " Ignore whitespace when diffing.
836 if has("diff")
837   se diffopt=filler,iwhite
838 endif
839
840 if has("autocmd")
841   if has("quickfix")
842     " Remember that we are opening the quickfix window.
843     au Mode BufWinEnter quickfix let g:quickfixing=1
844     au Mode BufUnload * if &ft == "qf" | let g:quickfixing=0 | endif
845   endif
846
847   " Allow in-place editing of crontabs.
848   au Mode FileType crontab set backupcopy=yes
849 endif
850
851 " Make * and # work the way you expect in visual mode.
852 vnoremap * y/\V<C-R>=substitute(escape(@@,"/\\"),"\n","\\\\n","ge")<CR><CR>
853 vnoremap # y?\V<C-R>=substitute(escape(@@,"?\\"),"\n","\\\\n","ge")<CR><CR>
854
855 " Set mark and update highlighting.
856 if has("signs")
857   au Signs BufReadPost * call <SID>Highlight_Signs()
858   au Signs CursorHold * call <SID>Highlight_Signs()
859 endif
860
861 " Helper to set buffer variable for a given sign.
862 fun! <SID>Prep_Sign(sign) "{{{2
863   if ! exists("b:sign" . a:sign) || ! g:marksigns
864     exe "let b:sign" . a:sign . "=0"
865    endif
866 endfun "}}}2
867
868 fun! <SID>Place_Sign(number, line, old, name) "{{{2
869   if a:line == a:old
870     return a:old
871   endif
872
873   exe "sign unplace " . (g:firstsign + a:number) . " buffer=" . bufnr("")
874   " Don't place the sign if it would conflict with the last change sign.
875   exe "sign place " . (g:firstsign + a:number) . " line=" . a:line . " name=" . a:name . " buffer=" . bufnr("")
876   return a:line
877 endfun "}}}2
878
879 fun! <SID>Highlight_Signs(...) "{{{2
880   if ! has("signs") || ! g:marksigns || Uncluttered_Buffer()
881     return
882   endif
883
884   let l:signs = g:iainsigns
885   let l:sign = ""
886   let l:i = 0
887   while strlen(l:signs)
888     let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
889
890     let l:name = substitute(l:sign, '[:.=-].*', "", "")
891     let l:var = tolower(l:name)
892     let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
893     let l:ascii = matchstr(l:sign, '^:.')
894     let l:mark = substitute(l:sign, '^\(:.\)*[.=-]', "", "")
895     if strlen(l:ascii)
896       let l:ascii = substitute(l:ascii, '^:', "", "")
897     else
898       let l:ascii = l:mark
899     endif
900     let l:ascii = substitute(l:ascii, '"', '\\"', "")
901
902     call <SID>Prep_Sign(l:var)
903     exe "let " . l:var . " = <SID>Place_Sign(" . l:i . ", line(\"'" . l:ascii . "\"), b:sign" . l:var . ", \"Mark" . l:name . "\")"
904     let l:i = l:i + 1
905
906     let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
907   endwhile
908 endfun "}}}2
909
910 " Toggle signs.
911 fun! <SID>Cycle_Signs(resize) "{{{2
912   if ! has("signs")
913     return
914   endif
915   call Iain_Vars()
916   let g:marksigns = ! g:marksigns
917
918   " Retrofit arrays on to Vim 6.
919   if ! exists("g:iainsigns")
920     " Signs are defined in g:iainsigns.  The syntax is as follows:
921     "
922     " Sign ::= Name (':' Mark)* Type Symbol
923     " Type ::= '=' | '-' | '.'
924     "
925     " Signs with Type '=' will be highlighted with the MarkSign group.
926     " Signs with Type '-' will be highlighted with the MarkLine group.
927     " Signs with Type '.' will be highlighted with the MarkDot group.
928     " Define the Mark where Symbol is not also the mark name, eg "']".
929     let 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"
930     if Has_Unicode()
931       let g:iainsigns = g:iainsigns . " Quote:\"=” Dash:'=’ Caret:^.ʌ Dot:..•"
932     else
933       let g:iainsigns = g:iainsigns . " Quote=\" Dash=' Caret.^ Dot:..*"
934     endif
935   endif
936
937   if g:marksigns
938     " Signs to highlight marks.
939     " Syntax won't work properly in Vim 6.
940     let l:signs = g:iainsigns
941     let l:sign = ""
942     while strlen(l:signs)
943       let l:sign = matchstr(l:signs, '^[A-Za-z]\+\(:.\)*[.=-][^ ]\+')
944
945       let l:name = substitute(l:sign, '[:.=-].*', "", "")
946       let l:sign = substitute(l:sign, '^[A-Za-z]\+', "", "")
947       let l:ascii = matchstr(l:sign, '^:.')
948       let l:mark = substitute(l:sign, '^\(:.\)*[.=-]', "", "")
949       if strlen(l:ascii)
950         let l:ascii = substitute(l:ascii, '^:', "", "")
951         let l:ascii = matchstr(l:ascii, '^.')
952       else
953         let l:ascii = l:mark
954       endif
955       let l:ascii = substitute(l:ascii, '"', '\\"', "")
956       let l:type = substitute(l:sign, '^:.', "", "")
957       let l:type = matchstr(l:type, '^.')
958
959       let l:hl = ""
960       if l:type == "="
961         let l:hl = "texthl=MarkSign text="
962       elseif l:type == "."
963         let l:hl = "texthl=MarkDot text="
964       elseif l:type == "-"
965         let l:hl = "texthl=MarkLine text="
966       endif
967
968       exe "sign define Mark" . l:name . " " . l:hl . l:mark
969
970       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
971     endwhile
972
973     if a:resize
974       call Resize_Columns("+", 2)
975     endif
976     call <SID>Highlight_Signs()
977   else
978     let l:i = 0
979     while l:i < 25
980       exe "sign unplace " . (g:firstsign + l:i)
981       let l:i = l:i + 1
982     endwhile
983
984     let l:signs = g:iainsigns
985     let l:sign = ""
986     while strlen(l:signs)
987       let l:sign = matchstr(l:signs, '^[A-Za-z]\+')
988
989       exe "sign undefine Mark" . l:sign
990       call <SID>Prep_Sign(tolower(l:sign))
991       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
992     endwhile
993
994     if a:resize
995       call Resize_Columns("-", 2)
996     endif
997   endif
998 endfun "}}}2
999
1000 " Change list mode.
1001 fun! Cycle_List() "{{{2
1002   " Pretty UTF-8 listchars.
1003   if Has_Unicode()
1004     let basic='tab:»·,trail:…,extends:«,precedes:»'
1005     let eol='eol:¶'
1006     if version >= "700"
1007       let basic=basic . ',nbsp:•'
1008     endif
1009   else
1010     let basic='tab:\\_,trail:_,extends:<,precedes:>'
1011     let eol='eol:$'
1012     if version >= "700"
1013       let basic=basic . ',nbsp:+'
1014     endif
1015   endif
1016   call Iain_Vars()
1017   let w:iainlist = w:iainlist + 1
1018   if w:iainlist > 2
1019     let w:iainlist = 0
1020   endif
1021   if w:iainlist == 0
1022     setlocal nolist
1023   elseif w:iainlist == 1
1024     exec "setlocal lcs=" . basic
1025     setlocal list
1026   else
1027     exec "setlocal lcs=" . basic . "," . eol
1028     setlocal list
1029   endif
1030
1031   call Resize_Columns(Extra_Columns("list", "iainlist", " == 2"), 1)
1032   call Extra_Whitespace_Match()
1033 endfun "}}}2
1034
1035 " Cycle between hex and decimal display of toolbar stuff.
1036 fun! Cycle_HexStatusLine() "{{{2
1037   call Iain_Vars()
1038   let b:iainhex = ! b:iainhex
1039   call Show_StatusLine()
1040 endfun "}}}2
1041
1042 " Cycle verbose display of toolbar stuff.
1043 fun! Cycle_VerboseStatusLine() "{{{2
1044   call Iain_Vars()
1045   let b:iainverbose = ! b:iainverbose
1046   call Show_StatusLine()
1047 endfun "}}}2
1048
1049 " Toggle quickfix window.
1050 fun! Cycle_Quickfix() "{{{2
1051   if ! has("quickfix")
1052     return
1053   endif
1054   if g:quickfixing == 1
1055     cclose
1056     let g:quickfixing=0
1057   else
1058     copen
1059   endif
1060 endfun "}}}2
1061
1062 " Toggle showing alternate buffer information.
1063 fun! Cycle_Alt() "{{{2
1064   call Iain_Vars()
1065   let b:iainalt = ! b:iainalt
1066   call Show_StatusLine()
1067 endfun "{{{2
1068
1069 " To be overridden later if applicable.
1070 fun! Extra_Whitespace_Match() "{{{2
1071   " NOP.
1072 endfun "}}}2
1073
1074 " Swap hex/decimal statusline with \x.
1075 call Mapping("x", ":call Cycle_HexStatusLine()<CR>:<CR>")
1076 " Change statusline verbosity with \v.
1077 call Mapping("V", ":call Cycle_VerboseStatusLine()<CR>:<CR>")
1078 " Cycle list styles with \l.
1079 call Mapping("l", ":call Cycle_List()<CR>:<CR>")
1080 " Toggle tags with \t.
1081 call Mapping("t", ":Tlist<CR>")
1082 " Change foldmethod with \f.
1083 call Mapping("f", ":se foldenable!<CR>:<CR>")
1084 " Toggle quickfix window with \q.
1085 call Mapping("q", ":call Cycle_Quickfix()<CR>:<CR>")
1086 " Rerun filetype detection with \s.  The s is for syntax, as this will be
1087 " updated as a side-effect.
1088 call Mapping("S", ":filetype detect<CR>:<CR>")
1089 " Toggle marks with \m.
1090 call Mapping("m", ":call <SID>Cycle_Signs(1)<CR>:<CR>")
1091
1092 if has("autocmd")
1093   " Show signs by default.
1094   au Display VimEnter * call <SID>Cycle_Signs(0)
1095 endif
1096 endif "}}}1
1097
1098 " move.
1099 nmap <A-u> <Plug>MoveLineHalfPageUp
1100 nmap <A-d> <Plug>MoveLineHalfPageDown
1101 vmap <A-u> <Plug>MoveBlockHalfPageUp
1102 vmap <A-d> <Plug>MoveBlockHalfPageDown
1103
1104 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1105 " Handle options only available in Vim 7 and above.
1106 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1107 if version >= "700" "{{{1
1108 version 7.0
1109
1110 " Helper to show tab name.
1111 fun! <SID>TabName(label, gui) "{{{2
1112   let l:label = a:label
1113   if l:label == ""
1114     let l:label = "No Name"
1115     if a:gui
1116       let l:label = "[" . l:label . "]"
1117     endif
1118   else
1119     let l:label = fnamemodify(l:label, ":t")
1120     if strlen(l:label) >= 18
1121       let l:label = l:label[0:17] . ".."
1122     endif
1123   endif
1124   return l:label
1125 endfun "}}}2
1126
1127 " Find out if any buffer was modified.
1128 fun! <SID>TabModified(buflist) "{{{2
1129   let l:i = 0
1130   while l:i < len(a:buflist)
1131     if getbufvar(a:buflist[l:i], "&modified") == 1
1132       return "+"
1133     endif
1134     let l:i = l:i + 1
1135   endwhile
1136   return ""
1137 endfun "}}}2
1138
1139 " Tab line.
1140 fun! Show_TabLine() "{{{2
1141   let l:s = "%#TabLineFill#Tabs:"
1142
1143   let l:i = 0
1144   while l:i < tabpagenr("$")
1145     let l:i = l:i + 1
1146     " Get the label.
1147     let l:buflist = tabpagebuflist(l:i)
1148     let l:winnr = tabpagewinnr(l:i)
1149     let l:n = tabpagewinnr(l:i, "$")
1150     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
1151     let l:modified = <SID>TabModified(l:buflist)
1152
1153     " Choose highlighting.
1154     if l:i == tabpagenr()
1155       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
1156     else
1157       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
1158     endif
1159   endwhile
1160
1161   " Padding.
1162   let l:s .= "%#TabLine#%T"
1163   return l:s
1164 endfun "}}}2
1165
1166 " Per tab label for the GUI.
1167 fun! Show_GUITabLine() "{{{2
1168   let l:buflist = tabpagebuflist(v:lnum)
1169   let l:winnr = tabpagewinnr(v:lnum)
1170   let l:s = tabpagewinnr(v:lnum, "$")
1171   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
1172   let l:modified = <SID>TabModified(l:buflist)
1173
1174   let l:s .= l:modified . " " . l:label
1175   return l:s
1176 endfun "}}}2
1177
1178 " Toggle highlighting cursor line when focus changes.
1179 fun! <SID>ToggleCursorLine() "{{{2
1180   call Iain_Vars()
1181
1182   if b:iainstatus =~# "H" && b:iainstatus =~# "I"
1183     " We are held in insert mode.
1184     if b:iainstatus =~# "f"
1185       " And focus was lost.
1186       let b:iaincul = getbufvar("", "&cursorline")
1187       setlocal cursorline
1188     elseif ! b:iaincul
1189       setlocal nocursorline
1190     endif
1191   endif
1192 endfun "}}}2
1193
1194 " Handle searching in a BufExplorer window.
1195 fun! <SID>BufExplorer_Search(n) "{{{2
1196   if a:n == 0
1197     let l:re = '^  *\d %'
1198   else
1199     let l:re = "^ *" . a:n
1200   endif
1201
1202   " Find matching line.
1203   let l:line = search(l:re, 'w')
1204   if ! l:line
1205     return
1206   endif
1207
1208   if a:n == 0
1209     return
1210   endif
1211
1212   " Peek ahead to the next matching line.
1213   let l:next = search(l:re, 'w')
1214
1215   " Select the buffer if the match is unambiguous.
1216   if l:next == l:line
1217     exe "normal \<CR>"
1218     return
1219   endif
1220
1221   " Go back.
1222   call cursor(l:line, 0)
1223 endfun! "}}}2
1224
1225 " Entering a BufExplorer window.
1226 fun! <SID>BufExplorer_Map() "{{{2
1227   for l:n in [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]
1228     exec "nnoremap <buffer> <silent>" . l:n . " :call <SID>BufExplorer_Search(" . l:n . ")<CR>"
1229   endfor
1230 endfun "}}}2
1231
1232 if has("windows")
1233   se tabline=%!Show_TabLine()
1234   se guitablabel=%!Show_GUITabLine()
1235 endif
1236
1237 if has("autocmd")
1238   au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1239   au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1240   au StatusLine FocusGained * call Highlight_StatusLine("F")
1241   au StatusLine FocusLost * call Highlight_StatusLine("f")
1242   au StatusLine InsertEnter * call Highlight_StatusLine("I")
1243   au StatusLine InsertLeave * call Highlight_StatusLine("i")
1244
1245   if has("syntax")
1246     au Display FocusGained,FocusLost * call <SID>ToggleCursorLine()
1247   endif
1248
1249   if has("signs")
1250     au Signs InsertEnter * call <SID>Highlight_Signs()
1251     au Signs InsertLeave * call <SID>Highlight_Signs()
1252   endif
1253
1254   au Mode BufEnter \[BufExplorer\] call <SID>BufExplorer_Map()
1255 endif
1256
1257 " Limit the size of the popup menu when completing.
1258 if has("insert_expand")
1259   se pumheight=20
1260 endif
1261
1262 " Make diffs vertical by default.
1263 if has("diff")
1264   se diffopt+=vertical
1265 endif
1266
1267 " Set size of numbers column.
1268 if has("linebreak")
1269   se numberwidth=5
1270 endif
1271
1272 " Add "previous tab" mapping as gb.
1273 map gb :tabprevious<CR>:<CR>
1274
1275 " Transparency.
1276 if has("gui_macvim")
1277   se transparency=15
1278 endif
1279
1280 " Yet more GUI options.  Add tabs.
1281 if has("gui")
1282   se go+=e
1283 endif
1284
1285 " Perforce.
1286 let g:p4EnableMenu=1
1287 let g:p4Presets='P4CONFIG'
1288
1289 " BufExplorer.
1290 let g:bufExplorerShowRelativePath=1
1291 let g:bufExplorerSplitOutPathName=0
1292
1293 " NERDcommenter.
1294 let g:NERDSpaceDelims=1
1295 endif "}}}1
1296
1297 " localvimrc.
1298 let g:localvimrc_persistent=1
1299
1300 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1301 " Handle options only available in Vim 7.2 and above.
1302 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1303 if version >= "702" "{{{1
1304 if has("autocmd")
1305   " http://vim.wikia.com/wiki/Highlight_unwanted_spaces
1306   augroup WhitespaceMatch
1307   autocmd!
1308   au Display BufWinEnter * call Extra_Whitespace_Match()
1309   au Display Syntax * call Extra_Whitespace_Match()
1310   au Display BufWinLeave * call clearmatches()
1311   augroup END
1312
1313   fun! Extra_Whitespace_Match() "{{{2
1314     " \s\+            <whitespace>
1315     "            $    <before end of line>
1316     "        \@<!     <unless preceded by>
1317     "     \%#         <cursor position, ie when typing>
1318     let l:pattern = '\s\+\%#\@<!$'
1319     " Don't match single space in first column of diff.
1320     if &ft =~# '^diff$\|git'
1321       "         \@!  <unless also matching>
1322       " \(^\s$\)     <a single whitespace>
1323       let l:pattern = '\(^\s$\)\@!' . l:pattern
1324     endif
1325
1326     let l:hl = 'ctermfg=red guifg=red'
1327     if ! &list
1328       " Underline if we aren't using listchars.
1329       let l:hl = l:hl . ' cterm=underline gui=underline'
1330     endif
1331     highlight clear ExtraWhitespace
1332     exe "highlight ExtraWhitespace " . l:hl
1333     if exists('w:whitespace_match_number')
1334       try
1335         call matchdelete(w:whitespace_match_number)
1336       catch
1337       endtry
1338       call matchadd('ExtraWhitespace', l:pattern, 10, w:whitespace_match_number)
1339     else
1340       let w:whitespace_match_number = matchadd('ExtraWhitespace', l:pattern)
1341     endif
1342   endfun "}}}2
1343
1344   call Extra_Whitespace_Match()
1345 endif
1346
1347 endif "}}}1
1348
1349 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1350 " Handle options only available in Vim 7.3 and above.
1351 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1352 if version >= "703" "{{{1
1353 version 7.3
1354
1355 " Toggle persistent undo with \u.
1356 call Mapping("u", ":call <SID>Cycle_Undo()<CR>:<CR>")
1357 " Remove persistent undo file with \U.
1358 call Mapping("U", ":call <SID>Clear_Undo()<CR>:<CR>")
1359
1360 " Toggle gundo window with \g.
1361 call Mapping("g", ":call gundo#GundoToggle()<CR>:<CR>")
1362
1363 " Use a persistent undo file if it exists.
1364 fun! <SID>Check_Undo() "{{{2
1365   if filereadable(undofile(expand("%")))
1366     setlocal undofile
1367   endif
1368 endfun "}}}2
1369
1370 " Toggle persistent undo for this buffer.
1371 fun! <SID>Cycle_Undo() "{{{2
1372   if has("persistent_undo")
1373     let &undofile = ! &undofile
1374   endif
1375 endfun "}}}2
1376
1377 " Remove the persistent undo file for this buffer.
1378 fun! <SID>Clear_Undo() "{{{2
1379   if ! has("persistent_undo")
1380     return
1381   endif
1382
1383   setlocal noundofile
1384
1385   let l:f = expand("%")
1386   if l:f == ""
1387     return
1388   endif
1389
1390   let l:u = undofile(l:f)
1391   if l:u == ""
1392     return
1393   endif
1394
1395   if ! filereadable(l:u) || ! filewritable(l:u)
1396     return
1397   endif
1398
1399   call delete(l:u)
1400 endfun "}}}2
1401
1402 " Toggle ColorColumn at cursor position.
1403 fun! <SID>Cycle_ColorColumn() "{{{2
1404   if ! has("syntax")
1405     return
1406   endif
1407
1408   let l:cc = &colorcolumn
1409   let l:column = col(".")
1410   let l:re = ",*\\<" . l:column . "\\>"
1411   if l:cc =~# l:re
1412     let l:cc = substitute(l:cc, l:re, "", "g")
1413   else
1414     let l:cc = l:cc . "," . l:column
1415   endif
1416   let &colorcolumn = substitute(l:cc, "^,*", "", "")
1417 endfun "}}}2
1418
1419 if has("syntax")
1420   " Enable showing ColorColumn at cursor position with \CC.
1421   call Mapping("CC", ":call <SID>Cycle_ColorColumn()<CR>:<CR>")
1422   " Remove last shown ColorColumn with \Cc.
1423   call Mapping("Cc", ":let &colorcolumn=substitute(&colorcolumn, \",*[0-9]*$\", \"\", \"\")<CR>:<CR>")
1424   " Remove all ColorColumns with \Cx.
1425   call Mapping("Cx", ":se colorcolumn=<CR>:<CR>")
1426 endif
1427
1428 " Use persistent undo if available.
1429 if has("autocmd")
1430   if has("persistent_undo")
1431     au File BufReadPost * call <SID>Check_Undo()
1432   endif
1433
1434   if has("cursorbind")
1435     au Display WinEnter * if &diff | se cursorbind | endif
1436   endif
1437 endif
1438
1439 " Mapping to reload the gundo window.
1440 if has("autocmd")
1441   au Mode BufEnter * if &ft == "gundo" | try | nnoremap <silent> <buffer> <unique> r :call gundo#GundoToggle()<CR>:call gundo#GundoToggle()<CR> | catch | endtry | endif
1442 endif
1443
1444 endif "}}}1
1445
1446 " Resize after startup.
1447 if version >= "500" "{{{1
1448 if has("autocmd")
1449   au Display VimEnter * call Startup_Resize()
1450 endif
1451 endif "}}}1