##// END OF EJS Templates
Improvements to tab completion in Qt GUI with new api....
Fernando Perez -
Show More
@@ -193,7 +193,7 b' class CompletionSplitter(object):'
193
193
194
194
195 class Completer(object):
195 class Completer(object):
196 def __init__(self,namespace=None,global_namespace=None):
196 def __init__(self, namespace=None, global_namespace=None):
197 """Create a new completer for the command line.
197 """Create a new completer for the command line.
198
198
199 Completer([namespace,global_namespace]) -> completer instance.
199 Completer([namespace,global_namespace]) -> completer instance.
@@ -343,10 +343,12 b' class IPCompleter(Completer):'
343 without readline, though in that case callers must provide some extra
343 without readline, though in that case callers must provide some extra
344 information on each call about the current line."""
344 information on each call about the current line."""
345
345
346 Completer.__init__(self,namespace,global_namespace)
346 Completer.__init__(self, namespace, global_namespace)
347
347
348 self.magic_escape = ESC_MAGIC
348 self.magic_escape = ESC_MAGIC
349
349
350 self.splitter = CompletionSplitter()
351
350 # Readline-dependent code
352 # Readline-dependent code
351 self.use_readline = use_readline
353 self.use_readline = use_readline
352 if use_readline:
354 if use_readline:
@@ -662,16 +664,20 b' class IPCompleter(Completer):'
662
664
663 return None
665 return None
664
666
665 def complete(self, text, line_buffer, cursor_pos=None):
667 def complete(self, text=None, line_buffer=None, cursor_pos=None):
666 """Return the state-th possible completion for 'text'.
668 """Return the state-th possible completion for 'text'.
667
669
668 This is called successively with state == 0, 1, 2, ... until it
670 This is called successively with state == 0, 1, 2, ... until it
669 returns None. The completion should begin with 'text'.
671 returns None. The completion should begin with 'text'.
670
672
673 Note that both the text and the line_buffer are optional, but at least
674 one of them must be given.
675
671 Parameters
676 Parameters
672 ----------
677 ----------
673 text : string
678 text : string, optional
674 Text to perform the completion on.
679 Text to perform the completion on. If not given, the line buffer
680 is split using the instance's CompletionSplitter object.
675
681
676 line_buffer : string, optional
682 line_buffer : string, optional
677 If not given, the completer attempts to obtain the current line
683 If not given, the completer attempts to obtain the current line
@@ -683,7 +689,20 b' class IPCompleter(Completer):'
683 Index of the cursor in the full line buffer. Should be provided by
689 Index of the cursor in the full line buffer. Should be provided by
684 remote frontends where kernel has no access to frontend state.
690 remote frontends where kernel has no access to frontend state.
685 """
691 """
686 #io.rprint('COMP', text, line_buffer, cursor_pos) # dbg
692 #io.rprint('COMP1 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
693
694 # if the cursor position isn't given, the only sane assumption we can
695 # make is that it's at the end of the line (the common case)
696 if cursor_pos is None:
697 cursor_pos = len(line_buffer) if text is None else len(text)
698
699 # if text is either None or an empty string, rely on the line buffer
700 if not text:
701 text = self.splitter.split_line(line_buffer, cursor_pos)
702
703 # If no line buffer is given, assume the input text is all there was
704 if line_buffer is None:
705 line_buffer = text
687
706
688 magic_escape = self.magic_escape
707 magic_escape = self.magic_escape
689 self.full_lbuf = line_buffer
708 self.full_lbuf = line_buffer
@@ -692,6 +711,8 b' class IPCompleter(Completer):'
692 if text.startswith('~'):
711 if text.startswith('~'):
693 text = os.path.expanduser(text)
712 text = os.path.expanduser(text)
694
713
714 #io.rprint('COMP2 %r %r %r' % (text, line_buffer, cursor_pos)) # dbg
715
695 # Start with a clean slate of completions
716 # Start with a clean slate of completions
696 self.matches[:] = []
717 self.matches[:] = []
697 custom_res = self.dispatch_custom_completer(text)
718 custom_res = self.dispatch_custom_completer(text)
@@ -716,8 +737,8 b' class IPCompleter(Completer):'
716 # simply collapse the dict into a list for readline, but we'd have
737 # simply collapse the dict into a list for readline, but we'd have
717 # richer completion semantics in other evironments.
738 # richer completion semantics in other evironments.
718 self.matches = sorted(set(self.matches))
739 self.matches = sorted(set(self.matches))
719 #io.rprint('MATCHES', self.matches) # dbg
740 #io.rprint('COMP TEXT, MATCHES: %r, %r' % (text, self.matches)) # dbg
720 return self.matches
741 return text, self.matches
721
742
722 def rlcomplete(self, text, state):
743 def rlcomplete(self, text, state):
723 """Return the state-th possible completion for 'text'.
744 """Return the state-th possible completion for 'text'.
@@ -1370,13 +1370,15 b' class InteractiveShell(Configurable, Magic):'
1370 #-------------------------------------------------------------------------
1370 #-------------------------------------------------------------------------
1371
1371
1372 def complete(self, text, line=None, cursor_pos=None):
1372 def complete(self, text, line=None, cursor_pos=None):
1373 """Return a sorted list of all possible completions on text.
1373 """Return the completed text and a list of completions.
1374
1374
1375 Parameters
1375 Parameters
1376 ----------
1376 ----------
1377
1377
1378 text : string
1378 text : string
1379 A string of text to be completed on.
1379 A string of text to be completed on. It can be given as empty and
1380 instead a line/position pair are given. In this case, the
1381 completer itself will split the line like readline does.
1380
1382
1381 line : string, optional
1383 line : string, optional
1382 The complete line that text is part of.
1384 The complete line that text is part of.
@@ -1384,6 +1386,14 b' class InteractiveShell(Configurable, Magic):'
1384 cursor_pos : int, optional
1386 cursor_pos : int, optional
1385 The position of the cursor on the input line.
1387 The position of the cursor on the input line.
1386
1388
1389 Returns
1390 -------
1391 text : string
1392 The actual text that was completed.
1393
1394 matches : list
1395 A sorted list with all possible completions.
1396
1387 The optional arguments allow the completion to take more context into
1397 The optional arguments allow the completion to take more context into
1388 account, and are part of the low-level completion API.
1398 account, and are part of the low-level completion API.
1389
1399
@@ -1394,23 +1404,17 b' class InteractiveShell(Configurable, Magic):'
1394
1404
1395 Simple usage example:
1405 Simple usage example:
1396
1406
1397 In [7]: x = 'hello'
1407 In [1]: x = 'hello'
1398
1399 In [8]: x
1400 Out[8]: 'hello'
1401
1402 In [9]: print x
1403 hello
1404
1408
1405 In [10]: _ip.complete('x.l')
1409 In [2]: _ip.complete('x.l')
1406 Out[10]: ['x.ljust', 'x.lower', 'x.lstrip']
1410 Out[2]: ('x.l', ['x.ljust', 'x.lower', 'x.lstrip'])
1407 """
1411 """
1408
1412
1409 # Inject names into __builtin__ so we can complete on the added names.
1413 # Inject names into __builtin__ so we can complete on the added names.
1410 with self.builtin_trap:
1414 with self.builtin_trap:
1411 return self.Completer.complete(text,line_buffer=text)
1415 return self.Completer.complete(text, line, cursor_pos)
1412
1416
1413 def set_custom_completer(self,completer,pos=0):
1417 def set_custom_completer(self, completer, pos=0):
1414 """Adds a new custom completer function.
1418 """Adds a new custom completer function.
1415
1419
1416 The position argument (defaults to 0) is the index in the completers
1420 The position argument (defaults to 0) is the index in the completers
@@ -69,10 +69,9 b' class CompletionSplitterTestCase(unittest.TestCase):'
69 self.sp = completer.CompletionSplitter()
69 self.sp = completer.CompletionSplitter()
70
70
71 def test_delim_setting(self):
71 def test_delim_setting(self):
72 self.sp.delims = ' '
72 self.sp.set_delims(' ')
73 # Validate that property handling works ok
73 nt.assert_equal(self.sp.get_delims(), ' ')
74 nt.assert_equal(self.sp.delims, ' ')
74 nt.assert_equal(self.sp._delim_expr, '[\ ]')
75 nt.assert_equal(self.sp.delim_expr, '[\ ]')
76
75
77 def test_spaces(self):
76 def test_spaces(self):
78 """Test with only spaces as split chars."""
77 """Test with only spaces as split chars."""
@@ -181,7 +181,10 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
181 cursor = self._get_cursor()
181 cursor = self._get_cursor()
182 if rep['parent_header']['msg_id'] == self._complete_id and \
182 if rep['parent_header']['msg_id'] == self._complete_id and \
183 cursor.position() == self._complete_pos:
183 cursor.position() == self._complete_pos:
184 text = '.'.join(self._get_context())
184 # The completer tells us what text was actually used for the
185 # matching, so we must move that many characters left to apply the
186 # completions.
187 text = rep['content']['matched_text']
185 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
188 cursor.movePosition(QtGui.QTextCursor.Left, n=len(text))
186 self._complete_with_items(cursor, rep['content']['matches'])
189 self._complete_with_items(cursor, rep['content']['matches'])
187
190
@@ -294,14 +297,22 b' class FrontendWidget(HistoryConsoleWidget, BaseFrontendMixin):'
294 """ Performs completion at the current cursor location.
297 """ Performs completion at the current cursor location.
295 """
298 """
296 # Decide if it makes sense to do completion
299 # Decide if it makes sense to do completion
297 context = self._get_context()
300
298 if not context:
301 # We should return only if the line is empty. Otherwise, let the
302 # kernel split the line up.
303 line = self._get_input_buffer_cursor_line()
304 if not line:
299 return False
305 return False
300
306
307 # We let the kernel split the input line, so we *always* send an empty
308 # text field. Readline-based frontends do get a real text field which
309 # they can use.
310 text = ''
311
301 # Send the completion request to the kernel
312 # Send the completion request to the kernel
302 self._complete_id = self.kernel_manager.xreq_channel.complete(
313 self._complete_id = self.kernel_manager.xreq_channel.complete(
303 '.'.join(context), # text
314 text, # text
304 self._get_input_buffer_cursor_line(), # line
315 line, # line
305 self._get_input_buffer_cursor_column(), # cursor_pos
316 self._get_input_buffer_cursor_column(), # cursor_pos
306 self.input_buffer) # block
317 self.input_buffer) # block
307 self._complete_pos = self._get_cursor().position()
318 self._complete_pos = self._get_cursor().position()
General Comments 0
You need to be logged in to leave comments. Login now