Move plugin.
[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 " move.
1074 nmap <A-u> <Plug>MoveLineHalfPageUp
1075 nmap <A-d> <Plug>MoveLineHalfPageDown
1076 vmap <A-u> <Plug>MoveBlockHalfPageUp
1077 vmap <A-d> <Plug>MoveBlockHalfPageDown
1078
1079 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1080 " Handle options only available in Vim 7 and above.
1081 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1082 if version >= "700" "{{{1
1083 version 7.0
1084
1085 " Helper to show tab name.
1086 fun! <SID>TabName(label, gui) "{{{2
1087   let l:label = a:label
1088   if l:label == ""
1089     let l:label = "No Name"
1090     if a:gui
1091       let l:label = "[" . l:label . "]"
1092     endif
1093   else
1094     let l:label = fnamemodify(l:label, ":t")
1095     if strlen(l:label) >= 18
1096       let l:label = l:label[0:17] . ".."
1097     endif
1098   endif
1099   return l:label
1100 endfun "}}}2
1101
1102 " Find out if any buffer was modified.
1103 fun! <SID>TabModified(buflist) "{{{2
1104   let l:i = 0
1105   while l:i < len(a:buflist)
1106     if getbufvar(a:buflist[l:i], "&modified") == 1
1107       return "+"
1108     endif
1109     let l:i = l:i + 1
1110   endwhile
1111   return ""
1112 endfun "}}}2
1113
1114 " Tab line.
1115 fun! Show_TabLine() "{{{2
1116   let l:s = "%#TabLineFill#Tabs:"
1117
1118   let l:i = 0
1119   while l:i < tabpagenr("$")
1120     let l:i = l:i + 1
1121     " Get the label.
1122     let l:buflist = tabpagebuflist(l:i)
1123     let l:winnr = tabpagewinnr(l:i)
1124     let l:n = tabpagewinnr(l:i, "$")
1125     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
1126     let l:modified = <SID>TabModified(l:buflist)
1127
1128     " Choose highlighting.
1129     if l:i == tabpagenr()
1130       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
1131     else
1132       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
1133     endif
1134   endwhile
1135
1136   " Padding.
1137   let l:s .= "%#TabLine#%T"
1138   return l:s
1139 endfun "}}}2
1140
1141 " Per tab label for the GUI.
1142 fun! Show_GUITabLine() "{{{2
1143   let l:buflist = tabpagebuflist(v:lnum)
1144   let l:winnr = tabpagewinnr(v:lnum)
1145   let l:s = tabpagewinnr(v:lnum, "$")
1146   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
1147   let l:modified = <SID>TabModified(l:buflist)
1148
1149   let l:s .= l:modified . " " . l:label
1150   return l:s
1151 endfun "}}}2
1152
1153 " Toggle highlighting cursor line when focus changes.
1154 fun! <SID>ToggleCursorLine() "{{{2
1155   call Iain_Vars()
1156
1157   if b:iainstatus =~# "H" && b:iainstatus =~# "I"
1158     " We are held in insert mode.
1159     if b:iainstatus =~# "f"
1160       " And focus was lost.
1161       let b:iaincul = getbufvar("", "&cursorline")
1162       setlocal cursorline
1163     elseif ! b:iaincul
1164       setlocal nocursorline
1165     endif
1166   endif
1167 endfun "}}}2
1168
1169 " Handle searching in a BufExplorer window.
1170 fun! <SID>BufExplorer_Search(n) "{{{2
1171   if a:n == 0
1172     let l:re = '^  *\d %'
1173   else
1174     let l:re = "^ *" . a:n
1175   endif
1176
1177   " Find matching line.
1178   let l:line = search(l:re, 'w')
1179   if ! l:line
1180     return
1181   endif
1182
1183   if a:n == 0
1184     return
1185   endif
1186
1187   " Peek ahead to the next matching line.
1188   let l:next = search(l:re, 'w')
1189
1190   " Select the buffer if the match is unambiguous.
1191   if l:next == l:line
1192     exe "normal \<CR>"
1193     return
1194   endif
1195
1196   " Go back.
1197   call cursor(l:line, 0)
1198 endfun! "}}}2
1199
1200 " Entering a BufExplorer window.
1201 fun! <SID>BufExplorer_Map() "{{{2
1202   for l:n in [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]
1203     exec "nnoremap <buffer> <silent>" . l:n . " :call <SID>BufExplorer_Search(" . l:n . ")<CR>"
1204   endfor
1205 endfun "}}}2
1206
1207 if has("windows")
1208   se tabline=%!Show_TabLine()
1209   se guitablabel=%!Show_GUITabLine()
1210 endif
1211
1212 if has("autocmd")
1213   au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1214   au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1215   au StatusLine FocusGained * call Highlight_StatusLine("F")
1216   au StatusLine FocusLost * call Highlight_StatusLine("f")
1217   au StatusLine InsertEnter * call Highlight_StatusLine("I")
1218   au StatusLine InsertLeave * call Highlight_StatusLine("i")
1219
1220   if has("syntax")
1221     au Display FocusGained,FocusLost * call <SID>ToggleCursorLine()
1222   endif
1223
1224   if has("signs")
1225     au Signs InsertEnter * call <SID>Highlight_Signs()
1226     au Signs InsertLeave * call <SID>Highlight_Signs()
1227   endif
1228
1229   au Mode BufEnter \[BufExplorer\] call <SID>BufExplorer_Map()
1230 endif
1231
1232 " Limit the size of the popup menu when completing.
1233 if has("insert_expand")
1234   se pumheight=20
1235 endif
1236
1237 " Make diffs vertical by default.
1238 if has("diff")
1239   se diffopt+=vertical
1240 endif
1241
1242 " Set size of numbers column.
1243 if has("linebreak")
1244   se numberwidth=5
1245 endif
1246
1247 " Add "previous tab" mapping as gb.
1248 map gb :tabprevious<CR>:<CR>
1249
1250 " Transparency.
1251 if has("gui_macvim")
1252   se transparency=15
1253 endif
1254
1255 " Yet more GUI options.  Add tabs.
1256 if has("gui")
1257   se go+=e
1258 endif
1259
1260 " Perforce.
1261 let g:p4EnableMenu=1
1262 let g:p4Presets='P4CONFIG'
1263
1264 " BufExplorer.
1265 let g:bufExplorerShowRelativePath=1
1266 let g:bufExplorerSplitOutPathName=0
1267
1268 " NERDcommenter.
1269 let g:NERDSpaceDelims=1
1270 endif "}}}1
1271
1272 " localvimrc.
1273 let g:localvimrc_persistent=1
1274
1275 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1276 " Handle options only available in Vim 7.2 and above.
1277 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1278 if version >= "702" "{{{1
1279 if has("autocmd")
1280   " http://vim.wikia.com/wiki/Highlight_unwanted_spaces
1281   augroup WhitespaceMatch
1282   autocmd!
1283   au Display BufWinEnter * call Extra_Whitespace_Match()
1284   au Display Syntax * call Extra_Whitespace_Match()
1285   au Display BufWinLeave * call clearmatches()
1286   augroup END
1287
1288   fun! Extra_Whitespace_Match() "{{{2
1289     " \s\+            <whitespace>
1290     "            $    <before end of line>
1291     "        \@<!     <unless preceded by>
1292     "     \%#         <cursor position, ie when typing>
1293     let l:pattern = '\s\+\%#\@<!$'
1294     " Don't match single space in first column of diff.
1295     if &ft =~# '^diff$\|git'
1296       "         \@!  <unless also matching>
1297       " \(^\s$\)     <a single whitespace>
1298       let l:pattern = '\(^\s$\)\@!' . l:pattern
1299     endif
1300
1301     let l:hl = 'ctermfg=red guifg=red'
1302     if ! &list
1303       " Underline if we aren't using listchars.
1304       let l:hl = l:hl . ' cterm=underline gui=underline'
1305     endif
1306     highlight clear ExtraWhitespace
1307     exe "highlight ExtraWhitespace " . l:hl
1308     if exists('w:whitespace_match_number')
1309       try
1310         call matchdelete(w:whitespace_match_number)
1311       catch
1312       endtry
1313       call matchadd('ExtraWhitespace', l:pattern, 10, w:whitespace_match_number)
1314     else
1315       let w:whitespace_match_number = matchadd('ExtraWhitespace', l:pattern)
1316     endif
1317   endfun "}}}2
1318
1319   call Extra_Whitespace_Match()
1320 endif
1321
1322 endif "}}}1
1323
1324 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1325 " Handle options only available in Vim 7.3 and above.
1326 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1327 if version >= "703" "{{{1
1328 version 7.3
1329
1330 " Toggle persistent undo with \u.
1331 call Mapping("u", ":call <SID>Cycle_Undo()<CR>:<CR>")
1332 " Remove persistent undo file with \U.
1333 call Mapping("U", ":call <SID>Clear_Undo()<CR>:<CR>")
1334
1335 " Use a persistent undo file if it exists.
1336 fun! <SID>Check_Undo() "{{{2
1337   if filereadable(undofile(expand("%")))
1338     setlocal undofile
1339   endif
1340 endfun "}}}2
1341
1342 " Toggle persistent undo for this buffer.
1343 fun! <SID>Cycle_Undo() "{{{2
1344   if has("persistent_undo")
1345     let &undofile = ! &undofile
1346   endif
1347 endfun "}}}2
1348
1349 " Remove the persistent undo file for this buffer.
1350 fun! <SID>Clear_Undo() "{{{2
1351   if ! has("persistent_undo")
1352     return
1353   endif
1354
1355   setlocal noundofile
1356
1357   let l:f = expand("%")
1358   if l:f == ""
1359     return
1360   endif
1361
1362   let l:u = undofile(l:f)
1363   if l:u == ""
1364     return
1365   endif
1366
1367   if ! filereadable(l:u) || ! filewritable(l:u)
1368     return
1369   endif
1370
1371   call delete(l:u)
1372 endfun "}}}2
1373
1374 " Toggle ColorColumn at cursor position.
1375 fun! <SID>Cycle_ColorColumn() "{{{2
1376   if ! has("syntax")
1377     return
1378   endif
1379
1380   let l:cc = &colorcolumn
1381   let l:column = col(".")
1382   let l:re = ",*\\<" . l:column . "\\>"
1383   if l:cc =~# l:re
1384     let l:cc = substitute(l:cc, l:re, "", "g")
1385   else
1386     let l:cc = l:cc . "," . l:column
1387   endif
1388   let &colorcolumn = substitute(l:cc, "^,*", "", "")
1389 endfun "}}}2
1390
1391 if has("syntax")
1392   " Enable showing ColorColumn at cursor position with \CC.
1393   call Mapping("CC", ":call <SID>Cycle_ColorColumn()<CR>:<CR>")
1394   " Remove last shown ColorColumn with \Cc.
1395   call Mapping("Cc", ":let &colorcolumn=substitute(&colorcolumn, \",*[0-9]*$\", \"\", \"\")<CR>:<CR>")
1396   " Remove all ColorColumns with \Cx.
1397   call Mapping("Cx", ":se colorcolumn=<CR>:<CR>")
1398 endif
1399
1400 " Use persistent undo if available.
1401 if has("autocmd")
1402   if has("persistent_undo")
1403     au File BufReadPost * call <SID>Check_Undo()
1404   endif
1405
1406   if has("cursorbind")
1407     au Display WinEnter * if &diff | se cursorbind | endif
1408   endif
1409 endif
1410 endif "}}}1
1411
1412 " Resize after startup.
1413 if version >= "500" "{{{1
1414 if has("autocmd")
1415   au Display VimEnter * call Startup_Resize()
1416 endif
1417 endif "}}}1