" .vimrc
"
" Noah Spurrier $Id: .vimrc 106 2007-11-15 19:41:08Z root $

" add the following to .profile or .bashrc
"export EDITOR=vim
"export VISUAL=vim
"export PAGER="col -b | view -c 'set ft=man nomod nolist nonumber' -"
"export MANPAGER="col -b | view -c 'set ft=man nomod nolist nonumber' -"

set nocompatible " use vim defaults (this should be first in .vimrc)
filetype plugin on " load ftplugin.vim
filetype indent on " load indent.vim

set history=1000 " number of commands and search patterns to save
if version >= 630
    set viminfo=!,%,'20,/100,:100,s100,n~/.viminfo " options for .viminfo
else
    set viminfo=!,%,'20,/100,:100,n~/.viminfo " options for .viminfo
endif
"set paste " ignore autoindent and formatoptions while pasting. does not hurt gvim.
set binary " show control characters (ignore 'fileformat')
set noautoindent " do not auto indent
set shiftround " align to standard indent when shifting with < and >
set formatoptions+=r " auto-format comments while typing
    " t_Co=16 is good on OSX, but not on Linux (leave unset for default)
"set t_Co=16 " assume we have more colors to work with for highlighting
set background=dark " set terminal background (see F11)
colorscheme native
"set guifont=Lucida_Console:h8 " set gvim font on Windows
syntax on " use syntax color highlighting
"colo ps_color " color scheme in ~/.vim/colors
"set visualbell " flash instead of beep -- this can be annoying
"set visualbell t_vb= " no beep or flash
"set mouse=a " enable VIM mouse (see map for F12)
set ttyfast " smoother display on fast network connections
set whichwrap=b,s,<,>,[,],~ " allow most motion keys to wrap
set backspace=indent,eol,start " allow bs over EOL, indent, and start of insert
set incsearch " incremental search
set nojoinspaces " use only one space when using join
set matchpairs+=<:> " add < > to chars that form pairs (see % command)
set showmatch " show matching brackets by flickering cursor
set matchtime=1 " show matching brackets quicker than default
set autoread " automatically read file changed outside of Vim
set autowrite " automatically save before commands like :next and :make
set splitbelow " open new split windows below the current one
set winminheight=0 " This makes more sense than the default of 1
set noequalalways " do not resize windows on split/close
"set shortmess="" " long messages -- does not seem to work
set showcmd " show partial command in status line
set suffixes+=.class,.pyc " skip bytecode files for filename completion
set suffixes-=.h " do not skip C header files for filename completion
set wrap " wrap long lines
set sidescroll=1 " smooth scroll if set nowrap. for slow terminals set to 0.
"set showbreak=>>>> " string to print before wrapped lines
if version >= 700
    set listchars=eol:$,tab:>-,trail:.,extends:>,precedes:<,nbsp:% " used when set list
else
    set listchars=eol:$,tab:>-,trail:.,extends:>,precedes:< " used when set list
endif
" set backup " backup files before editing
" set backupdir=~/tmp,.,/tmp,/var/tmp " backup locations
set dir=~/tmp,.,/tmp,/var/tmp " swap file locations
set virtualedit=block " allow Visual block select anywhere
set laststatus=2 " always show statusline 
set statusline=%n\ %1*%h%f%*\ %=%<[%3lL,%2cC]\ %2p%%\ 0x%02B%r%m
set ruler " show ruler, but only shown if laststatus is off
set rulerformat=%h%r%m%=%f " sane value in case laststatus is off
set nonumber " don't show line numbers
"set printoptions=number:y " put line numbers on hardcopy
" this turns on hlsearch, but clears the highlighting when Enter is hit
set wildmenu " show a menu of matches when doing completion
set hlsearch " highlight the current search pattern
set title " shows the current filename and path in the term title.
nnoremap <silent><CR> :nohlsearch<CR><CR> " in normal mode enter clears search highlight
if version >= 700
    "set cusorline " highlight the line with the cursor
    set numberwidth=4 " width of line numbers
endif

"
" tab settings
"
set tabstop=4|set shiftwidth=4|set expandtab " default
autocmd FileType python set tabstop=4|set shiftwidth=4|set expandtab " Python
autocmd FileType make set tabstop=8|set shiftwidth=8|set noexpandtab " Makefile
autocmd FileType man set tabstop=8|set shiftwidth=8|set noexpandtab " Man page (also used by psql to edit or view)
autocmd FileType calendar set tabstop=8|set shiftwidth=8|set noexpandtab

