5252from ConfigParser import ConfigParser , NoSectionError , NoOptionError
5353
5454# These are used for syntax hilighting.
55- from pygments import highlight
55+ from pygments import format
5656from pygments .lexers import PythonLexer
57+ from pygments .token import Token
5758from bpython .formatter import BPythonFormatter
59+ from itertools import chain
5860
5961# This for import completion
6062from bpython import importcompletion
@@ -119,8 +121,6 @@ def readlines(self, x):
119121#
120122# Tab completion does not work if not at the end of the line.
121123#
122- # Triple-quoted strings over multiple lines are not colourised correctly.
123- #
124124# Numerous optimisations can be made but it seems to do all the lookup stuff
125125# fast enough on even my crappy server so I'm not too bothered about that
126126# at the moment.
@@ -162,6 +162,18 @@ def make_colours():
162162 return c
163163
164164
165+ def next_token_inside_string (s , inside_string ):
166+ """Given a code string s and an initial state inside_string, return
167+ whether the next token will be inside a string or not."""
168+ for token , value in PythonLexer ().get_tokens (s ):
169+ if token is Token .String and value in ['"""' , "'''" , '"' , "'" ]:
170+ if not inside_string :
171+ inside_string = value
172+ elif value == inside_string :
173+ inside_string = False
174+ return inside_string
175+
176+
165177class Interpreter (code .InteractiveInterpreter ):
166178
167179 def __init__ (self ):
@@ -188,6 +200,7 @@ def showsyntaxerror(self, filename=None):
188200 sys .last_type = type
189201 sys .last_value = value
190202 if filename and type is SyntaxError :
203+ self .inside_string = False
191204 # Work hard to stuff the correct filename in the exception
192205 try :
193206 msg , (dummy_filename , lineno , offset , line ) = value
@@ -296,6 +309,7 @@ def __init__(self, scr, interp, statusbar=None, idle=None):
296309 self .matches = []
297310 self .argspec = None
298311 self .s = ''
312+ self .inside_string = False
299313 self .list_win_visible = False
300314 self ._C = {}
301315 sys .stdin = FakeStdin (self )
@@ -1377,6 +1391,9 @@ def lf(self):
13771391 for _ in range (self .cpos ):
13781392 self .mvc (- 1 )
13791393
1394+ self .inside_string = next_token_inside_string (self .s ,
1395+ self .inside_string )
1396+
13801397 self .echo ("\n " )
13811398
13821399 def addstr (self , s ):
@@ -1398,7 +1415,16 @@ def print_line(self, s, clr=False):
13981415 clr = True
13991416
14001417 if OPTS .syntax :
1401- o = highlight (s , PythonLexer (), BPythonFormatter ())
1418+ if self .inside_string :
1419+ # A string started in another line is continued in this
1420+ # line
1421+ tokens = PythonLexer ().get_tokens (self .inside_string + s )
1422+ token , value = tokens .next ()
1423+ if token is Token .String .Doc :
1424+ tokens = chain ([(Token .String , value [3 :])], tokens )
1425+ else :
1426+ tokens = PythonLexer ().get_tokens (s )
1427+ o = format (tokens , BPythonFormatter ())
14021428 else :
14031429 o = s
14041430
0 commit comments