Show More
@@ -82,7 +82,6 b' from IPython.core.prefilter import ESC_MAGIC' | |||
|
82 | 82 | from IPython.utils import generics |
|
83 | 83 | from IPython.utils.frame import debugx |
|
84 | 84 | from IPython.utils.dir2 import dir2 |
|
85 | import IPython.utils.rlineimpl as readline | |
|
86 | 85 | |
|
87 | 86 | #----------------------------------------------------------------------------- |
|
88 | 87 | # Globals |
@@ -107,6 +106,18 b' def protect_filename(s):' | |||
|
107 | 106 | for ch in s]) |
|
108 | 107 | |
|
109 | 108 | |
|
109 | def mark_dirs(matches): | |
|
110 | """Mark directories in input list by appending '/' to their names.""" | |
|
111 | out = [] | |
|
112 | isdir = os.path.isdir | |
|
113 | for x in matches: | |
|
114 | if isdir(x): | |
|
115 | out.append(x+'/') | |
|
116 | else: | |
|
117 | out.append(x) | |
|
118 | return out | |
|
119 | ||
|
120 | ||
|
110 | 121 | def single_dir_expand(matches): |
|
111 | 122 | "Recursively expand match lists containing a single dir." |
|
112 | 123 | |
@@ -250,7 +261,7 b' class IPCompleter(Completer):' | |||
|
250 | 261 | """Extension of the completer class with IPython-specific features""" |
|
251 | 262 | |
|
252 | 263 | def __init__(self,shell,namespace=None,global_namespace=None, |
|
253 | omit__names=0,alias_table=None): | |
|
264 | omit__names=0, alias_table=None, use_readline=True): | |
|
254 | 265 | """IPCompleter() -> completer |
|
255 | 266 | |
|
256 | 267 | Return a completer object suitable for use by the readline library |
@@ -273,17 +284,31 b' class IPCompleter(Completer):' | |||
|
273 | 284 | to be completed explicitly starts with one or more underscores. |
|
274 | 285 | |
|
275 | 286 | - If alias_table is supplied, it should be a dictionary of aliases |
|
276 |
to complete. |
|
|
287 | to complete. | |
|
288 | ||
|
289 | use_readline : bool, optional | |
|
290 | If true, use the readline library. This completer can still function | |
|
291 | without readline, though in that case callers must provide some extra | |
|
292 | information on each call about the current line.""" | |
|
277 | 293 | |
|
278 | 294 | Completer.__init__(self,namespace,global_namespace) |
|
279 | 295 | |
|
280 | 296 | self.magic_escape = ESC_MAGIC |
|
297 | ||
|
298 | # Readline-dependent code | |
|
299 | self.use_readline = use_readline | |
|
300 | if use_readline: | |
|
301 | import IPython.utils.rlineimpl as readline | |
|
281 | 302 | self.readline = readline |
|
282 | 303 | delims = self.readline.get_completer_delims() |
|
283 | 304 | delims = delims.replace(self.magic_escape,'') |
|
284 | 305 | self.readline.set_completer_delims(delims) |
|
285 | 306 | self.get_line_buffer = self.readline.get_line_buffer |
|
286 | 307 | self.get_endidx = self.readline.get_endidx |
|
308 | # /end readline-dependent code | |
|
309 | ||
|
310 | # List where completion matches will be stored | |
|
311 | self.matches = [] | |
|
287 | 312 | self.omit__names = omit__names |
|
288 | 313 | self.merge_completions = shell.readline_merge_completions |
|
289 | 314 | self.shell = shell.shell |
@@ -311,7 +336,8 b' class IPCompleter(Completer):' | |||
|
311 | 336 | self.file_matches, |
|
312 | 337 | self.magic_matches, |
|
313 | 338 | self.alias_matches, |
|
314 |
self.python_func_kw_matches |
|
|
339 | self.python_func_kw_matches, | |
|
340 | ] | |
|
315 | 341 | |
|
316 | 342 | # Code contributed by Alex Schmolck, for ipython/emacs integration |
|
317 | 343 | def all_completions(self, text): |
@@ -414,7 +440,8 b' class IPCompleter(Completer):' | |||
|
414 | 440 | protect_filename(f) for f in m0] |
|
415 | 441 | |
|
416 | 442 | #print 'mm',matches # dbg |
|
417 | return single_dir_expand(matches) | |
|
443 | #return single_dir_expand(matches) | |
|
444 | return mark_dirs(matches) | |
|
418 | 445 | |
|
419 | 446 | def magic_matches(self, text): |
|
420 | 447 | """Match magics""" |
@@ -583,50 +610,37 b' class IPCompleter(Completer):' | |||
|
583 | 610 | |
|
584 | 611 | return None |
|
585 | 612 | |
|
586 |
def complete(self, text, |
|
|
587 |
"""Return the |
|
|
613 | def complete(self, text, line_buffer, cursor_pos=None): | |
|
614 | """Return the state-th possible completion for 'text'. | |
|
588 | 615 | |
|
589 | 616 | This is called successively with state == 0, 1, 2, ... until it |
|
590 | 617 | returns None. The completion should begin with 'text'. |
|
591 | 618 | |
|
592 |
|
|
|
593 | - line_buffer: string | |
|
594 | If not given, the completer attempts to obtain the current line buffer | |
|
595 | via readline. This keyword allows clients which are requesting for | |
|
596 | text completions in non-readline contexts to inform the completer of | |
|
597 | the entire text. | |
|
598 | """ | |
|
599 | ||
|
600 | #print '\n*** COMPLETE: <%s> (%s)' % (text,state) # dbg | |
|
619 | Parameters | |
|
620 | ---------- | |
|
621 | text : string | |
|
622 | Text to perform the completion on. | |
|
601 | 623 |
|
|
602 | # if there is only a tab on a line with only whitespace, instead | |
|
603 | # of the mostly useless 'do you want to see all million | |
|
604 | # completions' message, just do the right thing and give the user | |
|
605 | # his tab! Incidentally, this enables pasting of tabbed text from | |
|
606 | # an editor (as long as autoindent is off). | |
|
624 | line_buffer : string, optional | |
|
625 | If not given, the completer attempts to obtain the current line | |
|
626 | buffer via readline. This keyword allows clients which are | |
|
627 | requesting for text completions in non-readline contexts to inform | |
|
628 | the completer of the entire text. | |
|
607 | 629 |
|
|
608 | # It should be noted that at least pyreadline still shows | |
|
609 | # file completions - is there a way around it? | |
|
610 | ||
|
611 | # don't apply this on 'dumb' terminals, such as emacs buffers, so we | |
|
612 | # don't interfere with their own tab-completion mechanism. | |
|
613 | if line_buffer is None: | |
|
614 | self.full_lbuf = self.get_line_buffer() | |
|
615 | else: | |
|
616 | self.full_lbuf = line_buffer | |
|
617 | ||
|
618 | if not (self.dumb_terminal or self.full_lbuf.strip()): | |
|
619 | self.readline.insert_text('\t') | |
|
620 | return None | |
|
630 | cursor_pos : int, optional | |
|
631 | Index of the cursor in the full line buffer. Should be provided by | |
|
632 | remote frontends where kernel has no access to frontend state. | |
|
633 | """ | |
|
621 | 634 | |
|
622 | 635 | magic_escape = self.magic_escape |
|
636 | self.full_lbuf = line_buffer | |
|
637 | self.lbuf = self.full_lbuf[:cursor_pos] | |
|
623 | 638 | |
|
624 | self.lbuf = self.full_lbuf[:self.get_endidx()] | |
|
625 | ||
|
626 | try: | |
|
627 | 639 |
|
|
628 | 640 |
|
|
629 | if state == 0: | |
|
641 | ||
|
642 | # Start with a clean slate of completions | |
|
643 | self.matches[:] = [] | |
|
630 | 644 |
|
|
631 | 645 |
|
|
632 | 646 |
|
@@ -644,15 +658,65 b' class IPCompleter(Completer):' | |||
|
644 | 658 |
|
|
645 | 659 |
|
|
646 | 660 |
|
|
647 | self.matches = list(set(self.matches)) | |
|
661 | # FIXME: we should extend our api to return a dict with completions for | |
|
662 | # different types of objects. The rlcomplete() method could then | |
|
663 | # simply collapse the dict into a list for readline, but we'd have | |
|
664 | # richer completion semantics in other evironments. | |
|
665 | self.matches = sorted(set(self.matches)) | |
|
666 | #from IPython.utils.io import rprint; rprint(self.matches) # dbg | |
|
667 | return self.matches | |
|
668 | ||
|
669 | def rlcomplete(self, text, state): | |
|
670 | """Return the state-th possible completion for 'text'. | |
|
671 | ||
|
672 | This is called successively with state == 0, 1, 2, ... until it | |
|
673 | returns None. The completion should begin with 'text'. | |
|
674 | ||
|
675 | Parameters | |
|
676 | ---------- | |
|
677 | text : string | |
|
678 | Text to perform the completion on. | |
|
679 | ||
|
680 | state : int | |
|
681 | Counter used by readline. | |
|
682 | ||
|
683 | """ | |
|
684 | ||
|
685 | #print "rlcomplete! '%s' %s" % (text, state) # dbg | |
|
686 | ||
|
687 | if state==0: | |
|
688 | self.full_lbuf = line_buffer = self.get_line_buffer() | |
|
689 | cursor_pos = self.get_endidx() | |
|
690 | ||
|
691 | # if there is only a tab on a line with only whitespace, instead of | |
|
692 | # the mostly useless 'do you want to see all million completions' | |
|
693 | # message, just do the right thing and give the user his tab! | |
|
694 | # Incidentally, this enables pasting of tabbed text from an editor | |
|
695 | # (as long as autoindent is off). | |
|
696 | ||
|
697 | # It should be noted that at least pyreadline still shows file | |
|
698 | # completions - is there a way around it? | |
|
699 | ||
|
700 | # don't apply this on 'dumb' terminals, such as emacs buffers, so | |
|
701 | # we don't interfere with their own tab-completion mechanism. | |
|
702 | if not (self.dumb_terminal or self.full_lbuf.strip()): | |
|
703 | self.readline.insert_text('\t') | |
|
704 | sys.stdout.flush() | |
|
705 | return None | |
|
706 | ||
|
707 | # This method computes the self.matches array | |
|
708 | self.complete(text, line_buffer, cursor_pos) | |
|
709 | ||
|
710 | # Debug version, since readline silences all exceptions making it | |
|
711 | # impossible to debug any problem in the above code | |
|
712 | ||
|
713 | ## try: | |
|
714 | ## self.complete(text, line_buffer, cursor_pos) | |
|
715 | ## except: | |
|
716 | ## import traceback; traceback.print_exc() | |
|
717 | ||
|
648 | 718 |
|
|
649 | #print "MATCH: %r" % self.matches[state] # dbg | |
|
650 | 719 |
|
|
651 | 720 |
|
|
652 | 721 |
|
|
653 | except: | |
|
654 | #from IPython.core.ultratb import AutoFormattedTB; # dbg | |
|
655 | #tb=AutoFormattedTB('Verbose');tb() #dbg | |
|
656 | 722 | |
|
657 | # If completion fails, don't annoy the user. | |
|
658 | return None |
@@ -1303,7 +1303,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
1303 | 1303 | else: |
|
1304 | 1304 | if exception_only: |
|
1305 | 1305 | stb = ['An exception has occurred, use %tb to see ' |
|
1306 | 'the full traceback.'] | |
|
1306 | 'the full traceback.\n'] | |
|
1307 | 1307 | stb.extend(self.InteractiveTB.get_exception_only(etype, |
|
1308 | 1308 | value)) |
|
1309 | 1309 | else: |
@@ -1327,7 +1327,9 b' class InteractiveShell(Configurable, Magic):' | |||
|
1327 | 1327 | Subclasses may override this method to put the traceback on a different |
|
1328 | 1328 | place, like a side channel. |
|
1329 | 1329 | """ |
|
1330 | self.write_err('\n'.join(stb)) | |
|
1330 | # FIXME: this should use the proper write channels, but our test suite | |
|
1331 | # relies on it coming out of stdout... | |
|
1332 | print >> sys.stdout, self.InteractiveTB.stb2text(stb) | |
|
1331 | 1333 | |
|
1332 | 1334 | def showsyntaxerror(self, filename=None): |
|
1333 | 1335 | """Display the syntax error that just occurred. |
@@ -1367,12 +1369,23 b' class InteractiveShell(Configurable, Magic):' | |||
|
1367 | 1369 | # Things related to tab completion |
|
1368 | 1370 | #------------------------------------------------------------------------- |
|
1369 | 1371 | |
|
1370 | def complete(self, text): | |
|
1372 | def complete(self, text, line=None, cursor_pos=None): | |
|
1371 | 1373 | """Return a sorted list of all possible completions on text. |
|
1372 | 1374 | |
|
1373 |
|
|
|
1375 | Parameters | |
|
1376 | ---------- | |
|
1377 | ||
|
1378 | text : string | |
|
1379 | A string of text to be completed on. | |
|
1374 | 1380 | |
|
1375 | - text: a string of text to be completed on. | |
|
1381 | line : string, optional | |
|
1382 | The complete line that text is part of. | |
|
1383 | ||
|
1384 | cursor_pos : int, optional | |
|
1385 | The position of the cursor on the input line. | |
|
1386 | ||
|
1387 | The optional arguments allow the completion to take more context into | |
|
1388 | account, and are part of the low-level completion API. | |
|
1376 | 1389 | |
|
1377 | 1390 | This is a wrapper around the completion mechanism, similar to what |
|
1378 | 1391 | readline does at the command line when the TAB key is hit. By |
@@ -1395,23 +1408,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
1395 | 1408 | |
|
1396 | 1409 | # Inject names into __builtin__ so we can complete on the added names. |
|
1397 | 1410 | with self.builtin_trap: |
|
1398 |
|
|
|
1399 | state = 0 | |
|
1400 | # use a dict so we get unique keys, since ipyhton's multiple | |
|
1401 | # completers can return duplicates. When we make 2.4 a requirement, | |
|
1402 | # start using sets instead, which are faster. | |
|
1403 | comps = {} | |
|
1404 | while True: | |
|
1405 | newcomp = complete(text,state,line_buffer=text) | |
|
1406 | if newcomp is None: | |
|
1407 | break | |
|
1408 | comps[newcomp] = 1 | |
|
1409 | state += 1 | |
|
1410 | outcomps = comps.keys() | |
|
1411 | outcomps.sort() | |
|
1412 | #print "T:",text,"OC:",outcomps # dbg | |
|
1413 | #print "vars:",self.user_ns.keys() | |
|
1414 | return outcomps | |
|
1411 | return self.Completer.complete(text,line_buffer=text) | |
|
1415 | 1412 | |
|
1416 | 1413 | def set_custom_completer(self,completer,pos=0): |
|
1417 | 1414 | """Adds a new custom completer function. |
@@ -1425,7 +1422,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
1425 | 1422 | |
|
1426 | 1423 | def set_completer(self): |
|
1427 | 1424 | """Reset readline's completer to be our own.""" |
|
1428 | self.readline.set_completer(self.Completer.complete) | |
|
1425 | self.readline.set_completer(self.Completer.rlcomplete) | |
|
1429 | 1426 | |
|
1430 | 1427 | def set_completer_frame(self, frame=None): |
|
1431 | 1428 | """Set the frame of the completer.""" |
@@ -1497,7 +1494,7 b' class InteractiveShell(Configurable, Magic):' | |||
|
1497 | 1494 | % inputrc_name) |
|
1498 | 1495 | |
|
1499 | 1496 | # save this in sys so embedded copies can restore it properly |
|
1500 | sys.ipcompleter = self.Completer.complete | |
|
1497 | sys.ipcompleter = self.Completer.rlcomplete | |
|
1501 | 1498 | self.set_completer() |
|
1502 | 1499 | |
|
1503 | 1500 | # Configure readline according to user's prefs |
@@ -360,6 +360,10 b' class TBTools(object):' | |||
|
360 | 360 | self.color_scheme_table.set_active_scheme('NoColor') |
|
361 | 361 | self.Colors = self.color_scheme_table.active_colors |
|
362 | 362 | |
|
363 | def stb2text(self, stb): | |
|
364 | """Convert a structured traceback (a list) to a string.""" | |
|
365 | return '\n'.join(stb) | |
|
366 | ||
|
363 | 367 | def text(self, etype, value, tb, tb_offset=None, context=5): |
|
364 | 368 | """Return formatted traceback. |
|
365 | 369 | |
@@ -367,7 +371,7 b' class TBTools(object):' | |||
|
367 | 371 | """ |
|
368 | 372 | tb_list = self.structured_traceback(etype, value, tb, |
|
369 | 373 | tb_offset, context) |
|
370 |
return |
|
|
374 | return self.stb2text(tb_list) | |
|
371 | 375 | |
|
372 | 376 | def structured_traceback(self, etype, evalue, tb, tb_offset=None, |
|
373 | 377 | context=5, mode=None): |
@@ -1008,6 +1012,11 b' class FormattedTB(VerboseTB, ListTB):' | |||
|
1008 | 1012 | |
|
1009 | 1013 | VerboseTB.__init__(self,color_scheme,tb_offset,long_header, |
|
1010 | 1014 | call_pdb=call_pdb,include_vars=include_vars) |
|
1015 | ||
|
1016 | # Different types of tracebacks are joined with different separators to | |
|
1017 | # form a single string. They are taken from this dict | |
|
1018 | self._join_chars = dict(Plain='', Context='\n', Verbose='\n') | |
|
1019 | # set_mode also sets the tb_join_char attribute | |
|
1011 | 1020 | self.set_mode(mode) |
|
1012 | 1021 | |
|
1013 | 1022 | def _extract_tb(self,tb): |
@@ -1016,10 +1025,9 b' class FormattedTB(VerboseTB, ListTB):' | |||
|
1016 | 1025 | else: |
|
1017 | 1026 | return None |
|
1018 | 1027 | |
|
1019 | def structured_traceback(self, etype, value, tb, tb_offset=None, | |
|
1020 | context=5, mode=None): | |
|
1028 | def structured_traceback(self, etype, value, tb, tb_offset=None, context=5): | |
|
1021 | 1029 | tb_offset = self.tb_offset if tb_offset is None else tb_offset |
|
1022 |
mode = self.mode |
|
|
1030 | mode = self.mode | |
|
1023 | 1031 | if mode in self.verbose_modes: |
|
1024 | 1032 | # Verbose modes need a full traceback |
|
1025 | 1033 | return VerboseTB.structured_traceback( |
@@ -1035,16 +1043,9 b' class FormattedTB(VerboseTB, ListTB):' | |||
|
1035 | 1043 | self, etype, value, elist, tb_offset, context |
|
1036 | 1044 | ) |
|
1037 | 1045 | |
|
1038 | def text(self, etype, value, tb, tb_offset=None, context=5, mode=None): | |
|
1039 | """Return formatted traceback. | |
|
1040 | ||
|
1041 | If the optional mode parameter is given, it overrides the current | |
|
1042 | mode.""" | |
|
1043 | ||
|
1044 | mode = self.mode if mode is None else mode | |
|
1045 | tb_list = self.structured_traceback(etype, value, tb, tb_offset, | |
|
1046 | context, mode) | |
|
1047 | return '\n'.join(tb_list) | |
|
1046 | def stb2text(self, stb): | |
|
1047 | """Convert a structured traceback (a list) to a string.""" | |
|
1048 | return self.tb_join_char.join(stb) | |
|
1048 | 1049 | |
|
1049 | 1050 | |
|
1050 | 1051 | def set_mode(self,mode=None): |
@@ -1063,6 +1064,8 b' class FormattedTB(VerboseTB, ListTB):' | |||
|
1063 | 1064 | self.mode = mode |
|
1064 | 1065 | # include variable details only in 'Verbose' mode |
|
1065 | 1066 | self.include_vars = (self.mode == self.valid_modes[2]) |
|
1067 | # Set the join character for generating text tracebacks | |
|
1068 | self.tb_join_char = self._join_chars[mode] | |
|
1066 | 1069 | |
|
1067 | 1070 | # some convenient shorcuts |
|
1068 | 1071 | def plain(self): |
@@ -1117,12 +1120,12 b' class AutoFormattedTB(FormattedTB):' | |||
|
1117 | 1120 | print "\nKeyboardInterrupt" |
|
1118 | 1121 | |
|
1119 | 1122 | def structured_traceback(self, etype=None, value=None, tb=None, |
|
1120 |
tb_offset=None, context=5 |
|
|
1123 | tb_offset=None, context=5): | |
|
1121 | 1124 | if etype is None: |
|
1122 | 1125 | etype,value,tb = sys.exc_info() |
|
1123 | 1126 | self.tb = tb |
|
1124 | 1127 | return FormattedTB.structured_traceback( |
|
1125 |
self, etype, value, tb, tb_offset, context |
|
|
1128 | self, etype, value, tb, tb_offset, context) | |
|
1126 | 1129 | |
|
1127 | 1130 | #--------------------------------------------------------------------------- |
|
1128 | 1131 | |
@@ -1151,14 +1154,10 b' class SyntaxTB(ListTB):' | |||
|
1151 | 1154 | self.last_syntax_error = None |
|
1152 | 1155 | return e |
|
1153 | 1156 | |
|
1154 | def text(self, etype, value, tb, tb_offset=None, context=5): | |
|
1155 | """Return formatted traceback. | |
|
1157 | def stb2text(self, stb): | |
|
1158 | """Convert a structured traceback (a list) to a string.""" | |
|
1159 | return ''.join(stb) | |
|
1156 | 1160 | |
|
1157 | Subclasses may override this if they add extra arguments. | |
|
1158 | """ | |
|
1159 | tb_list = self.structured_traceback(etype, value, tb, | |
|
1160 | tb_offset, context) | |
|
1161 | return ''.join(tb_list) | |
|
1162 | 1161 | |
|
1163 | 1162 | #---------------------------------------------------------------------------- |
|
1164 | 1163 | # module testing (minimal) |
@@ -293,8 +293,15 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):' | |||
|
293 | 293 | |
|
294 | 294 | # Send the completion request to the kernel |
|
295 | 295 | text = '.'.join(context) |
|
296 | ||
|
297 | # FIXME - Evan: we need the position of the cursor in the current input | |
|
298 | # buffer. I tried this line below but the numbers I get are bogus. - | |
|
299 | # Not sure what to do. fperez. | |
|
300 | cursor_pos = self._get_cursor().position() | |
|
301 | ||
|
296 | 302 | self._complete_id = self.kernel_manager.xreq_channel.complete( |
|
297 |
text, self._get_input_buffer_cursor_line(), |
|
|
303 | text, self._get_input_buffer_cursor_line(), cursor_pos, | |
|
304 | self.input_buffer) | |
|
298 | 305 | self._complete_pos = self._get_cursor().position() |
|
299 | 306 | return True |
|
300 | 307 |
@@ -286,7 +286,18 b' class Kernel(Configurable):' | |||
|
286 | 286 | return value |
|
287 | 287 | |
|
288 | 288 | def _complete(self, msg): |
|
289 | return self.shell.complete(msg.content.line) | |
|
289 | #from IPython.utils.io import rprint # dbg | |
|
290 | #rprint('\n\n**MSG**\n\n', msg) # dbg | |
|
291 | #import traceback; rprint(''.join(traceback.format_stack())) # dbg | |
|
292 | c = msg['content'] | |
|
293 | try: | |
|
294 | cpos = int(c['cursor_pos']) | |
|
295 | except: | |
|
296 | # If we don't get something that we can convert to an integer, at | |
|
297 | # leasat attempt the completion guessing the cursor is at the end | |
|
298 | # of the text | |
|
299 | cpos = len(c['text']) | |
|
300 | return self.shell.complete(c['text'], c['line'], cpos) | |
|
290 | 301 | |
|
291 | 302 | def _object_info(self, context): |
|
292 | 303 | symbol, leftover = self._symbol_from_context(context) |
@@ -182,7 +182,7 b' class XReqSocketChannel(ZmqSocketChannel):' | |||
|
182 | 182 | self._queue_request(msg) |
|
183 | 183 | return msg['header']['msg_id'] |
|
184 | 184 | |
|
185 | def complete(self, text, line, block=None): | |
|
185 | def complete(self, text, line, cursor_pos, block=None): | |
|
186 | 186 | """Tab complete text, line, block in the kernel's namespace. |
|
187 | 187 | |
|
188 | 188 | Parameters |
@@ -199,7 +199,7 b' class XReqSocketChannel(ZmqSocketChannel):' | |||
|
199 | 199 | ------- |
|
200 | 200 | The msg_id of the message sent. |
|
201 | 201 | """ |
|
202 | content = dict(text=text, line=line) | |
|
202 | content = dict(text=text, line=line, block=block, cursor_pos=cursor_pos) | |
|
203 | 203 | msg = self.session.msg('complete_request', content) |
|
204 | 204 | self._queue_request(msg) |
|
205 | 205 | return msg['header']['msg_id'] |
General Comments 0
You need to be logged in to leave comments.
Login now