" This was just too clever and never worked quite right.
" I still want something like this, so I keep it here in case
" I ever figure out a smarter way of doing this.
" use magictab
"inoremap <tab> <c-r>=MagicTabWrapper("forward")<cr>
"inoremap <s-tab> <c-r>=MagicTabWrapper("backward")<cr>

" This highlights suspicious whitespace.
"autocmd FileType * :call HighlightBadWS()

" These are used by the DirDiff plugin.
" DirDiff rules!
let g:DirDiffExcludes = ".svn,*.jpg,*.png,*.gif,*.swp,*.a,*.so,*.o,*.pyc,*.exe,*.class,CVS,core,a.out"
let g:DirDiffIgnore = "Id:,Revision:,Date:"

" Automatically load templates for new files. Silent if the template for the
" extension does not exist. Virtually all template plugins I have seen for Vim
" are too complicated. This just loads what extension matches in
" $VIMHOME/templates/. For example the contents of html.tpl would be loaded
" for new html documents.
augroup BufNewFileFromTemplate
au!
autocmd BufNewFile * silent! 0r $HOME/.vim/templates/%:e.tpl
autocmd BufNewFile * normal! G"_dd1G
autocmd BufNewFile * silent! match Todo /TODO/
augroup BufNewFileFromTemplate

"
" maps
"

" This one is major. In insert mode backspace becomes the same as
" <c-w> (delete word). You will easier see the benefit of this or
" it will drive you nuts. This is an experiment to train myself that
" <c-w> is better than reaching for the backspace.
"imap <backspace> <c-w>

" map Q as @q (replay the recording named q). I always use q as my throw-away
" recording name, so I start recording with "qq" then reply the recording with
" "Q". I never found a use for interactive ex-mode so I don't miss the
" original definition of Q.
nnoremap Q @q

" easy indentation in visual mode
" This keeps the visual selection active after indenting.
" Usually the visual selection is lost after you indent it.
vmap > >gv
vmap < <gv

" Use display movement with arrow keys for extra precision. Arrow keys will
" move up and down the next line in the display even if the line is wrapped.
" This is useful for navigating very long lines that you often find with
" automatically generated text such as HTML.
" This is not useful if you turn off wrap.
imap <up> <C-O>gk
imap <down> <C-O>gj
nmap <up> gk
nmap <down> gj
vmap <up> gk
vmap <down> gj

