diff --git a/bash_kernel.py b/bash_kernel.py index 00cc795..631b1a8 100644 --- a/bash_kernel.py +++ b/bash_kernel.py @@ -1,5 +1,5 @@ from IPython.kernel.zmq.kernelbase import Kernel -from pexpect import replwrap +from pexpect import replwrap, EOF import signal from subprocess import check_output @@ -27,6 +27,9 @@ class BashKernel(Kernel): def __init__(self, **kwargs): Kernel.__init__(self, **kwargs) + self._start_bash() + + def _start_bash(self): # Signal handlers are inherited by forked processes, and we can't easily # reset it from the subprocess. Since kernelapp ignores SIGINT except in # message handlers, we need to temporarily reset the SIGINT handler here @@ -41,7 +44,7 @@ class BashKernel(Kernel): allow_stdin=False): if not code.strip(): return {'status': 'ok', 'execution_count': self.execution_count, - 'payloads': [], 'user_expressions': {}} + 'payload': [], 'user_expressions': {}} interrupted = False try: @@ -51,16 +54,19 @@ class BashKernel(Kernel): interrupted = True self.bashwrapper._expect_prompt() output = self.bashwrapper.child.before + except EOF: + output = self.bashwrapper.child.before + 'Restarting Bash' + self._start_bash() if not silent: - stream_content = {'name': 'stdout', 'data':output} + stream_content = {'name': 'stdout', 'data': output} self.send_response(self.iopub_socket, 'stream', stream_content) if interrupted: return {'status': 'abort', 'execution_count': self.execution_count} try: - exitcode = int(self.run_command('echo $?').rstrip()) + exitcode = int(self.bashwrapper.run_command('echo $?').rstrip()) except Exception: exitcode = 1 @@ -69,7 +75,34 @@ class BashKernel(Kernel): 'ename': '', 'evalue': str(exitcode), 'traceback': []} else: return {'status': 'ok', 'execution_count': self.execution_count, - 'payloads': [], 'user_expressions': {}} + 'payload': [], 'user_expressions': {}} + + def do_complete(self, code, cursor_pos): + code = code[:cursor_pos] + default = {'matches': [], 'cursor_start': 0, + 'cursor_end': cursor_pos, 'metadata': dict(), + 'status': 'ok'} + + if not code or code[-1] == ' ': + return default + + tokens = code.replace(';', ' ').split() + if not tokens: + return default + + token = tokens[-1] + start = cursor_pos - len(token) + cmd = 'compgen -cdfa %s' % token + output = self.bashwrapper.run_command(cmd).rstrip() + + matches = output.split() + if not matches: + return default + matches = [m for m in matches if m.startswith(token)] + + return {'matches': matches, 'cursor_start': start, + 'cursor_end': cursor_pos, 'metadata': dict(), + 'status': 'ok'} if __name__ == '__main__': from IPython.kernel.zmq.kernelapp import IPKernelApp