" My ~/.vimrc file
"
" Maintainer: Kyle Wheeler
"
" To convert this file to html, do this:
" vim -f '+let html_use_css=1' '+let use_xhtml=1' '+so $VIMRUNTIME/syntax/2html.vim' +wq +q ~/.vimrc
"
" to get the pure version:
" wget http://memoryhole.net/~kyle/vimrc.txt

" This must be first (has side effects)
set nocompatible  " don't be very vi compatible (makes things break)
set cpoptions=aABceFs " These are the vi-compatable options

" ***********
" * Plugins *
" ***********

"set runtimepath=~/.vim,/Applications/Vim.app/Contents/Resources/vim/runtime,/usr/share/vim/addons,/usr/share/vim/vimfiles,/opt/local/share/vim/vimfiles,/opt/local/share/vim/vim63,/usr/share/vim/vimcurrent,/opt/local/share/vim/vimfiles/after,/usr/share/vim/vimfiles/after,/usr/share/vim/addons/after,~/.vim/after
"if $VIMRUNTIME != ""
    " gives you a file browser if you try to edit a directory
"   if filereadable($VIMRUNTIME . '/plugin/explorer.vim')
"       source $VIMRUNTIME/plugin/explorer.vim
"   endif
    " allows you to edit gzipped files directly
"   if filereadable($VIMRUNTIME . '/plugin/gzip.vim')
"       source $VIMRUNTIME/plugin/gzip.vim
"   endif
"endif

" *********************
" * Terminal settings *
" *********************

" you can compile in extra termcaps and then
" use :set term=builtin_beos-ansi, but it's
" not as good as this, more portable solution

