Show More
@@ -1,16 +1,8 b'' | |||
|
1 | 1 | # coding: utf-8 |
|
2 | 2 | """test the IPython Kernel""" |
|
3 | 3 | |
|
4 | #------------------------------------------------------------------------------- | |
|
5 | # Copyright (C) 2013 The IPython Development Team | |
|
6 | # | |
|
7 | # Distributed under the terms of the BSD License. The full license is in | |
|
8 | # the file COPYING, distributed as part of this software. | |
|
9 | #------------------------------------------------------------------------------- | |
|
10 | ||
|
11 | #------------------------------------------------------------------------------- | |
|
12 | # Imports | |
|
13 | #------------------------------------------------------------------------------- | |
|
4 | # Copyright (c) IPython Development Team. | |
|
5 | # Distributed under the terms of the Modified BSD License. | |
|
14 | 6 | |
|
15 | 7 | import io |
|
16 | 8 | import os.path |
@@ -26,10 +18,6 b' from IPython.utils.tempdir import TemporaryDirectory' | |||
|
26 | 18 | from .utils import (new_kernel, kernel, TIMEOUT, assemble_output, execute, |
|
27 | 19 | flush_channels, wait_for_idle) |
|
28 | 20 | |
|
29 | #------------------------------------------------------------------------------- | |
|
30 | # Tests | |
|
31 | #------------------------------------------------------------------------------- | |
|
32 | ||
|
33 | 21 | |
|
34 | 22 | def _check_mp_mode(kc, expected=False, stream="stdout"): |
|
35 | 23 | execute(kc=kc, code="import sys") |
@@ -222,3 +210,19 b' def test_is_complete():' | |||
|
222 | 210 | reply = kc.get_shell_msg(block=True, timeout=TIMEOUT) |
|
223 | 211 | assert reply['content']['status'] == 'incomplete' |
|
224 | 212 | assert reply['content']['indent'] == '' |
|
213 | ||
|
214 | def test_complete(): | |
|
215 | with kernel() as kc: | |
|
216 | execute(u'a = 1', kc=kc) | |
|
217 | wait_for_idle(kc) | |
|
218 | cell = 'import IPython\nb = a.' | |
|
219 | kc.complete(cell) | |
|
220 | reply = kc.get_shell_msg(block=True, timeout=TIMEOUT) | |
|
221 | c = reply['content'] | |
|
222 | nt.assert_equal(c['status'], 'ok') | |
|
223 | nt.assert_equal(c['cursor_start'], cell.find('a.')) | |
|
224 | nt.assert_equal(c['cursor_end'], cell.find('a.') + 2) | |
|
225 | matches = c['matches'] | |
|
226 | nt.assert_greater(len(matches), 0) | |
|
227 | for match in matches: | |
|
228 | nt.assert_equal(match[:2], 'a.') |
@@ -79,6 +79,8 b' def start_global_kernel():' | |||
|
79 | 79 | if KM is None: |
|
80 | 80 | KM, KC = start_new_kernel() |
|
81 | 81 | atexit.register(stop_global_kernel) |
|
82 | else: | |
|
83 | flush_channels(KC) | |
|
82 | 84 | return KC |
|
83 | 85 | |
|
84 | 86 | @contextmanager |
@@ -6,7 +6,7 b' import traceback' | |||
|
6 | 6 | |
|
7 | 7 | from IPython.core import release |
|
8 | 8 | from IPython.utils.py3compat import builtin_mod, PY3 |
|
9 | from IPython.utils.tokenutil import token_at_cursor | |
|
9 | from IPython.utils.tokenutil import token_at_cursor, line_at_cursor | |
|
10 | 10 | from IPython.utils.traitlets import Instance, Type, Any |
|
11 | 11 | from IPython.utils.decorators import undoc |
|
12 | 12 | |
@@ -186,7 +186,15 b' class IPythonKernel(KernelBase):' | |||
|
186 | 186 | return reply_content |
|
187 | 187 | |
|
188 | 188 | def do_complete(self, code, cursor_pos): |
|
189 | txt, matches = self.shell.complete('', code, cursor_pos) | |
|
189 | # FIXME: IPython completers currently assume single line, | |
|
190 | # but completion messages give multi-line context | |
|
191 | # For now, extract line from cell, based on cursor_pos: | |
|
192 | if cursor_pos is None: | |
|
193 | cursor_pos = len(code) | |
|
194 | line, offset = line_at_cursor(code, cursor_pos) | |
|
195 | line_cursor = cursor_pos - offset | |
|
196 | ||
|
197 | txt, matches = self.shell.complete('', line, line_cursor) | |
|
190 | 198 | return {'matches' : matches, |
|
191 | 199 | 'cursor_end' : cursor_pos, |
|
192 | 200 | 'cursor_start' : cursor_pos - len(txt), |
@@ -23,6 +23,34 b' def generate_tokens(readline):' | |||
|
23 | 23 | # catch EOF error |
|
24 | 24 | return |
|
25 | 25 | |
|
26 | def line_at_cursor(cell, cursor_pos=0): | |
|
27 | """Return the line in a cell at a given cursor position | |
|
28 | ||
|
29 | Used for calling line-based APIs that don't support multi-line input, yet. | |
|
30 | ||
|
31 | Parameters | |
|
32 | ---------- | |
|
33 | ||
|
34 | cell: text | |
|
35 | multiline block of text | |
|
36 | cursor_pos: integer | |
|
37 | the cursor position | |
|
38 | ||
|
39 | Returns | |
|
40 | ------- | |
|
41 | ||
|
42 | (line, offset): (text, integer) | |
|
43 | The line with the current cursor, and the character offset of the start of the line. | |
|
44 | """ | |
|
45 | offset = 0 | |
|
46 | lines = cell.splitlines(True) | |
|
47 | for line in lines: | |
|
48 | next_offset = offset + len(line) | |
|
49 | if next_offset >= cursor_pos: | |
|
50 | break | |
|
51 | offset = next_offset | |
|
52 | return (line, offset) | |
|
53 | ||
|
26 | 54 | def token_at_cursor(cell, cursor_pos=0): |
|
27 | 55 | """Get the token at a given cursor |
|
28 | 56 |
General Comments 0
You need to be logged in to leave comments.
Login now