" This is the _vimrc file used with Vim 7.2+ in Win32 GUI environment

" $Id: _vimrc,v 7.152 2011/01/08 20:30:23 slobin Exp $
" Source of this file: http://slobin.pp.ru/vim/_vimrc

" langmap in utf-8 mode requires at least Vim 7.2.109

" Language and encoding must be set as early as possible
language C
set all&
set encoding=utf-8

" A lot of miscellaneous settings
set autoindent
set backspace=indent,eol,start
set cinkeys=!^F,o,O
set cinoptions=p0
set display=lastline,uhex
set expandtab
set formatoptions=t2l1
set guicursor+=a:blinkon0
set guifont=Consolas:h10
set history=200
set ignorecase
set nojoinspaces
set keymodel=startsel
set langmap=йqцwуeкrеtнyгuшiщoзpх[ъ]фaыsвdаfпgрhоjлkдlж\\;э'
           \яzчxсcмvиbтnьmб\\,ю.ЙQЦWУEКRЕTНYГUШIЩOЗPХ{Ъ}
           \ФAЫSВDАFПGРHОJЛKДLЖ:Э\\"ЯZЧXСCМVИBТNЬMБ<Ю>ё`Ё~№#
set laststatus=2
set mousemodel=popup_setpos
set number
set shiftwidth=4
set sidescroll=1
set smartcase
set softtabstop=4
set spell
set spelllang=en_us,ru_yo
set textwidth=72
set viminfo=!,'20,<100,c,h,s10,ra:,rb:,rx:,ry:,rz:,n$VIM/_viminfo
set whichwrap=b,s,~,<,>,[,]
set nowrap

" Check for GUI here? XXX
set columns=96
set lines=30

" A set of the funny icons for the statusline
let icons = [">+<", "<+>", ">-<", "<->", ">#<", "<#>", ">=<", "<=>",
            \">O<", "<O>", ">o<", "<o>", ">X<", "<X>", ">x<", "<x>"]

" These encodings will be listed in the GUI menu
let encodings = ["ascii", "cp1251", "cp866", "iso-8859-5", "koi8-r",
               \ "latin1", "utf-16le", "utf-8"]

" These options will be kept between editing sessions
let options = ["spell", "textwidth", "wrap"]

" Miscellaneous defaults, will be changed by VimEnter() function
let EXTERNAL = 1
let SYNTAX = "on"

" Helpheight is different in GUI and text modes
let &helpheight = &lines - 8

" Bogus value, just not to leave it undefined
let was_modified = 2

" Phase of the Moon calculation
let time = localtime()
let fullday = 86400
let offset = 592500
let period = 2551443
let phase = (time - offset) % period
let phase = phase / fullday

" Funny icon for the statusline, combined from the set of status bits
function! Icon()
  return g:icons[8 * exists("b:syn_sync") + 4 * exists("g:syntax_on")
                \ + 2 * &spell + &wrap]
endfunction

" Value of a character under cursor; better than standard '0x%02B (%b)'
function! HexDec()
  let char = matchstr(getline("."), ".", col(".") - 1)
  if g:EXTERNAL
    let char = iconv(char, &encoding, &fileencoding)
    let format = "0x%02X <%d>"
  else
    let format = "0x%02X (%d)"
  endif
  let char = char2nr(char)
  return printf(format, char, char)
endfunction

" Custom completion for encoding names
function! EncList(ArgLead, CmdLine, CursorPos)
  return filter(copy(g:encodings),
              \ "strpart(v:val, 0, strlen(a:ArgLead)) == a:ArgLead")
endfunction

" Helper function for :DecodeQP and :DecodeURL commands
function! DecodeHex(arg)
  return iconv(printf("%c", str2nr(submatch(1), 16)), a:arg, &encoding)
endfunction

" Sets &fileencoding and &fileencodings options, but &modified flag kept
" intact - this is a bit illogical but handy
function! SetEncoding(encoding)
  let save_modified = &modified
  let &fileencoding = a:encoding
  let &fileencodings = a:encoding
  if &encoding == "utf-8"
    set fileencodings^=ucs-bom,ascii,utf-8
  else
    set fileencodings^=ascii
  endif
  let &modified = save_modified
endfunction

" Makes encoding menu if running GUI
function! MakeEncodingMenu()
  for enc in g:encodings
    execute printf("an <silent> E&ncoding.%s :SetEncoding %s<CR>", enc, enc)
  endfor