" This maps \y so that it will yank the visual selection, but also quote the
" regex metacharacters, so you can then paste into a search pattern. For
" example, use v to select some text. Press \y. Then start a search with /.
" Type CTRL-R" to insert the yanked selection. The last two mappings allow you
" to visual select an area and then search for other matches by typing * or #.
vmap <silent> <leader>y y:let @"=substitute(escape(@",'.$*[^\/~'),'\n','\\n','g')<CR>
vmap <silent> * y:let @/=substitute(escape(@",'.$*[^\/~'),'\n','\\n','g')<CR>n
vmap <silent> # y:let @/=substitute(escape(@",'.$*[^\/~'),'\n','\\n','g')<CR>N
vnoremap <silent> * :<C-U>
              \let old_reg=getreg('"')<bar>
              \let old_regmode=getregtype('"')<cr>
              \gvy/<C-R><C-R>=substitute(substitute(
              \escape(@", '\\/.*$^~[]' ), "\n$", "", ""),
              \"\n", '\\_[[:return:]]', "g")<cr><cr>
              \:call setreg('"', old_reg, old_regmode)<cr>
vnoremap <silent> # :<C-U>
              \let old_reg=getreg('"')<bar>
              \let old_regmode=getregtype('"')<cr>
              \gvy?<C-R><C-R>=substitute(substitute(
              \escape(@", '\\/.*$^~[]' ), "\n$", "", ""),
              \"\n", '\\_[[:return:]]', "g")<cr><cr>
              \:call setreg('"', old_reg, old_regmode)<cr>

" echo the date and time
"map <leader>d :echo strftime("%Y-%m-%d %H:%M:%S")<CR>

" spell check
" <F2> or \s
if version >= 700
    map <silent><F2> <ESC>:set spell!<CR>
    map <silent><leader>s <ESC>:set spell!<CR>
    "setlocal spell spelllang=en_us
else " older versions use external aspell
    map <silent><F2> <ESC>:!aspell -c "%"<CR>:edit! "%"<CR>
    map <silent><leader>s <ESC>:!aspell -c "%"<CR>:edit! "%"<CR>
endif

" tab support
if version >= 700
    map <S-left> :tabp<CR>
    map <S-right> :tabn<CR>
endif

" redraw window
" <F5>
map <silent><F5> :redraw!<CR>

" This runs the current buffer in an X terminal that disappears after 5 minutes.
" This needs the env var $TERM set to xterm or some compatible X11 terminal.
" This does not save first!
" <F7> or \r
function RunBufferInTerm ()
    if &filetype == 'python'
        silent !$TERM -bg black -fg green -e bash -c "python %; sleep 300" &
    elseif &filetype == 'sh'
        silent !$TERM -bg black -fg green -e bash -c "./%; sleep 300" &
    elseif &filetype == 'php'
        silent !$TERM -bg black -fg green -e bash -c "php %; sleep 300" &
    elseif &filetype == 'perl'
        silent !$TERM -bg black -fg green -e bash -c "perl %; sleep 300" &
    endif
    sleep 1
    redraw!
endfunction
map <silent><F7> :call RunBufferInTerm()<CR>
map <silent><leader>r :call RunBufferInTerm()<CR>

" yank all lines
" <F8> or \a
map <silent><F8> gg"+yG
map <silent><leader>a gg"+yG
" toggle line numbers
" <F10> or \n
map <silent><F10> :set number!<CR>
map <silent><leader>n :set number!<CR>
" toggle between dark and light backgrounds
" <F11>
map <silent><F11> :let &background=(&background == "dark"?"light":"dark")<CR>
" toggle mouse mode between VIM and xterm
" <F12>
function ShowMouseMode()
    if (&mouse == 'a')
        echo "MOUSE VIM"
    else
        echo "MOUSE X11"
    endif
endfunction
map <silent><F12> :let &mouse=(&mouse == "a"?"":"a")<CR>:call ShowMouseMode()<CR>

" This is now covered by the DirDiff plugin.
" extra diff support
"
"map <silent><leader>dp :diffput<CR>
"map <silent><leader>dg :diffget<CR>

" run Vim diff on HEAD copy in SVN.
map <silent><leader>ds :call SVNDiff()<CR>
function! SVNDiff()
   let fn = bufname("%")
   let newfn = fn . ".HEAD"
   let catstat = system("svn cat " . fn . " > " . newfn)
   if catstat == 0
      execute 'vert diffsplit ' . newfn
   else
      echo "*** ERROR: svn cat failed for " . fn . " (as " . newfn . ")"
   endif
endfunction

"
" folding using the current /search/ pattern -- very handy!
"
" \z
" This folds every line that does not contain the search pattern.
" So the end result is that you only see lines with the pattern
" see vimtip #282 and vimtip #108
"map <silent><leader>z :set foldexpr=getline(v:lnum)!~@/ foldlevel=0 foldcolumn=0 foldmethod=expr<CR>
map <silent><leader>z :set foldexpr=(getline(v:lnum)=~@/)?\">1\":\"=\" foldlevel=0 foldcolumn=0 foldmethod=expr<CR>
" space toggles the fold state under the cursor.
nnoremap <silent><space> :exe 'silent! normal! za'.(foldlevel('.')?'':'l')<CR>
" this folds all classes and functions to create a code index.
" mnemonic: think "function fold"
map <silent>zff :set foldexpr=UniversalFoldExpression(v:lnum) foldmethod=expr foldlevel=0 foldcolumn=0<CR><CR>
function UniversalFoldExpression(lnum)
    if a:lnum == 1
        return ">1"
    endif
    return (getline(a:lnum)=~"^\\s*public function\\s\\|^\\s*function\\s\\|^\\s*class\\s\\|^\\s*def\\s") ? ">1" : "="
endfunction
" This doesn't work quite right:
    "if &filetype == 'php'
    "    if getline(a:lnum) =~ '/\*\*'
    "        call cursor(a:lnum,1)
    "        let sp = searchpair ('/\*\*','','\*/')
    "        call cursor(sp,1)
    "        let ax = search ('\n*\s*function','cW')
    "        if ax != 0
    "            return ">1"
    "        endif
    "    endif
    "    return "="
    "endif
    " @/ is the register that holds the last search pattern.

" plugins
runtime ftplugin/man.vim " allow vim to read man pages

"
" type \doc to insert PHPdocs
" see vimtip #1355
"
augroup php_doc
au!
"autocmd BufReadPost *.php,*.inc source ~/.vim/php-doc.vim
autocmd BufReadPost *.php,*.inc nnoremap <leader>doc :call PhpDocSingle()<CR>
autocmd BufReadPost *.php,*.inc vnoremap <leader>doc :call PhpDocRange()<CR>
augroup END


"
" This sets mouse support for editing XPM images in gvim.
" see h: xpm
"
function! GetPixel()
    let c = getline(".")[col(".") - 1]
    echo c
    exe "noremap <LeftMouse> <LeftMouse>r".c
    exe "noremap <LeftDrag>  <LeftMouse>r".c
endfunction
autocmd BufReadPre *.xpm noremap <RightMouse> <LeftMouse>:call GetPixel()<CR>
autocmd BufReadPre *.xpm set guicursor=n:hor20 " to see the color under cursor

"
" Experimental stuff
"

function! AppendUnnamedReg()
    let old=@"
    yank
    let @" = old . @"
endfun

" online doc search
" TODO This needs some work.
map <silent><M-d> :call OnlineDoc()<CR>
function! OnlineDoc()
    if &ft =~ "cpp"
        let s:urlTemplate = "http://doc.trolltech.com/4.1/%.html"
    elseif &ft =~ "ruby"
        let s:urlTemplate = "http://www.ruby-doc.org/core/classes/%.html"
    elseif &ft =~ "php"
        let s:urlTemplate = "http://www.php.net/%"
    elseif &ft =~ "perl"
        let s:urlTemplate = "http://perldoc.perl.org/functions/%.html"
    elseif &ft =~ "python"
        let s:urlTemplate = "http://starship.python.net/crew/theller/pyhelp.cgi?keyword=%"
    else
        return
    endif
    let s:browser = "firefox"
    let s:wordUnderCursor = expand("<cword>")
    let s:url = substitute(s:urlTemplate, "%", s:wordUnderCursor, "g")
    let s:cmd = "silent !" . s:browser . " " . s:url
    execute  s:cmd
    redraw!
endfunction

" another online doc search
" TODO This also needs some work.
" vimtip #1354
function! OnlineDoc()
    let s:browser = "firefox"
    let s:wordUnderCursor = expand("<cword>")
    if &ft == "cpp" || &ft == "c" || &ft == "ruby" || &ft == "php" || &ft == "python"
        let s:url = "http://www.google.com/codesearch?q=".s:wordUnderCursor."+lang:".&ft
    elseif &ft == "vim"
        let s:url = "http://www.google.com/codesearch?q=".s:wordUnderCursor
    else
        return
    endif
    let s:cmd = "silent !" . s:browser . " " . s:url
    "echo  s:cmd
    execute  s:cmd
endfunction
" online doc search
map <LocalLeader>k :call OnlineDoc()<CR>

" simple calculator based loosely on vimtip #1349
" control the precision with this variable
let g:MyCalcPresition = 2
function MyCalc(str)
    return system("echo 'scale=" . g:MyCalcPresition . " ; print " . a:str . "' | bc -l")
endfunction
" Use \C to replace a math expression by the value of its computation
vmap <leader><silent>C :s/.*/\=MyCalc(submatch(0))/<cr>/<BS>
vmap <leader><silent>C= :B s/.*/\=submatch(0) . " = " . MyCalc(submatch(0))/<cr>/<BS>

" Python command Calc based on vimtip #1235
" does NOT use built-in vim python
command! -nargs=+ Calc :r! python -c "from math import *; print <args>"

" allow reading of PDF text documents
" On Ubuntu install the xpdf-utils deb package.
autocmd BufReadPre *.pdf set ro
autocmd BufReadPost *.pdf silent %!pdftotext -nopgbrk "%" - |fmt -csw78

" allow reading of MS Word doc documents
" on Ubuntu install the antiword deb package.
autocmd BufReadPre *.doc set ro
autocmd BufReadPost *.doc silent %!antiword -i 1 -s -f "%" - |fmt -csw78

" jump to the last known position in a file
autocmd BufReadPost * if line("'\"") > 0 && line("'\"") <= line("$") | exe "normal g'\"" | endif

