Add gist on using rx inside lisp-data

This commit is contained in:
Bram Schoenmakers 2024-05-26 20:54:36 +02:00
parent fd3d099105
commit 0dfe23c528
Signed by: bram
GPG key ID: 0CCD19DFDC63258F
2 changed files with 83 additions and 0 deletions

View file

@ -1140,6 +1140,50 @@ Which covers my (potential) GPG/SSH usage within Emacs. Now, anytime a I perform
(run-with-timer nil (* 2 60 60) (lambda () (run-with-idle-timer 120 nil 'elfeed-update))))
#+end_src
* Use rx style regular expressions in Lisp data files
#+begin_src org :noweb no :tangle gists/rx-in-lisp-data.org
Plain regular expressions are difficult to write and sometimes difficult to read, therefore I prefer constructing regular expressions with the =rx= macro. It will take care of the special characters and the proper escaping, as I can't remember those details that well. With =rx=, you construct regular expressions in a Lisp format, e.g.:
,#+begin_src elisp
(rx string-start (or "foo" "bar") string-end)
,#+end_src
,#+RESULTS:
: \`\(?:bar\|foo\)\'
It's not only more readable (in my opinion), but it's also easier to construct with all the Lisp writing tools that can be used within Emacs (e.g. paredit or puni).
However, using =rx= is not always possible. Lisp data files may contain regular expressions but they are treated as data and not as executable code.
One prime example is elfeed-score: an Emacs package that allows you to write scoring rules for elfeed entries. Scoring rules are defined with an Lisp data file, and a rule may allow regular expressions but they have to be written out verbatim.
Luckily there's a work-around with Org Mode:
- Write the scoring rules in an =lisp-data= source block.
- Tangle the file to a location that is read by the elfeed-score package (see variable ~elfeed-score-score-file~).
- For the regular expression we use a small =elisp= block as follows:
,#+begin_src org
,,#+name: rx
,,#+begin_src elisp :var expression='any :tangle=no
(string-replace "\\" "\\\\" (format "\"%s\"" (rx-to-string expression)))
,,#+end_src
,#+end_src
It accepts an /expression/ that is a Lisp form that =rx= accepts. It is converted to a string, surrounded by quotes and since we use it in a Lisp string, backslashes should be doubled.
- By naming the source block =rx= we can call it from other source blocks:
,#+begin_src org
,,#+begin_src lisp-data :tangle elfeed-scores.eld :noweb yes
(("title" (:text <<rx '(or "foo" "bar")>> :value 1 :type r)))
,,#+end_src
,#+end_src
Upon tangling, the <<rx ...>> is converted to a regex string and therefore readable by elfeed-score.
#+end_src
* Meta
** License

39
gists/rx-in-lisp-data.org Normal file
View file

@ -0,0 +1,39 @@
Plain regular expressions are difficult to write and sometimes difficult to read, therefore I prefer constructing regular expressions with the =rx= macro. It will take care of the special characters and the proper escaping, as I can't remember those details that well. With =rx=, you construct regular expressions in a Lisp format, e.g.:
#+begin_src elisp
(rx string-start (or "foo" "bar") string-end)
#+end_src
#+RESULTS:
: \`\(?:bar\|foo\)\'
It's not only more readable (in my opinion), but it's also easier to construct with all the Lisp writing tools that can be used within Emacs (e.g. paredit or puni).
However, using =rx= is not always possible. Lisp data files may contain regular expressions but they are treated as data and not as executable code.
One prime example is elfeed-score: an Emacs package that allows you to write scoring rules for elfeed entries. Scoring rules are defined with an Lisp data file, and a rule may allow regular expressions but they have to be written out verbatim.
Luckily there's a work-around with Org Mode:
- Write the scoring rules in an =lisp-data= source block.
- Tangle the file to a location that is read by the elfeed-score package (see variable ~elfeed-score-score-file~).
- For the regular expression we use a small =elisp= block as follows:
#+begin_src org
,#+name: rx
,#+begin_src elisp :var expression='any :tangle=no
(string-replace "\\" "\\\\" (format "\"%s\"" (rx-to-string expression)))
,#+end_src
#+end_src
It accepts an /expression/ that is a Lisp form that =rx= accepts. It is converted to a string, surrounded by quotes and since we use it in a Lisp string, backslashes should be doubled.
- By naming the source block =rx= we can call it from other source blocks:
#+begin_src org
,#+begin_src lisp-data :tangle elfeed-scores.eld :noweb yes
(("title" (:text <<rx '(or "foo" "bar")>> :value 1 :type r)))
,#+end_src
#+end_src
Upon tangling, the <<rx ...>> is converted to a regex string and therefore readable by elfeed-score.