Commits

Anonymous committed e3c8ed9

initial clone.

  • Participants

Comments (0)

Files changed (9)

File autoload/l9.vim

+"=============================================================================
+" Copyright (c) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if exists('g:loaded_autoload_l9')
+  finish
+endif
+let g:loaded_autoload_l9 = 1
+
+" }}}1
+"=============================================================================
+" COMPATIBILITY TEST {{{1
+
+"
+let s:L9_VERSION_CURRENT  = 101
+let s:L9_VERSION_PASSABLE = 101
+
+" returns true if given version is compatible.
+function l9#isCompatible(ver)
+  return 
+endfunction
+
+let s:VERSION_FACTOR = str2float('0.01')
+
+" returns false if the caller script should finish.
+" a:vimVersion: if 0, don't check vim version
+" a:l9Version: same rule as v:version
+function l9#guardScriptLoading(path, vimVersion, l9Version, exprs)
+  let loadedVarName = 'g:loaded_' . substitute(a:path, '\W', '_', 'g')
+  if exists(loadedVarName)
+    return 0
+  elseif a:vimVersion > 0 && a:vimVersion > v:version
+    echoerr a:path . ' requires Vim version ' . string(a:vimVersion * s:VERSION_FACTOR)
+    return 0
+  elseif a:l9Version > 0 && (a:l9Version > s:L9_VERSION_CURRENT ||
+        \                    a:l9Version < s:L9_VERSION_PASSABLE)
+    echoerr a:path . ' requires L9 library version ' . string(a:l9Version * s:VERSION_FACTOR)
+    return 0
+  endif
+  for expr in a:exprs
+    if !eval(expr)
+      echoerr a:path . ' requires: ' . expr
+      return 0
+    endif
+  endfor
+  let {loadedVarName} = 1
+  return 1
+endfunction
+
+" 
+function l9#getVersion()
+  return s:L9_VERSION_CURRENT
+endfunction
+
+" }}}1
+"=============================================================================
+" LIST {{{1
+
+" Removes duplicates (unstable)
+" This function doesn't change the list of argument.
+function l9#unique(items)
+  let sorted = sort(a:items)
+  if len(sorted) < 2
+    return sorted
+  endif
+  let last = remove(sorted, 0)
+  let result = [last]
+  for item in sorted
+    if item != last
+      call add(result, item)
+      let last = item
+    endif
+  endfor
+  return result
+endfunction
+
+" Removes duplicates (stable)
+" This function doesn't change the list of argument.
+function l9#uniqueStably(items)
+  let result = []
+  for item in a:items
+    if count(result, item, &ignorecase) == 0
+      call add(result, item)
+    endif
+  endfor
+  return result
+endfunction
+
+" [ [0], [1,2], [3] ] -> [ 0, 1, 2, 3 ]
+" This function doesn't change the list of argument.
+function l9#concat(items)
+  let result = []
+  for l in a:items
+    let result += l
+  endfor
+  return result
+endfunction
+
+" [ [0,1,2], [3,4], [5,6,7,8] ] -> [ [0,3,5],[1,4,6] ]
+" This function doesn't change the list of argument.
+function l9#zip(items)
+  let result = []
+  for i in range(min(map(copy(a:items), 'len(v:val)')))
+    call add(result, map(copy(a:items), 'v:val[i]'))
+  endfor
+  return result
+endfunction
+
+" filter() with the maximum number of items
+" This function doesn't change the list of argument.
+function l9#filterWithLimit(items, expr, limit)
+  if a:limit <= 0
+    return filter(copy(a:items), a:expr)
+  endif
+  let result = []
+  let stride = a:limit * 3 / 2 " x1.5
+  for i in range(0, len(a:items) - 1, stride)
+    let result += filter(a:items[i : i + stride - 1], a:expr)
+    if len(result) >= a:limit
+      return remove(result, 0, a:limit - 1)
+    endif
+  endfor
+  return result
+endfunction
+
+" Removes if a:expr is evaluated as non-zero and returns removed items.
+" This function change the list of argument.
+function l9#removeIf(items, expr)
+  let removed = filter(copy(a:items), a:expr)
+  call filter(a:items, '!( ' . a:expr . ')')
+  return removed
+endfunction
+
+" }}}1
+"=============================================================================
+" NUMERIC {{{1
+
+" }}}1
+"=============================================================================
+" STRING {{{1
+
+" Snips a:str and add a:mask if the length of a:str is more than a:len
+function l9#snipHead(str, len, mask)
+  if a:len >= len(a:str)
+    return a:str
+  elseif a:len <= len(a:mask)
+    return a:mask
+  endif
+  return a:mask . a:str[-a:len + len(a:mask):]
+endfunction
+
+" Snips a:str and add a:mask if the length of a:str is more than a:len
+function l9#snipTail(str, len, mask)
+  if a:len >= len(a:str)
+    return a:str
+  elseif a:len <= len(a:mask)
+    return a:mask
+  endif
+  return a:str[:a:len - 1 - len(a:mask)] . a:mask
+endfunction
+
+" Snips a:str and add a:mask if the length of a:str is more than a:len
+function l9#snipMid(str, len, mask)
+  if a:len >= len(a:str)
+    return a:str
+  elseif a:len <= len(a:mask)
+    return a:mask
+  endif
+  let len_head = (a:len - len(a:mask)) / 2
+  let len_tail = a:len - len(a:mask) - len_head
+  return  (len_head > 0 ? a:str[: len_head - 1] : '') . a:mask .
+        \ (len_tail > 0 ? a:str[-len_tail :] : '')
+endfunction
+
+"
+function l9#hash224(str)
+  let a = 0x00000800 " shift 11 bit (if unsigned)
+  let b = 0x001fffff " extract 11 bit (if unsigned)
+  let nHash = 7
+  let hashes = repeat([0], nHash)
+  for i in range(len(a:str))
+    let iHash = i % nHash
+    let hashes[iHash] = hashes[iHash] * a + hashes[iHash] / b
+    let hashes[iHash] += char2nr(a:str[i])
+  endfor
+  return join(map(hashes, 'printf("%08x", v:val)'), '')
+endfunction
+
+" wildcard -> regexp
+function l9#convertWildcardToRegexp(expr)
+  let re = escape(a:expr, '\')
+  for [pat, sub] in [ [ '*', '\\.\\*' ], [ '?', '\\.' ], [ '[', '\\[' ], ]
+    let re = substitute(re, pat, sub, 'g')
+  endfor
+  return '\V' . re
+endfunction
+
+" }}}1
+"=============================================================================
+" LINES {{{1
+
+" Removes from the line matching with a:begin first to the line matching with
+" a:end next and returns removed lines.
+" If matching range is not found, returns []
+function l9#removeLinesBetween(lines, begin, end)
+  for i in range(len(a:lines) - 1)
+    if a:lines[i] =~ a:begin
+      break
+    endif
+  endfor
+  for j in range(i + 1, len(a:lines) - 1)
+    if a:lines[j] =~ a:end
+      let g:l0 += [a:lines[i : j]]
+      return remove(a:lines, i, j)
+    endif
+  endfor
+  return []
+endfunction
+
+" }}}1
+"=============================================================================
+" PATH {{{1
+
+" returns the path separator charactor.
+function l9#getPathSeparator()
+  return (!&shellslash && (has('win32') || has('win64')) ? '\' : '/')
+endfunction
+
+" [ 'a', 'b/', '/c' ] -> 'a/b/c'
+function l9#concatPaths(paths)
+  let result = ''
+  for p in a:paths
+    if empty(p)
+      continue
+    elseif empty(result)
+      let result = p
+    else
+      let result = substitute(result, '[/\\]$', '', '') . l9#getPathSeparator()
+            \    . substitute(p, '^[/\\]', '', '')
+    endif
+  endfor
+  return result
+endfunction
+
+" path: '/a/b/c/d', dir: '/a/b' => 'c/d'
+function l9#modifyPathRelativeToDir(path, dir)
+  let pathFull = fnamemodify(a:path, ':p')
+  let dirFull = fnamemodify(a:dir, ':p')
+  if len(pathFull) < len(dirFull) || pathFull[:len(dirFull) - 1] !=# dirFull
+    return pathFull
+  endif
+  return pathFull[len(dirFull):]
+endfunction
+
+" }}}1
+"=============================================================================
+" FILE {{{1
+
+" Almost same as readfile().
+function l9#readFile(...)
+  let args = copy(a:000)
+  let args[0] = expand(args[0])
+  try
+    return call('readfile', args)
+  catch
+  endtry
+  return []
+endfunction
+
+" Almost same as writefile().
+function l9#writeFile(...)
+  let args = copy(a:000)
+  let args[1] = expand(args[1])
+  let dir = fnamemodify(args[1], ':h')
+  try
+    if !isdirectory(dir)
+      call mkdir(dir, 'p')
+    endif
+    return call('writefile', args)
+  catch
+  endtry
+  return -1 " -1 is error code.
+endfunction
+
+" }}}1
+"=============================================================================
+" BUFFER {{{1
+
+" :wall/:wall! wrapper. Useful for writing readonly buffers.
+function l9#writeAll()
+  try
+    silent update " NOTE: avoiding a problem with a buftype=acwrite buffer.
+    silent wall
+  catch /^Vim/ " E45, E505
+    if l9#inputHl('Question', v:exception . "\nWrite readonly files? (Y/N) : ", 'Y') ==? 'y'
+      redraw
+      :wall!
+    endif
+  endtry
+endfunction
+
+" Loads given files with :edit command
+function l9#loadFilesToBuffers(files)
+  for file in filter(copy(a:files), '!bufloaded(v:val)')
+    execute 'edit ' . fnameescape(file)
+    if !exists('bufNrFirst')
+      let bufNrFirst = bufnr('%')
+    endif
+  endfor
+  if exists('bufNrFirst')
+    execute bufNrFirst . 'buffer'
+  endif
+endfunction
+
+" Deletes all buffers except given files with :bdelete command
+function l9#deleteAllBuffersExcept(files)
+  let bufNrExcepts = map(copy(a:files), 'bufnr("^" . v:val . "$")')
+  for bufNr in filter(range(1, bufnr('$')), 'bufloaded(v:val)')
+    if count(bufNrExcepts, bufNr) == 0
+      execute bufNr . 'bdelete'
+    endif
+  endfor
+endfunction
+
+" }}}1
+"=============================================================================
+" WINDOW {{{1
+
+" move current window to next tabpage.
+function l9#shiftWinNextTabpage()
+  if tabpagenr('$') < 2
+    return
+  endif
+  let bufnr = bufnr('%')
+  tabnext
+  execute bufnr . 'sbuffer'
+  tabprevious
+  if winnr('$') > 1
+    close
+    tabnext
+  else
+    close " if tabpage is closed, next tabpage will become current
+  endif
+endfunction
+
+" move current window to previous tabpage.
+function l9#shiftWinPrevTabpage()
+  if tabpagenr('$') < 2
+    return
+  endif
+  let bufnr = bufnr('%')
+  tabprevious
+  execute bufnr . 'sbuffer'
+  tabnext
+  close
+  tabprevious
+endfunction
+
+" move to a window containing specified buffer.
+" returns 0 if the buffer is not found.
+function l9#moveToBufferWindowInCurrentTabpage(bufNr)
+  if bufnr('%') == a:bufNr
+    return 1
+  elseif count(tabpagebuflist(), a:bufNr) == 0
+    return 0
+  endif
+  execute bufwinnr(a:bufNr) . 'wincmd w'
+  return 1
+endfunction
+
+" returns 0 if the buffer is not found.
+function s:moveToOtherTabpageOpeningBuffer(bufNr)
+  for tabNr in range(1, tabpagenr('$'))
+    if tabNr != tabpagenr() && count(tabpagebuflist(tabNr), a:bufNr) > 0
+      execute 'tabnext ' . tabNr
+      return 1
+    endif
+  endfor
+  return 0
+endfunction
+
+" move to a window containing specified buffer.
+" returns 0 if the buffer is not found.
+function l9#moveToBufferWindowInOtherTabpage(bufNr)
+  if !s:moveToOtherTabpageOpeningBuffer(a:bufNr)
+    return 0
+  endif
+  return l9#moveToBufferWindowInCurrentTabpage(a:bufNr)
+endfunction
+
+" }}}1
+"=============================================================================
+" COMMAND LINE {{{1
+
+" echo/echomsg with highlighting.
+function l9#echoHl(hl, msg, prefix, addingHistory)
+  let echoCmd = (a:addingHistory ? 'echomsg' : 'echo')
+  execute "echohl " . a:hl
+  try
+    for l in (type(a:msg) == type([]) ? a:msg : split(a:msg, "\n"))
+      execute echoCmd . ' a:prefix . l'
+    endfor
+  finally
+    echohl None
+  endtry
+endfunction
+
+" input() with highlighting.
+" This function can take list as {completion} argument.
+function l9#inputHl(hl, ...)
+  execute "echohl " . a:hl
+  try
+    let args = copy(a:000)
+    if len(args) > 2 && type(args[2]) == type([])
+      let s:candidatesForInputHl = args[2]
+      let args[2] = 'custom,l9#completeForInputHl'
+    endif
+    let s = call('input', args)
+    unlet! s:candidatesForInputHl
+  finally
+    echohl None
+  endtry
+  redraw " needed to show following echo to next line.
+  return s
+endfunction
+
+" only called by l9#inputHl() for completion.
+function l9#completeForInputHl(lead, line, pos)
+  return join(s:candidatesForInputHl, "\n")
+endfunction
+
+" }}}1
+"=============================================================================
+" VISUAL MODE {{{1
+
+" returns last selected text in Visual mode.
+function l9#getSelectedText()
+  let reg_ = [@", getregtype('"')]
+  let regA = [@a, getregtype('a')]
+  if mode() =~# "[vV\<C-v>]"
+    silent normal! "aygv
+  else
+    let pos = getpos('.')
+    silent normal! gv"ay
+    call setpos('.', pos)
+  endif
+  let text = @a
+  call setreg('"', reg_[0], reg_[1])
+  call setreg('a', regA[0], regA[1])
+  return text
+endfunction
+
+
+" }}}1
+"=============================================================================
+" EVAL {{{1
+
+" loads given text as Vim script with :source command
+function l9#loadScript(text)
+  let lines = (type(a:text) == type([]) ? a:text : split(a:text, "\n"))
+  let fname = tempname()
+  call writefile(lines, fname)
+  source `=fname`
+  call delete(fname)
+endfunction
+
+
+" }}}1
+"=============================================================================
+" VARIABLES {{{1
+
+" 
+function l9#defineVariableDefault(name, default)
+  if !exists(a:name)
+    let {a:name} = a:default
+  endif
+endfunction
+
+" }}}1
+"=============================================================================
+" GREP {{{1
+
+" Execute :vimgrep and opens the quickfix window if matches are found.
+"
+" a:pattern: search pattern. If ommitted, last search pattern (@/) is used.
+" a:files: List of files
+function l9#grepFiles(pattern, files)
+  let target = join(map(a:files, 'escape(v:val, " ")'), ' ')
+  let pattern = (a:pattern[0] ==# '/' ? a:pattern[1:] : a:pattern)
+  let pattern = (empty(pattern)  ? @/ : pattern)
+  try
+    execute printf('vimgrep/%s/j %s', pattern, target)
+  catch /^Vim/
+    call setqflist([])
+  endtry
+  call l9#quickfix#sort()
+  call l9#quickfix#openIfNotEmpty(1, 0)
+endfunction
+
+" Execute :vimgrep for buffers using l9#grepFiles()
+" See also: :L9GrepBuffer :L9GrepBufferAll
+function l9#grepBuffers(pattern, bufNrs)
+  let files = map(filter(a:bufNrs, 'bufloaded(v:val)'), 'bufname(v:val)')
+  call l9#grepFiles(a:pattern, files)
+endfunction
+
+" }}}1
+"=============================================================================
+" SIGN {{{1
+
+" Highlights lines using :sign define and :sign place.
+" 
+" a:linehl, a:text, a:texthl: See |signs|. Ignored if empty string.
+" a:locations: List of [{buffer number}, {line number}] for highlighting
+function l9#placeSign(linehl, text, texthl, locations)
+  let argLinehl = (empty(a:linehl) ? '' : 'linehl=' . a:linehl)
+  let argText = (empty(a:text) ? '' : 'text=' . a:text)
+  let argTexthl = (empty(a:texthl) ? '' : 'texthl=' . a:texthl)
+  let name = 'l9--' . a:linehl . '--' . a:text . '--' . a:texthl
+  execute printf('sign define %s linehl=%s text=%s texthl=%s',
+        \        name, a:linehl, a:text, a:texthl)
+  for [bufNr, lnum] in a:locations
+    execute printf('sign place 1 line=%d name=%s buffer=%d', lnum, name, bufNr)
+  endfor
+endfunction
+
+" }}}1
+"=============================================================================
+" NOTIFY EXTERNALLY {{{1
+
+" Notify a message using an external program.
+" Currently supports Balloonly, Screen, and Tmux.
+function l9#notifyExternally(msg)
+  return     l9#notifyBalloonly(a:msg)
+        \ || l9#notifyScreen(a:msg)
+        \ || l9#notifyTmux(a:msg)
+endfunction
+
+"
+function l9#notifyBalloonly(msg)
+  if !(has('win32') || has('win64')) || !executable(g:l9_balloonly)
+    return 0
+  endif
+  execute 'silent !start ' . shellescape(g:l9_balloonly) . ' 4000 "l9" ' . shellescape(a:msg)
+  return 1
+endfunction
+
+"
+function l9#notifyScreen(msg)
+  if !has('unix') || has('gui_running') || $WINDOW !~ '\d' || !executable('screen')
+    return 0
+  endif
+  call system('screen -X wall ' . shellescape('l9: ' . a:msg))
+  return 1
+endfunction
+
+"
+function l9#notifyTmux(msg)
+  if !has('unix') || has('gui_running') || empty($TMUX) || !executable('tmux')
+    return 0
+  endif
+  call system('tmux display-message ' . shellescape('l9: ' . a:msg))
+  return 1
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:

File autoload/l9/async.py

+#!/usr/bin/env python
+
+from __future__ import with_statement
+import vim
+import os
+import subprocess
+import threading
+import Queue
+
+
+class Asyncer:
+
+    def __init__(self):
+        self._workers = {}
+
+    def execute(self, var_key, var_command, var_cwd, var_input, var_appends):
+        key     = vim.eval(var_key)
+        command = vim.eval(var_command)
+        cwd     = vim.eval(var_cwd)
+        input   = vim.eval(var_input)
+        appends = vim.eval(var_appends)
+        if key not in self._workers:
+            self._workers[key] = Worker()
+            self._workers[key].start()
+        self._workers[key].put(Executor(command, cwd, input, appends))
+
+    def print_output(self, var_key):
+        key = vim.eval(var_key)
+        if key not in self._workers:
+            return
+        for l in self._workers[key].copy_outputs():
+            print l,
+
+    def print_worker_keys(self):
+        for k in self._workers.keys():
+            print k
+
+    def print_active_worker_keys(self):
+        for k in self._workers.keys():
+            print k
+
+
+class Worker(threading.Thread):
+
+    def __init__(self):
+        threading.Thread.__init__(self)
+        self._queue = Queue.Queue()
+        self._lines = []
+        self._lock = threading.Lock()
+
+    def run(self):
+        while True:
+            self._queue.get().execute(self)
+            self._queue.task_done()
+
+    def put(self, executor):
+        self._queue.put(executor)
+
+    def clear_outputs(self):
+        with self._lock:
+            self._lines = []
+
+    def record_output(self, line):
+        with self._lock:
+            self._lines.append(line)
+
+    def copy_outputs(self):
+        with self._lock:
+            return self._lines[:]
+
+
+class Executor:
+
+    def __init__(self, command, cwd, input, appends):
+      self._command = command
+      self._cwd = cwd
+      self._input = input
+      self._appends = appends
+
+    def execute(self, worker):
+        if not self._appends:
+            worker.clear_outputs()
+        os.chdir(self._cwd)
+        p = subprocess.Popen(self._command, shell=True, stdin=subprocess.PIPE,
+                stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
+        p.stdin.write(self._input)
+        line = p.stdout.readline()
+        while line:
+            worker.record_output(line)
+            line = p.stdout.readline()
+
+

File autoload/l9/async.vim

+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, ['has("python")'])
+  finish
+endif
+
+" }}}1
+"=============================================================================
+" ASYNC EXECUTE {{{1
+
+"
+function s:checkKey(key)
+  if a:key =~ '\n' || a:key !~ '\S'
+    throw "Asyncer: Invalid key: " . a:key
+  endif
+endfunction
+
+" 
+function l9#async#execute(key, cmd, cwd, input, appends)
+  call s:checkKey(a:key)
+  python asyncer.execute('a:key', 'a:cmd', 'a:cwd', 'a:input', 'a:appends')
+endfunction
+
+"
+function l9#async#read(key)
+  call s:checkKey(a:key)
+  redir => result
+  silent python asyncer.print_output('a:key')
+  redir END
+  " NOTE: "\n" is somehow inserted by redir.
+  return (result[0] ==# "\n" ? result[1:] : result)
+endfunction
+
+"
+function l9#async#listWorkers()
+  redir => result
+  silent python asyncer.print_worker_keys()
+  redir END
+  return split(result, "\n")
+endfunction
+
+"
+function l9#async#listActiveWorkers()
+  redir => result
+  silent python asyncer.print_active_worker_keys()
+  redir END
+  return split(result, "\n")
+endfunction
+
+" }}}1
+"=============================================================================
+" INITIALIZATION {{{1
+
+let s:ASYNC_PY_PATH = fnamemodify(expand('<sfile>:p:h'), ':p') . 'async.py'
+
+pyfile `=s:ASYNC_PY_PATH`
+python asyncer = Asyncer()
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+
+

File autoload/l9/quickfix.vim

+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
+  finish
+endif
+
+" }}}1
+"=============================================================================
+" QUICKFIX {{{1
+
+" Returns non-zero if quickfix window is opened.
+function l9#quickfix#isWindowOpened()
+  return count(map(range(1, winnr('$')), 'getwinvar(v:val, "&buftype")'), 'quickfix') > 0
+endfunction
+
+" Opens quickfix window if quickfix is not empty, and echo the number of errors.
+"
+" a:onlyRecognized: if non-zero, opens only if quickfix has recognized errors.
+" a:holdCursor: if non-zero, the cursor won't move to quickfix window.
+function l9#quickfix#openIfNotEmpty(onlyRecognized, holdCursor)
+  let numErrors = len(filter(getqflist(), 'v:val.valid'))
+  let numOthers = len(getqflist()) - numErrors
+  if numErrors > 0 || (!a:onlyRecognized && numOthers > 0)
+    copen
+    if a:holdCursor
+      wincmd p
+    endif
+  else
+    cclose
+  endif
+  redraw
+  if numOthers > 0
+    echo printf('Quickfix: %d(+%d)', numErrors, numOthers)
+  else
+    echo printf('Quickfix: %d', numErrors)
+  endif
+endfunction
+
+" Toggles Quickfix window
+function l9#quickfix#toggleWindow()
+  if l9#quickfix#isWindowOpened()
+    cclose
+  else
+    call l9#quickfix#openIfNotEmpty(0, 0)
+  endif
+endfunction
+
+" Creates quickfix list form given lines and opens the quickfix window if
+" errors exists.
+"
+" a:lines: 
+" a:jump: if non-zero, jump to the first error.
+function l9#quickfix#setMakeResult(lines)
+  cexpr a:lines
+  call l9#quickfix#openIfNotEmpty(0, 1)
+endfunction
+
+" Compares quickfix entries for sorting.
+function l9#quickfix#compareEntries(e0, e1)
+  if     a:e0.bufnr != a:e1.bufnr
+    let i0 = bufname(a:e0.bufnr)
+    let i1 = bufname(a:e1.bufnr)
+  elseif a:e0.lnum != a:e1.lnum
+    let i0 = a:e0.lnum
+    let i1 = a:e1.lnum
+  elseif a:e0.col != a:e1.col
+    let i0 = a:e0.col
+    let i1 = a:e1.col
+  else
+    return 0
+  endif
+  return (i0 > i1 ? +1 : -1)
+endfunction
+
+" Sorts quickfix
+function l9#quickfix#sort()
+  call setqflist(sort(getqflist(), 'l9#quickfix#compareEntries'), 'r')
+endfunction
+
+" Highlights Quickfix lines by :sign.
+" Inspired by errormarker plugin.
+" 
+" You can customize the highlighting via L9ErrorLine and L9WarningLine
+" highlight groups.
+function l9#quickfix#placeSign()
+  let warnings = []
+  let errors = []
+  for e in filter(getqflist(), 'v:val.valid')
+    let warning = (e.type ==? 'w' || e.text =~? '^\s*warning:')
+    call add((warning ? warnings : errors), [e.bufnr, e.lnum])
+  endfor
+  sign unplace *
+  call l9#placeSign('L9WarningLine', '>>', '', warnings)
+  call l9#placeSign('L9ErrorLine', '>>', '', errors)
+endfunction
+
+highlight default L9ErrorLine   ctermfg=white ctermbg=52 guibg=#5F0000
+highlight default L9WarningLine ctermfg=white ctermbg=17 guibg=#00005F
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+

File autoload/l9/tempbuffer.vim

+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
+  finish
+endif
+
+" }}}1
+"=============================================================================
+" TEMPORARY BUFFER {{{1
+
+" each key is a buffer name.
+let s:dataMap = {}
+
+"
+function s:onBufDelete(bufname)
+  if exists('s:dataMap[a:bufname].listener.onClose')
+    call s:dataMap[a:bufname].listener.onClose(s:dataMap[a:bufname].written)
+  endif
+  if bufnr('%') == s:dataMap[a:bufname].bufNr && winnr('#') != 0
+    " if winnr('#') returns 0, "wincmd p" causes ringing the bell.
+    wincmd p
+  endif
+endfunction
+
+"
+function s:onBufWriteCmd(bufname)
+  if !exists('s:dataMap[a:bufname].listener.onWrite') ||
+        \ s:dataMap[a:bufname].listener.onWrite(getline(1, '$'))
+    setlocal nomodified
+    let s:dataMap[a:bufname].written = 1
+    call l9#tempbuffer#close(a:bufname)
+  else
+  endif
+endfunction
+
+" a:bufname:
+" a:height: Window height. If 0, default height is used.
+"           If less than 0, the window becomes full-screen. 
+" a:listener:
+"   a:listener.onClose(written)
+function l9#tempbuffer#openScratch(bufname, filetype, lines, topleft, vertical, height, listener)
+  let openCmdPrefix = (a:topleft ? 'topleft ' : '')
+        \           . (a:vertical ? 'vertical ' : '')
+        \           . (a:height > 0 ? a:height : '')
+  if !exists('s:dataMap[a:bufname]') || !bufexists(s:dataMap[a:bufname].bufNr)
+    execute openCmdPrefix . 'new'
+  else
+    call l9#tempbuffer#close(a:bufname)
+    execute openCmdPrefix . 'split'
+    execute 'silent ' . s:dataMap[a:bufname].bufNr . 'buffer'
+  endif
+  if a:height < 0
+    only
+  endif
+  setlocal buflisted noswapfile bufhidden=delete modifiable noreadonly buftype=nofile
+  let &l:filetype = a:filetype
+  silent file `=a:bufname`
+  call setline(1, a:lines)
+  setlocal nomodified
+  augroup L9TempBuffer
+    autocmd! * <buffer>
+    execute printf('autocmd BufDelete   <buffer>        call s:onBufDelete  (%s)', string(a:bufname))
+    execute printf('autocmd BufWriteCmd <buffer> nested call s:onBufWriteCmd(%s)', string(a:bufname))
+  augroup END
+  let s:dataMap[a:bufname] = {
+        \   'bufNr': bufnr('%'),
+        \   'written': 0,
+        \   'listener': a:listener,
+        \ }
+endfunction
+
+"
+function l9#tempbuffer#openReadOnly(bufname, filetype, lines, topleft, vertical, height, listener)
+  call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener)
+  setlocal nomodifiable readonly
+endfunction
+
+" a:listener:
+"   a:listener.onClose(written)
+"   a:listener.onWrite(lines)
+function l9#tempbuffer#openWritable(bufname, filetype, lines, topleft, vertical, height, listener)
+  call l9#tempbuffer#openScratch(a:bufname, a:filetype, a:lines, a:topleft, a:vertical, a:height, a:listener)
+  setlocal buftype=acwrite
+endfunction
+
+" makes specified temp buffer current.
+function l9#tempbuffer#moveTo(bufname)
+  return l9#moveToBufferWindowInCurrentTabpage(s:dataMap[a:bufname].bufNr) ||
+        \ l9#moveToBufferWindowInOtherTabpage(s:dataMap[a:bufname].bufNr)
+endfunction
+
+"
+function l9#tempbuffer#close(bufname)
+  if !l9#tempbuffer#isOpen(a:bufname)
+    return
+  endif
+  execute printf('%dbdelete!', s:dataMap[a:bufname].bufNr)
+endfunction
+
+"
+function l9#tempbuffer#isOpen(bufname)
+  return exists('s:dataMap[a:bufname]') && bufloaded(s:dataMap[a:bufname].bufNr)
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+

File autoload/l9/tempvariables.vim

+"=============================================================================
+" Copyright (C) 2010 Takeshi NISHIDA
+"
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 0, 0, [])
+  finish
+endif
+
+" }}}1
+"=============================================================================
+" TEMPORARY VARIABLES {{{1
+
+"
+let s:origMap = {}
+
+" set temporary variables
+function l9#tempvariables#set(group, name, value)
+  if !exists('s:origMap[a:group]')
+    let s:origMap[a:group] = {}
+  endif
+  if !exists('s:origMap[a:group][a:name]')
+    let s:origMap[a:group][a:name] = eval(a:name)
+  endif
+  execute 'let ' . a:name . ' = a:value'
+endfunction
+
+" set temporary variables
+function l9#tempvariables#setList(group, variables)
+  for [name, value] in a:variables
+    call l9#tempvariables#set(a:group, name, value)
+    unlet value " to avoid E706
+  endfor
+endfunction
+
+" get temporary variables
+function l9#tempvariables#getList(group)
+  if !exists('s:origMap[a:group]')
+    return []
+  endif
+  return map(keys(s:origMap[a:group]), '[v:val, eval(v:val)]')
+endfunction
+
+" restore original variables and clean up.
+function l9#tempvariables#end(group)
+  if !exists('s:origMap[a:group]')
+    return
+  endif
+  for [name, value] in items(s:origMap[a:group])
+    execute 'let ' . name . ' = value'
+    unlet value " to avoid E706
+  endfor
+  unlet s:origMap[a:group]
+endfunction
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker:
+
+*l9.txt*        Vimスクリプトライブラリ
+
+        Copyright (c) 2009-2010 Takeshi NISHIDA
+
+l9                                                                        *l9*
+
+概要                            |l9-introduction|
+インストール                    |l9-installation|
+使い方                          |l9-usage|
+CHANGELOG                       |l9-changelog|
+あばうと                        |l9-about|
+
+==============================================================================
+概要                                                         *l9-introduction*
+
+l9はVimスクリプトの関数やコマンドを提供するライブラリです。
+
+
+==============================================================================
+ インストール                                                *l9-installation*
+
+ZIPファイルをランタイムディレクトリに展開します。
+
+以下のようにファイルが配置されるはずです。
+>
+        <your runtime directory>/plugin/l9.vim
+        <your runtime directory>/doc/l9.txt
+        ...
+<
+もしランタイムディレクトリが多数のプラグインでごちゃごちゃになるのが嫌なら、各
+プラグインを個別のディレクトリに配置し、そのディレクトリのパスを 'runtimepath'
+に追加してください。アンインストールも楽になります。
+
+その後、ヘルプを有効にするためにタグファイルを更新してください。詳しくは
+|add-local-help|を参照してください。
+
+==============================================================================
+使い方                                                              *l9-usage*
+
+ソースコードを参照してください。
+
+==============================================================================
+あばうと                                   *l9-about* *l9-contact* *l9-author*
+
+作者:       Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
+ライセンス: MIT Licence
+URL:        http://www.vim.org/scripts/script.php?script_id=3252
+            http://bitbucket.org/ns9tks/vim-l9/
+
+バグや要望など ~
+
+こちらへどうぞ: http://bitbucket.org/ns9tks/vim-l9/issues/
+
+==============================================================================
+ vim:tw=78:ts=8:ft=help:norl:
+*l9.txt*        Vim-script library
+
+        Copyright (c) 2009-2010 Takeshi NISHIDA
+
+l9                                                                        *l9*
+
+INTRODUCTION                    |l9-introduction|
+INSTALLATION                    |l9-installation|
+USAGE                           |l9-usage|
+CHANGELOG                       |l9-changelog|
+ABOUT                           |l9-about|
+
+==============================================================================
+INTRODUCTION                                                 *l9-introduction*
+
+l9 is a Vim-script library, which provides some utility functions and commands
+for programming in Vim.
+
+==============================================================================
+ INSTALLATION                                                *l9-installation*
+
+Put all files into your runtime directory. If you have the zip file, extract
+it to your runtime directory.
+
+You should place the files as follows:
+>
+        <your runtime directory>/plugin/l9.vim
+        <your runtime directory>/doc/l9.txt
+        ...
+<
+If you are disgusted to make your runtime directory confused with a lot of
+plugins, put each of the plugins into a directory individually and just add
+the directory path to 'runtimepath'. It's easy to uninstall plugins.
+
+Then update your help tags files to enable help for this plugin. See
+|add-local-help| for details.
+
+==============================================================================
+USAGE                                                               *l9-usage*
+
+See source code.
+
+==============================================================================
+CHANGELOG                                                       *l9-changelog*
+
+1.1:
+  - Added l9#zip()
+  - Added l9#tempvariables#getList()
+  - Changed l9#guardScriptLoading()
+  - Removed l9#tempvariables#swap()
+
+1.0.1:
+  - Fixed a bug that floating point numbers weren't evaluated correctly and
+    caused errors on some non-English locales.
+
+1.0:
+  - First release.
+
+
+==============================================================================
+ABOUT                                      *l9-about* *l9-contact* *l9-author*
+
+Author:  Takeshi NISHIDA <ns9tks@DELETE-ME.gmail.com>
+Licence: MIT Licence
+URL:     http://www.vim.org/scripts/script.php?script_id=3252
+         http://bitbucket.org/ns9tks/vim-l9/
+
+Bugs/Issues/Suggestions/Improvements ~
+
+Please submit to http://bitbucket.org/ns9tks/vim-l9/issues/ .
+
+==============================================================================
+ vim:tw=78:ts=8:ft=help:norl:

File plugin/l9.vim

+"=============================================================================
+" Copyright (C) 2009-2010 Takeshi NISHIDA
+"
+" GetLatestVimScripts: 3252 1 :AutoInstall: L9
+"=============================================================================
+" LOAD GUARD {{{1
+
+if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 0, [])
+  finish
+endif
+
+" }}}1
+"=============================================================================
+" OPTIONS: {{{1
+
+call l9#defineVariableDefault('g:l9_balloonly', 'balloonly.exe')
+
+" }}}1
+"=============================================================================
+" ASSERTION: {{{1
+
+" This command has effect only if $L9_DEBUG is non-zero.
+" Used as follows:
+"   L9Assert a:i > 0
+" This command can't interpret script-local variables directly.
+"   NG: L9Assert s:a == 1
+"   OK: execute 'L9Assert ' . s:a . ' == 1'
+"
+if $L9_DEBUG
+  command -nargs=* L9Assert call eval((<args>) ? 0 : s:handleFailedAssersion(<q-args>))
+
+  function s:handleFailedAssersion(expr)
+    echoerr '[L9Assert] Assersion failure: ' . a:expr
+    if input('[L9Assert] Continue? (Y/N) ', 'Y') !=? 'Y'
+      throw 'L9Assert ' . a:expr
+    endif
+  endfunction
+
+else
+  command -nargs=* L9Assert :
+endif
+
+" }}}1
+"=============================================================================
+" TIMER: {{{1
+
+" These commands have effect only if $L9_TIMER is non-zero.
+" Used as follows:
+"   L9Timer foo
+"     ... (1)
+"   L9Timer bar
+"     ... (2)
+"   L9TimerStop
+"     ...
+"   L9TimerDump  <- shows each elapsed time of (1) and (2)
+"
+if $L9_TIMER
+  command -nargs=1 L9Timer call s:timerBegin(<q-args>)
+  command -nargs=0 L9TimerStop call s:timerStop()
+  command -nargs=0 L9TimerDump call s:timerDump()
+
+  let s:timerData = []
+  let s:timerTagMaxLen = 0
+
+  function s:timerBegin(tag)
+    L9TimerStop
+    let s:timerCurrent = {'tag': strftime('%c ') . a:tag . ' ', 'time': reltime()}
+    let s:timerTagMaxLen = max([len(s:timerCurrent.tag), s:timerTagMaxLen])
+  endfunction
+
+  function s:timerStop()
+    if !exists('s:timerCurrent')
+      return
+    endif
+    let s:timerCurrent.time = reltimestr(reltime(s:timerCurrent.time))
+    call add(s:timerData, s:timerCurrent)
+    unlet s:timerCurrent
+  endfunction
+
+  function s:timerDump()
+    L9TimerStop
+    let lines = map(s:timerData, 'v:val.tag . repeat(" ", s:timerTagMaxLen - len(v:val.tag)) . v:val.time')
+    call l9#tempbuffer#openReadOnly('[l9-timer]', '', lines, 0, 0, 0, {})
+    let s:timerData = []
+    let s:timerTagMaxLen = 0
+  endfunction
+
+else
+  command -nargs=1 L9Timer :
+  command -nargs=0 L9TimerStop :
+  command -nargs=0 L9TimerDump :
+endif
+
+" }}}1
+"=============================================================================
+" GREP BUFFER: {{{1
+
+" Grep for current buffer by l9#grepBuffers()
+" Used as :L9GrepBuffer/pattern
+command -nargs=? L9GrepBuffer    call l9#grepBuffers(<q-args>, [bufnr('%')])
+
+" Grep for all buffers by l9#grepBuffers()
+" Used as :L9GrepBufferAll/pattern
+command -nargs=? L9GrepBufferAll call l9#grepBuffers(<q-args>, range(1, bufnr('$')))
+
+" }}}1
+"=============================================================================
+" vim: set fdm=marker: