What I'm trying to do:
- Load a named org-mode file in the background
- Find a named heading in that file
- Locate the first list under that heading
- Get the names (as they appear in Emacs when I write them) of all items from that list as a ELisp list
- Return one of those randomly.
Basically, I'm trying to get a random list entry from a named heading in a named file.
My input file:
* Heading1
- Item1
- Item2
- Item3
* Heading2
From this, I want to be able to call a function with the name of the above file, a heading name ("Heading1") and get the following back:
("Item1" "Item2" "Item3")
Then, I'd easily be able to select one of those randomly (but I haven't gotten that far yet).
How I'm trying to do it
I have some ELisp experience, but not much. So as an experiment, I tried to get ChatGPT 4 to help me write this. I asked it to do it in chunks, which I have then put together.
I'm parsing the input file into an AST.
Anyway, here's the code I have so far:
(defun urpg-load-ast (filename)
"Load an org-file in the background and return its AST."
(with-temp-buffer
(insert-file-contents filename)
(org-element-parse-buffer)))
(defun urpg-find-first-list-under-heading (ast target-heading)
"Find the first list under a named heading in an AST and return it."
(let (found-heading)
(org-element-map ast 'headline
(lambda (headline)
(when (and (not found-heading)
(string= (org-element-property :raw-value headline)
target-heading))
(setq found-heading t)
(org-element-map headline 'plain-list
(lambda (plain-list)
plain-list)))))))
(setq ast (urpg-load-ast "~/test-file.org"))
(setq items (urpg-find-first-list-under-heading ast "Heading1"))
items
The output I get from running this
(((plain-list (:type unordered :begin 13 :end 37 :contents-begin 13 :contents-end 37 :structure ... ...) (item ... ...) (item ... ...) (item ... ...))))
The problem I'm facing
This gets as far as returning some sort of AST entry for the list I'm looking for in the input file. But my problem is I have no idea how to handle that AST entry - as you can see above, it has a bunch of data (all of which is not displayed), and I'm not sure how to extract the data I want - the names of the items. As I said above, I basically want this:
("Item1" "Item2" "Item3")