Emacs org-mode
Welcome to the Emacs org-mode category.
You can subscribe to this category only via RSS!
I am working on restoring some of my related posts from my old blog, so keep checking here for new content.

- I haven’t touched Elfeed in about a month
- I’ve been reading and interacting more with people’s posts than ever As I was looking at my Inkwell’s RSS feeds and cleaning up, I couldn’t help but notice how nice it looks:
- It creates a
datafolder (by default) inside the folder the org-file is in if it’s not there - It then gives the header (even if you don’t have one) a UUID (Universally Unique Identifier) and creates two more directories, one inside the other:
- The parent directory consists of the first part of the UUID
- The child directory consists of the rest of the UUID
- Lastly, the file itself will be copied into the child directory above.
brew uninstall emacs-plus@30brew cleanup(this removes dependencies, where I think the issue was)- Delete emacs.app and emacs-client.app from /Applications (I keep forgetting to do this)
brew install emacs-app(which is now emacs plus, from what I got through Homebrew)
Correcting photo orientation for org-mode in Linux
Here’s a niche problem: When viewing iPhone-captured photos in org-mode on Linux, they always appear in landscape orientation, even if you took them in portrait.
The reason is that the sensor of the camera on the phone is physically embedded in landscape mode, so all photos are in landscape mode; when you hold the phone in portrait mode (which is how you hold it most of the time), the phone detects that and implements a fix in the EXIF data file. Essentially, a software fix to a hardware design issue.
Since most photos I take are usually in portrait orientation, it means I need to twist my neck and view images at a 90-degree angle when I look at my Journelly entries.
The source of the problem seems to stem from how org-mode interprets EXIF data in the photo: it doesn’t. It relies on other parts of Emacs, which in turn rely on parts of the OS, to do the job. On Linux (at least on Kubuntu, which is what I use these days), those parts don’t handle EXIF orientation information. Why and how, I am not sure, it’s more digging than I have the time for right now… but anyway - there’s a simple fix.
Auto-orient, which is part of ImageMagick’s mogrify tool. And if you use Emacs on Linux, good chance it’s already installed:
This operator reads and resets the EXIF image profile setting ‘Orientation’ and then performs the appropriate 90 degree rotation on the image to orient the image, for correct viewing.
To execute on an image file: mogrify -auto-orient <file>.
And because I use Emacs, of course there’s a dwim-shell-command solution:
(defun jtr/dwim-image-auto-orient ()
"Auto-orient images based on EXIF data using mogrify."
(interactive)
(dwim-shell-command-on-marked-files
"Auto-orient images"
"mogrify -auto-orient '<<f>>'"
:utils "mogrify"
:silent-success t))
That last part,:silent-success, closes the empty buffer that pops up after successful execution, as mogrify doesn’t really produce an output window. So, it will just bring us back to Dired.
Installing Harper on Kubuntu: The Right Way. Maybe.
I recently installed Harper on my Linux Desktop to work with Emacs, but since I’m running Kubuntu, I ran into difficulties. In short, there’s no Flatpak or Apt option when it comes to Harper.
After a few interesting changes to the way I journal in Emacs (this is something I hope to discuss soon), I decided to go for the full version, and that meant installing Rust and Cargo.
This was another “programming quest” I didn’t know how to start in the past. I used Claude.ai to guide me, but as usual, I asked a million questions about everything, so I can explain it again here (this is my test to myself). So if you’re new to all of this like I am, take the explanations with a grain of salt, and if you’re an experienced developer who understands Rust (and curl, for that matter) feel free to reach out and educate me further.
Alright, here we go:
To install Rust and Cargo with it:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
The above is a bit more complex than what’s in Cargo’s documentation, but based on a quick search, it is what’s directly recommended in rustup, which is where you install Rust. The idea is the same as other curl installations, with a few more options for added security and to ensure we’re getting what we really want:
Run curl, but restrict it only to https (no http):
curl --proto '=https'
Somewhat redundant: curl will usually refuse anything lower than 1.2 by default. This forces TLS 1.2 as the minimum. This is good practice and also what they tell us to use, so why not:
--tlsv1.2
options for silent mode s (so don’t show us progress and status), but show us if we get errors S, and if we get a 404 error or similar, just stop silently f (otherwise it will pipe it into the sh command at the end):
-sSf
Then we have the URL to download from:
https://sh.rustup.rs
and finally we pipe it | into a shell sh command so it runs as a script as intended here. If you go to the above URL directly, it will download a shell script - so this is how we get it and run it in one go:
| sh
Because we’re about to run commands for Rust, it’s a good idea to add it to our source environment, the same as editing ~/.bashrc manually and adding . "$HOME/.cargo/env". Without it, we’ll have to specify where Cargo is installed for the next commands
source ~/.bashrc
At first, I installed what was available on crates.io. Crates, as I learned, is the official repository for Cargo, our “app store” for Rust, (or Elpa for Emacs). The individual packages are called “crates”. Makes sense now, but before it all looked like a bunch of command-line voodoo to me.
However, apperently what’s available on Crates is not up to snuff. The official repository for Harper is at https://github.com/Automattic/harper, and it specifies version 2.3.1, whereas the one available in Crates is 2.0.0. We are still using cargo (it’s the “installer” for Rust), but specify to get what we need directly from there:
cargo install --git https://github.com/Automattic/harper harper-ls --locked
The git option tells Cargo we’re installing directly with git, which is what we’re doing here; the locked option is specified in Harper’s documentation, and upon some research, I learned this forces the exact dependency versions specified in Cargo.lock. Without it, cargo might choose newer dependency versions that were not tested or are not specified in the documentation.
Finally, in Emacs, we want to tell eglot where to find Harper:
(when (eq system-type 'gnu/linux)
(add-to-list 'exec-path (expand-file-name "~/.cargo/bin")))
In my case, since I use the same config on my Mac, I want this to run only on Linux. On my Mac, Harper is installed without all these shenanigans directly from Homebrew, which also keeps it up to date. This is added to the same config block I specified in my earlier post. It now looks like this:
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(org-mode . ("harper-ls" "--stdio"))))
(setq-default eglot-workspace-configuration
'(:harper-ls (:dialect "American" :linters (:LongSentences :json-false :AvoidCurses :json-false))))
;; Besides choosing American as the language, I also want to ignore long sentences (the main issue is that it hides other errors nested in those), and I also want Harper not to tell me when it thinks something is offensive. I'm a big boy/an old fart. The full list of these options is in https://writewithharper.com/docs/rules. It needs to be nested inside the :linters option.
(when (eq system-type 'gnu/linux)
(add-to-list 'exec-path (expand-file-name "~/.cargo/bin")))
In the future, when I need to update:
cargo install --git https://github.com/Automattic/harper harper-ls --locked
Now, Harper works as it should on my Linux Desktop. Another geeky weekend project.
Using Denote for Email: A manual workflow
As I started to write more emails to other bloggers, the annoyance with macOS’ built-in email client grew. It wasn’t just the fact that it has small text that’s hard on the eyes especially on the harsh white background anymore; it just started to feel restricting.
Emacs is my natural writing environment for longer texts, like blog posts or the kind of emails I end up writing.
I’ve considered mu4e before, but setting it up seems a daunting overkill: the place I would benefit from mu4e is work, but I’m blocked by Microsoft-only 2FA authentication, so I have to stick with Outlook; meanwhile, for the three or so emails I write to other bloggers, it doesn’t require such heavy lifting.
One day about two weeks ago, I just fired up Denote, and suddenly it clicked. Denote, when you invoke it for a new note, asks for a directory - so I created an email directory in my parent Notes folder, and started writing. For a title, I use the subject, and the keyword is reserved for the recipient.
Now my eyes thank me again, as some of these emails can take an hour (and more even) to write. Links are a breeze to include, and quotes - which I use heavily in emails - are just a keyboard press away. It also looks nice when I go to the email directory and see all my drafts there, organized nicely as Denote knows how to do.
Since Denote doesn’t handle emails, for this I simply export the org file to HTML, and then with Dired (which opens in the same directory as the note I’m writing by default), I open the HTML file with my browser. From there, I copy-paste into Apple Mail, which acts as a proofread enhancer with Grammarly going to work there (this is something I’d miss if I were to use mu4e, though I could probably use Harper).
It’s a bit of a manual process, and I do need to delete the HTML files from the email directory every now and then, but for now it’s fine. It’s probably easy enough to create some shortcut that will open these HTML files directly with Mail instead of copy-pasting1 though.
Footnotes
1 Opening an HTML file with Dired with ! open -a Mail would make sense, but it opens Mail with the HTML file as an attachment, not as the body of the text.
Journelly and OSM for Emacs are good together
I mentioned OSM for emacs briefly before, but I haven’t played with it much. That’s because the maps never showed up correctly in the buffer: the map tiles were not aligned correctly and some appeared blank.
As it turns out, someone else had this problem and also found the culprit: visual-line-mode. I have it turned on by default as the majority of my work in Emacs involves org-mode and I need my lines wrapped in the buffer. With visual-line-mode disabled, OSM works as expected, including zooming in and out. Good stuff.
Now that I fixed OSM, I was wondering about something else I wanted to do for a while: having Journelly’s latitude and longitude fed automatically to OSM in Emacs, so I can view the location on a map.
Journelly captures locations and weather information for each note and stores those under properties, like so:
PROPERTIES:
:LATITUDE: ##.##########
:LONGITUDE: ##.##########
:WEATHER_TEMPERATURE: 62.1°F
:WEATHER_CONDITION: Cloudy
:WEATHER_SYMBOL: cloud
:END:
The OSM function that calls for those is osm-goto.
So what we need is a simple function to feed the properties values directly:
(defun jtr-goto-from-properties ()
(interactive)
(let ((lat (org-entry-get (point) "LATITUDE"))
(lon (org-entry-get (point) "LONGITUDE")))
(if (and lat lon)
(osm-goto (string-to-number lat) (string-to-number lon) osm-default-zoom)
(message "No LATITUDE/LONGITUDE properties found on this entry"))))
This is an interactive function that I use when I’m standing on the header in Journelly I want to see on a map. It’s quick and works well. Now I can use my Journelly entries, which are already in org-mode, as a base for a post with a map tile inside Emacs. OSM doesn’t have a native function to export an image, but since I usually want to annotate the image anyway before I make a post out of it, a regular screen-capture app is a good solution, at least for now.
I wrote about Harper before, but I wanted to expand now that I have it working on Kubuntu with a couple of more options.
Harper is good in two scenarios for me: first, when I want something quick and I don’t feel like starting a browser with Grammarly in it, and second, when I write a personal email and the idea of my words going to some AI grammar bot somewhere makes my skin crawl. Otherwise, for my blog (which is public anyway) and work email (I don’t care about those) Grammarly is definitely better.
The issue with Linux is that the makers of Harper geared it toward macOS (Homebrew) and Arch Linux, among other things. It was made for programmers by programmers, and these guys don’t bother with Ubuntu-like distros. Fair, but up until recently it meant I had to jump through hoops.
The quick and easy route in Ubuntu distros (which is what Kubuntu is) is to use snap. I know, I know. I didn’t want to either, but since the Harper makers don’t bother with flatpak, the other option was to install a Rust environment, which is a big overkill just for an app inside Emacs I use like once a month or so or less. I don’t like snap and I don’t use it, but I made an exception here. (Edit: I actually decided to go ahead with Rust and Cargo, and explained what I did)
Now, that snap “shortcut” is by a guy who works with Ubuntu (I think) and maintains his own package for it, so it’s on the edge channel (not stable) and seems to be a lot behind (version .49 to be exact, and Harper is currently 2.2.1!) so if Harper is your choice of grammar check, and you use it daily, I’d suggest against what I’m doing below. I’d install as needed in that case, Rust and all.
With that disclaimer, let’s move on: sudo snap install harper --edge.
Now in Emacs, in Linux, we want to tell it where harper is:
(when (eq system-type 'gnu/linux)
(add-to-list 'exec-path "/snap/harper/current/bin"))
When tells it to add the snap path only when running Linux, since I have the same config for both macOS and Linux.
That’s all… After that, I’ve added some of Harper’s flags, or linters. Here’s the whole code as I have it in my emacs org settings:
(with-eval-after-load 'eglot
(add-to-list 'eglot-server-programs
'(org-mode . ("harper-ls" "--stdio"))))
(setq-default eglot-workspace-configuration
'(:harper-ls (:dialect "American" :linters (:LongSentences :json-false :AvoidCurses :json-false))))
;; Besides choosing American as the language, I also want to ignore long sentences (the main issue is that it hides other errors nested in those) and I also want harper not to tell me when it thinks something is offensive. The full list of these options is in https://writewithharper.com/docs/rules. It needs to be nested inside the :linters option.
(when (eq system-type 'gnu/linux)
(add-to-list 'exec-path "/snap/harper/current/bin"))
;; on a mac, Harper is installed via Homebrew - on Kubuntu, the best option is snap - the harper team does not do a package (flatpak) unfortunately, and I don't want to install Rust just for harper. So.. meh. I did sudo 'snap install harper --edge' for this.
It's official: I prefer Inkwell over Elfeed
Last night I realized two things:
And, yes, I prefer it over my list of feeds in elfeed, which are stored in an .org file - essentially lines of text with comments and tags.
I’m pretty sure this is the opposite case for most folks who use Emacs. First, Emacs users want to use Emacs more, not less, and second, Inkwell is not available without Micro.blog1.
But I think this is the point I’m getting at: Inkwell belongs in Micro.blog; actually, it is Micro.blog.
When I started using Micro.blog three years ago, I considered it mostly an alternative to running my own static site with Hugo, between fixing issues with Hugo, my CSS, Netlify and understanding attempting to understand git and Magit. Yes, Micro.blog is an alternative to all of that, but it isn’t just a blogging platform; It’s a definition of a contemporary blogger.
If you look at Micro.blog’s set of tools, you’ll see what I mean: it contains tools to keep track and post about books, movies and TV shows, private (encrypted) notes, photos and self-made video clips2, save articles and qoutes from around the internet (pocket style), automatic integration with other social media where possible - all of this around your hosted blog, complete with plugins and a theme (and let’s not forget the AI integration, if you want it and turn it on) you can tweak and take with you - your posts, media, css, everything - wherever you go.
And Inkwell adds an important direction to this mix.
My blogging hour in the morning now continues where I left off the night before, with saved highlights and complete articles from other people I keep track of. The integration between Inkwell and Micro.blog, where my reading turns into writing, still requires some work as the UI and some of the bugs get sorted out, but it’s there. And it’s already better and more intuitive for me than Elfeed, which takes place in its own isolated space.
Elfeed is very good at what it does (and hopefully, what it will keep on doing, with its creator leaving Emacs), and it has been good to me. It still is. But Inkwell, Micro.blog, and my recent adventures with finding out more bloggers and learning more about the Indieweb feel like an evolution. It’s the next step of whatever I’m doing here.
Footnotes
1: I recall Manton borrowed the idea from a different RSS reader, but I can’t find the reference right now
2: Finding an alternative to YouTube these days is not easy, and if you’re not trying to “build a brand” and repeat the chant of “click and subscribe,” the only semi-reliable alternative that comes to mind is PeerTube and (maybe Dailymotion?) - but Manton found a way that seem sustainable, at least for now.
Yesterday morning, I imported an old-blog post of mine, which discusses org-id and UUIDs in org-mode. It’s a bit of a deep dive into how org-mode works. I find that I don’t do those as much anymore - probably because I mostly use Emacs “as is” with a few packages I use day to day, and my workflow has been pretty much the same (capture templates not included) for the last two years or so.
Display images with Org-attach and org-insert-link quickly and effectively
Suppose you have an org-mode file and want an image to appear in the buffer. The way to do that is to insert a link to the file, for example:
[[home/username/downloads/image.png]].
Then, you toggle inline images with C-c C-x C-v, and the image should display inside the org-mode buffer, provided the path in the link is correct. If you do this often in your notes as I do, you might as well just turn it on for the entire file with #+STARTUP: inlineimages at the top of your org file, with the rest of the options you have there; this way, images will always display when you load the file. This is all nice and good, and most of us org-mode users probably know that.
A common use case for a full workflow like this is attaching images to your org file. You have a file in your Downloads folder, as shown in the example above, and you want to keep the image with your org file where it belongs, rather than in Downloads, where it will be lost among other files sooner or later.
For this, as most of us know, we have org-attach (C-c C-a by default). This starts a wonderful organizational process for our files:
For example:
./data/acde070d/8c4c-4f0d-9d8a-162843c10333/someimage.png
If you’re not used to how org-attach works, it might take some time getting used to, but it’s worth it. Images (or any file, as we will deal with soon) are kept next to the files they are associated with. Of course, org-attach is customizable, and you can change those folders and UUIDs to make them less cryptic.
For example, my init includes this:
(setq org-id-method 'ts)
(setq org-attach-id-to-path-function-list
'(org-attach-id-ts-folder-format
org-attach-id-uuid-folder-format))
This tells org-mode to change the UUID to IOS date stamp format, so the folders under the data folder are dates, and tells org-mode to use that system (I wrote about this in length in my old blog; it is yet another post I need to bring over here it’s here now.).
In my case, this creates a file reference system by date: inside the data folder, each month of the year has a folder; inside those, a folder for the day and time (down to fractions of seconds) of the attachment. The beauty of org-attach is that you’re not meant to deal with the files directly. You summon the org-attach dispatcher and tell it to go to the relevant folder (C-c C-a to bring it up, then f as the option to go to that directory).
org-attach and displaying images inline are known to many org-mode users, but here comes the part I never realized:
org-attach stores the link to the file you just attached inside a variable called org-stored-link, along with other links you might have grabbed, like URLs from the web (take a look with C-h v org-stored-links). And, even better, these links are added to your org-insert-link, ready to go when you insert a link to your file with C-c C-l.
So when you have an image ready to attach to an org file, say in your Downloads folder, you could first attach it with org-attach, and then you can call it back quickly with C-c C-l. The trick is, since this is an image link (and not just any file), is not to give it a description. By default, org-mode will suggest you describe the link as the file you attached, but inline images do not work like that, and with a description, the image will just display as a file name. In other words:
A link to an image you want to display in the org buffer should look like:
[[file:/Home/username/downloads/someimage.jpg]]
But any other file would look like:
[[file:/Home/username/downloads/somefile.jpg][description]]
By deleting the suggestion, you are effectively creating the first case, the one that is meant to display images. This is explained nicely here.
There’s more to it. As it turns out, the variable org-attach-store-link-p is responsible for the links to these files to automatically be stored in org-insert-link (you can toggle it to change this option). This is why, when you use it, your files or images will show as [[attachment:description]], without the need for the path as specified above.
I have years of muscle memory to undo, as I’m used to manually inserting the links with the full path for my images. I did not realize the links to the images I’ve attached are right there, ready for me to place into the buffer if I only delete the description.
So emacs plus (through homebrew on macOS) keeps giving me this error: Invalid function: org-element-with-disabled-cache.
Does anyone know what this is about, and why it’s happening? No issue with Emacs on Linux (same config) or when I had emacsformacos (same config)
I believe I fixed it this morning (3/11) by removing Emacs-plus completely and reinstalling.
I also ran Brew Doctor between steps 2 and 3 and found a couple of issues I resolved, which shouldn’t be related, but you never know.
What started this whole thing, I think, was that I wanted to try the new org-mode on top of the old org-mode. I am not too sure, but it seems like that was the problem.
A new Emacs annoyance: org-capture: Capture abort: Invalid function: org-element-with-disabled-cache when I try to use org-capture. Fails the first time, works the second. Where did it come from and how do I get rid of it…?