Adding orgrr-related-notes

I wrote a new function to better surface related notes for my minimalist org-roam v1 clone orgrr. The function collects all notes related to a given note to the second degree – the backlinks for the backlinks and the outgoing links mentioned by outgoing links. To use the image of a family, it considers parents and grandparents as well as all children and grandchildren of a note. All links to a specific note are counted and the resulting list is ranked by frequency and presented in side-window (invoking the function again closes the side-window). Pretty stoked by the results!

Adding orgrr-projects

One of the main ideas of the Zettelkasten-approach (“This is the way”) is to be able to pull out a number of cards and to look at them at the same time. For a while I tried different ways to replicate this with orgroam (and orgrr).

One of my ideas was to open all relevant notes in a new frame. This worked only ok-ish. Managing multiple frames in Emacs is somewhat hard (for example, all windows have to be re-arranged manually) and there is a limit to the number of notes that you would be able to see at the same time.

Another idea was to use the great org-transclusion package. In my personal use, however, I frequently encountered two issues. First, I only needed a line or two from a note and entering the line-numbers for org-transclusion – despite being easy – added a bit of friction. Secondly, I frequently use my notes as a starting point to write more comprehensive articles/notes. This requires changes to the contents of an existing note that should not affect the source note.

So in sum, I wanted to see a number of snippets from different notes at the same time (with links to their respective sources) but fully moldable to my liking. And I wanted to be able to rapidly add snippets to different thematic “desktops”. Enter orgrr-projects.

Orgrr-projects is the first major deviation from the original org-roam v1 ideas in orgrr. All notes within the org-directory and the roam_tag orgrr-project are an orgrr-project. This makes it very easy to add a note to or to remove it from the list of orgrr-projects. orgrr-open-project presents you a list of all active projects and lets you quickly open the selected one. One use case, for example, would be to have quick access to your favorite problems.

orgrr-add-to-project now lets you add the current line – of either any visited org-document in the active buffer (within the org-directory) or in the *Orgrr Backlinks* buffer – to any of these projects. A link to the source document is also added.

orgrr: org-roam-ripgrep

Org-roam v2 is an amazing project and brought org-roam to a new level of sophistication. Still, I never made the switch. As a reminder, the crucial difference between the two was the move from files as the main unit of interaction to “nodes”, which are org headlines with an org-id attached to them. This allowed for impressive graphs and more thorough linking to headlines (and even to show backlinks for nodes) but it never clicked with me and so I continued to use v1.

This worked fine for me until recently, where some weird emacsql problem broke the interaction between Emacs 29 and orgroam v1 on a new (old) intel Mac from work, which I wanted to use for field research (instead of my newer and expensive MBP). Enter orgrr:

Orgrr is an almost feature-complete replica of the core functionality of org-roam v1, built using ripgrep(rg), a lot of regex and hashtables. It does recognize alternative note titles (#+roam_alias) and tags (#+roam_tags) as introduced by org-roam v1. Orgrr currently only works with org-files (i.e. files ending in .org). If you also miss the first version of org-roam or prefer to not use databases (or to reduce dependencies), then this might be something for you.

PS For full text search I strongly recommend deadgrep, which also uses rg.

Automatically add org-files to “org-agenda-files” or remove them, based on whether or not they contain org-keywords

As mentioned before, I use Emacs, org-roam and org-journal. In total I have about 3000 org-files and a tiny fraction of them contains org-keywords. Those files I would like to have in my org-agenda-files (so that they show up in my org-agenda). If there is no TODO or any other org-keyword left, these files should be automatically removed.

This is what I came up with: My solution uses rg (ripgrep) and directly modifies “org-agenda-files”. Put the snippet below in your .emacs, adjust your org-keyword and whenever you save a buffer, “agenda_files.el” is updated. rg is really fast and this causes no tangible delay in my setup.

(defun lt/auto-add-org-agenda ()
  "Automatically add org-files to org-agenda-files or remove them, based on whether or not they contain org-keywords."
  (interactive)
  (with-temp-file org-agenda-files (insert (shell-command-to-string (concat "rg --sort modified -e '\\*.(TODO|NEXT|WAITING|RECREATION|PROJECT).[^%]' -g \"*.org\" -l " org-directory)))))
  (add-hook 'org-agenda-mode-hook 'lt/auto-add-org-agenda)

Copy org-ified toot to clipboard/org-journal (mastodon.el)

(On the left is the orginal toot, on the right is the “org-ified” version pasted into org-journal.)

There is a lot of useful information flying around in Mastodon. Some of it I would like to archive in my text-based database (i.e. org-roam). To access Mastodon inside Emacs I use mastodon.el. This little hack copies an org-ified version of the “toot” at point in the mastodon.el timeline to the clipboard. It uses the URL of said toot to pull it’s title from the web (via org-web-tools) and creates an org-link as the heading/context for the toot. The content of the toot is then pasted between #+begin_quote and #+end_quote. I also added a keybinding (“j”) for this to work inside mastodon.el.

Caveats: For boosted toots you need to focus on the original toot first (via “T”). Line breaks are still a bit of a mess.

((defun lt/mastodon-toot--copy-orgified-toot-to-clipboard ()
          "Copy org-ified toot at point to clipboard."
            (interactive)
            (let* ((toot (mastodon-tl--property 'toot-json)))
            (when toot
              (let* 
              ((url (alist-get 'url toot))
               (content (mastodon-tl--content toot))
               (html (org-web-tools--get-url url))
               (title (org-web-tools--html-title html)))       
  (with-temp-buffer
     (emacs-lisp-mode)
     (insert content)
     (fill-region (point-min) (point-max))
     (let* ((content (buffer-substring (point-min) (point-max)))              
            (complete-toot (concat "\[\[" url "\]\[" title "\]\]\n\n" 
               "#+begin_quote\n\n" content "\n#+end_quote\n\n")))
            (kill-new complete-toot)
(message "Copied: '%s' to the clipboard." title)))))))
(define-key mastodon-mode-map (kbd "j") 'lt/mastodon-toot--copy-orgified-toot-to-clipboard)

Update 2023_02_04: I played around with this setup and decided to directly paste the toot into an org-journal entry. The following code will add that functionality to the keybinding “J” (when in Mastodon.el).

(defun lt/mastodon-toot--copy-orgified-toot-to-org-journal ()
          "Copy org-ified toot at point to org-journal."
            (interactive)
            (lt/mastodon-toot--copy-orgified-toot-to-clipboard)
            (org-journal-new-entry nil)
            (org-yank))
 (define-key mastodon-mode-map (kbd "J") 'lt/mastodon-toot--copy-orgified-toot-to-org-journal)

Btw: If you replace (org-journal-new-entry nil) in the second snipped with (org-capture nil "xyz") (whereby xyz stands for a template key) this should also work with org-capture.

Update 2023_02_11: Added a correction for the arbitary line breaks (via fill-region in a temporary buffer).

Add a website from Emacs to Things’ inbox

This code snippet will quickly add a website from any Emacs buffer to Things‘ inbox. The name of the new task is the name of the website, the URL is added as a note. It requires org-web-tools, uses the URL-scheme of Things and in Emacs the cursor must be on the URL you want to add. Everything happens in the background, the focus continues to be on Emacs.

 (cl-defun lt/add-url-to-things (&optional (url (org-web-tools--read-url)))
    "Add a website to Things' inbox."
    (interactive)
      (let* ((html (org-web-tools--get-url url))
         (title (org-web-tools--html-title html)))
         (setq things-url (concat "things:///add?title=" title "¬es=" url))
         (shell-command (concat "open " "-g " "\"" things-url "\""))
         (message "%s" (concat "\"" title "\"" " has been added to Things."))))

Backstory: I’m checking Mastodon with via mastodon.el in Emacs and often encounter interesting websites that I want to come back to later. In the past I’ve used pocket-reader.el to add these sites to Pocket. But this feels like wasting them – I don’t check Pocket just for fun and often just forget that I’ve added something there. Things is (currently) my task manager (despite using org-mode for a lot) and I like to process my findings here.

Reading Chinese

One reason I enjoy working with Emacs is the relative ease to process text in specific ways. One example: reading Chinese official documents can be quite exhausting, so I let them read to me. For a long time I used read-aloud.el for that. Unfortunately, macOS Ventura broke this package from 2016 – but I was able to replace it with this tiny function:

(defun lt/read-chinese (start end)
"Read region in Chinese."
(interactive "r")
(shell-command-on-region start end "say -v Ting-Ting"))