Show More
@@ -1,87 +1,91 b'' | |||||
1 | """Tab-completion over zmq""" |
|
1 | """Tab-completion over zmq""" | |
2 |
|
2 | |||
3 | # Trying to get print statements to work during completion, not very |
|
3 | # Trying to get print statements to work during completion, not very | |
4 | # successfully... |
|
4 | # successfully... | |
5 | from __future__ import print_function |
|
5 | from __future__ import print_function | |
6 |
|
6 | |||
7 | import itertools |
|
7 | import itertools | |
8 | import readline |
|
8 | try: | |
|
9 | import readline | |||
|
10 | except ImportError: | |||
|
11 | readline = None | |||
9 | import rlcompleter |
|
12 | import rlcompleter | |
10 | import time |
|
13 | import time | |
11 |
|
14 | |||
12 | import session |
|
15 | import session | |
13 |
|
16 | |||
14 | class KernelCompleter(object): |
|
17 | class KernelCompleter(object): | |
15 | """Kernel-side completion machinery.""" |
|
18 | """Kernel-side completion machinery.""" | |
16 | def __init__(self, namespace): |
|
19 | def __init__(self, namespace): | |
17 | self.namespace = namespace |
|
20 | self.namespace = namespace | |
18 | self.completer = rlcompleter.Completer(namespace) |
|
21 | self.completer = rlcompleter.Completer(namespace) | |
19 |
|
22 | |||
20 | def complete(self, line, text): |
|
23 | def complete(self, line, text): | |
21 | # We'll likely use linel later even if now it's not used for anything |
|
24 | # We'll likely use linel later even if now it's not used for anything | |
22 | matches = [] |
|
25 | matches = [] | |
23 | complete = self.completer.complete |
|
26 | complete = self.completer.complete | |
24 | for state in itertools.count(): |
|
27 | for state in itertools.count(): | |
25 | comp = complete(text, state) |
|
28 | comp = complete(text, state) | |
26 | if comp is None: |
|
29 | if comp is None: | |
27 | break |
|
30 | break | |
28 | matches.append(comp) |
|
31 | matches.append(comp) | |
29 | return matches |
|
32 | return matches | |
30 |
|
33 | |||
31 |
|
34 | |||
32 | class ClientCompleter(object): |
|
35 | class ClientCompleter(object): | |
33 | """Client-side completion machinery. |
|
36 | """Client-side completion machinery. | |
34 |
|
37 | |||
35 | How it works: self.complete will be called multiple times, with |
|
38 | How it works: self.complete will be called multiple times, with | |
36 | state=0,1,2,... When state=0 it should compute ALL the completion matches, |
|
39 | state=0,1,2,... When state=0 it should compute ALL the completion matches, | |
37 | and then return them for each value of state.""" |
|
40 | and then return them for each value of state.""" | |
38 |
|
41 | |||
39 | def __init__(self, client, session, socket): |
|
42 | def __init__(self, client, session, socket): | |
40 |
|
|
43 | # ugly, but we get called asynchronously and need access to some | |
41 |
|
|
44 | # client state, like backgrounded code | |
|
45 | assert readline is not None, "ClientCompleter depends on readline" | |||
42 | self.client = client |
|
46 | self.client = client | |
43 | self.session = session |
|
47 | self.session = session | |
44 | self.socket = socket |
|
48 | self.socket = socket | |
45 | self.matches = [] |
|
49 | self.matches = [] | |
46 |
|
50 | |||
47 | def request_completion(self, text): |
|
51 | def request_completion(self, text): | |
48 | # Get full line to give to the kernel in case it wants more info. |
|
52 | # Get full line to give to the kernel in case it wants more info. | |
49 | line = readline.get_line_buffer() |
|
53 | line = readline.get_line_buffer() | |
50 | # send completion request to kernel |
|
54 | # send completion request to kernel | |
51 | msg = self.session.send(self.socket, |
|
55 | msg = self.session.send(self.socket, | |
52 | 'complete_request', |
|
56 | 'complete_request', | |
53 | dict(text=text, line=line)) |
|
57 | dict(text=text, line=line)) | |
54 |
|
58 | |||
55 | # Give the kernel up to 0.5s to respond |
|
59 | # Give the kernel up to 0.5s to respond | |
56 | for i in range(5): |
|
60 | for i in range(5): | |
57 | ident,rep = self.session.recv(self.socket) |
|
61 | ident,rep = self.session.recv(self.socket) | |
58 | rep = Message(rep) |
|
62 | rep = Message(rep) | |
59 | if rep is not None and rep.msg_type == 'complete_reply': |
|
63 | if rep is not None and rep.msg_type == 'complete_reply': | |
60 | matches = rep.content.matches |
|
64 | matches = rep.content.matches | |
61 | break |
|
65 | break | |
62 | time.sleep(0.1) |
|
66 | time.sleep(0.1) | |
63 | else: |
|
67 | else: | |
64 | # timeout |
|
68 | # timeout | |
65 | print ('TIMEOUT') # Can't see this message... |
|
69 | print ('TIMEOUT') # Can't see this message... | |
66 | matches = None |
|
70 | matches = None | |
67 | return matches |
|
71 | return matches | |
68 |
|
72 | |||
69 | def complete(self, text, state): |
|
73 | def complete(self, text, state): | |
70 |
|
74 | |||
71 | if self.client.backgrounded > 0: |
|
75 | if self.client.backgrounded > 0: | |
72 | print("\n[Not completing, background tasks active]") |
|
76 | print("\n[Not completing, background tasks active]") | |
73 | print(readline.get_line_buffer(), end='') |
|
77 | print(readline.get_line_buffer(), end='') | |
74 | return None |
|
78 | return None | |
75 |
|
79 | |||
76 | if state==0: |
|
80 | if state==0: | |
77 | matches = self.request_completion(text) |
|
81 | matches = self.request_completion(text) | |
78 | if matches is None: |
|
82 | if matches is None: | |
79 | self.matches = [] |
|
83 | self.matches = [] | |
80 | print('WARNING: Kernel timeout on tab completion.') |
|
84 | print('WARNING: Kernel timeout on tab completion.') | |
81 | else: |
|
85 | else: | |
82 | self.matches = matches |
|
86 | self.matches = matches | |
83 |
|
87 | |||
84 | try: |
|
88 | try: | |
85 | return self.matches[state] |
|
89 | return self.matches[state] | |
86 | except IndexError: |
|
90 | except IndexError: | |
87 | return None |
|
91 | return None |
General Comments 0
You need to be logged in to leave comments.
Login now