I have a local abbrev table set up in a file. I have an abbrev that has the "+" character. By default, abbrev will not expand this abbrev because it sees "+" as a word boundary.

The docs say this can be resolved with the :regexp property.

I tried it out. Consider this setup:

(set-local-abbrevs '(
             ("mse" "mean square error" nil)
             ("wlog" "without loss of generality" nil)
             ("++" "\\+" nil)

(defvar my-abbrev-regexp
  ;; "\\([0-9A-Za-z._-]+\\)"

(abbrev-table-put local-abbrev-table :regexp  my-abbrev-regexp)

Let's for a minute forget the abbrev with the "+" character and try to expand "wlog". If I comment out the abbrev-table-put line, it expands it just fine when I press SPC. If I uncomment it, then I cannot get "wlog" to expand. I tried both regular expressions shown, both with and without the "+" quantifier.

I also tried the suggested solution here, adding the "<" character to the regexp, and it still doesn't expand.

Edit: Apparently set-local-abbrevs is a custom function I had in my config, taken from the Emacs Wiki. It creates a local abbrev table. Below is the definition.

(defun set-local-abbrevs (abbrevs)
    "Add ABBREVS to `local-abbrev-table' and make it buffer local.
     ABBREVS should be a list of abbrevs as passed to `define-abbrev-table'.
     The `local-abbrev-table' will be replaced by a copy with the new 
     abbrevs added, so that it is not the same as the abbrev table used
     in other buffers with the same `major-mode'."
    (let* ((bufname (buffer-name))
           (prefix (substring (md5 bufname) 0 (length bufname)))
           (tblsym (intern (concat prefix "-abbrev-table"))))
      (set tblsym (copy-abbrev-table local-abbrev-table))
      (dolist (abbrev abbrevs)
          (define-abbrev (eval tblsym)
            (car abbrev)
            (cadr abbrev)
            (caddr abbrev)))
    (setq-local local-abbrev-table (eval tblsym))))

I'll examine the definition in detail later, but a quick glance isn't finding an obvious cause for my problems.

Update: OK, Tyler's solution works if I put the string verbatim in abbrev-table-put, but not if I put it in the my-abbrev-regexp variable. Likely the number of backslashes?

Now that I have "wlog" working, I still can't get ++ to expand.My regexp is \\<\\([+[:word:]]+\\). Ideas?

  • What is set-local-abbrevs? It does not seem to be defined in my Emacs.
    – NickD
    Apr 24, 2023 at 20:47
  • 1
    Good catch. Apparently I got it from the Emacs Wiki. I've updated the question with the details.
    – Beetle B.
    Apr 25, 2023 at 1:25
  • Maybe not a bug: @Tyler's answer in the linked question fingers just this problem and modifies the regexp to do a greedy match supposedly - but I haven't tried it out to make sure that it works yet.
    – NickD
    Apr 25, 2023 at 12:04
  • @Tyler's answer works fine: it extends the match to the beginning of the word. So the simple examples (mse, wlog) work fine. Now to extend it...
    – NickD
    Apr 25, 2023 at 12:19
  • The backward search in abbrev--before-point (looking-back re (line-beginning-position)) is non-greedy, so it will stop e.g. at the g of wlog instead of consuming as much as possible (i.e. all of wlog). You can test by changing that line to add a t as a third argument which makes the search greedy. I thought this was a bug at first, but as the previous comments make clear, I think you have to specify the regexp as in @Tyler's answer to the linked question.
    – NickD
    Apr 25, 2023 at 15:25


Your Answer

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

Browse other questions tagged or ask your own question.