I want to write a mode for the Cadabra 2 computer algebra system, which has Python-like syntax, with an exception of having the hash character # as a wild card in expressions, in addition to being a comment starter like in regular Python. Consider the following code:

\dalembert{ A?? }::LaTeXForm(\Box A??).

{ \mu, \nu }::Indices(vector).
{ A_{\mu} }::Depends(\partial{#}).

# QED Lagrangian
lagrangian:= (a/2) A_{\mu} \dalembert{ A_{\mu} }
    + (b/2) A_{\mu} \partial_{\nu}{\partial_{\mu}{ A_{\nu} }}
    + (1/2) m**2 A_{\mu} * A^{\mu};

Here, the QED Lagrangian line is a comment, but }::Derivative. is not. I want Emacs to interpret # as a comment delimiter only if it is not enclosed by curly or regular braces, and am struggling to implement that. The way I believe it should be done is with the syntax propertization function:

(define-derived-mode my-cadabra2-mode python-mode "cadabra2 mode"
  "Major mode for Cadabra 2 computer algebra system"
  (setq-local font-lock-defaults '((my-cadabra2-font-lock-keywords)))
  (setq-local syntax-propertize-function
              (syntax-propertize-rules ("\\(?<!{\s*\\)#\\(?!\s*}\\)" (1 "< ")))))

I believe my regular expression is correct, it should match # if not preceded by { and not followed by } with any whitespace in between. Emacs still uses any hash as a comment starter however.

How do I implement this properly?

  • 1
    Well, just trying to eval your function in my *scratch* buffer gives an (invalid-regexp) in your argument to syntax-propetize-rules.
    – nega
    2 days ago
  • 1
    Looks like you've got a negative-lookbehind and a negative-lookahead, both of which aren't supported. Also it looks like you're trying to use \s to match whitespace. You want \s- instead. See emacswiki.org/emacs/RegularExpression for a good primer on emacs regexes.
    – nega
    2 days ago


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.