endfunction

" Smart search for a right &spellfile location
function! SetSpellFile(name)
  for dir in split(&runtimepath, ",")
    if filewritable(dir . "/spell/" . a:name) == 1
      let &spellfile = dir . "/spell/" . a:name
      return
    endif
  endfor
  for dir in split(&runtimepath, ",")
    if filewritable(dir) == 2
      if !isdirectory(dir . "/spell")
        call mkdir(dir . "/spell")
      endif
      let &spellfile = dir . "/spell/" . a:name
      return
    endif
  endfor
endfunction

" Colorscheme adjustments
function! AdjustColorScheme()
  hi LineNr guifg=LightBlue Guibg=LightGray
  hi MatchParen ctermbg=DarkMagenta guibg=LightMagenta
  hi Pmenu ctermbg=DarkCyan guibg=LightCyan
  hi PmenuSel cterm=bold gui=bold
  hi User1 ctermbg=DarkCyan ctermfg=Black gui=Bold guibg=DarkBlue guifg=White
endfunction

" Helper function for <Tab> key mapping
function! CleverTab()
  if strpart(getline('.'), 0, col('.')-1) =~ '\k$'
    return "\<C-N>"
  else
    return "\<Tab>"
  endif
endfunction

" Helper function for <F4> key mapping
function! SyntaxName()
  echomsg synIDattr(synID(line("."), col("."), 1), "name")
endfunction

" Helper function for <F5> key mapping
function! SyncToggle()
  if exists("b:syn_sync")
    syntax sync clear
    unlet b:syn_sync
  else
    syntax sync fromstart
    let b:syn_sync = 1
  endif
endfunction

" Helper function for <F7> key mapping
function! TextWidthToggle()
  if &textwidth > 0
    let b:back_width = &textwidth
    setlocal textwidth=0
  else
    if exists("b:back_width")
      let &l:textwidth = b:back_width
    else
      setlocal textwidth<
    endif
  endif
endfunction

" Helper function for <F10> key mapping
function! SyntaxToggle()
  execute "syntax" exists("g:syntax_on") ? "off" : "on"
endfunction

" Called automagically after every buffer read, enables fileencoding
" setting from modeline (see Tip #911)
function! AutoEncoding()
  if exists("b:justloaded")
    unlet b:justloaded
    if &modified && &fileencoding != ""
      execute "edit! ++enc=" . &fileencoding
    endif
  endif
endfunction

" Helper function for :WT command, updates 'Last change:' " timestamp
" and RCS Id (has called automagically before)
function! TimeStamp()
  let lines = line("$") < 10 ? line("$") : 10
  let pattern1 = '\(Last [Cc]hange:\s\+\)\d\d\d\d \u\l\l \d\d'
  let replace1 = '\1' . strftime("%Y %b %d")
  execute printf('1,%ds/\C\m%s/%s/e', lines, pattern1, replace1)
  execute printf('$-%d+1,$s/\C\m%s/%s/e', lines, pattern1, replace1)
  let pattern2 = '\($Id: \f\+ \d\+\.\d\+\(\.\d\+\.\d\+\)*\)\(+\(\d\+\)\)\? '
             \ . '\(\d\d\d\d[-/]\d\d[-/]\d\d \d\d:\d\d:\d\d\)\(+\d\d\)\?'
  let replace2 = '\=submatch(1) . "+" . (submatch(4) + 1) . " "'
             \ . '. strftime("%Y\/%m\/%d %H:%M:%S") . submatch(6)'
  execute printf('1,%ds/\C\m%s/%s/e', lines, pattern2, replace2)
  execute printf('$-%d+1,$s/\C\m%s/%s/e', lines, pattern2, replace2)
endfunction

" Called automagically after .viminfo and plugins are loaded, sets
" miscellaneous options from persistent global variables
function! VimEnter()
  for optname in g:options
    let varname = "g:OPT_" . toupper(optname)
    if exists(varname)
      execute "let &" . optname . " = " . varname
    endif
  endfor
  execute "syntax" g:SYNTAX
  if has("gui_running") && exists("g:WINPOSX") && exists("g:WINPOSY")
    execute "winpos" g:WINPOSX g:WINPOSY
  endif
  call AdjustColorScheme()
endfunction

