##// END OF EJS Templates
Improvements in the code that breaks up user input.
Thomas Kluyver -
Show More
@@ -38,7 +38,7 b' from IPython.utils.warn import warn, error'
38 #-----------------------------------------------------------------------------
38 #-----------------------------------------------------------------------------
39
39
40 # This is used as the pattern for calls to split_user_input.
40 # This is used as the pattern for calls to split_user_input.
41 shell_line_split = re.compile(r'^(\s*)(\S*\s*)(.*$)')
41 shell_line_split = re.compile(r'^(\s*)()(\S+)(.*$)')
42
42
43 def default_aliases():
43 def default_aliases():
44 """Return list of shell aliases to auto-define.
44 """Return list of shell aliases to auto-define.
@@ -222,7 +222,7 b' class AliasManager(Configurable):'
222 <16> 'q:/opt/np/notepad++.exe myfile.txt'
222 <16> 'q:/opt/np/notepad++.exe myfile.txt'
223 """
223 """
224
224
225 pre,fn,rest = split_user_input(line)
225 pre,_,fn,rest = split_user_input(line)
226 res = pre + self.expand_aliases(fn, rest)
226 res = pre + self.expand_aliases(fn, rest)
227 return res
227 return res
228
228
@@ -242,7 +242,7 b' class AliasManager(Configurable):'
242
242
243 done = set()
243 done = set()
244 while 1:
244 while 1:
245 pre,fn,rest = split_user_input(line, shell_line_split)
245 pre,_,fn,rest = split_user_input(line, shell_line_split)
246 if fn in self.alias_table:
246 if fn in self.alias_table:
247 if fn in done:
247 if fn in done:
248 warn("Cyclic alias definition, repeated '%s'" % fn)
248 warn("Cyclic alias definition, repeated '%s'" % fn)
@@ -24,12 +24,16 b' import os'
24 import sys
24 import sys
25 import types
25 import types
26 from collections import namedtuple
26 from collections import namedtuple
27 from itertools import izip_longest
27 try:
28 from itertools import izip_longest
29 except ImportError:
30 from itertools import zip_longest as izip_longest
28
31
29 # IPython's own
32 # IPython's own
30 from IPython.core import page
33 from IPython.core import page
31 from IPython.utils import PyColorize
34 from IPython.utils import PyColorize
32 from IPython.utils import io
35 from IPython.utils import io
36 from IPython.utils import py3compat
33 from IPython.utils.text import indent
37 from IPython.utils.text import indent
34 from IPython.utils.wildcard import list_namespace
38 from IPython.utils.wildcard import list_namespace
35 from IPython.utils.coloransi import *
39 from IPython.utils.coloransi import *
@@ -249,7 +253,7 b' class Inspector:'
249 try:
253 try:
250 # We need a plain string here, NOT unicode!
254 # We need a plain string here, NOT unicode!
251 hdef = oname + inspect.formatargspec(*getargspec(obj))
255 hdef = oname + inspect.formatargspec(*getargspec(obj))
252 return hdef.encode('ascii')
256 return py3compat.unicode_to_str(hdef.encode('ascii'))
253 except:
257 except:
254 return None
258 return None
255
259
@@ -362,7 +366,7 b' class Inspector:'
362 except:
366 except:
363 self.noinfo('source',oname)
367 self.noinfo('source',oname)
364 else:
368 else:
365 page.page(self.format(src))
369 page.page(self.format(py3compat.unicode_to_str(src)))
366
370
367 def pfile(self,obj,oname=''):
371 def pfile(self,obj,oname=''):
368 """Show the whole file where an object was defined."""
372 """Show the whole file where an object was defined."""
@@ -131,7 +131,7 b' class LineInfo(object):'
131 def __init__(self, line, continue_prompt):
131 def __init__(self, line, continue_prompt):
132 self.line = line
132 self.line = line
133 self.continue_prompt = continue_prompt
133 self.continue_prompt = continue_prompt
134 self.pre, self.ifun, self.the_rest = split_user_input(line)
134 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
135
135
136 self.pre_char = self.pre.strip()
136 self.pre_char = self.pre.strip()
137 if self.pre_char:
137 if self.pre_char:
@@ -630,7 +630,7 b' class MultiLineMagicChecker(PrefilterChecker):'
630 # both ! and !!.
630 # both ! and !!.
631 if line_info.continue_prompt \
631 if line_info.continue_prompt \
632 and self.prefilter_manager.multi_line_specials:
632 and self.prefilter_manager.multi_line_specials:
633 if line_info.ifun.startswith(ESC_MAGIC):
633 if line_info.esc == ESC_MAGIC:
634 return self.prefilter_manager.get_handler_by_name('magic')
634 return self.prefilter_manager.get_handler_by_name('magic')
635 else:
635 else:
636 return None
636 return None
@@ -644,14 +644,16 b' class EscCharsChecker(PrefilterChecker):'
644 """Check for escape character and return either a handler to handle it,
644 """Check for escape character and return either a handler to handle it,
645 or None if there is no escape char."""
645 or None if there is no escape char."""
646 if line_info.line[-1] == ESC_HELP \
646 if line_info.line[-1] == ESC_HELP \
647 and line_info.pre_char != ESC_SHELL \
647 and line_info.esc != ESC_SHELL \
648 and line_info.pre_char != ESC_SH_CAP:
648 and line_info.esc != ESC_SH_CAP:
649 # the ? can be at the end, but *not* for either kind of shell escape,
649 # the ? can be at the end, but *not* for either kind of shell escape,
650 # because a ? can be a vaild final char in a shell cmd
650 # because a ? can be a vaild final char in a shell cmd
651 return self.prefilter_manager.get_handler_by_name('help')
651 return self.prefilter_manager.get_handler_by_name('help')
652 else:
652 else:
653 if line_info.pre:
654 return None
653 # This returns None like it should if no handler exists
655 # This returns None like it should if no handler exists
654 return self.prefilter_manager.get_handler_by_esc(line_info.pre_char)
656 return self.prefilter_manager.get_handler_by_esc(line_info.esc)
655
657
656
658
657 class AssignmentChecker(PrefilterChecker):
659 class AssignmentChecker(PrefilterChecker):
@@ -872,6 +874,7 b' class AutoHandler(PrefilterHandler):'
872 ifun = line_info.ifun
874 ifun = line_info.ifun
873 the_rest = line_info.the_rest
875 the_rest = line_info.the_rest
874 pre = line_info.pre
876 pre = line_info.pre
877 esc = line_info.esc
875 continue_prompt = line_info.continue_prompt
878 continue_prompt = line_info.continue_prompt
876 obj = line_info.ofind(self)['obj']
879 obj = line_info.ofind(self)['obj']
877 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
880 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun,the_rest) # dbg
@@ -883,13 +886,13 b' class AutoHandler(PrefilterHandler):'
883 force_auto = isinstance(obj, IPyAutocall)
886 force_auto = isinstance(obj, IPyAutocall)
884 auto_rewrite = getattr(obj, 'rewrite', True)
887 auto_rewrite = getattr(obj, 'rewrite', True)
885
888
886 if pre == ESC_QUOTE:
889 if esc == ESC_QUOTE:
887 # Auto-quote splitting on whitespace
890 # Auto-quote splitting on whitespace
888 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
891 newcmd = '%s("%s")' % (ifun,'", "'.join(the_rest.split()) )
889 elif pre == ESC_QUOTE2:
892 elif esc == ESC_QUOTE2:
890 # Auto-quote whole string
893 # Auto-quote whole string
891 newcmd = '%s("%s")' % (ifun,the_rest)
894 newcmd = '%s("%s")' % (ifun,the_rest)
892 elif pre == ESC_PAREN:
895 elif esc == ESC_PAREN:
893 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
896 newcmd = '%s(%s)' % (ifun,",".join(the_rest.split()))
894 else:
897 else:
895 # Auto-paren.
898 # Auto-paren.
@@ -946,7 +949,7 b' class HelpHandler(PrefilterHandler):'
946 line = line[:-1]
949 line = line[:-1]
947 if line:
950 if line:
948 #print 'line:<%r>' % line # dbg
951 #print 'line:<%r>' % line # dbg
949 self.shell.magic_pinfo(line)
952 self.shell.magic_pinfo(line_info.ifun)
950 else:
953 else:
951 self.shell.show_usage()
954 self.shell.show_usage()
952 return '' # Empty string is needed here!
955 return '' # Empty string is needed here!
@@ -40,13 +40,15 b' from IPython.utils import py3compat'
40 # ! and !! trigger if they are first char(s) *or* follow an indent
40 # ! and !! trigger if they are first char(s) *or* follow an indent
41 # ? triggers as first or last char.
41 # ? triggers as first or last char.
42
42
43 # The three parts of the regex are:
43 # The four parts of the regex are:
44 # 1) pre: pre_char *or* initial whitespace
44 # 1) pre: initial whitespace
45 # 2) ifun: first word/method (mix of \w and '.')
45 # 2) esc: escape character
46 # 3) the_rest: rest of line (separated from ifun by space if non-empty)
46 # 3) ifun: first word/method (mix of \w and '.')
47 line_split = re.compile(r'^([,;/%?]|!!?|\s*)'
47 # 4) the_rest: rest of line (separated from ifun by space if non-empty)
48 line_split = re.compile(r'^(\s*)'
49 r'([,;/%?]|!!?)?'
48 r'\s*([\w\.]+)'
50 r'\s*([\w\.]+)'
49 r'(\s+.*$|$)')
51 r'(.*$|$)')
50
52
51 # r'[\w\.]+'
53 # r'[\w\.]+'
52 # r'\s*=\s*%.*'
54 # r'\s*=\s*%.*'
@@ -71,19 +73,14 b' def split_user_input(line, pattern=None):'
71 # print "split failed for line '%s'" % line
73 # print "split failed for line '%s'" % line
72 ifun, the_rest = line, u''
74 ifun, the_rest = line, u''
73 pre = re.match('^(\s*)(.*)',line).groups()[0]
75 pre = re.match('^(\s*)(.*)',line).groups()[0]
76 esc = ""
74 else:
77 else:
75 pre,ifun,the_rest = match.groups()
78 pre, esc, ifun, the_rest = match.groups()
76
79
77 if not py3compat.PY3:
80 if not py3compat.isidentifier(ifun, dotted=True):
78 # ifun has to be a valid python identifier, so it better encode into
81 the_rest = ifun + u' ' + the_rest
79 # ascii. We do still make it a unicode string so that we consistently
82 ifun = u''
80 # return unicode, but it will be one that is guaranteed to be pure ascii
81 try:
82 ifun = unicode(ifun.encode('ascii'))
83 except UnicodeEncodeError:
84 the_rest = ifun + u' ' + the_rest
85 ifun = u''
86
83
87 #print 'line:<%s>' % line # dbg
84 #print 'line:<%s>' % line # dbg
88 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
85 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
89 return pre, ifun.strip(), the_rest.lstrip()
86 return pre, esc, ifun.strip(), the_rest.lstrip()
@@ -10,6 +10,7 b' import nose.tools as nt'
10 # our own packages
10 # our own packages
11 from IPython.core import autocall
11 from IPython.core import autocall
12 from IPython.testing import decorators as dec
12 from IPython.testing import decorators as dec
13 from IPython.testing import tools as tt
13 from IPython.testing.globalipapp import get_ipython
14 from IPython.testing.globalipapp import get_ipython
14
15
15 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
@@ -40,15 +41,7 b' def run(tests):'
40 """Loop through a list of (pre, post) inputs, where pre is the string
41 """Loop through a list of (pre, post) inputs, where pre is the string
41 handed to ipython, and post is how that string looks after it's been
42 handed to ipython, and post is how that string looks after it's been
42 transformed (i.e. ipython's notion of _i)"""
43 transformed (i.e. ipython's notion of _i)"""
43 for pre, post in tests:
44 tt.check_pairs(ip.prefilter_manager.prefilter_lines, tests)
44 global num_tests
45 num_tests += 1
46 actual = ip.prefilter_manager.prefilter_lines(pre)
47 if actual != None:
48 actual = actual.rstrip('\n')
49 if actual != post:
50 failures.append('Expected %r to become %r, found %r' % (
51 pre, post, actual))
52
45
53
46
54 def test_handlers():
47 def test_handlers():
General Comments 0
You need to be logged in to leave comments. Login now