[Tips] How to combine `org-roam-capture`, `org-capture`, and other commands into a single menu prompt

This conversation prompted me.

Here is a minimal menu “system” I quickly put together.
You can combine different capture functions in the way you like. In fact… they don’t have to be capture functions (e.g. git-status).

The presentation of the menu is minimalistic, which I prefer to the standard org-capture's menu style, or hydra (it’s a bit too much to learn for me).

See it in the minibuffer at the bottom?

I do not know what exactlyl happens if you have “too many” items, or it can extend vertically (perhaps with \n).

See the code below. You should be able to easily adapt it with your own set of commands.
usls-new-note is my custom version of Prot’s USLS.

;; Idea taken from project.el package
(defvar my/switch-commands)
;; Set `my/swithc-command' in the way you like.
(setq my/switch-commands '((?f "Fleeting" (lambda () (org-roam-capture nil "f")))
                           (?p "Personal" (lambda () (org-roam-find-file-immediate nil)))
                           (?w "Work" usls-new-note)))

(defun my/keymap-prompt ()
  "Return a prompt for a switching dispatch menu."
  (mapconcat
   (pcase-lambda (`(,key ,label))
     (format "[%s] %s"
             (propertize (key-description `(,key)) 'face 'bold)
             label))
   my/switch-commands
   "  "))

(defun my/capture-prompt ()
  "My capture prompt. Set `my/switch-commands' to define your own menu."
  (interactive)
  (let ((choice
         (assq (read-event (my/keymap-prompt)) my/switch-commands)))
    (funcall (nth 2 choice))))

I took the idea from this commit of project.el – built-in project management package (talked about here for example). The latest commit mirrored in GitHub has already had improvement from the code base I have in my local, so it seems to be getting some traction for upcoming Emacs version 28.

2 Likes

Thanks for sharing this.

Here’s how I deal with this issue.

The core idea is that for most of my use cases. I just need a procedure as easy as possible. Any extra things will add more fiction to the process of capturing an idea. So, I deliberately avoid using more options when capturing the ZK ideas.

I see your point of dividing the personal and work using separated commands when you decide to add something to your ZK system. The issue with me is that sometimes, it requires a little bit of effort to think about where to put the content. This will increase the stress when writing slip box notes.

For fleeting notes, I just write it down into the daily. And later on, if I feel the urge to further improve the note, I will start on the daily and continue to improve the notes.

Thanks for that! That’s a nice easy way to make menu items for all sorts of commands.
I’ll definitely pinch it :slight_smile:

I’ll confess I went lazier (I’m very new to Emacs Lisp) and just edited the org-roam function directly to append the usual capture templates.

--- /home/josh/.emacs.d/elpa/org-roam-20210128.1341/org-roam-capture.el
+++ #<buffer org-roam-capture.el>
@@ -603,8 +603,8 @@
 The templates are defined at `org-roam-capture-templates'.  The
 GOTO and KEYS argument have the same functionality as
 `org-capture'."
-  (let* ((org-capture-templates (append org-capture-templates (mapcar #'org-roam-capture--convert-template org-roam-capture-templates)))
-	 (one-template-p (= (length org-capture-templates) 1))
+  (let* ((org-capture-templates (mapcar #'org-roam-capture--convert-template org-roam-capture-templates))
+         (one-template-p (= (length org-capture-templates) 1))
          org-capture-templates-contexts)
     (when one-template-p
       (setq keys (caar org-capture-templates)))

Is there anyway to achieve this with Elisps advice perhaps? I don’t really want to have to remember to keep checking the code and updating it on an update, thanks!

I don’t even know how to read this diff, so no idea - I don’t really use capture templates.
But even if you used advice, I believe you would still be checking the code. The signature might be changed (not very likely for these core functions).

If you want to try advice, I think you can just use either :override or :around. See the manual, (elisp) Advice Combinators. ← This seems to be a convention you refer to a part of the in-system manual. For the way you did this, I believe :override might be easier.

It took me some learning to how to make use of the in-system manual (Info and Help); I can say it was really worth learning how to use it properly by hitting h within Info to see help on Info :sweat_smile:) Reading manual saves a lot of frustration; this fact itself really took me some time to get…

If you type C-h i, you go to the top index of manual. If you are not at (dir)Top, press d to go back to it. Press m to select a menu item. First Elisp. Then m again for the menu within Elisp. Select Advice Combinators.

1 Like

i was also asking myself this question, as i already have org-capture templates set up and it would be nice to have the option of accessing both through the one binding.

it turns out org-capture-templates entries can accept a function as a target, so you can/should be able to get it to run org-roam-capture, like so:

(setq org-capture-templates
      '(
;; your existing org-capture-templates here
        ("r" "org-roam capture" plain
        "%?"
         (function org-roam-capture))))

but it doesn’t quite work smoothly, somehow it runs twice and errors on the second run.

1 Like