if !has("gui_running")
    if &term == 'dterm'
        set tsl=0 " Sun's terminal sucks bigtime
    elseif has("terminfo") && ! (&term == 'linux' || &term == 'Eterm' || &term == 'vt220' || &term == 'nsterm-16color' || &term == 'xterm-16color')
        " Force these terminals to accept my authority! (default)
        " number of colors
        set t_Co=16
        " ANSI background
        set t_AB=^[[%?%p1%{8}%<%t%p1%{40}%+%e%p1%{92}%+%;%dm
        " ANSI foreground
        set t_AF=^[[%?%p1%{8}%<%t%p1%{30}%+%e%p1%{82}%+%;%dm
    elseif &term == 'term' || &term == 'rxvt' || &term == 'vt100' || &term == 'screen'
        " Less-Cool Terminals (no terminfo)
        set t_Co=16
        set t_AB=^[[%?%p1%{8}%<%t4%p1%d%e%p1%{32}%+%d;1%;m
        set t_AF=^[[%?%p1%{8}%<%t3%p1%d%e%p1%{22}%+%d;1%;m
    else
        " Terminals that have trustworthy terminfo entries
        if &term == 'vt220'
            set t_Co=8
            " foreground
            set t_Sf=^[[3%dm
            " background
            set t_Sb=^[[4%dm
        elseif $TERM == 'xterm'
            set term=xterm-color
        endif
    endif
endif

if &term == 'term' || &term == 'aterm' || &term == 'Eterm' || &term == 'nsterm-16color'
    set ttyfast   " these terminals are also fast
endif
set backspace=2 " make the delete key work properly (backwards compatable)
" Scroll mice!
if has("mouse")
    set mouse=a
    set mousehide " hide mouse when typing
    set mousemodel=popup_setpos " popupmenu rather than selecting
endif

if has("multi_byte")
    set encoding=utf-8
    if $LANG !~ '\(UTF\|utf\)-\?8' && $LC_CTYPE !~ '\(UTF\|utf\)-\?8'
        " Note that this only works if your shell GUARANTEES that either LANG
        " or LC_CTYPE will be set correctly (as mine does). If not it would be
        " useful to do more thorough terminal detection here.
        set termencoding=latin1
    endif
endif

if has("autocmd")
    " Set the title consistently
    autocmd BufEnter * let &titlestring="VIM - ".expand("%:p")
endif


" ****************
" * Syntax Stuff *
" ****************

" enable filetype detection
if version >= 600
    filetype plugin indent on
else
    filetype on
endif
" make sure we have colors first
if &t_Co > 2 || has("gui_running")
    syntax on
endif
set modelines=5

set background=dark
if ( &term != "Eterm" )
    colorscheme kyle
endif

if has("eval")
    let is_bash=1 " Because it is, and not all my scripts start with #!/bin/bash
endif

set formatoptions+=tcrq2
set ai nosi
set winminheight=0 " let windows be squashed

if has("autocmd")
    autocmd Syntax mixed so ~/.vim/syntax/cmix.vim

    " When editing a file, always jump to the last known cursor position.
    " Don't do it when the position is invalid or when inside an event handler
    " (happens when dropping a file on gvim).
    autocmd BufReadPost *
      \ if line("'\"") > 0 && line("'\"") <= line("$") |
      \   exe "normal g`\"" |
      \ endif

    " Why is this not detected properly?
    au BufRead,BufNewFile *.vim set filetype=vim
    " my text
    au BufRead,BufNewFile *.txt setfiletype text
    " always defaults to plaintex, and I don't know plaintex
    au BufRead,BufNewFile *.tex set filetype=tex
    " my gnuplot extension
    autocmd BufRead,BufNewFile *.gplot setfiletype gnuplot
    " vim doesn't correctly identify Dtrace files
    autocmd BufRead,BufNewFile *.dt set filetype=dtrace
    " A neat spelling macro I found here:
    " http://use.perl.org/comments.pl?sid=19418&cid=29874
    "autocmd FileType *    command aspe ':w<CR>:!aspell    -c %<CR>:e<CR><CR>'
    "autocmd FileType mail command aspe ':w<CR>:!aspell -e -c %<CR>:e<CR><CR>'
    "autocmd FileType tex  command aspe ':w<CR>:!aspell -t -c %<CR>:e<CR><CR>'

    if $LANG =~ '^en_US.\(UTF\|utf\)-\?8$' || $LC_CTYPE =~ '^en_US.\(UTF\|utf\)-\?8$'
        autocmd FileType mail if strlen($pinevim) == 0 | call UniCycleOn() | endif
    endif
    autocmd FileType mail set nosi textwidth=70 expandtab comments+=nb:> formatoptions+=aw
    autocmd FileType mail command! Fixq call Fixflowed()
    autocmd Filetype mail vmap <Esc>[1;5C :s/\(.*\)\n/>\1\r/g<CR>:nohlsearch<CR>k
    autocmd Filetype mail imap <Esc>[1;5C <Esc>:s/\(.*\)\n/>\1\r/g<CR>:nohlsearch<CR>ka
    autocmd Filetype mail nmap <Esc>[1;5C :s/\(.*\)\n/>\1\r/g<CR>:nohlsearch<CR>k
    autocmd Filetype mail vmap <Esc>[1;5D :s/>\(.*\)\n/\1\r/g<CR>:nohlsearch<CR>k
    autocmd Filetype mail imap <Esc>[1;5D <Esc>:s/>\(.*\)\n/\1\r/g<CR>:nohlsearch<CR>ka
    autocmd Filetype mail nmap <Esc>[1;5D :s/>\(.*\)\n/\1\r/g<CR>:nohlsearch<CR>k
    autocmd Filetype mail autocmd BufWritePre <buffer> call Fixindented()
    autocmd Filetype mail call Fixapplemailflowed()

    " for C-style languages, cin is a must
    " since most people use 8-space tabs, set that too
    autocmd Filetype c,cpp,java,objc,cuda set cin tabstop=8 softtabstop=4 shiftwidth=4 formatoptions+=c formatoptions-=w

    " Makes it look good
    autocmd FileType text,tex,cvs set textwidth=78 nosi noai expandtab fo+=aw

    " I hope never to need these lines again
    autocmd Filetype scheme,lisp set lisp
endif

" some C vim options...
if has("eval")
    let c_gnu=1
    let c_space_errors=1
endif

" *******************
" * Spelling Prefs: *
" *******************

if version >= 700
    let loaded_matchparen = 1
    set spelllang=en
    set spellfile=~/.conf/vim/spellfile.utf-8.add
    if has("autocmd")
        autocmd FileType mail,tex set spell
    endif
endif

" ********************
" * Searching prefs: *
" ********************

if &t_Co > 2 || has("gui_running") && has("extra_search")
    set hlsearch " highlight search matches (hls)
    " since <C-/> is unreliable, <C-n> might be easy to remember...
    map <C-n> :nohlsearch<CR>
    imap <C-n> <Esc>:nohlsearch<CR>a
endif

set ignorecase  " search is case insensitive (ic)
set smartcase   " unless you use capitals (scs)
set incsearch   " show match for partially typed search (is)

" grep will sometimes skip displaying the file name if you search in a single
" file. This will confuse latex-suite. Set your grep program to always
" generate a file name
set grepprg=grep\ -nH\ $*

" file names to leave until the end during completion matching sequence
set suffixes=.bak,~,.o,.h,.info,.swp,.obj,.class,.doc,.aux,.log,.dvi,.bbl,.brf,.cb,.ind,.idx,.ilg,.inx,.out,.toc,.lof,.lot,.dvi,.blg,.pdf

" ******************
" * Editing prefs: *
" ******************

set pastetoggle=<F1> " the button to make vim ready to paste
if has("linebreak")
    set linebreak   " wrap long lines at sensible places (lbr)
endif

" Brilliant, though slow as all get out, way of pasting in OSX
" note that I'm using the named register "z to avoid overwriting any existing
" things in the unnamed register ("")
nmap <silent> <C-p> :call setreg("z", system("pbpaste"))<CR>"zp
imap <silent> <C-p> <Esc>:call setreg("z", system("pbpaste"))<CR>"zpa

" When I say tab, I mean *tab*
set noexpandtab
set tabstop=4     " tabs are 4 spaces for my own purposes (ts)
set softtabstop=0 " I prefer indenting 4 spaces (sts)
set shiftwidth=4  " in auto-indenting as well (sw)

set showmode      " display the current mode (-- INSERT --) (smd)
set ruler         " show the cursor position always (ru)
set showmatch     " show bracket matches briefly
set matchtime=3   " for 3 tenths of a second (mat)

set nobackup       " no backup files (nobk)
set nowritebackup  " ... ever (nowb)

" this makes gq format it the same way vim would (at least to the same margin)
" could also be done with: set equalprg='fmt 78 78'
"set fp='fmt 78 78'

" This makes vim understand my typing style: single space after period
set nojoinspaces

" Handy
if has('folding')
    set foldenable
    set foldmethod=manual
    if has('autocmd')
        autocmd FileType c,cpp,java,cuda set foldmethod=marker
    endif
endif

" *****************************
" * Miscellaneous Preferences *
" *****************************
if has('wildignore')
    set wildignore=*.o,*.obj,*.bak,*.tmp,*.d
endif
" Make filename completion bash-like (W00T!)
set wildmode=longest,list,full
if has('wildmenu')
    set wildmenu
endif

" *************************
" * Emacs-ish keybindings *
" *************************

" Doesn't matter since I set cpoptions above, but for those who might find it
" useful...
"set cpoptions-=<

" I want these to apply everywhere
map  <C-E> <End>
map! <C-E> <End>
map  <C-A> <Home>
map! <C-A> <Home>
map  <C-U> v^x
imap <C-T> <Esc>v^xi
map  <C-K> D
map! <C-K> <Esc><Right>Da
" Fix the delete key if it's borked.
map  <C-?> <C-H>
map! <C-?> <C-H>

" *******************
" * Fix broken keys *
" *******************
if ! has('gui_running')
    map  <Esc>[F  <End>
    map! <Esc>[F  <End>
    map  <Esc>[8~ <End>
    "$
    map! <Esc>[8~ <End>
    "<Esc>A
    map  <Esc>[H  <Home>
    map! <Esc>[H  <Home>
    map  <Esc>[7~ <Home>
    "^
    map! <Esc>[7~ <Home>
    "<Esc>I
    map  <Esc>[5~ <PageUp>
    "<C-B>
    map! <Esc>[5~ <PageUp>
    "<Esc><C-B>a
    map  <Esc>[6~ <PageDown>
    "<C-F>
    map! <Esc>[6~ <PageDown>
    "<C-F>
    map  <c-?> <BS>
    map! <c-?> <BS>
endif

" **************************************
" * Fix broken number pad keys *
" **************************************
if ! has('gui_running')
    map  <Esc>Oy 9
    map! <Esc>Oy 9
    map  <Esc>Ox 8
    map! <Esc>Ox 8
    map  <Esc>Ow 7
    map! <Esc>Ow 7
    map  <Esc>Ov 6
    map! <Esc>Ov 6
    map  <Esc>Ou 5
    map! <Esc>Ou 5
    map  <Esc>Ot 4
    map! <Esc>Ot 4
    map  <Esc>Os 3
    map! <Esc>Os 3
    map  <Esc>Or 2
    map! <Esc>Or 2
    map  <Esc>Oq 1
    map! <Esc>Oq 1
    map  <Esc>Op 0
    map! <Esc>Op 0
    map  <Esc>On .
    map! <Esc>On .
    map  <Esc>Oo /
    map! <Esc>Oo /
    map  <Esc>Oj *
    map! <Esc>Oj *
    map  <Esc>Om -
    map! <Esc>Om -
    map  <Esc>Ok +
    map! <Esc>Ok +
endif

" *******************
" * Useful Commands *
" *******************
" This allows me to indent a file, and end up in the exact same spot I was
" before I indented it.
if executable("gnuindent")
    function! KBW_Indent()
        let l = line(".")
        let c = col(".")
        execute '%!gnuindent'
        execute l . " normal " . c . "|"
    endfunction
elseif executable("indent")
    function! KBW_Indent()
        let l = line(".")
        let c = col(".")
        execute '%!indent'
        execute l . " normal " . c . "|"
    endfunction
else
    function! KBW_Indent()
        echo "Sorry, no indent was found on your system."
    endfunction
endif

map <C-T> :call KBW_Indent()<CR>
imap <C-T> <Esc>:call KBW_Indent()<CR>a
map <C-P> :%!gpg --noverbose --output - --armor --textmode --

" ************************************************************
" * Useful functions *
" ************************************************************
if has("user_commands")
function! ReverseVideo()
    highlight Normal ctermbg=White ctermfg=Black guifg=Gray guibg=Black
endfunction

" *************************************************************
" * Mail things *
" *************************************************************

function! Fixflowed()
    " save position
    let pos = getpos(".")
    " add spaces to the end of every line
    silent! %s/\([^]> :]\)\ze\n>[> ]*[^> ]/\1 /g
    " remove extraneous spaces
    silent! %s/ \+\ze\n[> ]*$//
    " make sure there's at most one space at the end of every line
    silent! %s/ \{2,}$/ /
    " now, fix the wockas spacing from the text
    silent! %s/^[> ]*>\ze[^> ]/& /
    " now, compress the wockas
    while search('^>\+ >', 'w') > 0
        s/^>\+\zs >/>/
    endwhile
    " restore the original location, such as it is
    call setpos('.',pos)
endfunction

function! Fixapplemailflowed()
    let pos = getpos(".")
    " make sure there's at most one space at the end of every line
    silent! %s/ \{2,}$/ /
    call setpos('.',pos)
endfunction

function! Fixindented()
    " remove spaces at the end of lines within indented blocks
    silent! %s/^\s.*\zs \+$//
endfunction

" *************
" * TeX Stuff *
" *************
" Stolen from http://mywebpage.netscape.com/bbenjif/vim/TeX/texmacro.vim
function! TeX_quote()
    let l = line(".")
    let c = col(".")
    if synIDattr(synID(l, c, 1), "name") =~ "^texMath"
                \ || (c > 1 && getline(l)[c-2] == '\')
        return '"'
    endif
    if exists("g:TeX_open")
        let open = g:TeX_open
    else
        let open = "``"
    endif
    if exists("g:TeX_close")
        let close = g:TeX_close
    else
        let close = "''"
    endif
    let boundary = '\|'
    if exists("g:TeX_strictquote")
        if( g:TeX_strictquote == "open" || g:TeX_strictquote == "both" )
            let boundary = '\<' . boundary
        endif
        if( g:TeX_strictquote == "close" || g:TeX_strictquote == "both" )
            let boundary = boundary . '\>'
        endif
    endif
    let q = open
    let ws_save = &wrapscan
    set wrapscan    " so the search will not fail
    while 1 " Look for preceding quote (open or close), ignoring
        " math mode and '\"' .
        execute 'normal ?^$\|"\|' . open . boundary . close . "\r"
        if synIDattr(synID(line("."), col("."), 1), "name") !~ "^texMath"
                    \ && (col(".") == 1 || getline(".")[col(".")-2] != '\')
            break
        endif
    endwhile
    " Now, test whether we actually found a _preceding_ quote; if so, is it
    " and open quote?
    if ( line(".") < l || line(".") == l && col(".") < c )
        if strlen(getline("."))
            if ( getline(".")[col(".")-1] == open[0] )
                let q = close
            endif
        endif
    endif
    " Return to line l, column c:
    execute l . " normal " . c . "|"
    let &wrapscan = ws_save
    return q
endfunction
" Invoke TeX_quote() by typing " in Insert or Replace mode
if has("autocmd")
    autocmd BufEnter *.tex,*.sty inoremap "
                \ "<Left><C-O>:let@9=TeX_quote()<CR><Del><C-R>9
    autocmd BufLeave *.tex,*.sty iunmap "
endif
endif

" *****************************************
" Source the local vimrc additions (if any)
" *****************************************
if filereadable($HOME . '/.vimrc.local')
    source $HOME/.vimrc.local
endif
" vim:ft=vim