5

Q: how can I change the syntax of a character for a single function?

In text-mode and its derivatives, the ' character has word syntax rather than, say punctuation or string quote syntax. That's a problem when using abbrev-mode, as I would like the ' character to fire the abbrev when I'm using a possessive.

For example, if the abbrev "pres" expands to "president" and I want to write the "president's cat", I'd expect to be able to type p r e s ' s, where "pres" expands automatically to "president" when I hit '.

Now: I don't want to change the syntax for ' globally or permanently, because I don't want to interfere with any other functions that depend on ' having word syntax. I tried the following:

(defadvice self-insert-command (around testing activate)
  (with-syntax-table (copy-syntax-table (syntax-table))
    (modify-syntax-entry ?' "\"")
    ad-do-it))

Two problems.

First: although it does fire the abbrev as expected, smartparens-mode complains every second time the abbrev fires (really: it's every second time). That's a tangent on the main point, however.

Second, and more importantly: this advice seems awfully costly for a function that gets invoked on every insertion command. It calls up the syntax table, copies it, modifies it, uses it, and then restores the original syntax table. That seems awfully silly when I really only care about one character, which leads me to suspect I'm going about this wrong.

Is there a smarter way to do this? (Note that I'm most interested in temporarily changing the syntax of a character and am using the abbrev example to motivate it.)

5
  • Why not change the syntax for all of text-mode? What harm would it do? Also I would think that you should remove single quotes from smart parens for text-mode buffers. That would likely solve all the issues. May 18, 2015 at 23:41
  • @JordonBiondo: as I mentioned, I don't know which other functions depend on ' having word syntax. It certainly changes the behavior of commands like forward-word and backward-word, however, which is reason enough not to make the change permanent.
    – Dan
    May 18, 2015 at 23:46
  • Here is a link that contains code demonstrating how I do my own forward/backward word using a custom syntax table for the duration of a function. stackoverflow.com/q/18675201/2112489 However, I've never tried using defadvice to modify the syntax of an existing function. I use the same custom syntax table for my own delete-word function stackoverflow.com/a/20456861/2112489 .
    – lawlist
    May 19, 2015 at 1:04
  • The function abbrev--check-chars is the only function in the abbrev.el library that contains syntax tables. Do you think it might be helpful to modify that one function to use your own custom syntax table? I could be wrong, but I don't think you would really be interested in changing self-insert-command.
    – lawlist
    May 19, 2015 at 2:09
  • @lawlist: as I mention at the end, I'm using the abbrev issue to motivate the problem. I'm more interested in modifying the syntax, which I need to do for a different function. (In other words: I'm not looking to hack abbrev-mode.)
    – Dan
    May 19, 2015 at 2:15

1 Answer 1

2

Use macro with-syntax-table. You create a syntax table (e.g. inheriting from the current table), then change the syntax of any chars you want in that new table, then pass that table to with-syntax-table, wrapping your code (e.g. your function) with the macro. Within the context of the macro, your code will use the syntax table you specify.

(If you have an older Emacs version, which does not have macro with-syntax-table, then you need to switch to a new table and then switch back again (e.g. using unwind-protect).)

Alternatively, you can save and restore particular syntax settings, modifying the current table in between, using modify-syntax-entry.

3
  • Thanks, but the current example already uses with-syntax-table (although it creates a copy of the current table at each invocation rather than storing a copy in a state variable). I'm wondering if there's a lighter-weight way to alter syntax temporarily (ie, without setting and resetting the whole table and/or saving another table to a variable). If the answer to the latter question is "no" (or perhaps "not easily enough to justify"), I'll accept that as an answer.
    – Dan
    May 19, 2015 at 10:07
  • I updated the answer to mention that you can save & restore particular settings, modifying the table, instead of using a new table.
    – Drew
    May 19, 2015 at 13:13
  • Thanks -- I'll leave the question open for a bit to see if anyone has alternative suggestions, but from your answer, it looks like this is the main idiom.
    – Dan
    May 19, 2015 at 14:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.