##// END OF EJS Templates
Fix split_user_input to correctly handle %% escape for cell magics.
Fernando Perez -
Show More
@@ -1,137 +1,137 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Simple utility for splitting user input. This is used by both inputsplitter and
3 Simple utility for splitting user input. This is used by both inputsplitter and
4 prefilter.
4 prefilter.
5
5
6 Authors:
6 Authors:
7
7
8 * Brian Granger
8 * Brian Granger
9 * Fernando Perez
9 * Fernando Perez
10 """
10 """
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Copyright (C) 2008-2011 The IPython Development Team
13 # Copyright (C) 2008-2011 The IPython Development Team
14 #
14 #
15 # Distributed under the terms of the BSD License. The full license is in
15 # Distributed under the terms of the BSD License. The full license is in
16 # the file COPYING, distributed as part of this software.
16 # the file COPYING, distributed as part of this software.
17 #-----------------------------------------------------------------------------
17 #-----------------------------------------------------------------------------
18
18
19 #-----------------------------------------------------------------------------
19 #-----------------------------------------------------------------------------
20 # Imports
20 # Imports
21 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
22
22
23 import re
23 import re
24 import sys
24 import sys
25
25
26 from IPython.utils import py3compat
26 from IPython.utils import py3compat
27 from IPython.utils.encoding import get_stream_enc
27 from IPython.utils.encoding import get_stream_enc
28
28
29 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
30 # Main function
30 # Main function
31 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
32
32
33 # RegExp for splitting line contents into pre-char//first word-method//rest.
33 # RegExp for splitting line contents into pre-char//first word-method//rest.
34 # For clarity, each group in on one line.
34 # For clarity, each group in on one line.
35
35
36 # WARNING: update the regexp if the escapes in interactiveshell are changed, as
36 # WARNING: update the regexp if the escapes in interactiveshell are changed, as
37 # they are hardwired in.
37 # they are hardwired in.
38
38
39 # Although it's not solely driven by the regex, note that:
39 # Although it's not solely driven by the regex, note that:
40 # ,;/% only trigger if they are the first character on the line
40 # ,;/% only trigger if they are the first character on the line
41 # ! and !! trigger if they are first char(s) *or* follow an indent
41 # ! and !! trigger if they are first char(s) *or* follow an indent
42 # ? triggers as first or last char.
42 # ? triggers as first or last char.
43
43
44 line_split = re.compile("""
44 line_split = re.compile("""
45 ^(\s*) # any leading space
45 ^(\s*) # any leading space
46 ([,;/%]|!!?|\?\??)? # escape character or characters
46 ([,;/%]|!!?|\?\??)? # escape character or characters
47 \s*(%?[\w\.\*]*) # function/method, possibly with leading %
47 \s*(%{0,2}[\w\.\*]*) # function/method, possibly with leading %
48 # to correctly treat things like '?%magic'
48 # to correctly treat things like '?%magic'
49 (.*?$|$) # rest of line
49 (.*?$|$) # rest of line
50 """, re.VERBOSE)
50 """, re.VERBOSE)
51
51
52
52
53 def split_user_input(line, pattern=None):
53 def split_user_input(line, pattern=None):
54 """Split user input into initial whitespace, escape character, function part
54 """Split user input into initial whitespace, escape character, function part
55 and the rest.
55 and the rest.
56 """
56 """
57 # We need to ensure that the rest of this routine deals only with unicode
57 # We need to ensure that the rest of this routine deals only with unicode
58 encoding = get_stream_enc(sys.stdin, 'utf-8')
58 encoding = get_stream_enc(sys.stdin, 'utf-8')
59 line = py3compat.cast_unicode(line, encoding)
59 line = py3compat.cast_unicode(line, encoding)
60
60
61 if pattern is None:
61 if pattern is None:
62 pattern = line_split
62 pattern = line_split
63 match = pattern.match(line)
63 match = pattern.match(line)
64 if not match:
64 if not match:
65 # print "match failed for line '%s'" % line
65 # print "match failed for line '%s'" % line
66 try:
66 try:
67 ifun, the_rest = line.split(None,1)
67 ifun, the_rest = line.split(None,1)
68 except ValueError:
68 except ValueError:
69 # print "split failed for line '%s'" % line
69 # print "split failed for line '%s'" % line
70 ifun, the_rest = line, u''
70 ifun, the_rest = line, u''
71 pre = re.match('^(\s*)(.*)',line).groups()[0]
71 pre = re.match('^(\s*)(.*)',line).groups()[0]
72 esc = ""
72 esc = ""
73 else:
73 else:
74 pre, esc, ifun, the_rest = match.groups()
74 pre, esc, ifun, the_rest = match.groups()
75
75
76 #print 'line:<%s>' % line # dbg
76 #print 'line:<%s>' % line # dbg
77 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
77 #print 'pre <%s> ifun <%s> rest <%s>' % (pre,ifun.strip(),the_rest) # dbg
78 return pre, esc or '', ifun.strip(), the_rest.lstrip()
78 return pre, esc or '', ifun.strip(), the_rest.lstrip()
79
79
80
80
81 class LineInfo(object):
81 class LineInfo(object):
82 """A single line of input and associated info.
82 """A single line of input and associated info.
83
83
84 Includes the following as properties:
84 Includes the following as properties:
85
85
86 line
86 line
87 The original, raw line
87 The original, raw line
88
88
89 continue_prompt
89 continue_prompt
90 Is this line a continuation in a sequence of multiline input?
90 Is this line a continuation in a sequence of multiline input?
91
91
92 pre
92 pre
93 Any leading whitespace.
93 Any leading whitespace.
94
94
95 esc
95 esc
96 The escape character(s) in pre or the empty string if there isn't one.
96 The escape character(s) in pre or the empty string if there isn't one.
97 Note that '!!' and '??' are possible values for esc. Otherwise it will
97 Note that '!!' and '??' are possible values for esc. Otherwise it will
98 always be a single character.
98 always be a single character.
99
99
100 ifun
100 ifun
101 The 'function part', which is basically the maximal initial sequence
101 The 'function part', which is basically the maximal initial sequence
102 of valid python identifiers and the '.' character. This is what is
102 of valid python identifiers and the '.' character. This is what is
103 checked for alias and magic transformations, used for auto-calling,
103 checked for alias and magic transformations, used for auto-calling,
104 etc. In contrast to Python identifiers, it may start with "%" and contain
104 etc. In contrast to Python identifiers, it may start with "%" and contain
105 "*".
105 "*".
106
106
107 the_rest
107 the_rest
108 Everything else on the line.
108 Everything else on the line.
109 """
109 """
110 def __init__(self, line, continue_prompt=False):
110 def __init__(self, line, continue_prompt=False):
111 self.line = line
111 self.line = line
112 self.continue_prompt = continue_prompt
112 self.continue_prompt = continue_prompt
113 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
113 self.pre, self.esc, self.ifun, self.the_rest = split_user_input(line)
114
114
115 self.pre_char = self.pre.strip()
115 self.pre_char = self.pre.strip()
116 if self.pre_char:
116 if self.pre_char:
117 self.pre_whitespace = '' # No whitespace allowd before esc chars
117 self.pre_whitespace = '' # No whitespace allowd before esc chars
118 else:
118 else:
119 self.pre_whitespace = self.pre
119 self.pre_whitespace = self.pre
120
120
121 def ofind(self, ip):
121 def ofind(self, ip):
122 """Do a full, attribute-walking lookup of the ifun in the various
122 """Do a full, attribute-walking lookup of the ifun in the various
123 namespaces for the given IPython InteractiveShell instance.
123 namespaces for the given IPython InteractiveShell instance.
124
124
125 Return a dict with keys: {found, obj, ospace, ismagic}
125 Return a dict with keys: {found, obj, ospace, ismagic}
126
126
127 Note: can cause state changes because of calling getattr, but should
127 Note: can cause state changes because of calling getattr, but should
128 only be run if autocall is on and if the line hasn't matched any
128 only be run if autocall is on and if the line hasn't matched any
129 other, less dangerous handlers.
129 other, less dangerous handlers.
130
130
131 Does cache the results of the call, so can be called multiple times
131 Does cache the results of the call, so can be called multiple times
132 without worrying about *further* damaging state.
132 without worrying about *further* damaging state.
133 """
133 """
134 return ip._ofind(self.ifun)
134 return ip._ofind(self.ifun)
135
135
136 def __str__(self):
136 def __str__(self):
137 return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest)
137 return "LineInfo [%s|%s|%s|%s]" %(self.pre, self.esc, self.ifun, self.the_rest)
@@ -1,32 +1,35 b''
1 # coding: utf-8
1 # coding: utf-8
2 from IPython.core.splitinput import split_user_input
2 from IPython.core.splitinput import split_user_input
3 from IPython.testing import tools as tt
3 from IPython.testing import tools as tt
4 from IPython.utils import py3compat
4 from IPython.utils import py3compat
5
5
6 tests = [
6 tests = [
7 ('x=1', ('', '', 'x', '=1')),
7 ('x=1', ('', '', 'x', '=1')),
8 ('?', ('', '?', '', '')),
8 ('?', ('', '?', '', '')),
9 ('??', ('', '??', '', '')),
9 ('??', ('', '??', '', '')),
10 (' ?', (' ', '?', '', '')),
10 (' ?', (' ', '?', '', '')),
11 (' ??', (' ', '??', '', '')),
11 (' ??', (' ', '??', '', '')),
12 ('??x', ('', '??', 'x', '')),
12 ('??x', ('', '??', 'x', '')),
13 ('?x=1', ('', '?', 'x', '=1')),
13 ('?x=1', ('', '?', 'x', '=1')),
14 ('!ls', ('', '!', 'ls', '')),
14 ('!ls', ('', '!', 'ls', '')),
15 (' !ls', (' ', '!', 'ls', '')),
15 (' !ls', (' ', '!', 'ls', '')),
16 ('!!ls', ('', '!!', 'ls', '')),
16 ('!!ls', ('', '!!', 'ls', '')),
17 (' !!ls', (' ', '!!', 'ls', '')),
17 (' !!ls', (' ', '!!', 'ls', '')),
18 (',ls', ('', ',', 'ls', '')),
18 (',ls', ('', ',', 'ls', '')),
19 (';ls', ('', ';', 'ls', '')),
19 (';ls', ('', ';', 'ls', '')),
20 (' ;ls', (' ', ';', 'ls', '')),
20 (' ;ls', (' ', ';', 'ls', '')),
21 ('f.g(x)', ('', '', 'f.g', '(x)')),
21 ('f.g(x)', ('', '', 'f.g', '(x)')),
22 ('f.g (x)', ('', '', 'f.g', '(x)')),
22 ('f.g (x)', ('', '', 'f.g', '(x)')),
23 ('?%hist', ('', '?', '%hist', '')),
23 ('?%hist1', ('', '?', '%hist1', '')),
24 ('?%%hist2', ('', '?', '%%hist2', '')),
25 ('??%hist3', ('', '??', '%hist3', '')),
26 ('??%%hist4', ('', '??', '%%hist4', '')),
24 ('?x*', ('', '?', 'x*', '')),
27 ('?x*', ('', '?', 'x*', '')),
25 ]
28 ]
26 if py3compat.PY3:
29 if py3compat.PY3:
27 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
30 tests.append((u"Pérez Fernando", (u'', u'', u'Pérez', u'Fernando')))
28 else:
31 else:
29 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
32 tests.append((u"Pérez Fernando", (u'', u'', u'P', u'érez Fernando')))
30
33
31 def test_split_user_input():
34 def test_split_user_input():
32 return tt.check_pairs(split_user_input, tests)
35 return tt.check_pairs(split_user_input, tests)
General Comments 0
You need to be logged in to leave comments. Login now