Show More
@@ -78,12 +78,14 b' import re' | |||||
78 | import shlex |
|
78 | import shlex | |
79 | import sys |
|
79 | import sys | |
80 |
|
80 | |||
|
81 | from IPython.config.configurable import Configurable | |||
81 | from IPython.core.error import TryNext |
|
82 | from IPython.core.error import TryNext | |
82 | from IPython.core.prefilter import ESC_MAGIC |
|
83 | from IPython.core.prefilter import ESC_MAGIC | |
83 | from IPython.utils import generics |
|
84 | from IPython.utils import generics | |
84 | from IPython.utils import io |
|
85 | from IPython.utils import io | |
85 | from IPython.utils.dir2 import dir2 |
|
86 | from IPython.utils.dir2 import dir2 | |
86 | from IPython.utils.process import arg_split |
|
87 | from IPython.utils.process import arg_split | |
|
88 | from IPython.utils.traitlets import CBool | |||
87 |
|
89 | |||
88 | #----------------------------------------------------------------------------- |
|
90 | #----------------------------------------------------------------------------- | |
89 | # Globals |
|
91 | # Globals | |
@@ -210,6 +212,8 b' def single_dir_expand(matches):' | |||||
210 |
|
212 | |||
211 | class Bunch(object): pass |
|
213 | class Bunch(object): pass | |
212 |
|
214 | |||
|
215 | DELIMS = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' | |||
|
216 | GREEDY_DELIMS = ' \r\n' | |||
213 |
|
217 | |||
214 | class CompletionSplitter(object): |
|
218 | class CompletionSplitter(object): | |
215 | """An object to split an input line in a manner similar to readline. |
|
219 | """An object to split an input line in a manner similar to readline. | |
@@ -228,7 +232,7 b' class CompletionSplitter(object):' | |||||
228 |
|
232 | |||
229 | # A string of delimiter characters. The default value makes sense for |
|
233 | # A string of delimiter characters. The default value makes sense for | |
230 | # IPython's most typical usage patterns. |
|
234 | # IPython's most typical usage patterns. | |
231 | _delims = ' \t\n`!@#$^&*()=+[{]}\\|;:\'",<>?' |
|
235 | _delims = DELIMS | |
232 |
|
236 | |||
233 | # The expression (a normal string) to be compiled into a regular expression |
|
237 | # The expression (a normal string) to be compiled into a regular expression | |
234 | # for actual splitting. We store it as an attribute mostly for ease of |
|
238 | # for actual splitting. We store it as an attribute mostly for ease of | |
@@ -260,11 +264,20 b' class CompletionSplitter(object):' | |||||
260 | return self._delim_re.split(l)[-1] |
|
264 | return self._delim_re.split(l)[-1] | |
261 |
|
265 | |||
262 |
|
266 | |||
263 |
class Completer( |
|
267 | class Completer(Configurable): | |
264 | def __init__(self, namespace=None, global_namespace=None): |
|
268 | ||
|
269 | greedy = CBool(False, config=True, | |||
|
270 | help="""Activate greedy completion | |||
|
271 | ||||
|
272 | This will enable completion on elements of lists, results of function calls, etc., | |||
|
273 | but can be unsafe because the code is actually evaluated on TAB. | |||
|
274 | """ | |||
|
275 | ) | |||
|
276 | ||||
|
277 | def __init__(self, namespace=None, global_namespace=None, config=None): | |||
265 | """Create a new completer for the command line. |
|
278 | """Create a new completer for the command line. | |
266 |
|
279 | |||
267 |
Completer( |
|
280 | Completer(namespace=ns,global_namespace=ns2) -> completer instance. | |
268 |
|
281 | |||
269 | If unspecified, the default namespace where completions are performed |
|
282 | If unspecified, the default namespace where completions are performed | |
270 | is __main__ (technically, __main__.__dict__). Namespaces should be |
|
283 | is __main__ (technically, __main__.__dict__). Namespaces should be | |
@@ -294,6 +307,8 b' class Completer(object):' | |||||
294 | self.global_namespace = {} |
|
307 | self.global_namespace = {} | |
295 | else: |
|
308 | else: | |
296 | self.global_namespace = global_namespace |
|
309 | self.global_namespace = global_namespace | |
|
310 | ||||
|
311 | super(Completer, self).__init__(config=config) | |||
297 |
|
312 | |||
298 | def complete(self, text, state): |
|
313 | def complete(self, text, state): | |
299 | """Return the next possible completion for 'text'. |
|
314 | """Return the next possible completion for 'text'. | |
@@ -349,14 +364,20 b' class Completer(object):' | |||||
349 |
|
364 | |||
350 | """ |
|
365 | """ | |
351 |
|
366 | |||
352 |
# |
|
367 | #io.rprint('Completer->attr_matches, txt=%r' % text) # dbg | |
353 | # Another option, seems to work great. Catches things like ''.<tab> |
|
368 | # Another option, seems to work great. Catches things like ''.<tab> | |
354 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) |
|
369 | m = re.match(r"(\S+(\.\w+)*)\.(\w*)$", text) | |
355 |
|
370 | |||
356 |
if |
|
371 | if m: | |
|
372 | expr, attr = m.group(1, 3) | |||
|
373 | elif self.greedy: | |||
|
374 | m2 = re.match(r"(.+)\.(\w*)$", self.line_buffer) | |||
|
375 | if not m2: | |||
|
376 | return [] | |||
|
377 | expr, attr = m2.group(1,2) | |||
|
378 | else: | |||
357 | return [] |
|
379 | return [] | |
358 |
|
|
380 | ||
359 | expr, attr = m.group(1, 3) |
|
|||
360 | try: |
|
381 | try: | |
361 | obj = eval(expr, self.namespace) |
|
382 | obj = eval(expr, self.namespace) | |
362 | except: |
|
383 | except: | |
@@ -380,8 +401,19 b' class Completer(object):' | |||||
380 | class IPCompleter(Completer): |
|
401 | class IPCompleter(Completer): | |
381 | """Extension of the completer class with IPython-specific features""" |
|
402 | """Extension of the completer class with IPython-specific features""" | |
382 |
|
403 | |||
383 | def __init__(self, shell, namespace=None, global_namespace=None, |
|
404 | def _greedy_changed(self, name, old, new): | |
384 | omit__names=True, alias_table=None, use_readline=True): |
|
405 | """update the splitter and readline delims when greedy is changed""" | |
|
406 | if new: | |||
|
407 | self.splitter.set_delims(GREEDY_DELIMS) | |||
|
408 | else: | |||
|
409 | self.splitter.set_delims(DELIMS) | |||
|
410 | ||||
|
411 | if self.readline: | |||
|
412 | self.readline.set_completer_delims(self.splitter.get_delims()) | |||
|
413 | ||||
|
414 | def __init__(self, shell=None, namespace=None, global_namespace=None, | |||
|
415 | omit__names=True, alias_table=None, use_readline=True, | |||
|
416 | config=None): | |||
385 | """IPCompleter() -> completer |
|
417 | """IPCompleter() -> completer | |
386 |
|
418 | |||
387 | Return a completer object suitable for use by the readline library |
|
419 | Return a completer object suitable for use by the readline library | |
@@ -411,8 +443,6 b' class IPCompleter(Completer):' | |||||
411 | without readline, though in that case callers must provide some extra |
|
443 | without readline, though in that case callers must provide some extra | |
412 | information on each call about the current line.""" |
|
444 | information on each call about the current line.""" | |
413 |
|
445 | |||
414 | Completer.__init__(self, namespace, global_namespace) |
|
|||
415 |
|
||||
416 | self.magic_escape = ESC_MAGIC |
|
446 | self.magic_escape = ESC_MAGIC | |
417 | self.splitter = CompletionSplitter() |
|
447 | self.splitter = CompletionSplitter() | |
418 |
|
448 | |||
@@ -424,6 +454,10 b' class IPCompleter(Completer):' | |||||
424 | else: |
|
454 | else: | |
425 | self.readline = None |
|
455 | self.readline = None | |
426 |
|
456 | |||
|
457 | # _greedy_changed() depends on splitter and readline being defined: | |||
|
458 | Completer.__init__(self, namespace=namespace, global_namespace=global_namespace, | |||
|
459 | config=config) | |||
|
460 | ||||
427 | # List where completion matches will be stored |
|
461 | # List where completion matches will be stored | |
428 | self.matches = [] |
|
462 | self.matches = [] | |
429 | self.omit__names = omit__names |
|
463 | self.omit__names = omit__names | |
@@ -579,7 +613,7 b' class IPCompleter(Completer):' | |||||
579 | def python_matches(self,text): |
|
613 | def python_matches(self,text): | |
580 | """Match attributes or global python names""" |
|
614 | """Match attributes or global python names""" | |
581 |
|
615 | |||
582 |
# |
|
616 | #io.rprint('Completer->python_matches, txt=%r' % text) # dbg | |
583 | if "." in text: |
|
617 | if "." in text: | |
584 | try: |
|
618 | try: | |
585 | matches = self.attr_matches(text) |
|
619 | matches = self.attr_matches(text) | |
@@ -680,7 +714,7 b' class IPCompleter(Completer):' | |||||
680 | return argMatches |
|
714 | return argMatches | |
681 |
|
715 | |||
682 | def dispatch_custom_completer(self, text): |
|
716 | def dispatch_custom_completer(self, text): | |
683 |
# |
|
717 | #io.rprint("Custom! '%s' %s" % (text, self.custom_completers)) # dbg | |
684 | line = self.line_buffer |
|
718 | line = self.line_buffer | |
685 | if not line.strip(): |
|
719 | if not line.strip(): | |
686 | return None |
|
720 | return None |
@@ -1771,12 +1771,14 b' class InteractiveShell(SingletonConfigurable, Magic):' | |||||
1771 | from IPython.core.completerlib import (module_completer, |
|
1771 | from IPython.core.completerlib import (module_completer, | |
1772 | magic_run_completer, cd_completer) |
|
1772 | magic_run_completer, cd_completer) | |
1773 |
|
1773 | |||
1774 | self.Completer = IPCompleter(self, |
|
1774 | self.Completer = IPCompleter(shell=self, | |
1775 | self.user_ns, |
|
1775 | namespace=self.user_ns, | |
1776 | self.user_global_ns, |
|
1776 | global_namespace=self.user_global_ns, | |
1777 | self.readline_omit__names, |
|
1777 | omit__names=self.readline_omit__names, | |
1778 | self.alias_manager.alias_table, |
|
1778 | alias_table=self.alias_manager.alias_table, | |
1779 |
self.has_readline |
|
1779 | use_readline=self.has_readline, | |
|
1780 | config=self.config, | |||
|
1781 | ) | |||
1780 |
|
1782 | |||
1781 | # Add custom completers to the basic ones built into IPCompleter |
|
1783 | # Add custom completers to the basic ones built into IPCompleter | |
1782 | sdisp = self.strdispatchers.get('complete_command', StrDispatch()) |
|
1784 | sdisp = self.strdispatchers.get('complete_command', StrDispatch()) |
@@ -181,3 +181,14 b' def test_local_file_completions():' | |||||
181 | finally: |
|
181 | finally: | |
182 | # prevent failures from making chdir stick |
|
182 | # prevent failures from making chdir stick | |
183 | os.chdir(cwd) |
|
183 | os.chdir(cwd) | |
|
184 | ||||
|
185 | def test_greedy_completions(): | |||
|
186 | ip = get_ipython() | |||
|
187 | ip.Completer.greedy = False | |||
|
188 | ip.ex('a=range(5)') | |||
|
189 | _,c = ip.complete('.',line='a[0].') | |||
|
190 | nt.assert_false('a[0].real' in c, "Shouldn't have completed on a[0]: %s"%c) | |||
|
191 | ip.Completer.greedy = True | |||
|
192 | _,c = ip.complete('.',line='a[0].') | |||
|
193 | nt.assert_true('a[0].real' in c, "Should have completed on a[0]: %s"%c) | |||
|
194 |
@@ -35,6 +35,7 b' from IPython.config.loader import (' | |||||
35 | from IPython.config.application import boolean_flag |
|
35 | from IPython.config.application import boolean_flag | |
36 | from IPython.core import release |
|
36 | from IPython.core import release | |
37 | from IPython.core import usage |
|
37 | from IPython.core import usage | |
|
38 | from IPython.core.completer import Completer | |||
38 | from IPython.core.crashhandler import CrashHandler |
|
39 | from IPython.core.crashhandler import CrashHandler | |
39 | from IPython.core.formatters import PlainTextFormatter |
|
40 | from IPython.core.formatters import PlainTextFormatter | |
40 | from IPython.core.application import ( |
|
41 | from IPython.core.application import ( | |
@@ -198,6 +199,7 b' class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):' | |||||
198 | TerminalInteractiveShell, |
|
199 | TerminalInteractiveShell, | |
199 | ProfileDir, |
|
200 | ProfileDir, | |
200 | PlainTextFormatter, |
|
201 | PlainTextFormatter, | |
|
202 | Completer, | |||
201 | ] |
|
203 | ] | |
202 |
|
204 | |||
203 | subcommands = Dict(dict( |
|
205 | subcommands = Dict(dict( |
1 | NO CONTENT: file was removed |
|
NO CONTENT: file was removed |
General Comments 0
You need to be logged in to leave comments.
Login now