Emacs

Converting Markdown to Org-mode syntax in current buffer

There are some great tools for bringing web content into Markdown files, but few that offer the same utility for Org-mode (Orgdown) files.

For example, I use Markdownload extension all the time. It works great with nearly every site I use it on, but instead of Markdown, I’d prefer having Org syntax, so I’ve worked around it by creating a function ((I may have copied this idea from somewhere but I don’t have a reference. If it was you, I apologize for not giving credit. Send me a note! )) which converts the current region from Markdown to Org.

(defun jab/md-to-org-region (start end)
  "Convert region from markdown to org, replacing selection"
  (interactive "r")
  (shell-command-on-region start end "pandoc -f markdown -t org" t t))

I copy the Markdown from the Markdownload window, paste it into an Org buffer, and run the function. It’s not perfect, but until someone creates an “Orgdownload” extension, it’ll do. (Pretty please, will someone create an Orgdownload extension?)

Keeping my Org Agenda updated based on Denote keywords

I’ve recently switched from using Org-roam to using Denote for my notes. Org-roam is powerful and cool, but I prefer the more straightforward approach of Denote.

I keep all my notes in Denote, including notes about current projects. For example, we’re planning to remodel our kitchen. This is a project and so I have a Denote file named “20221130T130143–kitchen-remodel-2023__house_project.org”. In this file, I keep a list of TODOs. In order to see these TODOs in my Org Agenda, I need to add the file to org-agenda-files. This can be done a few ways, but all are manual. I am forgetful, so I wanted a more automated way to keep my org-agenda-files up to date with Denote projects.

David of System Crafters created a video about hacking Org-roam containing something like what I was looking for in the show notes, but for Org-roam not Denote.

I took the idea and implemented it for Denote instead. All it does is search denote-directory for files with a specific pattern and append the results to my default list of org-agenda-files. It looks like this:

;; Add all Denote files tagged as "project" to org-agenda-files
(defun jab/denote-add-to-agenda-files (keyword)
  "Append list of files containing 'keyword' to org-agenda-files"
  (interactive)
  (jab/init-org-agenda-files) ;; start over
  (setq org-agenda-files (append org-agenda-files (directory-files denote-directory t keyword))))

(jab/denote-add-to-agenda-files "_project")

That’s it. Now I can keep my project TODOs in the project Org files and view them in the Agenda. You’ll notice that there’s nothing in there that actually depends on Denote. It’s all just basic Emacs stuff. That’s one of the reasons I love Denote so much; even I can riff off it. I haven’t found a good way to add newly-created project files to the agenda without reloading Emacs or calling the function manually, but I’ll get to that later.