" Called automagically before .viminfo is saved, saves miscellaneous
" options into persistent global variables
function! VimLeavePre()
  call filter(g:, 'v:key !~# "^OPT_"')
  for optname in g:options
    let varname = "g:OPT_" . toupper(optname)
    execute "let " . varname . " = &g:" . optname
  endfor
  let g:SYNTAX = exists("g:syntax_on") ? "on" : "off"
  if has("gui_running")
    let g:WINPOSX = getwinposx()
    let g:WINPOSY = getwinposy()
  endif
endfunction

" Called automagically in various conditions, sets statusline color
" depending of &modified state
function! WhenModified(force)
  if a:force || &modified != g:was_modified
    execute 'setlocal statusline=%' . &modified . '*'
        \ . '%t\ %L\ %y%r[%{&tw}]\%m%=(%{g:phase})\ %{Icon()}\ %{&fenc}'
        \ . '\ \ %-15(%{HexDec()}%)%-10(%l,%v%)%P'
    let g:was_modified = &modified
  endif
endfunction

" Command for decoding qp-encoded text
command! -bar -nargs=? -range -complete=customlist,EncList DecodeQP
       \ <line1>,<line2>s/=\(\x\x\|\n\)/\=DecodeHex(<q-args>)/eg

" Command for decoding url-encoded text
command! -bar -nargs=? -range -complete=customlist,EncList DecodeURL
       \ <line1>,<line2>s/%\(\x\x\)/\=DecodeHex(<q-args>)/eg

" Command interface for SetEncoding() function
command! -bar -nargs=1 -complete=customlist,EncList SetEncoding
       \ call SetEncoding(<q-args>)

" Command for sorting preserving current position
command! -bar -bang -nargs=* -range=% Sort
       \ mark s | <line1>,<line2> sort<bang> <args> | 's

" Command for writing timestamp to file
command! -bar -bang -nargs=* -range=% -complete=file WT
       \ mark s | call TimeStamp() | <line1>,<line2> write<bang> <args> | 's

" Arrows should go into wrapped lines, but not while popup menu is visible
map <Down> gj
map <Up> gk
imap <expr> <Down> pumvisible() ? "<Down>" : "<C-O>gj"
imap <expr> <Up> pumvisible() ? "<Up>" : "<C-O>gk"

" The <CR> key should select from completion menu without adding a newline
imap <expr> <CR> pumvisible() ? "<C-Y>" : "<CR>"

" The <Tab> key may insert tabs or start completion
inoremap <Tab> <C-R>=CleverTab()<CR>

" The <Tab> key jumps forth and back in normal mode
map <expr> <Tab> (virtcol(".") / &sts + 1) * &sts + 1 . "\|"
map <expr> <S-Tab> (virtcol(".") / &sts - 1) * &sts + 1 . "\|"

" J is for jump, and we need the <Tab> key for another purpose
" Instead of old <C-J> use plain j or <C-N>
noremap <C-J> <Tab>

" Shifting visual block should keep it selected
vnoremap < <gv
vnoremap > >gv

" $ and / are mirrored with ; and , for Cyrillic mode
map ; $
map , /
map ж $
map б /

" Toggle line wrap on/off (<F2> like in FAR or VC)
nmap <silent> <F2> :set wrap!<CR>
imap <F2> <C-O><F2>

" Display unicode name for the character under cursor
" nmap <F3> is defined later in Python section

" Display syntax group name for the word under cursor
nmap <silent> <F4> :call SyntaxName()<CR>

" Toggle syntax synchronization on/off
nmap <silent> <F5> :call SyncToggle()<CR>
imap <F5> <C-O><F5>

" Toggle character value display mode between &encoding and &fileecoding
nmap <silent> <F6> :let EXTERNAL = !EXTERNAL<CR>
imap <F6> <C-O><F6>

" Toggle text width between current value and zero
nmap <silent> <F7> :call TextWidthToggle()<CR>
imap <F7> <C-O><F7>

" Toggle spell checking on/off
nmap <silent> <F8> :set spell!<CR>
imap <F8> <C-O><F8>

" Format a paragraph (<F9> like in MicroMir)
nmap <F9> gqap
imap <F9> <C-O><F9>

" Toggle syntax highlighting on/off
nmap <silent> <F10> :call SyntaxToggle()<CR>
imap <F10> <C-O><F10>

" This check does not work, kept for documenting purpose only
if has("python")

python << END_OF_PYTHON

import vim, sys, rlcompleter, unicodedata
from itertools import *
vim_complete = rlcompleter.Completer().complete

