completer.py
81 lines
| 2.9 KiB
| text/x-python
|
PythonLexer
Omar Andres Zapata Mesa
|
r5584 | # -*- coding: utf-8 -*- | ||
MinRK
|
r16580 | """Adapt readline completer interface to make ZMQ request.""" | ||
# Copyright (c) IPython Development Team. | ||||
# Distributed under the terms of the Modified BSD License. | ||||
Thomas Kluyver
|
r13354 | try: | ||
from queue import Empty # Py 3 | ||||
except ImportError: | ||||
from Queue import Empty # Py 2 | ||||
Thomas Kluyver
|
r5595 | |||
Matthias BUSSONNIER
|
r11676 | from IPython.config import Configurable | ||
MinRK
|
r14878 | from IPython.core.completer import IPCompleter | ||
Min RK
|
r20028 | from IPython.utils.py3compat import str_to_unicode, unicode_to_str, cast_bytes, cast_unicode | ||
Matthias BUSSONNIER
|
r11676 | from IPython.utils.traitlets import Float | ||
MinRK
|
r15415 | import IPython.utils.rlineimpl as readline | ||
Matthias BUSSONNIER
|
r11676 | |||
MinRK
|
r14878 | class ZMQCompleter(IPCompleter): | ||
Omar Andres Zapata Mesa
|
r5584 | """Client-side completion machinery. | ||
How it works: self.complete will be called multiple times, with | ||||
state=0,1,2,... When state=0 it should compute ALL the completion matches, | ||||
and then return them for each value of state.""" | ||||
Matthias BUSSONNIER
|
r11676 | |||
timeout = Float(5.0, config=True, help='timeout before completion abort') | ||||
Omar Andres Zapata Mesa
|
r5584 | |||
Matthias BUSSONNIER
|
r11676 | def __init__(self, shell, client, config=None): | ||
super(ZMQCompleter,self).__init__(config=config) | ||||
MinRK
|
r5600 | self.shell = shell | ||
MinRK
|
r10287 | self.client = client | ||
Omar Andres Zapata Mesa
|
r5584 | self.matches = [] | ||
Min RK
|
r19990 | # don't do any splitting client-side, | ||
# rely on the kernel for that | ||||
self.splitter.delims = '\r\n' | ||||
if self.readline: | ||||
self.readline.set_completer_delims('\r\n') | ||||
MinRK
|
r16580 | def complete_request(self, text): | ||
Min RK
|
r20025 | line = str_to_unicode(readline.get_line_buffer()) | ||
byte_cursor_pos = readline.get_endidx() | ||||
# get_endidx is a byte offset | ||||
# account for multi-byte characters to get correct cursor_pos | ||||
Min RK
|
r20028 | bytes_before_cursor = cast_bytes(line)[:byte_cursor_pos] | ||
cursor_pos = len(cast_unicode(bytes_before_cursor)) | ||||
Thomas Kluyver
|
r5597 | |||
Omar Andres Zapata Mesa
|
r5585 | # send completion request to kernel | ||
Min RK
|
r19990 | # Give the kernel up to 5s to respond | ||
Thomas Kluyver
|
r19213 | msg_id = self.client.complete( | ||
MinRK
|
r16580 | code=line, | ||
cursor_pos=cursor_pos, | ||||
) | ||||
Steven Silvester
|
r20021 | |||
Matthias BUSSONNIER
|
r11676 | msg = self.client.shell_channel.get_msg(timeout=self.timeout) | ||
MinRK
|
r5600 | if msg['parent_header']['msg_id'] == msg_id: | ||
Steven Silvester
|
r20021 | content = msg['content'] | ||
cursor_start = content['cursor_start'] | ||||
matches = [ line[:cursor_start] + m for m in content['matches'] ] | ||||
if content["cursor_end"] < cursor_pos: | ||||
extra = line[content["cursor_end"]: cursor_pos] | ||||
matches = [m + extra for m in matches] | ||||
Min RK
|
r20025 | matches = [ unicode_to_str(m) for m in matches ] | ||
Steven Silvester
|
r20021 | return matches | ||
Thomas Kluyver
|
r5596 | return [] | ||
Omar Andres Zapata Mesa
|
r5584 | |||
MinRK
|
r5600 | def rlcomplete(self, text, state): | ||
Thomas Kluyver
|
r5595 | if state == 0: | ||
try: | ||||
self.matches = self.complete_request(text) | ||||
Thomas Kluyver
|
r5596 | except Empty: | ||
Matthias BUSSONNIER
|
r11676 | #print('WARNING: Kernel timeout on tab completion.') | ||
pass | ||||
Thomas Kluyver
|
r5595 | |||
Thomas Kluyver
|
r5591 | try: | ||
return self.matches[state] | ||||
except IndexError: | ||||
return None | ||||
MinRK
|
r5600 | |||
def complete(self, text, line, cursor_pos=None): | ||||
return self.rlcomplete(text, 0) | ||||