(or emacs irrelevant)

Saving match data in-between Elisp evals

This is a new feature I've added recently to lispy that's useful when debugging regex-related code.

The gist of it is that the match data is a single global object in Emacs. So if you call string-match with your C-x C-e, there's no guarantee that e.g. match-beginning will return the proper thing with another C-x C-e, since any package running in your Emacs could mess with the match data (packages that use timers or post-command hooks etc.).

After getting annoyed by this a few times, I've finally added a fail-safe to e (lispy-eval) and p (lispy-eval-other-window). Here's how it looks like:

(defvar lispy-eval-match-data nil)

(defun lispy--eval-elisp-form (form lexical)
  "Eval FORM and return its value.
If LEXICAL is t, evaluate using lexical scoping.
Restore and save `lispy-eval-match-data' appropriately,
so that no other packages disturb the match data."
  (let (val)
    (fset '\, #'identity)
    (set-match-data lispy-eval-match-data)
    (setq val (eval form lexical))
    (setq lispy-eval-match-data (match-data))
    (fset '\, nil)
    val))

There's also a little dance of ignoring comma operators in the rare case when I want to eval inside a backquoted list. The two functions that you can take away from this exercise are match-data and set-match-data which appropriately return and store a list of integers. Keeping the string separate from the regex match is a neat way to improve performance.