# depends on the dirty hack in sitecustomize.py
sys.setappdefaultencoding(vim.eval("&encoding"))

def vim_comp_list():
  """Implementation of CompList() function"""
  arglead = vim.eval("a:ArgLead")
  fence = int(vim.eval("match(a:ArgLead, '\(\w\|\.\)*$')"))
  left, right = arglead[:fence], arglead[fence:]
  try:
    completions = (vim_complete(right, i) for i in count())
    candidates = list(takewhile(bool, completions))
  except NameError:
    candidates = []
  suggestions = [left + x for x in candidates]
  vim.command("return " + repr(suggestions))

def vim_calc(command):
  """Implementation of :Calc command"""
  global _
  try:
    result = eval(command)
  except SyntaxError:
    exec command in globals()
  else:
    if result != None:
      print result
      _ = result
      xx = ''.join('\\x%02x' % ord(x) for x in str(_))
      vim.command('let @" = "%s"' % xx)

def vim_pydo(command):
  """Implementation of :Pydo command"""
  codeobj = compile(command, "command", "eval")
  line1 = vim.current.range.start
  line2 = vim.current.range.end
  delta = 0
  for numz in range(line1, line2+1):
    line = vim.current.buffer[numz-delta]
    line = unicode(line)
    num = numz + 1
    words = line.split()
    result = eval(codeobj, globals(), locals())
    if result is None or result is False:
      del vim.current.buffer[numz-delta]
      delta += 1
      continue
    if isinstance(result, list) or isinstance(result, tuple):
      result = " ".join(map(str, result))
    else:
      result = str(result)
    vim.current.buffer[numz-delta] = result

def vim_unicode_name():
  """Helper function for <F11> key mapping"""
  try:
    char = vim.eval("matchstr(getline('.'), '.', col('.') - 1)")
    print map(unicodedata.name, char.decode(vim.eval("&encoding")))
  except (AttributeError, ValueError), target:
    print "%s: %s" % (target.__class__.__name__, target.message)

END_OF_PYTHON

" Custom completion for python expressions
function! CompList(ArgLead, CmdLine, CursorPos)
  python vim_comp_list()
endfunction

" Python command line calculator
command! -nargs=+ -range -complete=customlist,CompList Calc
       \ <line1>,<line2> python vim_calc(<q-args>)

" Python text range filter
command! -nargs=+ -range -complete=customlist,CompList Pydo
       \ <line1>,<line2> python vim_pydo(<q-args>)

" Display unicode name for the character under cursor
nmap <silent> <F3> :python vim_unicode_name()<CR>

endif

" Magic autocommands installed here
autocmd!
autocmd BufEnter,BufReadPost,BufWritePost * call WhenModified(1)
autocmd BufReadPost * let b:justloaded = 1
autocmd BufWinEnter * if !&swapfile | set viminfo= | endif
autocmd BufWinEnter * call AutoEncoding()
autocmd BufNewFile,BufReadPre,ColorScheme * call AdjustColorScheme()
autocmd CursorMoved,CursorMovedI * call WhenModified(0)
autocmd VimEnter * call VimEnter()
autocmd VimLeavePre * call VimLeavePre()

" Enable all possible intelligence
filetype indent plugin on

" Language-specific settings
call SetEncoding("cp1251")
call SetSpellFile("xx.utf-8.add")

" Just in case settings are reloaded
call WhenModified(1)

" Menu adjustments
execute printf('an 20.437 &Edit.&Reload\ Settings :source %s<CR>',
              \ expand("<sfile>"))
call MakeEncodingMenu()

" Filetype-specific settings
autocmd! filetypedetect BufNewFile,BufRead *.jbo set filetype=lojban
autocmd! filetypedetect BufNewFile,BufRead *.fal set filetype=falcon
autocmd! filetypedetect BufNewFile,BufRead *.lsp set filetype=newlisp
autocmd! filetypedetect BufNewFile,BufRead *.zu,*.zwt set filetype=zimbu

autocmd FileType vim setlocal sw=2 sts=2
autocmd FileType python setlocal formatoptions+=crq

let g:is_bash = 1
let g:vimsyntax_noerror = 1

" Last-minute tweakings are going here
if filereadable(expand("<sfile>") . "1")
  source <sfile>1
endif

" I'll mend it, and then play. (W. Shakespeare, "Antony and Cleopatra")