diff --git a/.gitignore b/.gitignore index 0a56e3f..2b261e6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /doc/tags +*.pyc diff --git a/README.markdown b/README.markdown index 05ac822..c02c37b 100644 --- a/README.markdown +++ b/README.markdown @@ -37,7 +37,7 @@ to multiple instances of nREPL for different projects, and it will use the right one automatically. 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][] lets it fall back to using `java clojure.main`, using a class path based on diff --git a/autoload/nrepl/fireplace_connection.vim b/autoload/nrepl/fireplace_connection.vim index 61b8257..362090f 100644 --- a/autoload/nrepl/fireplace_connection.vim +++ b/autoload/nrepl/fireplace_connection.vim @@ -6,6 +6,8 @@ if exists("g:autoloaded_nrepl_fireplace_connection") || &cp endif let g:autoloaded_nrepl_fireplace_connection = 1 +let s:python_dir = fnamemodify(expand(""), ':p:h:h:h') . '/python' + function! s:function(name) abort return function(substitute(a:name,'^s:',matchstr(expand(''), '\d\+_'),'')) endfunction @@ -197,22 +199,16 @@ function! s:extract_last_stacktrace(nrepl) endfunction function! s:nrepl_call(payload) dict abort - let in = 'ruby -rsocket -e '.s:shellesc( - \ 'begin;' . - \ 'TCPSocket.open(%(' . self.host . '), ' . self.port . ') {|s|' . - \ 's.write(ARGV.first); loop {' . - \ 'body = s.readpartial(8192);' . - \ '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 in = 'python' + \ . ' ' . s:shellesc(s:python_dir.'/nrepl_fireplace.py') + \ . ' ' . s:shellesc(self.host) + \ . ' ' . s:shellesc(self.port) + \ . ' ' . s:shellesc(nrepl#fireplace_connection#bencode(a:payload)) let out = system(in) if !v:shell_error return nrepl#fireplace_connection#bdecode('l'.out.'e') endif - throw 'nREPL: '.split(out, "\n")[0] + throw 'nREPL: '.out endfunction let s:nrepl = { @@ -225,12 +221,16 @@ if !has('python') finish 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 import vim -import select -import socket -import string -import re def fireplace_string_encode(input): str_list = [] @@ -244,38 +244,19 @@ def fireplace_string_encode(input): def fireplace_let(var, value): return vim.command('let ' + var + " = " + fireplace_string_encode(value)) +def fireplace_check(): + vim.eval('getchar(1)') + def fireplace_repl_interact(): - 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)') - 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 - fireplace_let('out', buffer) - except Exception, e: - fireplace_let('err', str(e)) - finally: - s.close() + fireplace_let('out', nrepl_fireplace.repl_send(vim.eval('self.host'), int(vim.eval('self.port')), vim.eval('payload'), fireplace_check)) + except Exception, e: + fireplace_let('err', str(e)) EOF function! s:nrepl_call(payload) dict abort let payload = nrepl#fireplace_connection#bencode(a:payload) - python << EOF -fireplace_repl_interact() -EOF + python fireplace_repl_interact() if !exists('err') return nrepl#fireplace_connection#bdecode('l'.out.'e') endif diff --git a/doc/fireplace.txt b/doc/fireplace.txt index f766f46..60b1a9e 100644 --- a/doc/fireplace.txt +++ b/doc/fireplace.txt @@ -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. 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 -accident of history.) +|if_pyth| or the python command in your PATH. LEININGEN *fireplace-leiningen* diff --git a/python/nrepl_fireplace.py b/python/nrepl_fireplace.py new file mode 100644 index 0000000..202ff45 --- /dev/null +++ b/python/nrepl_fireplace.py @@ -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:])