|
|
|
|
|
|
Python Mode Frequently Asked Questions
- Why does font-lock sometimes get confused?
There are two problems that are generally at the root of
font-lock (syntax highlighting) problems in Python mode. Neither
are actually caused -- or fixable -- by python-mode.el, but you
should be aware of them so that you can implement the necessary
workarounds in your own code.
First, you should understand some basics of the way
X/Emacs1
parsing code in language modes. Most parsing for indentation and
font-locking is performed by built-in primitives driven by a data
structure called a syntax table. The main thing
to know about syntax tables is that they describe characters in
the language that delineate comments, strings,
parentheses expressions, etc.. The latter include such things as
(...) [...] {...} and possibly <...> (the first three being fairly
common in Python code). Also understand that syntax tables are
pretty simple structures; for example they can't be taught to
recognize Python's triple quoted strings (TQS). More on this
below.
|
These built-in primitives are used for most parsing because
they're fast; much faster than doing the same thing in Lisp.
Think of the difference between running pure Python code and
running code in a C extension. And for font-lock, the problem is
even worse. It would be so slow as to be useless if it were all
done in Lisp. Pymode does need to define such things as the
Python keywords and a few other regular expressions, but these
don't impact performance much.
So you can probably guess at least one thing that can confuse
X/Emacs: triple quoted strings. In fact, X/Emacs doesn't even
recognize TQS; for example the following Python code:
"""This is a documentation string."""
is parsed as three consecutive strings:
""
"This is a documentation string."
""
So you can see that if you were to embed a " character in
that docstring, X/Emacs would get confused because you'd have an
unbalanced string in there. This is more easily seen with this
example:
'''If I were you I wouldn't write it this way.'''
because this is parsed as:
''
'If I were you I wouldn'
t write it this way.
''
'
Yikes! That last quote leaves everything that follows inside a
string! The work arounds for this problem are simple. Either put a
backslash in front of the quote in wouldn't, or use a
DQTQS (double quote triple quoted string): """. Of course
you might have a docstring that contains both embedded single and
double quotes; in that case you'll need to backslash escape one or
the other style of embedded quotes, or always make sure that your
embedded quotes are balanced. For example, the following should
work just fine:
"""You might "want" to do it this way."""
or, as a last resort, use this gross hack:
'''Here is a triple quoted string.
This shouldn't be written this way.
''' # For Emacs -> '
Here, the last line acts like a comment to Python, and the final
quote closes the string for X/Emacs.
A second problem is, AFAIK, only apparent on XEmacs 20 and 21.
XEmacs has a kudge in its builtin parsing routines which
short-circuits the search for the beginning of a top-level function
definition. XEmacs looks for a parenthesis (also square or curly
brace) in column zero somewhere higher up in the file. This makes
a lot of sense for C and Lisp, but really sucks for Python, which
doesn't use parens in column zero to start a function definition.
Unfortunately, there's no way to turn this off for Python mode
buffers. Further, this short-circuit is triggered even if the
paren is inside a TQS!. The only answer here is to backslash
escape the parenthesis, or move it out of column zero.
1When I say X/Emacs I'm using a generic term that
includes both XEmacs and the
Free Software Foundation's version of
Emacs. When I need to refer to a specific version I'll use
XEmacs or Emacs respectively.