-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Takeshi NISHIDA
committed
Sep 14, 2010
0 parents
commit 1fd47dd
Showing
9 changed files
with
1,167 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
#!/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() | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"============================================================================= | ||
" Copyright (C) 2009-2010 Takeshi NISHIDA | ||
" | ||
"============================================================================= | ||
" LOAD GUARD {{{1 | ||
|
||
if !l9#guardScriptLoading(expand('<sfile>:p'), 702, 100) || !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: | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
"============================================================================= | ||
" Copyright (C) 2009-2010 Takeshi NISHIDA | ||
" | ||
"============================================================================= | ||
" LOAD GUARD {{{1 | ||
|
||
if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion()) | ||
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: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
"============================================================================= | ||
" Copyright (C) 2009-2010 Takeshi NISHIDA | ||
" | ||
"============================================================================= | ||
" LOAD GUARD {{{1 | ||
|
||
if !l9#guardScriptLoading(expand('<sfile>:p'), 702, l9#getVersion()) | ||
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) | ||
" a:listener.onWrite(lines) | ||
function l9#tempbuffer#open(bufname, filetype, lines, topleft, vertical, height, writable, 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 s:dataMap[a:bufname].bufNr . 'buffer' | ||
endif | ||
let s:dataMap[a:bufname] = { | ||
\ 'bufNr': bufnr('%'), | ||
\ 'written': 0, | ||
\ 'listener': a:listener, | ||
\ } | ||
if a:height < 0 | ||
only | ||
endif | ||
setlocal buflisted noswapfile bufhidden=delete | ||
let &l:filetype = a:filetype | ||
silent file `=a:bufname` | ||
call setline(1, a:lines) | ||
if a:writable | ||
setlocal nomodified modifiable noreadonly buftype=acwrite | ||
else | ||
setlocal nomodified nomodifiable readonly buftype=nofile | ||
endif | ||
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 | ||
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: | ||
|
Oops, something went wrong.