From 9a6ffd97e93bbb497b2cfea36b4e9b4e48935ecf Mon Sep 17 00:00:00 2001 From: simonzack Date: Sat, 21 Dec 2013 22:36:12 +1100 Subject: [PATCH 1/8] fixed windows-specific problem in subprocess_repl.read_bytes(), so that more than 1 byte is returned on every read, by converting the pipe to an asynchronous one --- repls/subprocess_repl.py | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/repls/subprocess_repl.py b/repls/subprocess_repl.py index 5a23791e..263b601f 100644 --- a/repls/subprocess_repl.py +++ b/repls/subprocess_repl.py @@ -184,26 +184,42 @@ def name(self): def is_alive(self): return self.popen.poll() is None - def read_bytes(self): + def read_bytes(self, buffer_size=4096): out = self.popen.stdout if POSIX: while True: i, _, _ = select.select([out], [], []) if i: - return out.read(4096) + return out.read(buffer_size) else: - # this is windows specific problem, that you cannot tell if there - # are more bytes ready, so we read only 1 at a times + import _winapi + import msvcrt + _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 1, None, None) + + buffer_size=1 + + bytes_read=bytearray() + #wait for some output + #'Invalid Argument' means that there are no more bytes left to read while True: - byte = self.popen.stdout.read(1) - if byte == b'\r': - # f'in HACK, for \r\n -> \n translation on windows - # I tried universal_endlines but it was pain and misery! :'( + try: + cur_bytes_read=out.read(buffer_size) + bytes_read.extend(cur_bytes_read) + #read all remaining output + while True: + try: + cur_bytes_read=out.read(buffer_size) + bytes_read.extend(cur_bytes_read) + except OSError: + break + break + except OSError: continue - return byte - + # f'in HACK, for \r\n -> \n translation on windows + # I tried universal_endlines but it was pain and misery! :'( + return bytes_read.replace(b'\r\n', b'\n') def write_bytes(self, bytes): si = self.popen.stdin From 02b9abb8be1ee157942e8e695da22d17db1dbb4c Mon Sep 17 00:00:00 2001 From: simonzack Date: Mon, 23 Dec 2013 03:44:15 +1100 Subject: [PATCH 2/8] fixed 100% cpu usage by allowing read_bytes() to non-busily block until there are bytes to be read --- repls/subprocess_repl.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/repls/subprocess_repl.py b/repls/subprocess_repl.py index 263b601f..c6e82067 100644 --- a/repls/subprocess_repl.py +++ b/repls/subprocess_repl.py @@ -195,27 +195,26 @@ def read_bytes(self, buffer_size=4096): import _winapi import msvcrt - _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 1, None, None) - buffer_size=1 - bytes_read=bytearray() - #wait for some output + + #wait for some output synchronously, to not cause infinite loop + bytes_read.extend(out.read(buffer_size)) + + #read until end of current output + _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 1, None, None) #'Invalid Argument' means that there are no more bytes left to read + cur_bytes_read=out.read(buffer_size) + bytes_read.extend(cur_bytes_read) while True: try: cur_bytes_read=out.read(buffer_size) + if not cur_bytes_read: + break bytes_read.extend(cur_bytes_read) - #read all remaining output - while True: - try: - cur_bytes_read=out.read(buffer_size) - bytes_read.extend(cur_bytes_read) - except OSError: - break - break except OSError: - continue + break + _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 0, None, None) # f'in HACK, for \r\n -> \n translation on windows # I tried universal_endlines but it was pain and misery! :'( From b4322e79a99bb4e4eb04fb68758547ef33c4beea Mon Sep 17 00:00:00 2001 From: simonzack Date: Fri, 27 Dec 2013 20:39:45 +1100 Subject: [PATCH 3/8] fixed bug in read_bytes(), the call to read() should be inside the loop --- repls/subprocess_repl.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/repls/subprocess_repl.py b/repls/subprocess_repl.py index c6e82067..6f23775a 100644 --- a/repls/subprocess_repl.py +++ b/repls/subprocess_repl.py @@ -204,8 +204,6 @@ def read_bytes(self, buffer_size=4096): #read until end of current output _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 1, None, None) #'Invalid Argument' means that there are no more bytes left to read - cur_bytes_read=out.read(buffer_size) - bytes_read.extend(cur_bytes_read) while True: try: cur_bytes_read=out.read(buffer_size) From 44a9a0c30c7c980810fa0699c9d1eba940b84b19 Mon Sep 17 00:00:00 2001 From: simonzack Date: Fri, 27 Dec 2013 21:45:05 +1100 Subject: [PATCH 4/8] sublime text 2 compatibility --- repls/subprocess_repl.py | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/repls/subprocess_repl.py b/repls/subprocess_repl.py index 6f23775a..3edb8cf7 100644 --- a/repls/subprocess_repl.py +++ b/repls/subprocess_repl.py @@ -192,17 +192,18 @@ def read_bytes(self, buffer_size=4096): if i: return out.read(buffer_size) else: - import _winapi + import ctypes import msvcrt + kernel32 = ctypes.windll.kernel32 - buffer_size=1 - bytes_read=bytearray() + buffer_size = 1 + bytes_read = bytearray() #wait for some output synchronously, to not cause infinite loop bytes_read.extend(out.read(buffer_size)) #read until end of current output - _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 1, None, None) + kernel32.SetNamedPipeHandleState(ctypes.c_void_p(msvcrt.get_osfhandle(out.fileno())), ctypes.byref(ctypes.c_int(1)), None, None) #'Invalid Argument' means that there are no more bytes left to read while True: try: @@ -210,9 +211,9 @@ def read_bytes(self, buffer_size=4096): if not cur_bytes_read: break bytes_read.extend(cur_bytes_read) - except OSError: + except (OSError, IOError): break - _winapi.SetNamedPipeHandleState(msvcrt.get_osfhandle(out.fileno()), 0, None, None) + kernel32.SetNamedPipeHandleState(ctypes.c_void_p(msvcrt.get_osfhandle(out.fileno())), ctypes.byref(ctypes.c_int(0)), None, None) # f'in HACK, for \r\n -> \n translation on windows # I tried universal_endlines but it was pain and misery! :'( From 2a811526afecf8a1b479878211c439fcee8c3acc Mon Sep 17 00:00:00 2001 From: simonzack Date: Thu, 5 Jun 2014 18:35:33 +1000 Subject: [PATCH 5/8] get rid of junk --- .hgignore | 3 --- .no-sublime-package | 1 - foo.html | 0 3 files changed, 4 deletions(-) delete mode 100644 .hgignore delete mode 100644 foo.html diff --git a/.hgignore b/.hgignore deleted file mode 100644 index ab016a31..00000000 --- a/.hgignore +++ /dev/null @@ -1,3 +0,0 @@ -syntax: glob -*.pyc -doc/_build/* diff --git a/.no-sublime-package b/.no-sublime-package index 8b137891..e69de29b 100644 --- a/.no-sublime-package +++ b/.no-sublime-package @@ -1 +0,0 @@ - diff --git a/foo.html b/foo.html deleted file mode 100644 index e69de29b..00000000 From 027d1b93c6c37530740579f51f67376f27833861 Mon Sep 17 00:00:00 2001 From: simonzack Date: Thu, 5 Jun 2014 18:40:36 +1000 Subject: [PATCH 6/8] fixed linter problems --- config/NodeJS/repl.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/config/NodeJS/repl.js b/config/NodeJS/repl.js index fd39e685..7d1686b4 100644 --- a/config/NodeJS/repl.js +++ b/config/NodeJS/repl.js @@ -19,7 +19,7 @@ client.on('data', function(data) { var strData = data.toString(); var index = strData.indexOf(":"); - var json = strData.slice(index+1, strData.length - 1) + var json = strData.slice(index+1, strData.length - 1); var inData = JSON.parse(json); var wordIndex = inData.line.slice(inData.cursor_pos).search(/\b/); if(wordIndex !== 0){ @@ -30,8 +30,8 @@ var comps = completions[0]; var msg = JSON.stringify([inData.line, comps]); var payload = msg.length + ":" + msg + ","; - client.write(payload) - } + client.write(payload); + }; rep.rli.completer(inData.line, send); }); From a718cf3f5169baaa6ecd921c7a97d66cb7cee66d Mon Sep 17 00:00:00 2001 From: simonzack Date: Thu, 5 Jun 2014 18:45:44 +1000 Subject: [PATCH 7/8] updated readme --- README.md | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index 9588c6e1..acfe059f 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,16 @@ SublimeREPL for SublimeText (2 and 3) ===================================== -IMPORTANT NOTE - DISCLAIMER ---------------------------- - -Due to and uncertain future of SublimeText and its current **abandonware** status (no new releases for several months, no communication with the community, non-existent technical support on disintegrating forums) all of my SublimeText plugins including SublimeREPL are currently **ON HOLD**. I'll reconsider support and development **if and only if** *SublimeHQ* resumes operation that can be considered acceptable for a company licensing a paid software. Until then I'm limiting time spent supporting my ST plugins to the absolute minimum. - - - -[![Stories in Ready](https://badge.waffle.io/wuub/SublimeREPL.png?label=ready)](http://waffle.io/wuub/SublimeREPL) - -If you would like to donate to support SublimeREPL development, you can do so using [GitTip](https://www.gittip.com/wuub/) or [PayPal](https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=4DGEPH7QAVHH6&lc=GB&item_name=SublimeREPL¤cy_code=USD&bn=PP%2dDonationsBF%3abtn_donateCC_LG%2egif%3aNonHosted). Someone willing to take care of documentation would also be very welcome :-) +SublimeREPL +----------- +Picks up the torch where wuub left off. Features -------- #### Common - * Run an interpreter (REPL) inside SublimeText2 view/tab. + * Run an interpreter (REPL) inside SublimeText view/tab. * Per-language persistent REPL history. * Easily evaluate code in the running REPL * Replace your current build system, and use stdin in your programs. @@ -26,7 +19,7 @@ Features #### Python * Launch python in local or remote(1) virtualenv. * Quickly run selected script or launch PDB. - * Use SublimeText2 Python console with history and multiline input. + * Use SublimeText Python console with history and multiline input. (1) - (ssh, linux/osx only) @@ -50,7 +43,7 @@ Installation 2. Install SublimeREPL 1. `Preferences | Package Control | Package Control: Install Package` 2. Choose `SublimeREPL` -3. Restart SublimeText2 +3. Restart SublimeText 4. Configure `SublimeREPL` (default settings in `Preferences | Package Settings | SublimeREPL | Settings - Default` should be modified in `Preferences | Package Settings | SublimeREPL | Settings - User`, this way they will survive package upgrades! Documentation @@ -82,14 +75,12 @@ then type "SublimeREPL" and select the approperiate language. Note: ctrl+,, f means: press Ctrl and Comma, release all, press F. -License and Price +License ================= Since version 1.2.0 SublimeREPL is licensed under GPL. Previous versions were licensed under BSD. -If you're using SublimeREPL in commercial environment a donation is strongly encouraged ;-) Compatibility ================ SublimeREPL is developed against the latest dev build of SublimeText3. -Ubuntu 13.04 is main From 4f2f671823e61fb7df2ca5f7db42b973f7759382 Mon Sep 17 00:00:00 2001 From: simonzack Date: Thu, 5 Jun 2014 19:32:37 +1000 Subject: [PATCH 8/8] fixed node repl so it works with node v0.11.13 --- config/NodeJS/repl.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/config/NodeJS/repl.js b/config/NodeJS/repl.js index 7d1686b4..d8985475 100644 --- a/config/NodeJS/repl.js +++ b/config/NodeJS/repl.js @@ -1,16 +1,15 @@ (function () { + /* global require, process */ var repl = require('repl'); var rep = repl.start({ - prompt: null, //'> ', - source: null, //process.stdin, - eval: null, //require('vm').runInThisContext, - useGlobal: true, //false + input: process.stdin, + output: process.stdout, + useGlobal: true, useColors: false }); - var net = require('net'); var ac_port = process.env.SUBLIMEREPL_AC_PORT; var client = new net.Socket();