Fixes for console mode vim on Windows.
[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("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     if Has_Unicode()
930       let g:iainsigns = "Dash:'=’ Dot:..• Quote:\"=” Caret:^.ʌ"
931     else
932       let g:iainsigns = "Dash=' Dot:..* Quote=\" Caret.^"
933     endif
934     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"
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:sign = substitute(l:sign, ':.', "", "")
946       let l:sign = substitute(l:sign, '=', " texthl=MarkSign text=", "")
947       let l:sign = substitute(l:sign, '\.', " texthl=MarkDot text=", "")
948       let l:sign = substitute(l:sign, '-', " texthl=MarkLine linehl=MarkLine text=", "")
949
950       exe "sign define Mark" . l:sign
951
952       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
953     endwhile
954
955     if a:resize
956       call Resize_Columns("+", 2)
957     endif
958     call <SID>Highlight_Signs()
959   else
960     let l:i = 0
961     while l:i < 25
962       exe "sign unplace " . (g:firstsign + l:i)
963       let l:i = l:i + 1
964     endwhile
965
966     let l:signs = g:iainsigns
967     let l:sign = ""
968     while strlen(l:signs)
969       let l:sign = matchstr(l:signs, '^[A-Za-z]\+')
970
971       exe "sign undefine Mark" . l:sign
972       call <SID>Prep_Sign(tolower(l:sign))
973       let l:signs = substitute(l:signs, '^[^ ]\+ *', "", "")
974     endwhile
975
976     if a:resize
977       call Resize_Columns("-", 2)
978     endif
979   endif
980 endfun "}}}2
981
982 " Change list mode.
983 fun! Cycle_List() "{{{2
984   " Pretty UTF-8 listchars.
985   if Has_Unicode()
986     let basic='tab:»·,trail:…,extends:«,precedes:»'
987     let eol='eol:¶'
988     if version >= "700"
989       let basic=basic . ',nbsp:•'
990     endif
991   else
992     let basic='tab:\\_,trail:_,extends:<,precedes:>'
993     let eol='eol:$'
994     if version >= "700"
995       let basic=basic . ',nbsp:+'
996     endif
997   endif
998   call Iain_Vars()
999   let w:iainlist = w:iainlist + 1
1000   if w:iainlist > 2
1001     let w:iainlist = 0
1002   endif
1003   if w:iainlist == 0
1004     setlocal nolist
1005   elseif w:iainlist == 1
1006     exec "setlocal lcs=" . basic
1007     setlocal list
1008   else
1009     exec "setlocal lcs=" . basic . "," . eol
1010     setlocal list
1011   endif
1012
1013   call Resize_Columns(Extra_Columns("list", "iainlist", " == 2"), 1)
1014   call Extra_Whitespace_Match()
1015 endfun "}}}2
1016
1017 " Cycle between hex and decimal display of toolbar stuff.
1018 fun! Cycle_HexStatusLine() "{{{2
1019   call Iain_Vars()
1020   let b:iainhex = ! b:iainhex
1021   call Show_StatusLine()
1022 endfun "}}}2
1023
1024 " Cycle verbose display of toolbar stuff.
1025 fun! Cycle_VerboseStatusLine() "{{{2
1026   call Iain_Vars()
1027   let b:iainverbose = ! b:iainverbose
1028   call Show_StatusLine()
1029 endfun "}}}2
1030
1031 " Toggle quickfix window.
1032 fun! Cycle_Quickfix() "{{{2
1033   if ! has("quickfix")
1034     return
1035   endif
1036   if g:quickfixing == 1
1037     cclose
1038     let g:quickfixing=0
1039   else
1040     copen
1041   endif
1042 endfun "}}}2
1043
1044 " Toggle showing alternate buffer information.
1045 fun! Cycle_Alt() "{{{2
1046   call Iain_Vars()
1047   let b:iainalt = ! b:iainalt
1048   call Show_StatusLine()
1049 endfun "{{{2
1050
1051 " To be overridden later if applicable.
1052 fun! Extra_Whitespace_Match() "{{{2
1053   " NOP.
1054 endfun "}}}2
1055
1056 " Swap hex/decimal statusline with \x.
1057 call Mapping("x", ":call Cycle_HexStatusLine()<CR>:<CR>")
1058 " Change statusline verbosity with \v.
1059 call Mapping("V", ":call Cycle_VerboseStatusLine()<CR>:<CR>")
1060 " Cycle list styles with \l.
1061 call Mapping("l", ":call Cycle_List()<CR>:<CR>")
1062 " Toggle tags with \t.
1063 call Mapping("t", ":Tlist<CR>")
1064 " Change foldmethod with \f.
1065 call Mapping("f", ":se foldenable!<CR>:<CR>")
1066 " Toggle quickfix window with \q.
1067 call Mapping("q", ":call Cycle_Quickfix()<CR>:<CR>")
1068 " Rerun filetype detection with \s.  The s is for syntax, as this will be
1069 " updated as a side-effect.
1070 call Mapping("S", ":filetype detect<CR>:<CR>")
1071 " Toggle marks with \m.
1072 call Mapping("m", ":call <SID>Cycle_Signs(1)<CR>:<CR>")
1073
1074 if has("autocmd")
1075   " Show signs by default.
1076   au Display VimEnter * call <SID>Cycle_Signs(0)
1077 endif
1078 endif "}}}1
1079
1080 " move.
1081 nmap <A-u> <Plug>MoveLineHalfPageUp
1082 nmap <A-d> <Plug>MoveLineHalfPageDown
1083 vmap <A-u> <Plug>MoveBlockHalfPageUp
1084 vmap <A-d> <Plug>MoveBlockHalfPageDown
1085
1086 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1087 " Handle options only available in Vim 7 and above.
1088 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1089 if version >= "700" "{{{1
1090 version 7.0
1091
1092 " Helper to show tab name.
1093 fun! <SID>TabName(label, gui) "{{{2
1094   let l:label = a:label
1095   if l:label == ""
1096     let l:label = "No Name"
1097     if a:gui
1098       let l:label = "[" . l:label . "]"
1099     endif
1100   else
1101     let l:label = fnamemodify(l:label, ":t")
1102     if strlen(l:label) >= 18
1103       let l:label = l:label[0:17] . ".."
1104     endif
1105   endif
1106   return l:label
1107 endfun "}}}2
1108
1109 " Find out if any buffer was modified.
1110 fun! <SID>TabModified(buflist) "{{{2
1111   let l:i = 0
1112   while l:i < len(a:buflist)
1113     if getbufvar(a:buflist[l:i], "&modified") == 1
1114       return "+"
1115     endif
1116     let l:i = l:i + 1
1117   endwhile
1118   return ""
1119 endfun "}}}2
1120
1121 " Tab line.
1122 fun! Show_TabLine() "{{{2
1123   let l:s = "%#TabLineFill#Tabs:"
1124
1125   let l:i = 0
1126   while l:i < tabpagenr("$")
1127     let l:i = l:i + 1
1128     " Get the label.
1129     let l:buflist = tabpagebuflist(l:i)
1130     let l:winnr = tabpagewinnr(l:i)
1131     let l:n = tabpagewinnr(l:i, "$")
1132     let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 0)
1133     let l:modified = <SID>TabModified(l:buflist)
1134
1135     " Choose highlighting.
1136     if l:i == tabpagenr()
1137       let l:s .= "%#TabLineSel#[" . l:n . l:modified . " " . l:label . "]"
1138     else
1139       let l:s .= "%#TabLine# " . l:n . l:modified . " " . l:label . " "
1140     endif
1141   endwhile
1142
1143   " Padding.
1144   let l:s .= "%#TabLine#%T"
1145   return l:s
1146 endfun "}}}2
1147
1148 " Per tab label for the GUI.
1149 fun! Show_GUITabLine() "{{{2
1150   let l:buflist = tabpagebuflist(v:lnum)
1151   let l:winnr = tabpagewinnr(v:lnum)
1152   let l:s = tabpagewinnr(v:lnum, "$")
1153   let l:label = <SID>TabName(bufname(l:buflist[l:winnr - 1]), 1)
1154   let l:modified = <SID>TabModified(l:buflist)
1155
1156   let l:s .= l:modified . " " . l:label
1157   return l:s
1158 endfun "}}}2
1159
1160 " Toggle highlighting cursor line when focus changes.
1161 fun! <SID>ToggleCursorLine() "{{{2
1162   call Iain_Vars()
1163
1164   if b:iainstatus =~# "H" && b:iainstatus =~# "I"
1165     " We are held in insert mode.
1166     if b:iainstatus =~# "f"
1167       " And focus was lost.
1168       let b:iaincul = getbufvar("", "&cursorline")
1169       setlocal cursorline
1170     elseif ! b:iaincul
1171       setlocal nocursorline
1172     endif
1173   endif
1174 endfun "}}}2
1175
1176 " Handle searching in a BufExplorer window.
1177 fun! <SID>BufExplorer_Search(n) "{{{2
1178   if a:n == 0
1179     let l:re = '^  *\d %'
1180   else
1181     let l:re = "^ *" . a:n
1182   endif
1183
1184   " Find matching line.
1185   let l:line = search(l:re, 'w')
1186   if ! l:line
1187     return
1188   endif
1189
1190   if a:n == 0
1191     return
1192   endif
1193
1194   " Peek ahead to the next matching line.
1195   let l:next = search(l:re, 'w')
1196
1197   " Select the buffer if the match is unambiguous.
1198   if l:next == l:line
1199     exe "normal \<CR>"
1200     return
1201   endif
1202
1203   " Go back.
1204   call cursor(l:line, 0)
1205 endfun! "}}}2
1206
1207 " Entering a BufExplorer window.
1208 fun! <SID>BufExplorer_Map() "{{{2
1209   for l:n in [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ]
1210     exec "nnoremap <buffer> <silent>" . l:n . " :call <SID>BufExplorer_Search(" . l:n . ")<CR>"
1211   endfor
1212 endfun "}}}2
1213
1214 if has("windows")
1215   se tabline=%!Show_TabLine()
1216   se guitablabel=%!Show_GUITabLine()
1217 endif
1218
1219 if has("autocmd")
1220   au StatusLine CursorHoldI * call Highlight_StatusLine("H")
1221   au StatusLine CursorMovedI * call Highlight_StatusLine("h")
1222   au StatusLine FocusGained * call Highlight_StatusLine("F")
1223   au StatusLine FocusLost * call Highlight_StatusLine("f")
1224   au StatusLine InsertEnter * call Highlight_StatusLine("I")
1225   au StatusLine InsertLeave * call Highlight_StatusLine("i")
1226
1227   if has("syntax")
1228     au Display FocusGained,FocusLost * call <SID>ToggleCursorLine()
1229   endif
1230
1231   if has("signs")
1232     au Signs InsertEnter * call <SID>Highlight_Signs()
1233     au Signs InsertLeave * call <SID>Highlight_Signs()
1234   endif
1235
1236   au Mode BufEnter \[BufExplorer\] call <SID>BufExplorer_Map()
1237 endif
1238
1239 " Limit the size of the popup menu when completing.
1240 if has("insert_expand")
1241   se pumheight=20
1242 endif
1243
1244 " Make diffs vertical by default.
1245 if has("diff")
1246   se diffopt+=vertical
1247 endif
1248
1249 " Set size of numbers column.
1250 if has("linebreak")
1251   se numberwidth=5
1252 endif
1253
1254 " Add "previous tab" mapping as gb.
1255 map gb :tabprevious<CR>:<CR>
1256
1257 " Transparency.
1258 if has("gui_macvim")
1259   se transparency=15
1260 endif
1261
1262 " Yet more GUI options.  Add tabs.
1263 if has("gui")
1264   se go+=e
1265 endif
1266
1267 " Perforce.
1268 let g:p4EnableMenu=1
1269 let g:p4Presets='P4CONFIG'
1270
1271 " BufExplorer.
1272 let g:bufExplorerShowRelativePath=1
1273 let g:bufExplorerSplitOutPathName=0
1274
1275 " NERDcommenter.
1276 let g:NERDSpaceDelims=1
1277 endif "}}}1
1278
1279 " localvimrc.
1280 let g:localvimrc_persistent=1
1281
1282 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1283 " Handle options only available in Vim 7.2 and above.
1284 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1285 if version >= "702" "{{{1
1286 if has("autocmd")
1287   " http://vim.wikia.com/wiki/Highlight_unwanted_spaces
1288   augroup WhitespaceMatch
1289   autocmd!
1290   au Display BufWinEnter * call Extra_Whitespace_Match()
1291   au Display Syntax * call Extra_Whitespace_Match()
1292   au Display BufWinLeave * call clearmatches()
1293   augroup END
1294
1295   fun! Extra_Whitespace_Match() "{{{2
1296     " \s\+            <whitespace>
1297     "            $    <before end of line>
1298     "        \@<!     <unless preceded by>
1299     "     \%#         <cursor position, ie when typing>
1300     let l:pattern = '\s\+\%#\@<!$'
1301     " Don't match single space in first column of diff.
1302     if &ft =~# '^diff$\|git'
1303       "         \@!  <unless also matching>
1304       " \(^\s$\)     <a single whitespace>
1305       let l:pattern = '\(^\s$\)\@!' . l:pattern
1306     endif
1307
1308     let l:hl = 'ctermfg=red guifg=red'
1309     if ! &list
1310       " Underline if we aren't using listchars.
1311       let l:hl = l:hl . ' cterm=underline gui=underline'
1312     endif
1313     highlight clear ExtraWhitespace
1314     exe "highlight ExtraWhitespace " . l:hl
1315     if exists('w:whitespace_match_number')
1316       try
1317         call matchdelete(w:whitespace_match_number)
1318       catch
1319       endtry
1320       call matchadd('ExtraWhitespace', l:pattern, 10, w:whitespace_match_number)
1321     else
1322       let w:whitespace_match_number = matchadd('ExtraWhitespace', l:pattern)
1323     endif
1324   endfun "}}}2
1325
1326   call Extra_Whitespace_Match()
1327 endif
1328
1329 endif "}}}1
1330
1331 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1332 " Handle options only available in Vim 7.3 and above.
1333 """"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""
1334 if version >= "703" "{{{1
1335 version 7.3
1336
1337 " Toggle persistent undo with \u.
1338 call Mapping("u", ":call <SID>Cycle_Undo()<CR>:<CR>")
1339 " Remove persistent undo file with \U.
1340 call Mapping("U", ":call <SID>Clear_Undo()<CR>:<CR>")
1341
1342 " Use a persistent undo file if it exists.
1343 fun! <SID>Check_Undo() "{{{2
1344   if filereadable(undofile(expand("%")))
1345     setlocal undofile
1346   endif
1347 endfun "}}}2
1348
1349 " Toggle persistent undo for this buffer.
1350 fun! <SID>Cycle_Undo() "{{{2
1351   if has("persistent_undo")
1352     let &undofile = ! &undofile
1353   endif
1354 endfun "}}}2
1355
1356 " Remove the persistent undo file for this buffer.
1357 fun! <SID>Clear_Undo() "{{{2
1358   if ! has("persistent_undo")
1359     return
1360   endif
1361
1362   setlocal noundofile
1363
1364   let l:f = expand("%")
1365   if l:f == ""
1366     return
1367   endif
1368
1369   let l:u = undofile(l:f)
1370   if l:u == ""
1371     return
1372   endif
1373
1374   if ! filereadable(l:u) || ! filewritable(l:u)
1375     return
1376   endif
1377
1378   call delete(l:u)
1379 endfun "}}}2
1380
1381 " Toggle ColorColumn at cursor position.
1382 fun! <SID>Cycle_ColorColumn() "{{{2
1383   if ! has("syntax")
1384     return
1385   endif
1386
1387   let l:cc = &colorcolumn
1388   let l:column = col(".")
1389   let l:re = ",*\\<" . l:column . "\\>"
1390   if l:cc =~# l:re
1391     let l:cc = substitute(l:cc, l:re, "", "g")
1392   else
1393     let l:cc = l:cc . "," . l:column
1394   endif
1395   let &colorcolumn = substitute(l:cc, "^,*", "", "")
1396 endfun "}}}2
1397
1398 if has("syntax")
1399   " Enable showing ColorColumn at cursor position with \CC.
1400   call Mapping("CC", ":call <SID>Cycle_ColorColumn()<CR>:<CR>")
1401   " Remove last shown ColorColumn with \Cc.
1402   call Mapping("Cc", ":let &colorcolumn=substitute(&colorcolumn, \",*[0-9]*$\", \"\", \"\")<CR>:<CR>")
1403   " Remove all ColorColumns with \Cx.
1404   call Mapping("Cx", ":se colorcolumn=<CR>:<CR>")
1405 endif
1406
1407 " Use persistent undo if available.
1408 if has("autocmd")
1409   if has("persistent_undo")
1410     au File BufReadPost * call <SID>Check_Undo()
1411   endif
1412
1413   if has("cursorbind")
1414     au Display WinEnter * if &diff | se cursorbind | endif
1415   endif
1416 endif
1417 endif "}}}1
1418
1419 " Resize after startup.
1420 if version >= "500" "{{{1
1421 if has("autocmd")
1422   au Display VimEnter * call Startup_Resize()
1423 endif
1424 endif "}}}1