##// END OF EJS Templates
Return command to the next prompt if help was called halfway through a command. Also, ? at the end of a comment should not trigger help.
Thomas Kluyver -
Show More
@@ -70,6 +70,8 b' import ast'
70 import codeop
70 import codeop
71 import re
71 import re
72 import sys
72 import sys
73 import tokenize
74 from StringIO import StringIO
73
75
74 # IPython modules
76 # IPython modules
75 from IPython.utils.text import make_quoted_expr
77 from IPython.utils.text import make_quoted_expr
@@ -155,6 +157,24 b' def remove_comments(src):'
155 """
157 """
156
158
157 return re.sub('#.*', '', src)
159 return re.sub('#.*', '', src)
160
161 def has_comment(src):
162 """Indicate whether an input line has (i.e. ends in, or is) a comment.
163
164 This uses tokenize, so it can distinguish comments from # inside strings.
165
166 Parameters
167 ----------
168 src : string
169 A single line input string.
170
171 Returns
172 -------
173 Boolean: True if source has a comment.
174 """
175 readline = StringIO(src).readline
176 toktypes = set(t[0] for t in tokenize.generate_tokens(readline))
177 return(tokenize.COMMENT in toktypes)
158
178
159
179
160 def get_input_encoding():
180 def get_input_encoding():
@@ -672,12 +692,19 b' _help_end_re = re.compile(r"""(%?'
672 def transform_help_end(line):
692 def transform_help_end(line):
673 """Translate lines with ?/?? at the end"""
693 """Translate lines with ?/?? at the end"""
674 m = _help_end_re.search(line)
694 m = _help_end_re.search(line)
675 if m is None:
695 if m is None or has_comment(line):
676 return line
696 return line
677 target = m.group(1)
697 target = m.group(1)
678 esc = m.group(3)
698 esc = m.group(3)
679 lspace = _initial_space_re.match(line).group(0)
699 lspace = _initial_space_re.match(line).group(0)
680 return _make_help_call(target, esc, lspace)
700 newline = _make_help_call(target, esc, lspace)
701
702 # If we're mid-command, put it back on the next prompt for the user.
703 if line.strip() != m.group(0):
704 newline += "; get_ipython().set_next_input(%s)" % \
705 make_quoted_expr(line.rstrip('?'))
706
707 return newline
681
708
682
709
683 class EscapedTransformer(object):
710 class EscapedTransformer(object):
@@ -25,6 +25,7 b' import nose.tools as nt'
25
25
26 # Our own
26 # Our own
27 from IPython.core import inputsplitter as isp
27 from IPython.core import inputsplitter as isp
28 from IPython.testing import tools as tt
28
29
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30 # Semi-complete examples (also used as tests)
31 # Semi-complete examples (also used as tests)
@@ -92,9 +93,7 b' def test_spaces():'
92 ('\tx', 1),
93 ('\tx', 1),
93 ('\t x', 2),
94 ('\t x', 2),
94 ]
95 ]
95
96 tt.check_pairs(isp.num_ini_spaces, tests)
96 for s, nsp in tests:
97 nt.assert_equal(isp.num_ini_spaces(s), nsp)
98
97
99
98
100 def test_remove_comments():
99 def test_remove_comments():
@@ -106,9 +105,19 b' def test_remove_comments():'
106 ('line # c \nline#c2 \nline\nline #c\n\n',
105 ('line # c \nline#c2 \nline\nline #c\n\n',
107 'line \nline\nline\nline \n\n'),
106 'line \nline\nline\nline \n\n'),
108 ]
107 ]
109
108 tt.check_pairs(isp.remove_comments, tests)
110 for inp, out in tests:
109
111 nt.assert_equal(isp.remove_comments(inp), out)
110 def test_has_comment():
111 tests = [('text', False),
112 ('text #comment', True),
113 ('text #comment\n', True),
114 ('#comment', True),
115 ('#comment\n', True),
116 ('a = "#string"', False),
117 ('a = "#string" # comment', True),
118 ('a #comment not "string"', True),
119 ]
120 tt.check_pairs(isp.has_comment, tests)
112
121
113
122
114 def test_get_input_encoding():
123 def test_get_input_encoding():
@@ -445,9 +454,10 b' syntax = \\'
445 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
454 ('%hist?', 'get_ipython().magic(u"pinfo %hist")'),
446 ('f*?', 'get_ipython().magic(u"psearch f*")'),
455 ('f*?', 'get_ipython().magic(u"psearch f*")'),
447 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
456 ('ax.*aspe*?', 'get_ipython().magic(u"psearch ax.*aspe*")'),
448 ('a = abc?', 'get_ipython().magic(u"pinfo abc")'),
457 ('a = abc?', 'get_ipython().magic(u"pinfo abc"); get_ipython().set_next_input(u"a = abc")'),
449 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe")'),
458 ('a = abc.qe??', 'get_ipython().magic(u"pinfo2 abc.qe"); get_ipython().set_next_input(u"a = abc.qe")'),
450 ('a = *.items?', 'get_ipython().magic(u"psearch *.items")'),
459 ('a = *.items?', 'get_ipython().magic(u"psearch *.items"); get_ipython().set_next_input(u"a = *.items")'),
460 ('a*2 #comment?', 'a*2 #comment?'),
451 ],
461 ],
452
462
453 # Explicit magic calls
463 # Explicit magic calls
@@ -513,11 +523,11 b' syntax_ml = \\'
513
523
514
524
515 def test_assign_system():
525 def test_assign_system():
516 transform_checker(syntax['assign_system'], isp.transform_assign_system)
526 tt.check_pairs(isp.transform_assign_system, syntax['assign_system'])
517
527
518
528
519 def test_assign_magic():
529 def test_assign_magic():
520 transform_checker(syntax['assign_magic'], isp.transform_assign_magic)
530 tt.check_pairs(isp.transform_assign_magic, syntax['assign_magic'])
521
531
522
532
523 def test_classic_prompt():
533 def test_classic_prompt():
@@ -532,34 +542,34 b' def test_ipy_prompt():'
532 transform_checker(example, isp.transform_ipy_prompt)
542 transform_checker(example, isp.transform_ipy_prompt)
533
543
534 def test_end_help():
544 def test_end_help():
535 transform_checker(syntax['end_help'], isp.transform_help_end)
545 tt.check_pairs(isp.transform_help_end, syntax['end_help'])
536
546
537 def test_escaped_noesc():
547 def test_escaped_noesc():
538 transform_checker(syntax['escaped_noesc'], isp.transform_escaped)
548 tt.check_pairs(isp.transform_escaped, syntax['escaped_noesc'])
539
549
540
550
541 def test_escaped_shell():
551 def test_escaped_shell():
542 transform_checker(syntax['escaped_shell'], isp.transform_escaped)
552 tt.check_pairs(isp.transform_escaped, syntax['escaped_shell'])
543
553
544
554
545 def test_escaped_help():
555 def test_escaped_help():
546 transform_checker(syntax['escaped_help'], isp.transform_escaped)
556 tt.check_pairs(isp.transform_escaped, syntax['escaped_help'])
547
557
548
558
549 def test_escaped_magic():
559 def test_escaped_magic():
550 transform_checker(syntax['escaped_magic'], isp.transform_escaped)
560 tt.check_pairs(isp.transform_escaped, syntax['escaped_magic'])
551
561
552
562
553 def test_escaped_quote():
563 def test_escaped_quote():
554 transform_checker(syntax['escaped_quote'], isp.transform_escaped)
564 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote'])
555
565
556
566
557 def test_escaped_quote2():
567 def test_escaped_quote2():
558 transform_checker(syntax['escaped_quote2'], isp.transform_escaped)
568 tt.check_pairs(isp.transform_escaped, syntax['escaped_quote2'])
559
569
560
570
561 def test_escaped_paren():
571 def test_escaped_paren():
562 transform_checker(syntax['escaped_paren'], isp.transform_escaped)
572 tt.check_pairs(isp.transform_escaped, syntax['escaped_paren'])
563
573
564
574
565 class IPythonInputTestCase(InputSplitterTestCase):
575 class IPythonInputTestCase(InputSplitterTestCase):
General Comments 0
You need to be logged in to leave comments. Login now