reddit / emacs

Elegant way to parse lines of a buffer depending on characters at start of line?

cottasteel · 2022-06-30 08:57
I made an elisp function for parsing some org table-like data in a buffer. My function scans each line of the buffer, and depending on the characters at the start of the line, it jumps to a certain point in the line and inserts some text. The relevant part of the function is below: (beginning-of-buffer) (while (not (eobp)) (cond ((looking-at header-re-1) (search-forward marker1 nil nil count1) (insert text1)) ((looking-at header-re-2) (search-forward marker2 nil nil count2) (insert text2)) ((looking-at header-re-3) (search-forward marker3 nil nil count3) (insert text3)) (t)) (forward-line)) My function works okay, but it seems a little inelegant, because the `cond` consists of three blocks of `looking-at` followed by `search-forward` followed by `insert`, only with different arguments each time. Is there a more clever way to do this that only needs one call to `looking-at`, `search-forward`, and `insert`, using something like, say `pcase`?
nv-elisp · 2022-06-30 09:04
You don't need clever. Store values that are dependent on the regexp in variables. Set those variables during your cond. After the body of the cond call what you're repeating now with the variables once.
cottasteel · 2022-06-30 09:13
Yeah that can work, or alternatively I could make a helper function does `search-forward` and `insert`. I was looking to see if there is a way to also avoid the multiple calls to `looking-at`.
_viz_ · 2022-06-30 17:02
You could try something like (looking-at "re1\\\\|re2\\\\|...") then compare against the match-string
github-alphapapa · 2022-07-01 05:44
You could do as viz suggests, but keep in mind that Emacs's regexp matching is very fast, so I would just use it. If you want to reduce repetition in your code, you could use `cl-labels` to define a function that does what each cond does (or `cl-flet`, or `cl-macrolet`, etc).