-
Notifications
You must be signed in to change notification settings - Fork 6
Home
Ahmed Shariff edited this page May 17, 2025
·
5 revisions
Welcome to the org-roam-ql wiki! Recording a few predicates/expansion functions that can be used.
(defvar consult-org-roam-ql--history nil)
(defun consult-org-roam-ql (&optional initial-input filter-fn sort-fn
require-match prompt)
"Consult with org-roam-ql for searching/narrowing."
(interactive)
(minibuffer-with-setup-hook
(lambda ()
;; KLUDGE: No idea why this is here!
(set-syntax-table emacs-lisp-mode-syntax-table)
(add-hook 'completion-at-point-functions
#'org-roam-ql--completion-at-point nil t))
(let* (split-pos mb-str is-highlight
(consult-async-split-styles-alist
`((org-roam-ql
;; :initial ?\; ;; this was interacting with the embark
:function
;; Override how the empty string is handled!
;; When empty async-str should return default candidates
,(lambda (str style)
(pcase-let* ((res (consult--split-perl str style))
(`(,async-str ,pos ,start-highlight . ,end-highlight) res)
(force (or (get-text-property 0 'consult--force async-str)
(and (not (null start-highlight)) (not (null end-highlight))))))
;; This gets called at severaal places. We only want the data when it is
;; called with the force value!
(setq is-highlight (or start-highlight end-highlight))
(when force
(setq split-pos pos
mb-str str))
(cond
((and force (equal "" async-str))
(setf (car res) (propertize "-" 'consult--force end-highlight)))
;; when no leading char split-perl can use, just fallback to normal matching
((and (not (or is-highlight
(string-empty-p async-str))))
(setf res (list (propertize (car res) 'consult--org-roam-ql-state 'no-narrow)
;; forcing the actual matching to work
0 '(0 . 0) '(0 . 0)))))
res)))))
(corfu-auto nil)
(consult-async-input-debounce 1)
;; Default candidates
(nodes (mapcar (lambda (node)
(cons (propertize (org-roam-node-title node) 'node node) node))
(org-roam-node-list)))
;; The sink is what holds the candidates and feed it back to all-completions
(sink (consult--async-sink))
(overriden-keymap (make-sparse-keymap))
(delete-minibuffer-override
(lambda ()
(interactive)
(cond
((and mb-str split-pos)
(delete-minibuffer-contents)
(insert (substring mb-str 0 split-pos)))
((not is-highlight)
(delete-minibuffer-contents))))))
(define-key overriden-keymap "\M-d" delete-minibuffer-override)
(define-key overriden-keymap "\M-D" #'delete-minibuffer-contents)
(define-key overriden-keymap (kbd "C-,") (lambda ()
(interactive)
(when (minibufferp)
(embark-select)
(funcall delete-minibuffer-override))))
(when (not (featurep 'org-roam-ql))
(require 'org-roam-ql))
(set-keymap-parent overriden-keymap org-roam-ql--read-query-map)
;; Feeding initial set of candidates to sink
(funcall sink nodes)
(-->
(consult--async-pipeline
(consult--async-split 'org-roam-ql)
(consult--dynamic-collection
(lambda (input)
(if (or (length= input 0)
(equal input "-")
(eq (get-text-property 0 'consult--org-roam-ql-state input)
'no-narrow))
nodes
(condition-case err
(mapcar
(lambda (node)
(cons (propertize (org-roam-node-title node) 'node node) node))
(org-roam-ql-nodes (read input)))
(user-error
(minibuffer-message (propertize (cadr err) 'face 'consult-async-failed))
nodes)))))
(consult--async-indicator)
(consult--async-refresh))
(funcall it sink)
(consult--read
it
:prompt (or prompt "Node: ")
:initial (if initial-input initial-input ";")
:keymap overriden-keymap
:category 'org-roam-node
:sort nil ;; TODO
:require-match require-match
:async-wrap nil
:state (amsha/consult-org-roam--node-preview
(lambda (node)
(not (string-match "research_papers" (org-roam-node-file node)))))
:history 'consult-org-roam-ql--history
;; Taken from consult-org-roam
;; Uses the DEFAULT argument of alist-get to return input in case the input is not found as key.
:lookup (lambda (selected candidates input narrow) (alist-get selected candidates input nil #'equal)))
(if (org-roam-node-p it)
it
(org-roam-node-create :title it))))))
(advice-add #'consult-org-roam-node-read :override #'consult-org-roam-ql))
For example, with org-roam-node-find
, one could use org-roam-ql to narrow down the nodes showing up with the following:
To provide context:
- I have an org-roam-ql saved-query (
fam
- in the image above) which allows me to quickly filter with queries I use often. - This also has the same completion-at-point function in org-roam-ql (see demo) configured, which is handy.
- I don’t use the org-roam’ templating for completion candidates. Instead, I have a custom marginalia annotator. I use orderless’s annotation search when I want to further query on the annotations.
- I prefer “;” as the default value for consult’s perl split style 😅
The consult-org-roam-ql function:
(defvar consult-org-roam-ql--history nil)
;; TODO: filter-fn and sort-fn does notthing now!
(defun consult-org-roam-ql (&optional initial-input filter-fn sort-fn
require-match prompt)
"Consult with org-roam-ql for searching/narrowing."
(interactive)
(minibuffer-with-setup-hook
(lambda ()
;; KLUDGE: No idea why this is here!
(set-syntax-table emacs-lisp-mode-syntax-table)
(add-hook 'completion-at-point-functions
#'org-roam-ql--completion-at-point nil t))
(let* (split-pos mb-str
(consult-async-split-styles-alist
`((org-roam-ql
;; :initial ?\; ;; this was interacting with the embark
:function
;; Override how the empty string is handled!
;; When empty async-str should return default candidates
,(lambda (str style)
(pcase-let* ((res (consult--split-perl str style))
(`(,async-str ,pos ,start-highlight . ,end-highlight) res)
(force (or (get-text-property 0 'consult--force async-str)
(and (not (null start-highlight)) (not (null end-highlight))))))
;; This gets called at severaal places. We only want the data when it is
;; called with the force value!
(when force
(setq split-pos pos
mb-str str))
(when (and force (equal "" async-str))
(setf (car res) (propertize "-" 'consult--force end-highlight)))
res)))))
(corfu-auto nil)
(consult-async-input-debounce 1)
;; Default candidates
(nodes (mapcar (lambda (node)
(cons (propertize (org-roam-node-title node) 'node node) node))
(org-roam-node-list)))
;; The sink is what holds the candidates and feed it back to all-completions
(sink (consult--async-sink))
(overriden-keymap (make-sparse-keymap))
(delete-minibuffer-override
(lambda ()
(interactive)
(when (and mb-str split-pos)
(delete-minibuffer-contents)
(insert (substring mb-str 0 split-pos))))))
(define-key overriden-keymap "\M-d" delete-minibuffer-override)
(define-key overriden-keymap "\M-D" #'delete-minibuffer-contents)
(define-key overriden-keymap (kbd "C-,") (lambda ()
(interactive)
(when (minibufferp)
(embark-select)
(funcall delete-minibuffer-override))))
(when (not (featurep 'org-roam-ql))
(require 'org-roam-ql))
(set-keymap-parent overriden-keymap org-roam-ql--read-query-map)
;; Feeding initial set of candidates to sink
(funcall sink nodes)
(-->
(consult--async-pipeline
(consult--async-split 'org-roam-ql)
(consult--dynamic-collection
(lambda (input)
(if (and (> (length input) 0) (not (equal input "-")))
;; TODO: can I update the state/indicator somehow?
(condition-case err
(mapcar
(lambda (node)
(cons (propertize (org-roam-node-title node) 'node node) node))
(org-roam-ql-nodes (read input)))
(user-error
(minibuffer-message (propertize (cadr err) 'face 'consult-async-failed))
nodes))
nodes)))
(consult--async-indicator)
(consult--async-refresh))
(funcall it sink)
(consult--read
it
:prompt (or prompt "Node: ")
:initial (if initial-input initial-input ";")
:keymap overriden-keymap
:category 'org-roam-node
:sort nil ;; TODO
:require-match require-match
:async-wrap nil
:state (consult-org-roam--node-preview)
:history 'consult-org-roam-ql--history
;; Taken from consult-org-roam
;; Uses the DEFAULT argument of alist-get to return input in case the input is not found as key.
:lookup (lambda (selected candidates input narrow) (alist-get selected candidates input nil #'equal)))
(if (org-roam-node-p it)
it
(org-roam-node-create :title it))))))
(advice-add #'consult-org-roam-node-read :override #'consult-org-roam-ql))
Note that the above also uses consult-org-roam--node-preview
from consult-org-roam to preview state. You can have the :state
in consult--read
if you don't want previews.
Originally posted in: https://org-roam.discourse.group