Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Help defining new source for consult-buffer #660

Closed
apc opened this issue Oct 3, 2022 · 8 comments
Closed

Help defining new source for consult-buffer #660

apc opened this issue Oct 3, 2022 · 8 comments

Comments

@apc
Copy link

apc commented Oct 3, 2022

Short version

Following the examples in the Wiki and the README, I've created a new source for consult-buffer that includes only the buffers corresponding to org-roam files. Is there a way of changing the way items in the source are listed, so that what I see is the value of a function that takes a buffer name, rather than the buffer name? Specifically, I'm trying to have the items listed using their org-roam titles.

What I've tried

Here's what I've tried.

First, letting buffers be listed by their names works fine:

(autoload 'org-roam-buffer-list "org-roam")

(defvar org-roam-buffer-source
  `(:name     "Org-roam"
              :hidden   t
              :narrow   ?r
              :category buffer
              :state    ,#'consult--buffer-state
              :items    ,(lambda () (consult--buffer-query :sort 'visibility :as #'buffer-name :filter nil :predicate (lambda (buf) (org-roam-buffer-p buf))))))

(add-to-list 'consult-buffer-sources 'org-roam-buffer-source 'append)

Calling consult-buffer followed by r and SPC gives me the list of all and only my org-roam buffers:

image

Naively, I thought I could just replace buffer-name as the value of the :as key (?), and instead use a little function that takes the outputs the title of the org-roam node.

(defun buffer-roam-name (buf)
  (when (org-roam-buffer-p buf)
        (with-current-buffer buf (org-roam-db--file-title))))

But if I replace buffer-name with buffer-roam-name in the definition of my new source, I run into trouble.

image

From what I can tell, changing the value of :as breaks everything: the titles of open org-roam buffers show up, but none of the items on that list are recognized as buffers. As a result, not only do I not see the metadata, but if I select an item on that list, I do not end up at the corresponding buffer.

@minad
Copy link
Owner

minad commented Oct 3, 2022

Yes, if you display the title instead of the buffer name you also have to change the :action or :state function of the source. These functions must handle the node title and convert it back to the buffer. See also the other source types, e.g. for recent files or bookmarks. These sources have their own functions to handle their item type.

Btw, are you aware of @jgru's https://github.com/jgru/consult-org-roam? Maybe you could also ask there if adding certain Consult sources would be a possibility?

@minad minad closed this as completed Oct 3, 2022
@apc
Copy link
Author

apc commented Oct 3, 2022

Thanks for taking the time to write back—very helpful stuff. I'll look into that other package too.

@apc
Copy link
Author

apc commented Oct 4, 2022

Sorry to bug again, but maybe someone following at home can lend a hand?

I've played around with creating a state function for the new org-roam source, but I run into an error I cannot make sense of.

I basically have two functions org-roam-buffer-get-title and org-roam-buffer-with-title that serve as 'translation' functions. The first will get the title of an org-roam-buffer and the second will get the name of the corresponding org-roam buffer given a title.

I then have a pair of functions, consult--org-roam-buffer-preview and consult--org-roam-buffer-action which are designed to be just like consult--buffer-preview and consult--buffer-action but which first make use of the 'translation' functions.

Finally, I call consult--define-state to generate the state function I will use in the new source. I can now see the list of titles and open the corresponding buffers, but when trying to navigate the list of titles I get an error: Error in post-command-hook (consult--preview-post-command): (void-variable other-win).

I must be making some basic error somewhere but I cannot see what it is.

(defun org-roam-buffer-get-title (buffer)
  "Get title for BUFFER when it corresponds to an org-roam buffer"
  (when (org-roam-buffer-p buffer)
        (with-current-buffer buffer (org-roam-db--file-title))))

(defun org-roam-buffer-add-title (buffer)
  "Build a cons consisting of the BUFFER title and the BUFFER name"
  (cons (org-roam-buffer-get-title buffer) buffer))

(defun org-roam-update-open-buffer-list ()
  "Generate a list of pairs of the form `(TITLE BUF)’, where TITLE is the title of an open org-roam BUFfer"
  (setq org-roam-open-buffer-list (mapcar #'org-roam-buffer-add-title (org-roam-buffer-list))))

(defun org-roam-buffer-with-title (title)
  "Find buffer name with TITLE from among the list of open org-roam buffers"
  (org-roam-update-open-buffer-list)
  (cdr (assoc title org-roam-open-buffer-list)))

(defun consult--org-roam-buffer-preview ()
  "Buffer preview function."
  (let ((orig-buf (current-buffer)) other-win)
    (lambda (action cand)
      (when (eq action 'preview)
        (when (and (eq consult--buffer-display #'switch-to-buffer-other-window)
                   (not other-win))
          (switch-to-buffer-other-window orig-buf)
          (setq other-win (selected-window)))
        (let ((win (or other-win (selected-window)))
              (realcand (org-roam-buffer-with-title cand)))
          (when (window-live-p win)
            (with-selected-window win
              (cond
               ((and realcand (get-buffer realcand))
                (switch-to-buffer realcand 'norecord))
               ((buffer-live-p orig-buf)
                (switch-to-buffer orig-buf 'norecord))))))))))

(defun consult--org-roam-buffer-action (title &optional norecord)
  "Act on buffer with TITLE using `consult--buffer-display’"
  (funcall consult--buffer-display (org-roam-buffer-with-title title) norecord))

(consult--define-state org-roam-buffer)

(autoload 'org-roam-buffer-list "org-roam")

(defvar org-roam-buffer-source
  `(:name     "Org-roam"
              :hidden   t
              :narrow   ?r
              :category buffer
              :state    ,#'consult--org-roam-buffer-state
              :items    ,(lambda () (consult--buffer-query :sort 'visibility :as #'org-roam-buffer-get-title :filter nil :predicate (lambda (buf) (org-roam-buffer-p buf))))))

(add-to-list 'consult-buffer-sources 'org-roam-buffer-source 'append)

@minad
Copy link
Owner

minad commented Oct 4, 2022

Maybe you don't have lexical-binding enabled? I suggest to not copy consult--buffer-preview and consult--buffer-state. Instead call consult--buffer-state and return a new lambda which does the translation. Reuse the functions!

(defun my-state ()
  (let ((state (consult--buffer-state)))
    (lambda (action cand)
       (funcall state (and cand (lookup-buffer-by-title cand))))))

@apc
Copy link
Author

apc commented Oct 4, 2022

Maybe you don't have lexical-binding enabled?

Indeed. When will I learn my lesson? 🤦‍♂️

Good point re: reusing the functions, of course. I may have more questions about marginalia at some point, but I will post those in the right place. Thanks again for your help.

@jgru
Copy link

jgru commented Oct 4, 2022

Hi @apc,

this is a nice idea and good effort. Do you want to consider to add this to consult-org-roam. A PR would be welcome.

Best regards,
jgru

P.S.: Thanks @minad for referencing consult-org-roam.

@apc
Copy link
Author

apc commented Oct 5, 2022

Thanks, @jgru. Would be happy to contribute in whatever way I can. Not sure what I got is ready for a PR just yet, but I'll post an issue over at consult-org-roam with the suggestion and my prototype and see if people who know more than I do can see ways of improving it.

@jgru
Copy link

jgru commented Oct 6, 2022

Happy that you added an issue to consult-org-roam. I commented on it and propose some changes here.
Maybe some others (@minad?) also have a comment or two on this.

Best regards,
jgru

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants