Python all the way

This commit is contained in:
Tim Pope 2014-01-06 22:41:03 -05:00
parent fa4e0ed143
commit 4ce1f8fbfa
5 changed files with 64 additions and 45 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/doc/tags /doc/tags
*.pyc

View File

@ -37,7 +37,7 @@ to multiple instances of nREPL for different projects, and it will use the
right one automatically. right one automatically.
The only external dependency is that you have either a Vim with Python support The only external dependency is that you have either a Vim with Python support
compiled in, or `ruby` in your path. (Don't ask.) compiled in, or `python` in your path.
Oh, and if you don't have an nREPL connection, installing [classpath.vim][] Oh, and if you don't have an nREPL connection, installing [classpath.vim][]
lets it fall back to using `java clojure.main`, using a class path based on lets it fall back to using `java clojure.main`, using a class path based on

View File

@ -6,6 +6,8 @@ if exists("g:autoloaded_nrepl_fireplace_connection") || &cp
endif endif
let g:autoloaded_nrepl_fireplace_connection = 1 let g:autoloaded_nrepl_fireplace_connection = 1
let s:python_dir = fnamemodify(expand("<sfile>"), ':p:h:h:h') . '/python'
function! s:function(name) abort function! s:function(name) abort
return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),'')) return function(substitute(a:name,'^s:',matchstr(expand('<sfile>'), '<SNR>\d\+_'),''))
endfunction endfunction
@ -197,22 +199,16 @@ function! s:extract_last_stacktrace(nrepl)
endfunction endfunction
function! s:nrepl_call(payload) dict abort function! s:nrepl_call(payload) dict abort
let in = 'ruby -rsocket -e '.s:shellesc( let in = 'python'
\ 'begin;' . \ . ' ' . s:shellesc(s:python_dir.'/nrepl_fireplace.py')
\ 'TCPSocket.open(%(' . self.host . '), ' . self.port . ') {|s|' . \ . ' ' . s:shellesc(self.host)
\ 's.write(ARGV.first); loop {' . \ . ' ' . s:shellesc(self.port)
\ 'body = s.readpartial(8192);' . \ . ' ' . s:shellesc(nrepl#fireplace_connection#bencode(a:payload))
\ 'raise %(not an nREPL server: upgrade to Leiningen 2) if body =~ /=> $/;' .
\ 'print body;' .
\ 'break if body =~ /6:statusl(5:error|14:session-closed)?4:done/ }};' .
\ 'rescue; abort $!.to_s;' .
\ 'end') . ' ' .
\ s:shellesc(nrepl#fireplace_connection#bencode(a:payload))
let out = system(in) let out = system(in)
if !v:shell_error if !v:shell_error
return nrepl#fireplace_connection#bdecode('l'.out.'e') return nrepl#fireplace_connection#bdecode('l'.out.'e')
endif endif
throw 'nREPL: '.split(out, "\n")[0] throw 'nREPL: '.out
endfunction endfunction
let s:nrepl = { let s:nrepl = {
@ -225,12 +221,16 @@ if !has('python')
finish finish
endif endif
if !exists('s:python')
exe 'python sys.path.insert(0, "'.s:python_dir.'")'
let s:python = 1
python import nrepl_fireplace
else
python reload(nrepl_fireplace)
endif
python << EOF python << EOF
import vim import vim
import select
import socket
import string
import re
def fireplace_string_encode(input): def fireplace_string_encode(input):
str_list = [] str_list = []
@ -244,38 +244,19 @@ def fireplace_string_encode(input):
def fireplace_let(var, value): def fireplace_let(var, value):
return vim.command('let ' + var + " = " + fireplace_string_encode(value)) return vim.command('let ' + var + " = " + fireplace_string_encode(value))
def fireplace_repl_interact(): def fireplace_check():
buffer = ''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
host = vim.eval('self.host')
port = int(vim.eval('self.port'))
s.settimeout(8)
try:
try:
s.connect((host, port))
s.setblocking(1)
s.sendall(vim.eval('payload'))
while True:
while len(select.select([s], [], [], 0.1)[0]) == 0:
vim.eval('getchar(1)') vim.eval('getchar(1)')
body = s.recv(8192)
if re.search("=> $", body) != None: def fireplace_repl_interact():
raise Exception("not an nREPL server: upgrade to Leiningen 2") try:
buffer += body fireplace_let('out', nrepl_fireplace.repl_send(vim.eval('self.host'), int(vim.eval('self.port')), vim.eval('payload'), fireplace_check))
if re.search('6:statusl(5:error|14:session-closed)?4:done', body):
break
fireplace_let('out', buffer)
except Exception, e: except Exception, e:
fireplace_let('err', str(e)) fireplace_let('err', str(e))
finally:
s.close()
EOF EOF
function! s:nrepl_call(payload) dict abort function! s:nrepl_call(payload) dict abort
let payload = nrepl#fireplace_connection#bencode(a:payload) let payload = nrepl#fireplace_connection#bencode(a:payload)
python << EOF python fireplace_repl_interact()
fireplace_repl_interact()
EOF
if !exists('err') if !exists('err')
return nrepl#fireplace_connection#bdecode('l'.out.'e') return nrepl#fireplace_connection#bdecode('l'.out.'e')
endif endif

View File

@ -26,8 +26,7 @@ buffer and classpath.vim is installed, java (or $JAVA_CMD) is invoked
directly, which can be quite slow depending on your setup. directly, which can be quite slow depending on your setup.
The only adapter shipped with fireplace.vim is for nREPL. You need either The only adapter shipped with fireplace.vim is for nREPL. You need either
|if_pyth| or the ruby command in your PATH. (This curious combination is an |if_pyth| or the python command in your PATH.
accident of history.)
LEININGEN *fireplace-leiningen* LEININGEN *fireplace-leiningen*

38
python/nrepl_fireplace.py Normal file
View File

@ -0,0 +1,38 @@
import sys
import select
import socket
import re
def repl_send(host, port, payload, callback):
buffer = ''
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(8)
try:
s.connect((host, port))
s.setblocking(1)
s.sendall(payload)
while True:
while len(select.select([s], [], [], 0.1)[0]) == 0:
callback()
body = s.recv(8192)
if re.search("=> $", body) != None:
raise Exception("not an nREPL server: upgrade to Leiningen 2")
buffer += body
if re.search('6:statusl(5:error|14:session-closed)?4:done', body):
break
return buffer
finally:
s.close()
def noop():
pass
def main(host, port, payload):
try:
sys.stdout.write(repl_send(host, int(port), payload, noop))
except Exception, e:
print(e)
exit(1)
if __name__ == "__main__":
main(*sys.argv[1:])