Org tips and Tricks thread

This is an open thread for any sort of tips and tricks we have accumulated for org, org-roam or any other things related to our favourite life planning software!

2 Likes

I might as well start it off

(defadvice! yeet/org-roam-in-own-workspace-a (&rest _)
  "Open all roam buffers in there own workspace."
  :before #'org-roam-node-find
  :before #'org-roam-node-random
  :before #'org-roam-buffer-display-dedicated
  :before #'org-roam-buffer-toggle
  (when (featurep! :ui workspaces)
    (+workspace-switch "*roam*" t)))

this piece of advice switches to a dedicated roam workspace before opening any roam buffer, it saves me littering org roam buffers all over my workspaces, though this may not be for everyone.

5 Likes

A little function I found browsing someone’s dotfiles.

;; a useful function I took from (https://github.com/SqrtMinusOne/dotfiles/blob/4b176a5bb1a5e20a7fdd7398b74df79701267a7e/.emacs.d/init.el)
(defun kev/org-link-copy (&optional arg)
  "Extract URL from org-mode link and add it to kill ring."
  (interactive "P")
  (let* ((link (org-element-lineage (org-element-context) '(link) t))
         (type (org-element-property :type link))
         (url (org-element-property :path link))
         (url (concat type ":" url)))
    (kill-new url)
    (message (concat "Copied URL: " url))))
3 Likes

dEcLaRaTiVe snippets

  • Create a heading like below
* Snippets
:PROPERTIES:
:header-args:snippet: :mkdirp yes :tangle (expand-file-name (downcase (elt (org-get-outline-path t) (- (length (org-get-outline-path t)) 1))) (expand-file-name (downcase (elt (org-get-outline-path t) 1)) "snippets"))
:END:
  • Create a hook
(add-hook! 'org-babel-pre-tangle-hook
  (when (file-directory-p "snippets")
    (require 'async)
    (async-start
     (lambda ()
       (delete-directory "snippets" t (not (null delete-by-moving-to-trash))))
     (lambda (result)
       (print! "Delete snippets dir got: " result)))))

Then, under the “Snippets” heading a structure like

image

expands to

image

4 Likes

In org-roam I use manual alphanumeric IDs instead of the traditional Timestamp. In this case, I prefer that my links show the ID as part of the description to point me out the note’s address directly in the text. Something like this:

[[id:2a1b][2a1b My great note]]

I had to modify two functions to create the behavior.

For org-roam-node-insert-id I changed the description by (concat id " " description)

org-roam-node-insert-id
(defun maikol/org-roam-node-insert-id (&optional filter-fn &key templates info)
    "Find an Org-roam node and insert (where the point is) an \"id:\" link to it.
FILTER-FN is a function to filter out nodes: it takes an `org-roam-node',
and when nil is returned the node will be filtered out.
The TEMPLATES, if provided, override the list of capture templates (see
`org-roam-capture-'.)
The INFO, if provided, is passed to the underlying `org-roam-capture-'."
    (interactive)
    (unwind-protect
        ;; Group functions together to avoid inconsistent state on quit
        (atomic-change-group
          (let* (region-text
                 beg end
                 (_ (when (region-active-p)
                      (setq beg (set-marker (make-marker) (region-beginning)))
                      (setq end (set-marker (make-marker) (region-end)))
                      (setq region-text (org-link-display-format (buffer-substring-no-properties beg end)))))
                 (node (org-roam-node-read region-text filter-fn))
                 (description (or region-text
                                  (org-roam-node-formatted node))))
            (if (org-roam-node-id node)
                (progn
                  (when region-text
                    (delete-region beg end)
                    (set-marker beg nil)
                    (set-marker end nil))
                  (let* ((id (org-roam-node-id node))
                         (description (concat id " " description)))
                    (insert (org-link-make-string
                             (concat "id:" id)
                             description))
                    (run-hook-with-args 'org-roam-post-node-insert-hook
                                        id description)))
              (org-roam-capture-
               :node node
               :info info
               :templates templates
               :props (append
                       (when (and beg end)
                         (list :region (cons beg end)))
                       (list :link-description description
                             :finalize 'insert-link))))))
      (deactivate-mark)))

And for org-roam-link-replace-at-point-id I added a (concat (org-roam-node-id node)). This function is triggered every time org-roam replaces a roam link.

org-roam-link-replace-at-point-id
(defun maikol/org-roam-link-replace-at-point-id (&optional link)
    "Replace \"roam:\" LINK at point with an \"id:\" link."
    (save-excursion
      (save-match-data
        (let* ((link (or link (org-element-context)))
               (type (org-element-property :type link))
               (path (org-element-property :path link))
               (desc (and (org-element-property :contents-begin link)
                          (org-element-property :contents-end link)
                          (buffer-substring-no-properties
                           (org-element-property :contents-begin link)
                           (org-element-property :contents-end link))))
               node)
          (goto-char (org-element-property :begin link))
          (when (and (org-in-regexp org-link-any-re 1)
                     (string-equal type "roam")
                     (setq node (save-match-data (org-roam-node-from-title-or-alias path))))
            (replace-match (org-link-make-string
                            (concat "id:" (org-roam-node-id node))
                            (concat (org-roam-node-id node) " " (or desc path)))))))))

Finally, I have those to make them the default functions,

  (advice-add #'org-roam-node-insert :override #'maikol/org-roam-node-insert-id)
  (advice-add #'org-roam-link-replace-at-point :override #'maikol/org-roam-link-replace-at-point-id)
2 Likes

This one is probably obvious to anyone who has used org mode beyond a beginner level, but I’ll still highlight a lil’ something called

org-cliplink SPC m l c

Takes a link you have in your clipboard, then inserts it as an org link with the description being the URL’s title.

Very useful if you find materials for your project and want to put them into your document quickly. Eliminates the step of having to describe your link.

6 Likes

oh my lord I have been doing this manually for so long

1 Like

I recently added something similar to that to my config for files.

(defun +org-insert-file-link ()
  "Insert a file link.  At the prompt, enter the filename."
  (interactive)
  (insert (format "[[%s]]" (org-link-complete-file))))

(map! :after org
      :map org-mode-map
      :localleader
      "l f" #'+org-insert-file-link)

1 Like

This is very useful, thanks

1 Like