Later: Protesilaos Stavrou (known as “Prot”), the author of Denote, was kind enough to send me the following code for helping automatically maintain the list of org-agenda-files…

    (defvar my-denote-to-agenda-regexp "_project"
      "Denote file names that are added to the agenda.
    See `my-add-denote-to-agenda'.")

    (defun my-denote-add-to-agenda ()
      "Add current file to the `org-agenda-files', if needed.
    The file's name must match the `my-denote-to-agenda-regexp'.

    Add this to the `after-save-hook' or call it interactively."
      (interactive)
      (when-let* ((file (buffer-file-name))
                  ((denote-file-is-note-p file))
                  ((string-match-p my-denote-to-agenda-regexp (buffer-file-name))))
        (add-to-list 'org-agenda-files file)))

    ;; Example to add the file automatically.  Uncomment it:

    ;; (add-hook 'after-save-hook #'my-denote-add-to-agenda)

    (defun my-denote-remove-from-agenda ()
      "Remove current file from the `org-agenda-files'.
    See `my-denote-add-to-agenda' for how to add files to the Org
    agenda."
      (interactive)
      (when-let* ((file (buffer-file-name))
                  ((string-match-p my-denote-to-agenda-regexp (buffer-file-name))))
        (setq org-agenda-files (delete file org-agenda-files))))

This works great. Thanks, Prot!

Book logging in Emacs

I’ve kept a list of books I’ve read as a plain text (well, technically, Markdown) file for years. I wrote about it here . The public version is rendered using Github Pages at books.baty.net . This is fine, but at some point last year I also started logging books in an Org mode file, just to see how it felt. It felt pretty good!

Continue reading…

Publishing portions of my Org-roam database

I’m trying something new.

I’ve become a pretty heavy user of Org-roam  for personal notes. I put nearly everything there now; technical notes, contact information, project notes, vendor info, etc. These notes are all nicely linked and backlinked and live in my main ~/org directory so I can easily find things right within Emacs.

A portion of these notes might be useful to other people. So I’m exporting the shareable notes from Org-roam as Hugo -compatible Markdown files. This turned out to be surprisingly easy. You can see the results at https://notes.baty.net and the details of how it works makes a good example.

I’m sure there are a dozen ways to do this, but this seems to work quite well.

Aligning comments in Emacs

I want my per-line code comments to line up nicely, so I’ll often add a bunch of spaces by hand to make things just so. I realized that, being Emacs, there must be an easier way to handle this. Of course there is.

Continue reading…

Configuring the org-download save directory

When I drag and drop an image into Emacs, I want the attached file to end up in ./img/YYYY/. This is how I tried configuring org-download in my setup (I use Doom Emacs):

(setq org-download-method 'directory
        org-download-image-dir (concat "img/"  (format-time-string "%Y") "/")
        org-download-image-org-width 600
        org-download-heading-lvl 1)
(setq org-download-method 'directory
        org-download-image-dir (concat "img/"  (format-time-string "%Y") "/")
        org-download-image-org-width 600
        org-download-heading-lvl 1)

For some reason, org-download-method was being reset from 'directory to 'attachafter loading, and this broke things. I thought maybe I needed to set the variables afterorg-download was loaded, so I did this:

(after! org-download
  (setq org-download-method 'directory
        org-download-image-dir (concat "img/"  (format-time-string "%Y") "/")
        org-download-image-org-width 600
        org-download-heading-lvl 1))

That didn’t work. At startup I was seeing this error:

Error (org-mode-hook): Error running hook “org-fancy-priorities-mode” because: (void-variable org-download-image-dir)

Huh. I guess not everything can be set after org-download, so I tried only setting org-download-method

(after! org-download
  (setq org-download-method 'directory))

This worked. The other settings are done in the (after! org block.

It feels like I have to fight Doom too often, but the details and refinement of Doom is worth the trouble.

Doom Emacs from scratch

A week ago I decided to cancel Doom Emacs and go back to building Emacs from Scratch , and once again I was reminded what a terrible idea that is.

Seriously, stock Emacs, even with a leg up from Nano Emacs , gets so many things “wrong” that I could spend the rest of my life fixing things and still wanting more. I thought building from scratch would help me avoid Configuration Fatigue . Wow, was I wrong.

So, back to Doom. I started from scratch with the usual…

git clone --depth 1 https://github.com/hlissner/doom-emacs ~/.emacs.d~/.emacs.d/bin/doom install

Then I edited init.el and enabled just a few non-stock things. “Zen” mode, org-journal, and pandoc-mode. Otherwise, it’s right out of the box.

I copied the gotta-haves from my original config.el. Most of these are around file paths, Org mode, and LaTeX. Plus a few of my favorite key bindings. Otherwise, I left it alone. So far.

Doom Emacs is simply too good to pass up. It handles all of the little behavioral and visual tweaks that would otherwise take forever to learn about and modify on my own. Half of the things it does for me I just expect to be part of Emacs, and am surprised when I find they’re not.

I’m still using the default Doom theme, which isn’t my favorite, but I’m trying to resist farting around with that for at least a couple of days while I get settled back in.