The joke about Emacs being an operating system is an old one but lately the idea seems to be being taken more seriously. Here’s the latest example. Significantly, the poster, Bi-Jean, is a self-confessed n00b who doesn’t work in the tech industry, just someone who likes playing with computers and is curious about the best ways of using them. The idea seems natural to Bi-Jean.
If you believe, as I do, that the best way of thinking of Emacs is as a latter-day Lisp Machine, the idea of it being an OS makes more sense. Specialized applications aside, there’s basically no function that you can’t implement from within Emacs except arguably a decent Web browser. From that perspective, the “real” OS is viewed as a set of device drivers for Emacs. It’s a point of view adopted by many Emacsers who claim not to care what OS it’s running on.
My own view, as someone who does almost everything from within Emacs, is that “My operating system is Emacs and Linux/macOS/Windows is just a set of device drivers” is a nice joke that captures an underlying truth but isn’t truly realistic. I always say that I do virtually everything in Emacs and Safari but the “virtually” provides a little wiggle room. For example, I use Fantastical to sync my calendar across all my devices, the Reminders app to set a reminder across all my devices, and the Apple Messages app for texting—although I do use Emacs to compose the text—so it’s not really Emacs all the way down.
Still, a case can be made that in an essential way, Emacs really is my OS. Perhaps more important is the fact that it doesn’t really matter. I do most of my work—other than browsing—from within Emacs and if that makes Emacs my operating system, fine but I also depend on macOS for more than just running Emacs.
As you all know by now, I’m all in on Journelly. I use it to implement my memo book in which I record virtually everything that happens in my day. For me, one of its major benefits is that it uses Org mode markup to record its data and can (optionally) export it to the iCloud so that I can interact with it on my Mac, which sees the data as a normal Org file.
“Interact” means that I can read, edit, and add to the data in my memo book from any of my devices including my Mac. It’s a lot better than I expected it would be compared to my previous procedure of using the Apple Notes app. I find that I take better, more comprehensive notes and can easily add pictures and links to things on the Web.
That brings me to a post on the Emacs subreddit from TeeMcBee that asks how people interact with Journelly from their Mac. It’s a natural question, especially for those who haven’t been involved with Journelly from the beginning. In the comments, Álvero Ramírez offers up his own solution, which is similar but identical to mine. Our main difference is where we export the data to. The easiest thing is to simply choose iCloud Drive as your storage option. That’s what Ramírez does.
The problem with that option is that it stores the data at a place with a complicated path in the iCloud. Because of that, I chose to use the Other… option and directed it to a subdirectory of my Documents folder. I thought that that would avoid having to set symlink to the file. It turns out, though, that it was still easier to set a symlink so I recommend that you choose the iCloud Drive option and set a symlink to it from wherever is convenient.
To kickstart the Emacs Carnival, and as a hat tip to our recent inspiration, this month’s topic is borrowed from the June IndieWeb Blog Carnival: the topic is “Take Two”, hosted by Nick Simon:
Ever wish for a do-over? “Take two!” (or three, four, etc.) might be shouted by a film director or audio engineer looking to get a somewhat different outcome from a group of actors or musical performers. Would you like a second shot at something that didn’t land?
This is a perfect fit for Emacs users:
We usually don’t nail “it” on our first try – init.el bancruptcy; refactoring hacky Emacs Lisp code; leaving Emacs only to come back englightened much later; running two Emacsens in parallel. There are plenty of possible second takes when it comes to Emacs!
So for this month, our first community blog carnival, I want you to:
mediate on “Emacs” and “take two”,
blog about it,
then send me a link to your blog post.
That’s it! I’ll aggregate submissions for all of June in this post.
Don’t have a blog, yet?
Well, just start one already! :)
It’s the future of the internet!
Blogging is the future, and the future is now!
What’s a Blog Carnival, Again?
This is our first Emacs Carnival, so you may not know the format. A blog carnival is a fun way to tie together a community with shared writing prompts, and marvel at all the creative interpretations of the topic of the month. I’ve provided a couple of interpretations above, but you may think of something else entirely. That’s amazing, roll with it, that’s what makes this fun!
Thanks to Sacha Chua for her post “Working on the plumbing of a small web community” that was part of the May 2025 IndieWeb Carnival, and got me thinking why there’s no Emacs Carnival, yet, and for her encouragement to kickstart this.
For future Carnivals, check out the “Carnival” page on EmacsWiki . It includes instructions, and is our community space to coordinate participants and topic ideas.
Submissions
Comment below or DM/email me with your submission! I’ll collect submissions up to, and including, July 1st (Central European Time), so that every time zone has had a chance to meet the June 30th deadline :)
In I used Emacs📖
for the second time…the time that it stuck. The first
time was in . I was transitioning from a Microsoft and International Business Machines Corporation📖
shop
to a Linux📖
shop. At the previous job, I used the tools offered: a green screen
text editor for Report Program Generator programming language from IBM (IBM RPG 📖)
, Microsoft Access/Visual Basic, and Plex (a case tool
allowed multiple inheritance and could build either C or IBM RPG
) programs.
I’ve thought a lot, though never all that deep, about that decision to set Emacs
aside. And wonder at that moment in had I chosen to adopt Emacs
; what
might that path have been? For a few months after stepping away from Emacs
I
used JEdit📖
. Then switched to Textmate📖
in , in large part because
that was the de facto editor of Ruby on Rails (Rails 📖)
.
What would’ve made the then Emacs
sticky enough for me to use? I was then in
the process of learning PHP Programming Language (PHP 📖)
and pre-Prototype Ajax calls.
(Sidenote: Before jQuery there was Prototype and before that an even hotter mess. I
remember adopting Rico.)
At home, I was
using Lotus Notes to model data for Role Playing Games (RPGs 📖)
.
Why Lotus Notes? It was the tool I had and knew. Further, the database and
data were all in one file that I could use. A portability. Contrast with work,
where I was dipping into the realm of Postgresql📖
and MySQL.
Standing and running those locally was not quite something I wanted to pursue;
and for my hobby I would’ve also needed an application. The person who nudged
me to consider Emacs
was also writing RPG
tools, but was choosing to write in
Python. Had they said “I’m writing this all in Emacs
”, I think I would’ve
listened a bit more.
Reflecting on the following decade or so, I abandoned that Lotus Notes project;
it worked well enough but I was losing access to the license to run it. I was
on the path to making various Rails
applications. So I spent time migrating
that Lotus Notes application to a Rails
application. But I abandoned that
application and started up several successors; all abandoned.
For these personal projects, nothing quite stuck. Things came close in my
gm-notepad: A command-line tool to help with your GM-ing. Started before I
switched to Emacs
, it was a Read-eval-print loop (REPL 📖)
environment that could be used for note taking
while running a game. And generating results from random tables (that could be
created on the fly).
Had I been using Emacs
just enough before Rails
, what would’ve kept me from
later jumping to Textmate
?
I would’ve had about four months to acclimate to Emacs
. And in that time I
would’ve needed to see the potential of a Lisp📖
machine; namely its REPL
and how
I might be able to model that Lotus Notes application in Emacs
. That was a
likely crease.
Looking to the switch that stuck, from the to the four months
later my Emacs config I made 231 commits into my Emacs
configuration. During
that time I had accumulated/created 3200 lines of Lisp. Granted, that 4 month
window was one in which I had minimal job responsibilities and no social
engagements; meaning lots of time for exploration.
Contrast with the time frame to , in which my
children were quite young. We were also hosting twice a week events at our
house and a full-time job that was very much new to me.
My available time would’ve been different.
I’m also unclear how I would’ve managed packages. And what packages were
available? The baseline Emacs, with tutorial, is quite robust. The features of
bare Emacs
were “competitive” with my understanding of what I needed in a text
editor.
I don’t know what Emacs 22 of would’ve felt like compared to me joining
around Emacs 27. How many init.el bankruptcies might I have declared in those
two decades?
Factors that might have helped:
First, learning about Structure and Interpretation of Computer Programs (SICP 📖)
during that time. While I haven’t read SICP
, knowing
then that it described concepts in Scheme, a Lisp
dialect, I might have pursued
reading it.
(Sidenote: I don’t feel the same compulsion now to read it as I would’ve then. But
maybe I should seek out a print copy.)
I learned about it one year later, in .
Second, stumbling upon the EmacsWiki, mailing list, and Internet Relay Chat (IRC 📖)
. That is finding
the places where folks were troubleshooting their Emacs
problems but also
exploring how to extend Emacs
.
Third, learning of Alex Schroeder, both involved in RPGs
and Emacs
, may have
helped. That is finding just enough folks at the intersection of two aspects of
my then (and current) interests. There are a few others.
I’m wondering how a younger me would’ve handled being a few months into Emacs
and then seeing the flashy Textmate
. Would that time with Emacs
have been
sticky enough to keep with it? And had I chosen Textmate
, when it soured, would
I have considered a return to Emacs
? Or would Sublime Text📖
win out? What of
Atom📖
?
It took me attending the funeral of three text editors to finally wake and pick
Emacs
; but even then only after exploring Visual Studio Code (VS Code 📖)
and again saying “nope” to
Vim📖
.
(Sidenote: I can use Vim
just well enough to favor it over something like Nano.)
Adopting Emacs
took me knowing the baseline of what I wanted from my editor and
a prior memory of Emacs
.
Would I know that without the years of practice? It also took experiencing
skill obsolescence; each bit of learning how to extend an editor is useful but
the specifics are often non-transferable.
Would I have the wisdom to pierce the veil of first Textmate
then Sublime Text
then Atom
? And see that by construction and design they would only be able to
be a narrower subset of Emacs
’s capability? Could I have seen past the gloss
and chrome?
Would I have considered the Lindy Effect📖
? Or understood the potential of the
cumulative effect of my editor? Moving away from one editor has meant leaving
behind knowledge of its configuration and extension; each their own foibles.
Would I have been able to see the difference of extending Emacs
versus extending
Textmate
? Emacs
hits different than Textmate
, Sublime Text
, and Atom
. Where
Emacs
’s currency is buffers, lists, and functions; the others had
hard-boundaries and Application Programming Interfaces (APIs 📖)
.
About a year before leaving Atom
, I set about writing an extension. My memory
is that it was hellish process; and more than just needing to create two almost
duplicate chunks of code/data to make much of anything happen.
Contrast Emacs
, where extending is assumed, encouraged, consistent, and
facilitated by powerful introspection. I’ve learned a lot by reading Emacs
commands, seeing what they compose and choosing one of those “inner” functions
from which to build.
That hits different than reading an editor’s extension API
, which is the
implementation teams means of stating “this is how you are allowed to
change this program.”
I’ve also thought recently about I found a way to create order from my jumbled
ideas. I use Emacs to think as well as help recall those thoughts. The
functions I’ve written are a mix of help me write and help me find what I wrote.
Those functions provide breadcrumbs for further extensions; with the
thought being that I’m most likely to extend/enhance functionality adjacent to
or overlapping with a concept I’ve already “touched.”
I just published the latest stable release of the Modus
themes. The change log
entry is reproduced further below. For any questions, you are welcome
to contact me. I will now work to
apply these same changes to emacs.git, so please wait a little longer
for the updates to trickle down to you.
Package name (GNU ELPA): modus-themes (also built into Emacs 28+)
Backronym: My Old Display Unexpectedly Sharpened … themes.
4.8.0 on 2025-06-11
This is a small release that corrects a mistake I made in the previous
version. It also introduces some minor refinements.
Matching parentheses are easy to spot
In version 4.7.0, I made the mistake of merging some stylistic
tweaks to show-paren-mode that I was experimenting with. The idea
was to get a feel for how the subtle colouration of matching
delimiters affects the usability of the themes. In short, it is not a
good default for our purposes (though users have the option to
override the applicable colours, as explained in the Modus themes
manual).
The bg-paren-match of modus-vivendi-tinted is a bit greener
We go from #5f789f to #4f7f9f. The latter fits better with the
rest of the theme.
Refined the “mail” semantic mappings of the tinted themes
This concerns message.el and anything building on top of it, like
Gnus, Mu4e, and Notmuch. I made modus-operandi-tinted and
modus-vivendi-tinted use two colours that are more in line with the
established patterns of their respective theme. The changes are small,
but contribute to a more consistent experience.
A new property semantic mapping is available
By default, it uses the same colour as the variable. Users who want
to have more refined colouration in supported modes (typically
involving tree-sitter), can change the relevant “palette overrides”
user option we provide, such as modus-themes-common-palette-overrides
or modus-operandi-palette-overrides and related.
Its faces were already consistent with the Modus themes, though now I
cover them at the theme level to subject them to palette overrides.
The “ancient” Gnus messages are styled properly
Those are only ever seen if the user configures Gnus in a certain way
and follows a specific workflow. They now get a subtle foreground
value. This is in response to the issue 119 by sivaramn:
https://github.com/protesilaos/modus-themes/issues/119.
The modus-themes-rotate command can now go backwards
When called with a prefix argument (C-u by default), this command
will rotate the modus-themes-to-rotate from right to left.
Otherwise, it goes from left to right.
I’ve written several times about Álvaro Ramírez’s DWIM tools [1, 2, 3, 4, 5, 6] and their use in easily invoking command line utilities from the comfort of Emacs. Ramírez has a large collection of such utilities built on the DWIM Tool framework but I’ve never seen anyone else use it for their own work.
Now JTR over at The Art Of Not Asking Why has a post that describes his own use of DWIM Tools. JTR wanted to compress videos while preserving their resolution. That’s pretty easy to do using FFmpeg and JTR knew how to do it but he decided to see if he could use DWIM Tools for the job.
It turned out to be pretty easy as you can read at JTR’s post. The lesson I take from this is not that there’s another application available under the DWIM Tools umbrella but that it’s pretty easy to add one. If you have some command line utility that would be convenient to invoke from within Emacs, you should take a look at DWIM Tools. It’s available from Melpa and GitHub.
Back when we were colleagues, I was still a Vim user but had already begun making feeble attempts to move to Emacs. It was always a silly thing, like the default scrolling behavior, that drove me away. In my case, it was finally moving to Lisp that pushed me over the edge to embracing Emacs. Martin’s journey was similar. He tried several times to move to Emacs but it just wouldn’t take, until it did.
While we Emacers can rejoice in another convert, Martin’s post is actually a balanced account of the strengths and weaknesses of Emacs. The downsides that Martin mentions are mostly the usual difficulties that n00bies encounter. Those of us who have made the journey from n00bie to journeyman can forget how hard it was at first. In particular, Martin calls out the difficulty of coercing Emacs into behaving as a “modern” editor by which he means using things like Tree-sitter and LSP. He complains, correctly, that there isn’t a good guide to help beginners configure Emacs to support a useful, modern workflow.
On the other hand, he notes that Emacs can molded into whatever you want it to be. It is, as I always say, a light weight Lisp Machine, although Martin doesn’t use that term. That fact, he says, makes it unlikely that folks who aren’t willing to “hack around with their editors” will ever adopt Emacs.
Martin ends by saying,
But the thing is, I think I also get Emacs. And once you get Emacs, there’s probably no going back.
I doubt he understands how true that is. He’s like a guy who’s fallen into quicksand and doesn’t realize it. For him, as for us, there is no escape.
I mentioned Rameriez’s dwim tools, and it’s only natural to do some IT for fun when I rest from IT at work on the weekend, Right…? Eh, don’t answer that.
One of the important and excellent things about Rameriez’s package is that it makes it easy to build something custom of your own using the “Lego blocks” he provided with the package.
For example, one of the commands that comes with the package is dwim-shell-commands-resize-video, which lets you resize the resolution of a video (and through that, its size). It does the job well, but I wanted something that compresses videos while retaining their resolution for quality. I know how to do this directly with ffmpeg, so I thought I’d give dwim a go, and got something working pretty quickly:
(defun jtr/dwim-shell-command-compress-mp4-fast ()
"Compresses mp4 down further using slow preset."
(interactive)
(dwim-shell-command-on-marked-files
"Compresses MP4s with libx265 using slow preset to bring down size""ffmpeg -i '<<f>>' -c:v libx265 -crf 25 -preset slow '<<fne>>_compressed.mp4'":utils"ffmpeg"))
There are a couple of things at work here with ffmpeg:
First, libx265, which is a newer decoder than the default libx264. The newer version does a better job at retaining video quality when compressing, but at the cost of compatibility; some older systems might not be able to play the resulting MP4 file or say there’s something wrong with it until you install the needed decoder. If you’re playing with ffmpeg regularly, you probably won’t have a problem - but the people you send these videos to might, so keep that in mind.
Second, the slow preset. This increases the time it takes ffmpeg to work on the video as it combs through the frames more carefully. I forget exactly what it does, but I believe it grabs a smaller group of frames each time, so more frame groups (hence more time) with different compression values.
Lastly, the CRF value is at 25, a bit less than the default 28 for libx265, so a bit less compression. I can probably push it up a bit further, but the above already reduces the file size dramatically.
Jorgensen has his own post on the matter that goes into a bit more detail. As far as I can tell, unless your using Mitsuharu Yamamoto’s Emacs port for the mac this isn’t a problem but if you’re not using a NextStep based port, you’re probably going to have a problem using macOS keybindings in Emacs.
Not to worry though. If you want those keybindings and your port doesn’t provide them, Jorgensen shows you how to get them. His setup assumes the ⌘ Cmd key is mapped to Super so that, for instance, ⌘ Cmd+s is mapped to Super+s. If you have ⌘ Cmd mapped to something else, it may not work as well. For example, if you map ⌘ Cmd to Meta the way many people do, then ⌘ Cmd+v is going to get you a scroll up rather than a paste.
As I said in my original post, I don’t think that there’s a lot a value in having these bindings added to Emacs—but see hmelman’s comment for an contrary viewpoint—so I wouldn’t bother changing my mappings if you’re a ⌘ Cmd == Meta user. Regardless, as Jorgensen says, “Emacs is a wonderfully flexible tool, is it not?”
macOS uses some common Emacs editing keystrokes by default, and that
You can do much better by adding other Emacs keystrokes to those that macOS will recognize.
Here’s one such recent reminder. Now Bozhidar Batsov has turned the tables and revealed that Emacs also recognizes many macOS commands1. If you look in ns-win.el you’ll see a rather long list of macOS bindings that Emacs will recognize. You can, for example, save a file with ⌘ Cmd+s or start an incremental search with ⌘ Cmd+f. There’s a surprisingly large number of other such bindings. Take a look at Batsov’s post or ns-win.el for the details.
I didn’t know about any of this except for using ⌘ Cmd+f for isearch. I stumbled on that because I rebound Ctrl+s to swiper-isearch but sometimes wanted to do a regular incremental search. Even then, it didn’t click that Emacs was emulating macOS keybindings.
Other than that—and examples like it that other users may need—I can’t see the point of using those bindings. It seems like just another way of confusing my muscle memory. Of course, as I’ve confessed before, I’m very bad at handling multiple sets of keybindings.
For me, it makes more sense to make Emacs keybinding available to macOS rather than the other way around. Of course, you may disagree and want to standardize on macOS bindings. The great thing is that, as usual, Emacs2 let’s us have it our way.
Charles Choi has another great addition to his Casual Suite. This time he helps us with the common problem of figuring out what time it is in some other place. As Choi says, the Internet makes it common to communicate regularly with people from all over the world. Even the introverts at Irreal find themselves dealing with this.
Choi says that the most common way of dealing with the problem is with a clock app—which typically show times from all over the world—or just looking it up on the Internet. I do the latter. When I want to communicate with someone in, say, London, I simply search for something along the lines of “what time is it in London?”.
Choi notes that Emacs already has all the machinery to deal with this sort of thing. It just needs to be pulled together into a user accessible package. That’s what Casual Timezone does. It provides a myriad of ways to map the time at one place to the time at another.
At this point, the Casual Suite has so many useful apps that it’s probably best to simply install the whole suite even if there are some that you don’t use. Choi’s use of transient menus makes it easy to use them without having to deal with a bunch of bindings that you seldom use and probably won’t remember. Take a look at his post for an animation of Casual Timezone in action and see it it’s something that might fit your needs.
Bozhidar Batsov has a post up about Little known macOS keybindings. It’s great with one large caveat: it’s only true for some Emacsen on macOS. There are two basic ports (not to be confused with macports or similar): NextStep (ns) and Cocoa (mac). A quick search will explain the names, but one might recognize the abbreviations if one has ever added some Mac-specific code in their config that includes something like:
Here is a sample of what I do in my config to get (most) of these keybindings in my Emacs suited to my needs:
;; My Super (s-) maps
(use-package emacs
:bind
(
("C-s-SPC" . nil ) ; blocked by Alfred for me; ns-do-show-character-palette in NS port
("M-s-h" . nil ) ; ns-do-hide-others in NS port
("s-&" . kill-current-buffer )
("s-'" . next-window-any-frame )
("s-'" . other-frame )
("s-," . customize )
("s-0" . text-scale-reset )
("s-:" . ispell )
("s-<" . text-scale-decrease )
("s-<down>" . end-of-buffer )
("s-<left>" . backward-sentence ) ; move-beginning-of-line in NS port
("s-<right>" . forward-sentence ) ; move-end-of-line in NS port
("s-<up>" . beginning-of-buffer )
("s->" . text-scale-increase )
("s-?" . info ) ; conflicts w/ MacOS
("s-C" . nil ) ; conflicts w/ Named Keyboard Switcher; ns-popup-color-panel in NS port
("s-D" . dired )
("s-E" . edit-abbrevs )
("s-H" . nil ) ; ns-do-hide-others in NS port
("s-L" . shell-command )
("s-M" . manual-entry )
("s-S" . write-file ) ; ns-write-file-using-panel in NS port
("s-Z" . redo )
("s-a" . mark-whole-buffer )
("s-c" . my-smart-copy-dwim ) ; ns-copy-including-secondary in NS port
("s-d" . nil ) ; isearch-repeat-backward in NS port
("s-e" . isearch-yank-kill ) ; blocked by my Keyboard Maestro macro top open Finder window
("s-f" . consult-line-multi ) ; isearch-forward in NS port
("s-g" . er-keyboard-quit )
("s-h" . nil ) ; ns-do-hide-emacs in NS port
("s-j" . exchange-point-and-mark )
("s-k" . kill-current-buffer ) ; Xah has a better function for this
("s-l" . goto-line )
("s-m" . iconify-frame )
("s-n" . make-frame )
("s-o" . mac-open-file-using-panel ) ; ns-open-file-using-panel in NS port
("s-p" . print-buffer ) ; conflicts w/ MacOS print
("s-q" . save-buffers-kill-emacs ) ; TODO make this safer
("s-s" . save-buffer )
("s-t" . menu-set-font )
("s-u" . revert-buffer )
("s-v" . xah-paste-or-paste-previous) ; yank in NS port
("s-w" . xah-close-current-buffer ) ; delete-frame in NS port
("s-x" . my-smart-cut-dwim )
("s-y" . nil ) ; ns-paste-secondary on NS port
("s-z" . undo )
("s-|" . nil ) ; shell-command-on-region in NS port
("s-~" . previous-frame )
:map org-mode-map
(
("s-'" . org-single-quote-region-or-point)
("s-+" . cc/emphasize-strike-through )
("s--" . org-subscript-region-or-point ) ; center-line in NS port
("s-<tab>" . completion-at-point )
("s-=" . cc/emphasize-verbatim )
("s-C" . cc/emphasize-code )
("s-\"" . org-double-quote-region-or-point)
("s-^" . org-superscript-region-or-point ) ; orig. kill-some-buffer
("s-_" . cc/emphasize-underline )
("s-b" . cc/emphasize-bold )
("s-e" . cc/emphasize-dwim )
("s-i" . cc/emphasize-italic )
("s-r" . cc/emphasize-remove )
("s-l" . org-goto-line )
)
:map markdown-mode-map
(
("s-<tab>" . completion-at-point )
("s-=" . cc/emphasize-verbatim )
("s-C" . cc/emphasize-code )
("s-_" . cc/emphasize-underline )
("s-b" . cc/emphasize-bold )
("s-e" . cc/emphasize-dwim )
("s-i" . cc/emphasize-italic )
("s-s" . cc/emphasize-strike-through)
)
)
)
Some of the functions I call come from other bits of my config. ※ Where one sees ‘nil’ above is where there’s a conflict or where I’m not sure what I want on that keybinding yet.
Here’s a neat one that opens a file using the macOS dialog:
(defun mac-open-file-using-panel ()
"A quick way to open files with your system file picker,
URL `https://christiantietze.de/posts/2022/12/use-file-open-dialog-for-file-actions/'
Created: 2025-06-04
Version: 2025-06-04"
(interactive)
(let ((last-nonmenu-event nil)
(use-dialog-box t)
(use-file-dialog t))
(call-interactively #'find-file))
)
A couple of people wrote back to me regarding my last post about the challenges I have with Journelly (which, again, don’t really have anything to do with the app itself, but my workflow).
In an Email, HTH let me know that while Syncthing is not officially supported on iOS, there is an app that works and does the job just fine: SyncTrain. I tested it, and it successfully synced my files to my iPhone, iCloud not included. That’s an amazing find.
Meanwhile, I was thinking about how I can better streamline my process of refiling Journelly’s entries to my journal, where they are… archived. Duh! I can simply use org-mode to archive entries into my journal file. All I need to do is define the file I want them to archive into in the file options at the start of the file. Journelly even has an archive feature built in, but since I want to save my entries off the phone, it won’t work for me.
However, I realized I might not want to send my Journelly entries away. Journelly is convenient, and I use it constantly for notes. Having these available on my iPhone (where Journelly has an excellent search feature with tags) and on Emacs on the Mac at the same time is a boon to my productivity, not to mention, it just looks so nice on the phone.
So now I’m considering a different mental approach. Instead of refiling and moving entries away from Journelly, I’m going to try and expand on what I have there later. Some of this I already discussed before: things like meeting entries, for example, can be copied later to my dedicated meeting file, and activities can be copied to my event file, if I feel there’s more to add. The missing piece is expanding on “mind dumps” in Journelly that go into tangents. For that, I want to break the ideas into specific subjects with Denote later. For example, if I write an entry in the morning about Journelly and I’m realizing I’m rambling about the app and have ideas, I can later put these ideas into a “Journelly thoughts” note later with Denote, along with the appropriate keywords and attachments, as needed. This, I think, also covers the concern I have regarding privacy and iCloud, as the Journelly entry will just cover the initial nugget, where I will write some key points which I will later develop in a dedicated note off Apple’s servers.
This is all pretty new and raw in my head, so I’m going to try that out for the rest of the week and see how I feel.
While packages like orderless provide flexible “any word, any order” completion, sometimes you want something lightweight and easy to tweak (well I do anyway). In this post, I’ll show you how to implement a simple orderless-like completion style using only Emacs Lisp, and how to integrate it smoothly into your workflow.
Traditional completion in Emacs often matches prefixes or substrings, but sometimes you want to type a few key parts of a word, in any order, and jump straight to your target. That’s what orderless and similar completion styles allow. But what if you want to write your own, or experiment with the logic?, well I will show you how…
The user’s input (a string) is split into words on spaces, dashes, or commas. This produces a list of “search terms.” This means that, in the minibuffer, the word separator can be any of these characters. I was initially really faffing around and struggling to work out how to insert a space between words in the minibuffer, as it seems to perform some form of completion. However, I eventually figured out that M-SPC actually inserts a space, allowing you to separate words. I use fido-mode, so I’m not sure if this is the same for other minibuffer completion systems.
After initially adding in the comma separator however I found that I actually prefer it, it is easier to access and I don’t think any keywords, functions e.t.c will typically contain a comma?
Pattern Construction:
For each word, a regex pattern is constructed: \\b.*WORD.*.
This means: “find a word boundary, followed by any characters, then the word, then anything else.” This is a bit looser than strict word matching, and you can tune it.
Candidate Filtering:
We generate all possible completions with all-completions and then filter them down. For a candidate to match, all the search terms (words) must appear somewhere, in any order.
Case Sensitivity:
Matching respects completion-ignore-case, so your results will be case-insensitive if you want of course.
Registering and Using the Style
To make Emacs aware of your new completion style, add it to completion-styles-alist:
You might not want this style everywhere (which I suspect is likely). For example, in file completion you might prefer strict prefix matching. So, let’s activate it only in the minibuffer:
(defun setup-minibuffer-completion-styles ()
"Use orderless completion in minibuffer, regular completion elsewhere.";; For minibuffer: use orderless first, then fallback to flex and basic (setq-local completion-styles '(basic simple-orderless flex substring)))
;; Hook into minibuffer setup(add-hook 'minibuffer-setup-hook#'setup-minibuffer-completion-styles)
Tweaking and Extending
Pattern Tuning:
The regexes can be made stricter or looser (e.g., remove \\b for more “fuzzy” matching).
Word Separators:
You can split on other characters if your workflow uses different delimiters.
Order of Styles:
Adjust the order in completion-styles to prefer your custom style over others. I found that if the simple-orderless style was listed first, pressing Tab to bring up the completions buffer doesn’t work, which I like to use sometimes, so that is why basic is first.
Conclusion
With just a handful of lines, you can build your own orderless-like completion style, giving you full control and transparency. This is a great starting point for experimenting with more advanced completion logic, and a good illustration of the power of Emacs’ built-in completion framework!
Bozhidar Batsov is back with a quick tip that many of you will probably find useful. It’s an improvement to keyboard-quit or, as we all know and love it, Ctrl+g.
One of Batsov’s pet peeves is that keyboard-quit doesn’t function as expected when the minibuffer is active. Happily that and a few other infelicities are easily fixed as he shows in his post. The code that Batsov presents in his post is short. It’s more comment than code yet it does fix the problems that were annoying Batsov.
Here, from the code comments, is what his improved code does:
The DWIM behaviour of this command is as follows:
- When the region is active, disable it.
- When a minibuffer is open, but not focused, close the minibuffer.
- When the Completions buffer is selected, close it.
- In every other case use the regular `keyboard-quit'."
You don’t have to edit Emacs source code. You simply include his function in your init.el and remap Ctrl+g to it. It’s easy to try out his code and if you don’t like it, simply drop back to the default behavior by undoing the key sequence remapping.
I just published a video about a Reddit post in which an Obsidian user asks about Emacs: pros and cons, and “aha” moments.
I’m not big on software supremacy type arguments. Whatever tool you decide to use is the best tool for you. I don’t see the point in forever touting one tool over another.
However, I don’t want to downplay the philosophical side of the argument. People who spend time carefully plotting out software choices are no different than laborers in any other field who want to pick the best tool for whatever job they’re doing.
For whatever reason (and I would be curious to get reader comments on this), users of open source tools tend to be more philosophical, I’ve noticed, than users of Windows or Mac products. What I mean by that is, FOSS users tend to value choice, and with that choice there is a greater assumption that you can make wise choices and unwise choices.
Quick example. A Mac user who needs to do some design work has no choice: they have to shell out for a Photoshop license. (They could consider using something like GIMP, but for most users that option would be too beyond the pale, and they might fear the difficulty of integrating a non-standard open source tool within their existing workflow.)
On the other hand, someone who has grown accustomed to open source tools takes on a whole different set of questions. “Can I use GIMP for my project? Of course, but do I need to use it? Couldn’t I just assemble my graphical items into a script and pipe it into ffmpeg? What is the best tool for this particular job? What is my ideal result? Should I favor speed or accuracy? Or both?”
Anyway… back to the Obsidian question.
Obsidian is a fine tool. If anyone is purely interested in taking notes and does not use Emacs already, I’d recommend just sticking with Obsidian. It does exactly what you need it to do.
However, if you’re using Emacs already, and you’re comfortable with the interface, I couldn’t think of a good reason to use Obsidian, unless you want to show off a cool hyperlinked graph of your notes and tags.
A few of the other points I mentioned in the video:
Emacs provides a superior writing environment.
You can code your own note system with Emacs lisp.
Emacs’s longevity makes it a safer choice for long term projects.
Whatever tool you decide to use, it’s always best to first take a step back and decide what your ideal outcome would be. Then you can more quickly sample different tools and get an idea of which one will work best for you.
Tree-sitter has taken the world of programming by a storm.
Together with LSP, it’s probably the technology that has influenced the
most programming editors and IDEs in the past several years.
And now that Emacs 29+ comes with built-in Tree-sitter support
I’ve been spending a lot of quality time with it, working
on clojure-ts-mode and neocaml-mode.
There’s a lot I’d like to share with you about using Tree-sitter effectively, but
today I’ll focus on a different topic. When most people hear about Tree-sitter
they think of font-locking (syntax highlighting) and indentation powered by
the abstract syntax tree (AST), generated by a Tree-sitter grammar.
For a while I’ve also been thinking that the AST data can also be used
for simple, yet reasonably accurate, code completion. (within the context of
a single code buffer, that is) That’s definitely not nearly as powerful
of what you’d normally get from a dedicated tool (e.g. an LSP server), as
those usually have project-wide completion capabilities, but it’s pretty
sweet given that it’s trivial to implement and doesn’t require any
external dependencies.
Below, you’ll find a simple proof of concept for such a completion, in the context
of clojure-ts-mode:1
(defvarclojure-ts--completion-query-globals(treesit-query-compile'clojure`((source(list_lit((sym_lit)@sym(:match,clojure-ts--variable-definition-symbol-regexp@sym)):anchor[(comment)(meta_lit)(old_meta_lit)]:*:anchor((sym_lit)@var-candidate)))(source(list_lit((sym_lit)@sym(:match,clojure-ts--function-type-regexp@sym)):anchor[(comment)(meta_lit)(old_meta_lit)]:*:anchor((sym_lit)@fn-candidate))))))(defconstclojure-ts--completion-annotations(list'var-candidate" Global variable"'fn-candidate" Function"))(defunclojure-ts--completion-annotation-function(candidate)(thread-lastminibuffer-completion-table(alist-getcandidate)(plist-getclojure-ts--completion-annotations)))(defunclojure-ts-completion-at-point-function()(when-let*((bounds(bounds-of-thing-at-point'symbol))(source(treesit-buffer-root-node'clojure))(nodes(treesit-query-capturesourceclojure-ts--completion-query-globals)))(list(carbounds)(cdrbounds)(thread-lastnodes(seq-filter(lambda(item)(not(equal(caritem)'sym))))(seq-map(lambda(item)(cons(treesit-node-text(cdritem)t)(caritem))))):exclusive'no:annotation-function#'clojure-ts--completion-annotation-function)))
I hope you’ll agree that the code is both simple and easy to follow (especially
if you know a bit about Tree-sitter queries and Emacs’s completion APIs). The
meat of the example is clojure-ts--completion-annotation-function, the rest is
just completion scaffolding.
And the result looks like this:
Not too shabby for 30 lines of code, right? With a bit more efforts this can be made
smarter (e.g. to include local bindings as well), and potentially we can even be
consulting all open buffers running clojure-ts-mode to fetch completion data
from the as well. (although that’s probably an overkill)
Still, I think that’s an interesting use of Tree-sitter that some of you might
find useful. It seems that Nic Ferrier has been playing with this idea recently
as well - check out his recent video on the subject
here.
In time Tree-sitter will redefine how we’re building Emacs major modes and what they can do.2
It’s still early days and sky is the limit. Exciting times ahead!
That’s all I have for you today. Keep hacking!
P.S. I plan to write more on the topic of Tree-sitter and how to use it
in Emacs major modes, but in the mean time you might find some of my development notes
useful:
Today’s article is going to be a bit more weird than usual… mostly because I’ve
set to write about one topic, and ended up about writing something completely different
in the end… Here we go!
TL;DR Many common macOS keybindings (e.g. Command-s, Command-z,
Command-f, etc) work in Emacs. And, of course, it’s well known that
macOS uses by default Emacs-like (readline) keybindings everywhere. (e.g. C-a and C-e)
I’m guessing 99% of Emacs users know that the most common ways to start isearch
are with isearch-forward (C-s) and isearch-backward (C-r). That’s not
the full story, though! While working on my recent isearch article I noticed that
out-of-the-box there are two other keybindings for those commands:
s-f (isearch-forward)
s-F (isearch-backward)
Note:s in this context means Super, which is usually Win in Windows and Command
in macOS.
When I saw those I was like “hmm, seems someone wanted to make Emacs a bit more
approachable to macOS users coming other editors”. But here things got
interesting…
I tried to find out where those extra keybindings were defined, and
after a bit of digging I found them in the ns-win.el library1, which defines a
ton of macOS-specific keybindings:
;; Here are some Nextstep-like bindings for command key sequences.(define-keyglobal-map[?\s-,]'customize)(define-keyglobal-map[?\s-']'next-window-any-frame)(define-keyglobal-map[?\s-`]'other-frame)(define-keyglobal-map[?\s-~]'ns-prev-frame)(define-keyglobal-map[?\s--]'center-line)(define-keyglobal-map[?\s-:]'ispell)(define-keyglobal-map[?\s-?]'info)(define-keyglobal-map[?\s-^]'kill-some-buffers)(define-keyglobal-map[?\s-&]'kill-current-buffer)(define-keyglobal-map[?\s-C]'ns-popup-color-panel)(define-keyglobal-map[?\s-D]'dired)(define-keyglobal-map[?\s-E]'edit-abbrevs)(define-keyglobal-map[?\s-L]'shell-command)(define-keyglobal-map[?\s-M]'manual-entry)(define-keyglobal-map[?\s-S]'ns-write-file-using-panel)(define-keyglobal-map[?\s-a]'mark-whole-buffer)(define-keyglobal-map[?\s-c]'ns-copy-including-secondary)(define-keyglobal-map[?\s-d]'isearch-repeat-backward)(define-keyglobal-map[?\s-e]'isearch-yank-kill)(define-keyglobal-map[?\s-f]'isearch-forward)(define-keyesc-map[?\s-f]'isearch-forward-regexp)(define-keyminibuffer-local-isearch-map[?\s-f]'isearch-forward-exit-minibuffer)(define-keyisearch-mode-map[?\s-f]'isearch-repeat-forward)(define-keyglobal-map[?\s-F]'isearch-backward)(define-keyesc-map[?\s-F]'isearch-backward-regexp)(define-keyminibuffer-local-isearch-map[?\s-F]'isearch-reverse-exit-minibuffer)(define-keyisearch-mode-map[?\s-F]'isearch-repeat-backward)(define-keyglobal-map[?\s-g]'isearch-repeat-forward)(define-keyglobal-map[?\s-h]'ns-do-hide-emacs)(define-keyglobal-map[?\s-H]'ns-do-hide-others)(define-keyglobal-map[?\M-\s-h]'ns-do-hide-others)(define-keyglobal-map[?\s-j]'exchange-point-and-mark)(define-keyglobal-map[?\s-k]'kill-current-buffer)(define-keyglobal-map[?\s-l]'goto-line)(define-keyglobal-map[?\s-m]'iconify-frame)(define-keyglobal-map[?\s-n]'make-frame)(define-keyglobal-map[?\s-o]'ns-open-file-using-panel)(define-keyglobal-map[?\s-p]'ns-print-buffer)(define-keyglobal-map[?\s-q]'save-buffers-kill-emacs)(define-keyglobal-map[?\s-s]'save-buffer)(define-keyglobal-map[?\s-t]'menu-set-font)(define-keyglobal-map[?\s-u]'revert-buffer)(define-keyglobal-map[?\s-v]'yank)(define-keyglobal-map[?\s-w]'delete-frame)(define-keyglobal-map[?\s-x]'kill-region)(define-keyglobal-map[?\s-y]'ns-paste-secondary)(define-keyglobal-map[?\s-z]'undo)(define-keyglobal-map[?\s-+]'text-scale-adjust)(define-keyglobal-map[?\s-=]'text-scale-adjust)(define-keyglobal-map[?\s--]'text-scale-adjust)(define-keyglobal-map[?\s-0]'text-scale-adjust)(define-keyglobal-map[?\s-|]'shell-command-on-region)(define-keyglobal-map[s-kp-bar]'shell-command-on-region)(define-keyglobal-map[?\C-\s-]'ns-do-show-character-palette)(define-keyglobal-map[s-right]'move-end-of-line)(define-keyglobal-map[s-left]'move-beginning-of-line)(define-keyglobal-map[home]'beginning-of-buffer)(define-keyglobal-map[end]'end-of-buffer)(define-keyglobal-map[kp-home]'beginning-of-buffer)(define-keyglobal-map[kp-end]'end-of-buffer)(define-keyglobal-map[kp-prior]'scroll-down-command)(define-keyglobal-map[kp-next]'scroll-up-command);; Allow shift-clicks to work similarly to under Nextstep.(define-keyglobal-map[S-mouse-1]'mouse-save-then-kill)(global-unset-key[S-down-mouse-1]);; Special Nextstep-generated events are converted to function keys. Here;; are the bindings for them. Note, these keys are actually declared in;; x-setup-function-keys in common-win.(define-keyglobal-map[ns-power-off]'save-buffers-kill-emacs)(define-keyglobal-map[ns-open-file]'ns-find-file)(define-keyglobal-map[ns-open-temp-file][ns-open-file])(define-keyglobal-map[ns-open-file-line]'ns-open-file-select-line)(define-keyglobal-map[ns-spi-service-call]'ns-spi-service-call)(define-keyglobal-map[ns-new-frame]'make-frame)(define-keyglobal-map[ns-toggle-toolbar]'ns-toggle-toolbar)(define-keyglobal-map[ns-show-prefs]'
Some of them look quite convenient (easy to press), so I might add a few
to my daily work. I’m shocked I never trying any of the standard macOS
keybindings for things like adjusting text size in Emacs. Or perhaps I tried
them and then I forgot about them… :D
Still, even though I’m a macOS users (at least for the time being), I doubt I’ll end
up using many of them. The reason for this is that I learned Emacs on Linux
and I’m extremely used to the default keybindings. Between remembering all of those,
and trying to master Vim (as of late), it’s hard to teach this old dog any new tricks.
That being sad, I can imagine those keybindings being useful to many other people, especially
if they haven’t learned Emacs on Linux 20 years ago.
Tip: Do a M-x find-library RET ns-win to see what else the library has in store
for macOS users.
All of this is, of course, made possible by the fact that macOS relies heavily on the
Command key which normally isn’t used in Emacs at all. For similar reasons it’s
“easier” to copy/paste text from/in your shell on macOS, compared to Linux and Windows, as
keybindings like Command + c and Command + v are not used by any shell.
That’s all I have for you today! Keep hacking!
P.S. After writing this article I was really amused that I’ve been using macOS on and
off for over 10 years and I never bothered to try whether something like Command-s or
Command-z works in Emacs! Oh, well… habits!
Emacs stubbornly keeps refering to macOS by its ancient name NextStep in much of the code and its documentation. ↩
Lately, I've been messing with Codelist Tools, a Rust library for working with medical codelists. Among other things, it uses PyO3 to provide bindings that enable its use from Python. I had not tried this before. It's fun!
It occurred to me that it should also work from Hy, a Lisp dialect for Python. So, I gave it a try…and it does!
Running either of these produces
Over at the Emacs subreddit, EachDaySameAsLast asks the perennial question: why does Emacs take so long to load. Actually, his question is, “Why do people say Emacs takes so long to load?” He has, he says, been using Emacs since its TECO days and has never, even in the old days, experienced overly long load times. To be sure, his configuration file is relatively short—about 100 lines—but Emacs loads for him in under 2 seconds.
Of course, as many of us have been saying and saying, none of that matters. For almost every user, Emacs shouldn’t be started very often: once a day at most, once every week or month typically.
As usual, the interesting part of the post is the comments. Almost everyone agrees: the load times don’t matter but if you use use-package and the defer option judiciously, your load time can be small too.
I’m beginning to feel as if I’m codependent with those people claiming that Emacs takes too long to load. I should probably just stop writing about it. Of course, it won’t matter. People—many of whom don’t even use Emacs—will keep repeating it.
But let me just repeat, with Batsov, that Emacs load time doesn’t matter. It really doesn’t.
Because the Internet, it is a blessing of our time that interacting with people in different time zones is commonplace. In this, the question is often raised: “what time is it there?” This is routinely answered using a clock app or a website.
While Emacs has long had the ability to make time zone calculations, it seemed overdue to have tooling that takes advantage of it.
The following screencast shows Casual Timezone in action, in this case a meeting planner (command: casual-timezone-planner) that compares the hours with your local time zone with that of another.
Casual Timezone also lets you directly ask:
“What time is it over there?” (command: casual-timezone-local-time-to-remote)
“That time over there, what is it here?” (command: casual-timezone-remote-time-to-local)
Note that at current, Casual Timezone only supports Unix-variant systems as it relies on the tz database. It has been tested on macOS 15.5 and Ubuntu Linux 22.04. Sorry Windows users, but I’m open for a PR for Windows support if a workaround for zoneinfo is available.
Closing Thoughts
With experience, I’ve learned to be humble about working with time APIs. While I’ve done much to ensure the results are accurate, I would not be surprised if there are bugs, especially for a first release. Let me know if you find any.
On reflection, putting Casual Timezone together was relatively easy as it was largely an exercise in integrating different Elisp packages:
From Org, the command org-read-date provided the date picker UI.
Built-in completion provided the UI for selecting a time zone.
vtable provided the table interface for casual-timezone-planner.
The table interface was configured as a derived mode to provide mode-specific behavior.
The built-in time functions were used for time zone calculations and formatting.
Transient provided support for menus.
Gonna call this an Elisp code-reuse success story.
I’ll be pretty brief today. keyboard-quit (C-g) is one of the most
used commands, but unfortunately it’s not very smart. Most annoyingly,
it doesn’t work as expected when the minibuffer is active.
Fortunately, fixing such problems (and then some) is trivial in Emacs:
(defuner-keyboard-quit()"Smater version of the built-in `keyboard-quit'.
The generic `keyboard-quit' does not do the expected thing when
the minibuffer is open. Whereas we want it to close the
minibuffer, even without explicitly focusing it."(interactive)(if(active-minibuffer-window)(if(minibufferp)(minibuffer-keyboard-quit)(abort-recursive-edit))(keyboard-quit)))
I’d suggest to just remap keyboard-quit to our improved version:
There are other ways to tackle this particular issue, of course,
and different people might prefer an even more complicated
version of the smarter keyboard-quit or one that does fewer
things. One of my readers suggested in the comments a similar
solution using an advice:
(define-advicekeyboard-quit(:around(quit)quit-current-context)"Quit the current context.
When there is an active minibuffer and we are not inside it close
it. When we are inside the minibuffer use the regular
`minibuffer-keyboard-quit' which quits any active region before
exiting. When there is no minibuffer `keyboard-quit' unless we
are defining or executing a macro."(if(active-minibuffer-window)(if(minibufferp)(minibuffer-keyboard-quit)(abort-recursive-edit))(unless(ordefining-kbd-macroexecuting-kbd-macro)(funcall-interactivelyquit))))
This has the benefit of directly modifying the original command, so you don’t
really need to rebind anything. On the other hand - advices are arguably
a bit more complicated to understand and debug. Personally, I like
to replace functions in my own setup with versions that I prefer,
as I think this makes the modifications more obvious.
(defunprot/keyboard-quit-dwim()"Do-What-I-Mean behaviour for a general `keyboard-quit'.
The generic `keyboard-quit' does not do the expected thing when
the minibuffer is open. Whereas we want it to close the
minibuffer, even without explicitly focusing it.
The DWIM behaviour of this command is as follows:
- When the region is active, disable it.
- When a minibuffer is open, but not focused, close the minibuffer.
- When the Completions buffer is selected, close it.
- In every other case use the regular `keyboard-quit'."(interactive)(cond((region-active-p)(keyboard-quit))((derived-mode-p'completion-list-mode)(delete-completion-window))((>(minibuffer-depth)0)(abort-recursive-edit))(t(keyboard-quit))))
I know this version of the command is quite popular in the wild, as many
people follow Prot’s work, but looking at the code of the actual keyboard-quit
it seems to me that Prot’s version is more complicated than it needs to be:
;; This executes C-g typed while Emacs is waiting for a command.;; Quitting out of a program does not go through here;;; that happens in the maybe_quit function at the C code level.(defunkeyboard-quit()"Signal a `quit' condition.
During execution of Lisp code, this character causes a quit directly.
At top-level, as an editor command, this simply beeps."(interactive);; Avoid adding the region to the window selection.(setqsaved-region-selectionnil)(let(select-active-regions)(deactivate-mark))(if(fboundp'kmacro-keyboard-quit)(kmacro-keyboard-quit))(whencompletion-in-region-mode(completion-in-region-mode-1));; Force the next redisplay cycle to remove the "Def" indicator from;; all the mode lines.(ifdefining-kbd-macro(force-mode-line-updatet))(setqdefining-kbd-macronil)(let((debug-on-quitnil))(signal'quitnil)))
As you can see it already handles things like the selected region
and completion in region. But perhaps I’m missing what Prot was
trying to achieve with his version.
Which of the three approaches do you prefer?
How would you improve er-keyboard-quit-dwim further?
Journelly keeps getting updated with good features. One of the latest features I noticed (I’m not sure if it was part of the latest patch) is that locations tagged with entries can be revisited in iOS Maps from the app. This makes Journelly a good spot to save locations and integrate them with personal memories, to be revisited later on the map. I would like to use this (instead of, say, a saved of locations on Google Maps), but I can’t - for two reasons.
The first one, which I can work around, is that the list of entries on Journelly quickly becomes long, and finding where you were a couple of weeks ago requires some scrolling. While Journelly has a search option, I usually don’t remember the name of the place I’m searching for, which is why I’m searching for it in the first place. Still, I could probably look for who I was with at the time, or even better, use the tagging feature, which was introduced a couple of weeks ago, for, say, “#cafes” to filter down cafes only.
The other issue is more challenging: I don’t keep my notes in Journelly. I keep refiling my entries into my main journal file. That file, while still on my Mac, is not synced with iCloud. Call me paranoid, but I don’t trust Apple’s iCloud with my personal notes along with my pictures throughout the years. As far as I’m concerned, Apple just has a better PR department than Google and Microsoft, and they only care about their users' privacy as long as it’s what looks good in the news. Because of that, I am not comfortable with Journelly being my archive of notes. There could be other options besides iCloud, but as far as I know, they all involve a cloud company somewhere. On Android and macOS, I still use the excellent Syncthing, which doesn’t involve any cloud storage. However, Syncthing doesn’t work on iOS, so I’m out of luck.
Besides these two issues (which have nothing to do with the app), the app is terrific. It’s amazing how polished and responsive it is.
Joar Von Arndt has an interesting post on a subject that many Emacs users obsess about: how to bring Web browser functionality into Emacs. As, I’ve said many times, virtually all my tube time is either in Emacs or Safari. I would, of course, like to get that down to just Emacs. To be sure, I do use some other apps but my time with them is basically in the noise. Almost everything I do on the computer involves Emacs or the browser.
Von Arndt looks at eww, w3m, Xwidgets, and EAF. He discusses the pros and cons of each. He appears to think that eww—with some customization—is the best solution.
My solution is to use Xwidgets for rendering Email posts that need it and for my RSS feed via Elfeed. My email client, mu4e, makes it easy to switch between text and HTML rendered displays. It is, in a way, the best of both worlds. I can read most of my emails in plain text, as the elders decreed, but can switch to an HTML rendered display when I need to.
I use elfeed-webkit to display my RSS feed with Elfeed. It brings up each entry in a browser like display and, of course, can be easily be toggled on and off. It’s a bit fragile, as Von Arndt says, but it easier than invoking the brower for each entry.
The sad news is that there still isn’t a good solution but what solutions there are are getting better. Perhaps we will soon have a way of bringing the final major holdout into the Emacs fold.
The IndieWeb Carnival prompt for May is small web
communities. I've been exploring some thoughts on
how a little effort goes a long way to connecting
a community. Sometimes I think of it as working on
the plumbing so that ideas can flow more smoothly.
It feels a little different from the direct
contribution of knowledge or ideas. I also want to
connect with other people who do this kind of
thing.
Emacs is a text editor that has been around since
the 1970s. It's highly programmable, so people
have come up with all sorts of ways to modify it
to do what they want. It's not just for
programmers. My favourite examples include
novelists and bakers and musicians who use Emacs
in unexpected ways. Because Emacs is so flexible,
community is important. The source code and
documentation don't show all the possible
workflows. As people figure things out by
themselves and together, more possibilities open
up.
I love tweaking Emacs to help me with different
things I want to do, and I love learning about how
other people use it too. I've been sharing my
notes on Emacs on this blog since 2001 or so. In
2015, as I was getting ready to become a parent, I
knew I was going to have much less time and
focused attention, which meant less time playing
with Emacs. Fortunately, around that time, John
Wiegley (who was one of the maintainers of Emacs
at the time) suggested that it would be helpful if
I could keep an eye on community updates and
summarize them. This worked well with the
fragmentation of my time, since I could still
speed-read updates and roughly categorize them.
You don't have to fill the pipes all by yourself. Just help things flow.
I want to share some of the things we're doing in the Emacs community
so that I can convince you that building plumbing for your community can be fun, easy, and awesome.
This is great because enthusiasm spreads.
virtuous cycle
Other places: YouTube, Reddit, HN, lobste.rs, Mastodon, PeerTube, mailing lists….
Blog aggregator
Planet Emacs Life (uses Planet Venus) - update: [2025-05-31 Sat] I wrote my own RSS feed aggregator instead.
EmacsConf: < USD 50 hosting costs + donated server + volunteer time
Tips:
Make it fun for yourself.
Build processes and tools.
Let people help
2024-01-31-05
Some more notes on the regular flows built up by
this kind of community plumbing:
Daily: Lots of people post on reddit.com/r/emacs
and on Mastodon with the #emacs hashtag. I also
aggregate Emacs-related blog posts at
planet.emacslife.com, taking over from
planet.emacsen.org when Tess had DNS issues. There
are a number of active channels on YouTube and
occasionally some on PeerTube instances as well. I
don't need to do much work to keep this flowing,
just occasionally adding feeds to the aggregator
for planet.emacslife.com.
Weekly: I collect posts from different sources,
remove duplicates, combine links talking about the
same thing, categorize the links, put them roughly
in order, and post Emacs News to a website, an RSS
feed, and a mailing list. This takes me maybe 1.5
hours each week. It's one of the highlights of my
week. I get to learn about all sorts of cool
things.
Weekly seems like a good rhythm for me considering
how active the Emacs community is. Daily would be
too much time. Monthly would lead to either too
long of a post or too much lost in curation, and
the conversations would be delayed.
Sometimes I feel a twinge of envy when I check out
other people's newsletter posts with commentary or
screenshots or synthesis. (So cool!) But hey, I'm
still here posting Emacs News after almost ten
years, so that's something. =) A long list of
categorized links fits the time I've got and the
way my mind works, and other people can put their
own spin on things.
Monthly: There are a number of Emacs user
groups, both virtual and in-person. Quite a few of
them use Emacs News to get the discussion rolling
or fill in gaps in conversation, which is
wonderful.
Some meetups use meet.jit.si, Zoom, or Google
Meet, but some are more comfortable on a
self-hosted service using free software. I help by
running a BigBlueButton web conferencing server
that I can now automatically scale up and down on
a schedule, so the base cost is about 60 USD/year.
Scaling it up for each meetup costs about USD 0.43
for a 6-hour span. It's pretty automated now,
which is good because I tend to forget things that
are scheduled for specific dates. My schedule
still hasn't settled down enough for me to host
meetups, but I like to drop by once in a while.
Yearly:EmacsConf is the one big project I like
to work on. It's completely online. It's more of a
friendly get-together than a formal conference. I
have fun trying to fit as many proposed talks as
possible into the schedule. We nudge speakers to
send us recorded presentations of 5-20 minutes
(sometimes longer), although they can share live
if they want to. A number of volunteers help us
caption the videos. Each presentation is followed
by Q&A over web conference, text chat, and/or
collaborative document. Other volunteers handle
checking in speakers and hosting the Q&A sessions.
It's a lot of fun for surprisingly little money.
For the two-day conference itself, the website
hosting cost for EmacsConf 2024 was about USD 56
and our setup was able to handle 400 viewers
online (107 max simultaneous users in various web
conferences).
EmacsConf takes more time. For me, it's about 1.5
hours a day for 4 months, but I think mostly
that's because I have so much fun figuring out how
to automate things and because I help with the
captions. Lots of other people put time into
preparing presentations, hosting Q&A,
participating, etc. It's worth it, though.
I like doing this because it's a great excuse to
nudge people to get cool stuff out of their head
and into something they can share with other
people, and it helps people connect with other
people who are interested in the same things. Some
Q&A sessions have run for hours and turned into
ongoing collaborations. I like turning videos into
captions and searchable text because I still don't
have the time/patience to actually watch videos,
so it's nice to be able to search. And it's
wonderful gathering lots of people into the same
virtual room and seeing the kind of enthusiasm and
energy they share.
So yeah, community plumbing turns out to be pretty
enjoyable. If this resonates with you, maybe you
might want to see if your small web community
could use a blog aggregator or a newsletter.
Doesn't have to be anything fancy. You could start
with a list of interesting links you've come
across. I'm curious about what other people do in
their communities to get ideas flowing!
This is a small release that makes spacious-padding-mode work as
intended when used in tandem with the Emacs daemon and subsequent
calls to emacsclient -c. I made the function responsible for
triggering the “spacious padding” effects work with individual frames
and then I responded to issue 33 by Lou Woell about integrating that
with the server-after-make-frame-hook: https://github.com/protesilaos/spacious-padding/issues/33.
Additionally, the package now defines two faces that can be used to
configure the user option spacious-padding-subtle-mode-line (read
its documentation string for all the possible values it accepts).
Here is how they can be set (default value is nil):
Reload the spacious-padding-mode for changes to take effect.
When configured this way and with default styles they make the mode
line use a minimalist overline with no background colour. The active
mode line has a more noticeable border than the inactive ones. All my
themes are designed to support this aesthetic (though themes can style
those faces as they see fit).
About Spacious Padding
This package provides a global minor mode to increase the
spacing/padding of Emacs windows and frames. The idea is to make
editing and reading feel more comfortable. Enable the mode with M-x
spacious-padding-mode. Adjust the exact spacing values by modifying
the user option spacious-padding-widths.
Today, I was reading Why Use Structured Errors in Rust Applications? and one of the issues discussed is jumping away from the code you're working on to look at the definition of the error. On the one hand, rust-analyzer makes it really easy to jump to the error, but on the other hand they felt that they sometimes had to do so unnecessarily.
In the comments on lobste.rs, matklad mentioned that he recently adopted the habit of splitting the screen first and going to the definition in the split (in Emacs terms, in the other window).
Two weeks ago I wrote about using defcustom’s :get and :set keywords, allowing the user to set an option containing a Unix timestamp (that is, a number) using an ISO-8601 timestamp. Today I am going to use such an option.
My journey into using Hledger with Emacs to track my share investments continues. Last Time
I looked at a way to track shares using a plain text file. Since then I have made some tweaks to my workflow as I gain more experience:
naming conventions that support multiple stock brokers
booking brokerage fees in a better way to support the Australian tax system.
Naming convention
Over the past month I was not overly impressed with my existing stock broker, which led me to explore other stock brokers that may offer a more reliable service at a cheaper rate. It is expensive to transfer stocks over to a new broker, so I decided to cap further investment at my current broker and instead make any new purchases at a different broker. This meant that I would need an account structure that lets me easily identify which share lots were purchased through which broker.
Please note that planet.emacslife.com aggregates blogs, and blog authors might mention or link to nonfree things. To add a feed to this page, please e-mail the RSS or ATOM feed URL to sacha@sachachua.com . Thank you!