reddit / emacs

How to write an elisp function that takes varied-length parameters for emacs-sql / org-roam-db-query?

franticnerd · 2022-10-26 04:50
​ Hi everyone, ​ I'm trying to write an elisp function that allows me to more easily query org-roam database with various keywords. ​ Suppose I want to find all the titles that contain both "hello" and "world", I know this can be done with a single query instance like the following: ​ (org-roam-db-query \[:select \* :from titles :where (and (like title "%hello%") (like title "%world%")) \] ) ​ Now I'm trying to turn this into an elisp function to make it easier to use. However, the challenge is my queries can contain an arbitrary number of keywords, for example: (org-roam-db-query \[:select \* :from titles :where (and (like title "%hello%") (like title "%world%") (like title "%again%")) \] ) ​ The function should thus accept a list of keywords and return the notes that contains ALL the keywords in that list, something like: ​ my-func('("hello" "world")) -> should return all notes containing "hello" "world" my-func('("hello" "world" "again")) -> should return all notes containing "hello" "world" "again" ​ Can anyone suggest how to implement such a function?
Careful_Assignment · 2022-10-26 06:01
Here's a way to get your query from a list of keywords. This is using "thread-last" from the "subr-x" library and some "seq-" functions from the "seq" library. From there the function should be easy to write: (thread-last '("an" "arbitrary" "number" "of" "key" "words") (seq-map (lambda (w) (list 'like 'title (concat "%" w "%")))) (seq-concatenate 'list (list 'and)) list (seq-concatenate 'vector [:select * from titles :where])) "org-roam-db-query" isn't a macro. So, passing it the generated query should give you what you're looking for.
howardthegeek · 2022-10-26 14:31
Look to see if &rest beginning your parameters helps, as it turns all parameters into a list.
franticnerd · 2022-10-26 15:08
Works perfectly and very interesting solution, thank you!!