The other day, I wrote about Xah Lee’s post on temporary syntax tables and the with-syntax-table
macro. Subsequently, Lee discovered a nasty side effect that he wrote about on the G+ Emacs Community site. The problem was that his code
(with-syntax-table (standard-syntax-table) (modify-syntax-entry ?\« "(»") (modify-syntax-entry ?\» ")«") ;; … )
modified the original standard syntax table for all buffers.
The problem is (standard-syntax-table)
doesn’t copy the standard syntax table; it just returns a pointer to the standard syntax table object. This is the same thing that happens if you assign a list to a variable:
(setq x '(1 2 3)) (setq y x) (setf (car y) 5) (message "x is %s" x)
returns
x is (5 2 3)
because x
and y
refer to the same object.
What we need to do is first make a copy of the standard syntax table. Happily, the copy-syntax-table
function does just that1 so if we evaluate
(with-syntax-table (copy-syntax-table) (modify-syntax-entry ?‹ "(›") (describe-syntax))
the ‹ is described as an open bracket but if we open a new fundamental buffer and call describe-syntax
it is described as punctuation, as expected.
Lee solved this problem by creating a new syntax table with make-syntax-table
and added his definitions to it. You might think that Lee’s solution is incorrect because the other syntax definitions will be missing from his new table but it is correct because make-syntax-table
will create a table that inherits from the standard syntax table (or whatever table you specify).
Footnotes:
copy-syntax-table
copies standard syntax table by default but you can specify a table explicitly if you want to start with some other table.