Lisp expression replacements with query-regexp-replace
I rarely use query-replace-regexp
's lisp expression replacement
feature, but I came upon a good use for it today!
Recently, I've been testing out org-srs for practicing Mandarin vocab.
So far, it works very well! When I asked to truncate the serialized
data which gets written to the Org files to reduce diff noise and to
make the state
column fit on my small laptop screen, the package
author kindly offered a workaround1, which causes this:
# Without workaround: #+NAME: srsitem:2d51efcd-8523-4432-b074-50d1ba4c45b3 | ! | timestamp | rating | stability | difficulty | state | |---+----------------------+--------+--------------------+-------------------+-----------| | | 2024-12-11T18:37:19Z | | 0.0 | 0.0 | :new | | | 2024-12-11T18:38:23Z | :again | 0.4072 | 7.2102 | :learning | | | 2024-12-11T18:39:05Z | :easy | 0.9375660842587888 | 6.078123501986166 | :review | | | 2024-12-14T07:07:08Z | :easy | 16.133939701409084 | 4.972537594025855 | :review | | * | 2024-12-30T07:07:08Z | | | | |
to become this:
# With workaround: #+NAME: srsitem:2d51efcd-8523-4432-b074-50d1ba4c45b3 | ! | timestamp | rating | stability | difficulty | state | |---+----------------------+--------+-----------+------------+-----------| | | 2024-12-11T18:37:19Z | | 0.0 | 0.0 | :new | | | 2024-12-11T18:38:23Z | :again | 0.41 | 7.21 | :learning | | | 2024-12-11T18:39:05Z | :easy | 0.94 | 6.08 | :review | | | 2024-12-14T07:07:08Z | :easy | 16.13 | 4.97 | :review | | * | 2024-12-30T07:07:08Z | | | | |
However, I already had some existing data in my chinese.org
file.
To truncate that data, I used this lisp expression replacement with
query-replace-regexp
:
[0-9]+\.\([0-9]+\) → \,(if (length> \1 2) (format "%0.02f" \#0) \0)
The regexp matches the numbers in the stability
and difficulty
columns. My chinese.org
file conveniently contains no other numbers
in decimal-point notation. The lisp expression checks if the part
after the decimal point contains more than two numbers, since I don't
want 0.0
to become 0.00
. If it does, then the format
expression
rounds it to two decimal places. Otherwise, the match is left as-is.
Note that \#0
in the replacement text converts the match string to a
number, which is required by the %f
format type specifier.
After replacing all of the numbers in the buffer, I ran a quick
keyboard macro to align all of the srsitem
tables to fit the
narrower contents, but I'll leave that as an exercise to the reader.
I hope this helps you. Feel free to contact me with suggestions, corrections, or questions!
Footnotes:
Workaround to truncate the data:
(cl-defmethod org-srs-algorithm-repeat :around ((_ fsrs-scheduler) _) (let ((output (cl-call-next-method))) (setf (alist-get 'stability output) (format "%.02f" (alist-get 'stability output)) (alist-get 'difficulty output) (format "%.02f" (alist-get 'difficulty output))) output))