Jeremy Friesen: Using Magit Built-in Functions for Workflow

Yesterday I wrote Emacs Script to Review Git Status of Repositories for creating a checklist of repositories to review. Over on /r/emacs, someone provided the following: Similar to that, one can define magit-repository-directories which is a list of folders for magit to look for git projects - including an optional integer per each representing how deep to search. After you do that you can get a status overview using magit-list-repositories which shows projects name, version, status (untracked, unstaged, staged) and numbers of unpushed/unpulled commits from upstream.
-1:-- Using Magit Built-in Functions for Workflow (Post)--L0--C0--August 03, 2021 01:47 PM

yuri tricys: How to Check for Internet and Load Hackernews With Emacs

Hackernews is an emacs package delivering daily sets of rss links, much like the elfeed package. You can program your emacs configuration to load hackernews at start up so you can scan for the latest relevant links. The code throws an error, however, if emacs starts when the internet is disconnected. One fix is to have emacs check the internet connection and load hackersnews only if it's live. You need your connection checking code to load before hackernews code.
-1:-- How to Check for Internet and Load Hackernews With Emacs (Post)--L0--C0--August 03, 2021 07:00 AM

Alex Schroeder: Emacs Wiki and IPv6

Here’s something weird: I can no longer connect to Emacs Wiki. At first, I thought it was only a problem on my iPhone or iPad, but apparently it’s more widespread.

Could not connect to the server. NSURLErrorDomain

This is for Firefox and Safari which makes me think it’s a problem with the networking layer in the operating system, not the browser. I can connect just fine to the other domains hosted on the same machine (alike this one).

On my laptop, using traceroute:

alex@melanobombus ~> traceroute -n
traceroute to (, 30 hops max, 60 byte packets
12  7.562 ms  7.605 ms  4.772 ms
alex@melanobombus ~> traceroute -n -4
traceroute to (, 30 hops max, 60 byte packets
12  2.809 ms  5.176 ms  5.716 ms
alex@melanobombus ~> traceroute -n -6 Name or service not known
Cannot handle "host" cmdline arg `' on position 1 (argc 3)
alex@melanobombus ~> traceroute -n -6
traceroute to (2a02:418:6a04:178:209:50:237:1), 30 hops max, 80 byte packets
12  2a02:418:6a04:178:209:50:237:1  8.651 ms  9.542 ms  7.917 ms

Apparently, there’s an IPv6 problem for but not for

Checking DNS…

@ 10800 IN SOA 1589061328 10800 3600 604800 10800
@ 10800 IN A
@ 10800 IN AAAA 2a02:418:6a04:178:209:50:237:1
@ 10800 IN MX 10
@ 10800 IN MX 20
@ 10800 IN TXT "openpgp4fpr:df9446eb7b7846387ccc018bc78ca29bacecfeae"
@ 10800 IN TXT "v=spf1 a mx ~all"
_dmarc 10800 IN TXT "v=DMARC1; p=reject"
default._domainkey 10800 IN TXT "v=DKIM1; k=rsa; s=email; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCmaqj01Yu19QPNpkSbuQJNZ8OIe4h3gYw3WPqdDxC0OIN5HMxlNFE3AWcpgdmjgjBF2a3X63Ux8PExP6f0qPBoiMO0wvV3MhSwF1kXwuzuhTgtlwf+3v7EIGytQJ8+Y88+bgRfRhaRQfkTeEw1EI2/5yLeEWpqZOdV3tYyvx8dawIDAQAB"
www 10800 IN A

That’s right: no AAAA record for www!

For the moment, dig is reporting it’s OK:

alex@melanobombus ~> dig -t AAAA

; <<>> DiG 9.11.5-P4-5.1+deb10u5-PureOS <<>> -t AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 12984
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 1232

;; ANSWER SECTION:	10800	IN	AAAA	2a02:418:6a04:178:209:50:237:1

;; Query time: 24 msec
;; SERVER: …
;; WHEN: Tue Aug 03 07:40:42 CEST 2021
;; MSG SIZE  rcvd: 74

alex@melanobombus ~> dig -6 -t AAAA

; <<>> DiG 9.11.5-P4-5.1+deb10u5-PureOS <<>> -6 -t AAAA
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7984
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

; EDNS: version: 0, flags:; udp: 1232

;; ANSWER SECTION:	10631	IN	AAAA	2a02:418:6a04:178:209:50:237:1

;; Query time: 4 msec
;; SERVER: …
;; WHEN: Tue Aug 03 07:43:31 CEST 2021
;; MSG SIZE  rcvd: 74

Well, that alone does not fix it. How strange.

alex@melanobombus ~> traceroute -n -6 Name or service not known
Cannot handle "host" cmdline arg `' on position 1 (argc 3)

Firefox also seems to be caching the info somewhere. I always suspect that it has its own DNS subsystem somewhere. In any case, setting “network.dnsCacheExpiration” and “network.dnsCacheExpirationGracePeriod” both to 0 and then back to 60 did not help.

But yeah, something is still amiss. It’s not just Firefox – curl is doing it, too:

alex@melanobombus ~> curl -I
HTTP/1.1 301 Moved Permanently
Date: Tue, 03 Aug 2021 05:36:31 GMT
Server: Apache
Permissions-Policy: interest-cohort=()
Content-Type: text/html; charset=iso-8859-1

alex@melanobombus ~> curl -I
curl: (7) Failed to connect to port 443: Connection refused

-1:-- Emacs Wiki and IPv6 (Post)--L0--C0--August 03, 2021 05:24 AM

Alex Schroeder: Apple and Emacs Wiki

Here’s something weird: I can no longer connect to Emacs Wiki using my iPhone or iPad.

Could not connect to the server. NSURLErrorDomain

This is for Firefox and Safari which makes me think it’s a problem with the networking layer in the operating system, not the browser. I can connect just fine to the other domains hosted on the same machine (alike this one).

-1:-- Apple and Emacs Wiki (Post)--L0--C0--August 03, 2021 04:18 AM

Irreal: Progress ⁢⨉ 2

There were two bits of progress reported yesterday. The first is the announcement of the release of Magit 3.2. I’d describe the changes, as listed in the announcement, tweaks that make Magit more useful but nothing earth shattering. You can check the entire change log for all the details.

Magit is one of the gems in the Emacs crown and if you haven’t yet supported tarsius (Jonas Bernoulli), now would be a good time. We certainly want to keep those updates coming.

The other sign of progress is a post by Lars Ingebrigtsen on the Emacs Devel List concerning the release of Emacs 28. That’s still in the future but Ingebrigtsen suggests that the beginning of the release process is about to begin. He says that in the middle of September (at the earliest) they will cut the Emacs 28 branch and begin the debugging process leading to Emacs 28.1. That’s still months away but getting the process underway is a significant milestone.

Emacs 28 will be a big release for me. First, it reportedly fixes the annoying buffer repaints and flickers in macOS. If you’re a Mac user, this is a big deal. More significant, of course, is native compilation. Everything I read about it suggests that this is going to be a game changer. I’m really looking forward to trying it out.

The naysayers are fond of pontificating on how Emacs is old and dead. Except, of course, that everyone’s trying to copy Org-mode and Magit. Wait until we get native compilation. While all the cool kids are strutting around with their “pretty” GUIs, we Emacs users will be blowing them away as we edit at the speed of light.

-1:-- Progress ⁢⨉ 2 (Post jcs)--L0--C0--August 02, 2021 04:46 PM

Jeremy Friesen: Emacs Script to Review Git Status of Repositories

Aug 3, 2021 update: After some input on /r/emacs, I wrote Using Magit Built-in Functions for Workflow. Those changes supplant what I’ve written below. Throughout my day, I work on several different Git 🔍 repositories. And sometimes, I can lose track of what all I’ve worked on. To help with this task, I created the following Emacs 🔍 variable and function to let me quickly and methodically check the status of those repositories.
-1:-- Emacs Script to Review Git Status of Repositories (Post)--L0--C0--August 02, 2021 12:59 PM

Emacs Redux: NonGNU ELPA Package Repository

Ever since package.el became the standard package manager for Emacs, there has been an official Emacs package repository called GNU ELPA. As of the time of this writing it hosts around 280 packages. A respectable number, but quite far from the 5000 packages available in the popular community-maintained MELPA repository. Not to mention that many of the packages in GNU ELPA are bundled with Emacs (meaning they originated from people involved with Emacs’s development) - e.g. cl-lib, eldoc, xref, etc.

Where’s the huge difference of scale between ELPA and MELPA coming from? To me, the answer is quite obvious - the amount of work a package maintainer needs to do in both cases. With MELPA there are no copyright assignments (and by associations - no contribution limitations) and you don’t need to host your package in the ELPA git repo. As GitHub is super popular with developers today, few people are willing to forgo it. In practice every package that goes into GNU ELPA will likely see few external contributions as most people are unwilling to deal with copyright assignment hassle and Emacs’s bug tracker.

The Emacs development team tried to alleviate the situation last year, by proposing a default NonGNU ELPA package repository, that eliminates the need for a copyright assignment. One year later the repository is a reality and it’s available here. NonGPU ELPA will be enabled by default in Emacs 28, but for the time being you’ll need to enable it manually like this:

(add-to-list 'package-archives '("nongnu" . ""))

As you can see, however, currently the repo boasts a grand total of 5 packages. This implies that most people are probably too attached to their GitHub tool chain (and the reach that GitHub has) and are unwilling to move their projects to the NonGNU ELPA git repo. Obviously one can also adopt an approach where the development happens mostly on GitHub and the GitHub repo changes are applied afterwards to NonGNU ELPA, but I guess few people are willing to bother with this either.

This certainly applies for me - I wouldn’t mind if it was easier for Emacs users to install my packages, but I’m extremely happy with GitHub and MELPA and I’m not willing to create additional work for myself just to make my work available on NonGNU ELPA. OSS maintainers are already way too busy and we should value and respect their time.1

As, with GNU ELPA, there’s also a “devel” version of the NonGNU repository, for unstable releases of the packages hosted on NonGNU ELPA. You can enable it like this, if you ever need something from there:

(add-to-list 'package-archives '("nongnu-devel" . ""))

In the end of the day, while I welcome the efforts of Emacs’s team to lower the bar for contributions, I think they are not considering how hard it is to compete with the GitHub development flow that most developers are accustomed to today. As the topic of Emacs and GitHub resurfaces constantly, I won’t really dive in it - I’ve said many times that I’d love to see Emacs’s development happening on GitHub/GitLab, but I’m well aware this is never going to happen. I’ll just say that I doubt NonGNU ELPA will gain any meaningful traction and disrupt the dominance of MELPA in our community. I hope that at some point Emacs will start enabling by default MELPA Stable, instead of trying to compete it with it. It’s good have some consistent political views you abide by, but a bit of pragmatism doesn’t hurt either.

Going back to the topic of NonGNU ELPA. It seems to me that going forward it doesn’t make much sense for new packages to be added to GNU ELPA, unless they are going to be bundled with Emacs. Why limit the number of potential contributors for your projects for no good reason? I expect that over the course of time NonGNU ELPA will become the primary “standard” package repository. Perhaps we’ll even see some packages move between GNU ELPA and NonGNU ELPA. Time will tell. Down the road I plan to try to publish a few on my own packages to NonGNU ELPA to assess first-hand how much of overhead does it add for package maintainers. Perhaps the process is easier than I imagine it to be.

That’s all I have for you today. Keep hacking!

  1. It was pointed out to me that I might be mistaken about the amount of work needed to add a package hosted on GitHub to (Non)GNU ELPA. I’ll try the process myself and write an update afterwards. 

-1:-- NonGNU ELPA Package Repository (Post Bozhidar Batsov)--L0--C0--August 02, 2021 07:22 AM

Marcin Borkowski: Reordering sentences in Emacs

I’m probably in a minority, but I am a heavy user of Emacs’ transpose-* commands, most notably transpose-words and transpose-chars. This is probably because I have spent a lot of time editing texts in Emacs – not writing, but editing, and wrong order of words is a very common mistake I often needed to fix. One problem with transpose-words, though, is that it can only swap two words, usually two adjacent ones
-1:-- Reordering sentences in Emacs (Post)--L0--C0--August 02, 2021 04:15 AM

Sacha Chua: 2021-08-02 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file, Emacs Calendar and emacs-devel.

-1:-- 2021-08-02 Emacs news (Post Sacha Chua)--L0--C0--August 02, 2021 12:00 AM

T. V. Raman: Contextual Context Switching For An Efficient Workflow

Contextual Context Switching For An Efficient Workflow

1 Executive Summary

Context switching in an Emacs workflow comes down to switching buffers — and Emacs provides a large number of built-ins and extensions packages for switching buffers. One can put together numerous workflows by picking among these to make context switching contextual — using the most appropriate workflow can lead to being able to focus much better on the core task of creating, editing, reviewing and publishing all forms of content ranging from research papers and presentations to Open Source Software.

This article summarizes my present workflow — it's entirely keyboard driven and optimized for an eyes-free workflow.

2 Where Does Context Come From?

Context as used in this article can be traced back to the current task at hand — here are some illustrative examples:

  1. Editing a set of related files. (.c, .h)
  2. Switching among a collection of chat buffers. (major-mode)
  3. Switching among a collection of mail folders. (major-mode)
  4. Switching among a collection of open Web pages. (major-mode)
  5. Switching among a small number of recently used buffers. (recency)
  6. Switching among buffers in the same project (project)
  7. Switching between project-specific shells and buffers. (project)

3 Building Blocks For Context Switching

Here are some of the building blocks I use to construct workflows that meet the use-cases enumerated in the previous section. Many of these are built into Emacs; some come from extra packages and a few are implemented in Emacspeak to fill the gaps. See the related article Search, Input, Filter, Target (SIFT) interaction described in a previous article for a more detailed explanation or properties that characterize effective eyes-free interaction.

  1. Built-in Command next-buffer and previous-buffer bound to hyper-, and hyper-..
  2. Builtin Command ~ other-window bound to C-x o.
  3. Emacspeak Commands emacspeak-wizards-cycle-to-next-buffer and emacspeak-wizards-cycle-to-previous-buffer bound to Alt-n and Alt-p.
  4. Emacspeak Command emacspeak-wizards-shell-toggle bound to Super-,.
  5. Emacspeak Command emacspeak-wizards-shell-by-key bound to C-c [1-9].

3.1 Things To Note

  1. Notice that many of these commands come in pairs and use key-bindings that also pair-up with respect to muscle memory; over time I have found this type of pairing to be essential for them to become part of one's daily habit.
  2. And when these task-specific commands dont get you the buffer you want with one or two keystrokes, one can always fallback to switch-to-buffer.
  3. Built-in Command switch-to-buffer bound to C-x b which in my environment maps to ido-switch-buffer with fuzzy completion.

3.2 Related Packages

There are of course many alternatives to the building blocks above, here is a non-exhaustive list:

  • Package helm with ivy, counsel and friends.
  • Package selectrum.
  • Additionally organizing one's workspace using Emacs Frames with each frame dedicated to tasks like email — visual workspaces.

    In general, I've not found any of the above adding much in the context of eyes-free interaction.

4 Conclusion

Emacs has a large number of facilities that lend themselves to multiple workflows. Investing some time in putting together workflows that suit one's needs has a large pay-back over time.

-1:-- Contextual Context Switching For An Efficient Workflow (Post T. V. Raman ( 01, 2021 04:39 PM

Irreal: Org-roam As a Second Brain

David Wilson over at the YouTube System Crafters channel has a new video up on getting started with Org-roam and building a second brain. It’s the best introductory video I’ve seen on Org-roam and, of course, Wilson is promising more.

The video covers Org-roam V2 and except for mentioning how to get rid of the warning message for V1 users, doesn’t mention V1 at all. By the end of the video you’ll know how to set up a working Org-roam installation and start taking notes. Later videos will cover more advanced topics but this one will end with you being productive with the package.

The video shows you how to create new nodes and link one node to another. The heart of a Zettelkasten is the idea that you can not only follow forward links from a parent node to a child but also back links from a child to its parents. The plural “parents” is important: the whole point of the Zettelkasten method is to discover hidden relationships between the individual notes so the backlinks buffer will show every reference to the current note. This is a realization of the idea that the Zettelkasten method produces a graph of the notes and their connections rather than just a hierarchy.

The video covers a couple of other topics like creating aliases for nodes and linking to a subtree of a note. These are interesting but not really that important to the effective use of Org-roam as a Zettelkasten.

If you’ve been wanting to try out the Zettelkasten method, this video will get you up and running with a minimum of fuss. The video is 34 minutes, 18 seconds so you’ll need to schedule some time but it moves quickly and is easy to get through.

-1:-- Org-roam As a Second Brain (Post jcs)--L0--C0--August 01, 2021 04:16 PM

This Month in Org: July 2021

Last month I not-at-all-subtly hinted that a certain long-awaited feature was arriving imminently. At this point, I think it's a good idea to set the tone for the rest of this post.



After years of (on and off) discussion[fn1], I am elated to be able to present Org's new native citation syntax. Org has grown a thoroughly designed, modular, capable citation system. At last you can refer to Org for all your attribution needs. Special thanks must go to Nicolas Goaziou for leading the charge, John Kitchin for paving the way with the org-ref package, Bruce D'Arcus for driving a lot of careful consideration of design decisions and starting to document some of the details --- and the many other denizens of the mailing list who have contributed to the discussion over the years.

András Simonyi's also deserves a special mention for his work creating the Elisp CSL library Citeproc.el, which while not directly included in Org is crucial to providing robust CSL support, and integrates with oc-csl.el.

1.1. Outline

Citations have been carefully designed in such a way that users and Elisp tinkerers will be able to easily adapt and extend it to fit their needs. To that end, Org Cite (or OC for short) has been split into two halves: oc.el which defines the syntax and provides some machinery to interact with citations Citation processors which interface with oc.el to produce nicely-formatted citations to be inserted in your bibliography, within the text, and even rendered in the buffer[fn2]

There are four capabilities that Org Cite uses the processors for Inserting and editing citations Following citations to their definition Fontifying the citations in the buffer Exporting the citations

Each capability can have a particular citation processor assigned, independently of the others. Out of the box, Org uses the basic processor for all of these tasks.

The basic citation processor is one of four currently bundled with Org: basic, which has no dependencies and provides all four capabilities. It export to all formats, but only provides very simple citations. biblatex and natbib, which provide the export capability to create citations via Biber and (to a lesser extent) natbib, but only for LaTeX. csl, which provides the export capability using the Citation Style Language, and exports to HTML, LaTeX, Org, and plain text (with an open issue for ODT) — but depends on citeproc.el.

This provides a solid foundation for other packages to build off, and despite Org Cite being yet to be released or documented in the manual we are already seeing the development of packages like org-ref-cite (by John Kitchin).

1.2. Basic usage

To get started with Org Cite, we must have some form of bibliography. This can either be a BibTeX file or a CSL-JSON file.

As an example, say we have a file orgcite.bib containing the following

    author={org, mode and Syntax, Citation and List, Mailing and Effort, Time},
    journal={Journal of Plain Text Formats},
    title={Elegant Citations with Org-Mode},

First we need to let Org know about this bibliography file (which must have a .bib, .bibtex, or .json extension), which we do either via the #+bibliography keyword, or the variable org-cite-global-bibliography.

    #+bibliography: orgcite.bib

Once you have a bibliography source, you can start referencing to your heart’s content! The basic citation syntax is as follows:

citation-structure-basic.svg Figure 1: The new citation syntax, for simple citations

Using the default style [cite:@OrgCitations] produces . For more information on the styles currently available, see 1.

Finally, to insert a bibliography somewhere, we just need to insert the #+print_bibliography keyword, like so:


So, to summarise, all one needs to get started is:

    #+bibliography: references.bib

That’s it! 🎉

1.3. The cite syntax

Don’t let the simplicity in the examples above fool you, the new syntax is quite capable of expressing more complex forms. Here’s the full version of the new cite syntax:

citation-structure-full.svg Figure 2: The new citations syntax, in full

The style and variant determine what form the exported citation takes The common prefix and suffix and put at the start and end of the generated citation, respectively The citation key refers to a Bib(La)TeX or CSL-JSON key The citation prefix and suffix are put before and after the reference to the key Some citation processors recognise locators, which refer to a particular part of the work, for example: p. 7 to refer to page 7.

Using the default CSL citation style (Chicago author-name) [cite/l/b:see @OrgCitations pp. 7 for fun] becomes .

The citation styles and variants, and recognised locators are handled by the citation processors. Org cite’s bundled processors currently supports the following citation styles.

Table 1: The current set of supported citation styles with variants, with samples generated by oc-csl.el and citeproc.el.
Style Variant Sample Bib(La)TeX NatBib
a author cf caps-full   Citeauthor  
a author f full   citeauthor citeauthor*
a author c caps   Citeauthor* Citeauthor
a author     citeauthor* citeauthor
na noauthor b bare     citeyear
na noauthor     autocite* citeyearpar
l locators bc bare-caps   Notecite  
l locators b bare   notecite  
l locators bc caps   Pnotecite  
l locators     pnotecite  
n nocite     nocite nocite
t text b bare     citealp
t text c caps   Textcite Citep
t text f full     citep*
t text bc bare-caps     Citealp
t text bf bare-full     citealp*
t text cf caps-full     Citep*
t text bcf bare-caps-full     Citealp*
t text     textcite  
(default) b bare   cite citealp
(default) bc bare-caps   Cite Citealp
(default) f full     citep*
(default) bf bare-full     citealp
(default) cf caps-full     Citep*
(default) bcf bare-caps-full     Citealp*
(default)     autocite citep

The CSL processor supports the following locators: book, bk., bks. chapter, chap., chaps. column, col., cols. figure, fig., figs. folio, fol., fols. number, no., Os. line, l., ll. note, n., nn. opus, op., opp. page, p, p., pp. paragraph, para., paras., , ¶¶, §, §§ part, pt., pts. section, sec., secs. sub verbo, s.v., s.vv. verse, v., vv. volume, vol., vols.

1.4. More on exporting

The style of the citations and the bibliography depend on three things: The citation processor used The citation style The bibliography style

The citation processor is automatically selected based on org-cite-export-processors based on the export format being used, but can be set on a per-document basis via the #+cite_export keyword. Here, I shall use the csl processor,

    #+cite_export: csl

With org-cite-export-processors, you can also set the bibliography and citation style by giving a triplet of parameters (PROCESSOR BIBLIOGRAPHY-STYLE CITATION-STYLE) instead of just the processor. You can also use this triplet of values with the #+cite_export keyword

    #+cite_export: processor bibliography-style citation-style

There are also some more options about how the bibliography is produced. These options are handled by the active citation processor. For example, while the CSL processor does not currently support any options, the BibLaTeX processor passes options to a \printbibliography command, allowing for the following:

    #+print_bibliography: :section 2 :heading subbibliography
    #+print_bibliography: :keyword abc,xyz :title "Primary Sources"

1.5. Using CSL

Citeproc is currently available on MELPA, and so can be installed via your package manager of choice so long as MELPA is included in your package-archives. When available, it will be automatically loaded by oc-csl.el.

It currently supports exporting to: HTML LaTeX Org Plain text

Should you be interested in other formats, know that Citeproc is designed to easily support adding new formats (see citeproc-formatters.el for examples).

Citeproc can currently retrieve bibliographic information from the following formats: CSL-JSON Bib(La)TeX org-bibtex

Though support for Bib(La)TeX and org-bibtex is rudimentary compared to CSL-JSON.

When exporting, you can set the style by providing a path to CSL style files, either absolute or relative to org-cite-csl-styles-dir. For example, if I download apa.csl I can use it like so:

    #+cite_export: csl ~/Downloads/apa.csl

When no style is given org-cite-csl--fallback-style-file will be used, which defaults to a bundled Chicago author-date style.

1.6. Working with Zotero

There are quite a few reference managers available, however, the list rapidly shrinks if you restrict yourself to applications which are: somewhat feature-rich open source software not owned by a parasitic company[fn3]

Zotero is a good option, and if you’re using it it’s quite easy to use it with Org Cite. Out of the box, you can tell it to export your library, or parts of it, to a .bib file and automatically keep it in sync. I’d recommend installing the Better BibTeX extension though.

zotero-export-library.png Figure 3: Zotero library right click context menu, showing the export option
zotero-export-options-prompt.png Figure 4: Zotero collection export dialog

Zotero also works well with CSL. In addition to supporting CSL-JSON exports, Zotero also features an easy way to install CSL styles within the preferences.

zotero-cite-styles-menu.png Figure 5: Zotero CSL style management within preferences

Since these files are put under ~/Zotero/styles, you can use them with Org Cite and Citeproc simply by setting org-cite-csl-styles-dir to the Zotero styles directory.

  (setq org-cite-csl-styles-dir "~/Zotero/styles")

To then use the citation style defined by ~/Zotero/styles/apa.csl one can then simply refer to apa.csl when using the #+cite_export keyword.

    #+cite_export: csl apa.csl

1.7. A bright future

Org Cite has only just been merged in the past month, and is yet to be included in an Org release, but we’re seeing a tremendous degree of community interest. There are already promising developments with third-party packages, such as bibtex-actions and org-ref-cite. I can’t wait to see how the ecosystem continues to develop 😃.


[fn1] Citations were first being mentioned on the mailing list back in 2007, in a thread about footnotes.

[fn2]There is currently an ongoing effort to use oc.el and citeproc.el to produce citation overlays in the buffer.

[fn3] I’m talking about a certain company created by a British Fraudster that has a 40% profit margin, engages in blackmail-like practices with universities, prompted 19,000 researchers to boycott them, published six fake journals, vigorously lobbys against Open Access, charged for Open Acess articles (repeatedly), made financial contributions to politicians who then tried to prevent publicly accesible reaserch, and whose reference manager encrypted reaserchers’ own databases “to comply with GDPR”.

-1:-- July 2021 (Post TEC ( 01, 2021 04:00 PM

This Month in Org: June 2021

The previous two months have been pretty good for Org development --- with many bug fixes and feature improvements. This month has been substantially slower than the last[fn1], but that's not to say not much is happening: in fact, there are some rather nifty contributions lined up for the not-too-distant future and a certain long-awaited feature branch[fn2] is getting very close to merging 😀. You'll just have to stick around to hear about those in a future edition of TMIO 😉.

dilbert-zenos-paradox.jpg Figure 6: It's right around the corner, I swear!

Customise the reference command used in LaTeX

Previously, whenever you linked to another part of your document (with or without giving it a name) --- for example with [[Profound section]] or similar --- when exporting to LaTeX Org would always use the \ref command.

org-latex-default-reference-to-sec.png Figure 7: A LaTeX export of a simple document with a reference to both the first and second section. "2" what? Section 2, Table 2, Figure 2, ...

You can now set the format string org-latex-reference-command (\\ref{%s} by default) to anything you'd like. For example, making use of the cleveref package I can set this to \\cref{%s} and then add ("capitalize" "cleveref" nil)[fn3] to org-latex-packages-alist.

org-latex-cref-reference-to-sec.png Figure 8: A LaTeX export of the same document, but now using cleveref. Note the change from "1" and "2" to "Section 1" and "Section 2".

A diversion into writing Org for LaTeX

Speaking of LaTeX exports, a member of the Org mailing list recently told us about a paper pushed to arXiv which was written entirely in Org. Why don't we use that as a prompt to talk a bit about generating LaTeX documents from Org?

For an experienced LaTeX-er, Org may initially appear best suited to simple documents, but in fact it's possible to reproduce any LaTeX structure in Org with no more difficulty (often less) than in LaTeX.

2.1. Simple elements

The “basic” Org elements are simply translated to their LaTeX counterparts. Markup like bold, italic, etc. are simply translated through org-latex-text-markup-alist.

For those of us who dabble with equations, Org is very accomodating. You can type (LaTeX-style) inline and display equations in exactly the same way (\( \) and \[ \]), and what’s more, if you have a LaTeX environment statement \begin{...} on its own line, Org will recognise it and pass it into the generated LaTeX.

2.2. Figures and tables

One area where the improvement when moving to Org is particularly apparent is with figures and tables. To simply include an image, an image link alone is sufficient.

When exported to LaTeX this will be expanded to


As soon as you add a #+caption, though, Org knows you mean business and generates a proper figure.

  \caption{A famous surrealist painting}

As you may have guessed from the fact this works without a LaTeX-specific keyword, this works nicely in HTML too 🙂.

salvador-dali-persistence-of-memory.jpg Figure 9: A famous surrealist painting

The LaTeX backend also accepts additional image attributes (manual page). For example, to set the image width I can simply add

  #+attr_latex: :width 0.4\linewidth

above the image link.

You can do the same with tables:

  #+caption: A selection of famous paintings by Salvador Dalí
  | Year | Painting                   |
  | 1931 | The persistence of memory  |
  | 1937 | Swans reflecting elephants |
  | 1837 | Metamorphosis of narcissus |
  | 1952 | Galatea of the spheres     |
  | 1966 | Tuna fishing               |

I like to set (setq org-latex-tables-booktabs t) to use the nice booktabs rules in the generated tables. Just remember to ensure the booktabs package is loaded.

  \caption{A selection of famous paintings by Salvador Dalí}
  Year & Painting\\
  1931 & The persistence of memory\\
  1937 & Swans reflecting elephants\\
  1837 & Metamorphosis of narcissus\\
  1952 & Galatea of the spheres\\
  1966 & Tuna fishing\\

Org is nice and does the right thingTM by including the caption at the top.

org-table-to-latex-example.png Figure 10: Look ma, I put the caption in the right place.

There are also some more attributes you can supply to tables. Should I want the table to spread out I could use #+attr_latex: :environment tabularx (as long as I’ve loaded the tabularx package) and then set the columns with :align lX.

2.3. Code blocks

By default, source code blocks are translated verbatim. We can do better than that however. We can tell Org to use listings, but I’d recommend going one step further and using minted. For this to work we need to perform three actions: Tell Org we want to use minted environments for source code Load the minted package by default Add -shell-escape to our LaTeX compiler flags, so minted may call pygments.

This can easily be accomplished via the following snippet:

  (setq org-latex-listings 'minted
  ;; as long as you have latexmk installed
  '("latexmk -f -pdf -%latex -shell-escape -interaction=nonstopmode -output-directory=%o %f"))
  (add-to-list 'org-latex-packages-alist '("" "minted"))

To customise minted, as well as inserting content into the preamble, one can also customise org-latex-minted-options to control what options are applied to each minted environment.

2.4. Custom environments

Org has a number of blocks which are treated specially, like #+begin_src for source code, and #+begin_centre for centred text. When exporting this same syntax allows you to wrap Org content in any LaTeX environments (as long as it doesn’t match one of Org’s recognised environments).

For example, if you wrote a warning environment in LaTeX to box and emphasise text, to wrap some Org content in it one simply needs to write:

  Pay close attention! This is very important.

and the content will be wrapped in \begin{warning} ... \end{warning}.

2.5. The LaTeX escape hatches

Should there be a particular LaTeX command you wish to insert somewhere, you simply need to put it on its own line with #+latex: in front and it will be transferred to the generated LaTeX (this works with other formats too).

  #+latex: \newpage

For larger snippets of LaTeX, there’s always the export block.

  #+begin_export latex
    \hfil This page is intentionally left blank \hfil

2.6. Preamble content

Should you wish to include the line in the preamble (before \begin{document}), then all you need to do is use #+latex_header:.

  #+latex_header: \newcommand{\RR}{\mathbb{R}}
    #+latex_header: \usepackage{svg} % so that [[file:*.svg]] works nicely

This is great for adding one-off \usepackage commands, but what if you find yourself wanting a package (like svg) to be always included? Well the we have the aforementioned org-latex-packages-alist which will include the packages set when exporting; you can even set some packages to only be included when using a certain LaTeX compiler.

Should you want to use a certain preset preamble, you can make use of the #+latex_class keyword. This is used to set the base preamble template used when generating the LaTeX. See org-latex-classes for what’s available by default. You should see entries for: article report book beamer

One of these is always used when generating LaTeX; when no #+latex_class is set in the document, the template named by org-latex-default-class will be used.

What’s great about this is that is makes it really easy to add your own templates. Each template simply takes three components: A name A preamble template A series of format strings to translate headings to LaTeX, with and without numbering

For example, I’m quite a fan of the KOMA-script family. Should I want to add a kart class (for: koma article), I simply need to do something like the following:

  (add-to-list 'org-latex-classes
  '("kart" ; class name
  "\\documentclass{scrartcl}" ; preamble template
  ("\\section{%s}" . "\\section*{%s}") ; H1 translation
  ("\\subsection{%s}" . "\\subsection*{%s}") ; H2 translation
  ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ; H3...
  ("\\paragraph{%s}" . "\\paragraph*{%s}")
  ("\\subparagraph{%s}" . "\\subparagraph*{%s}")))

See the documentation for org-latex-classes for more information on how the preamble template in handled.

Other improvements ox-koma-letter.el has been brought into Org’s main directory from the ) contrib/ repo Bastien Guerry Speed up publishing by using delayed hooks and temp buffers instead of finding files Gustav Wikström Improve generated HTML quality: prevent W3C warning and add some accessibility labels TEC Make the behaviour of the “goto variant” of org-refile (org-speed-commands) less confusing Marco Wahl Backport an update to the OpenDocument schema Kyle Meyer Bugfixes Off by one error in texinfo menu generation Nicolas Goaziou Error in entry/conversion of non-24h times in the agenda Nicolas Goaziou Only use replace-buffer-contents with Emacs 27+ when saving src blocks, as the behaviour isn’t consistent until then Nicolas Goaziou Prevent “before first headline” error in org-clock when clocking out Nicolas Goaziou Avoid setting the global agenda name when following a timestamp link Ingo Lohmar Don’t bind <tab> in org-mode-map Nicolas Goaziou Erroneous tangling of source block with :tangle no to a file no when the tangle command is called with a single universal argument Jacopo De Simoi Footnotes

[fn1] As has been the writing of this blog post 😜

[fn2] First-class support for citations is coming to Org! With support for CSL and BibTeX, with a number of citation processors 🙌. SoonTM

[fn3] I’m rather a fan of the capitalize option because (1) technically the reference to a named object is a proper noun, and (2) this means you don’t have to worry about references not being capitalized when appearing at the start of a sentence.

-1:-- June 2021 (Post TEC ( 01, 2021 04:00 PM

This Month in Org: May 2021

Async Babel sessions have landed

Jack Kamm has made a fantastic contribution to Org: ob-comint.el now supports asynchronous output from source blocks with full support for sessions 🎉.

If you haven't used sessions before, you're in for a treat! By simply assigning a named session to a source code block, e.g. :session foo, the same process will be reused for any other code blocks that specify the foo session. To do this for a certain language across the entire document, you can set the header argument property, i.e.

  #+property: header-args:lang :session foo

Along with the asynchronous process communication in ob.comint.el, we have an implementation for Python, and we should see support for R and Ruby in the not-too-distant future 😍.

To use this, just add the :async parameter to a python block. Instead of Emacs freezing until it completes execution, you'll see a placeholder inserted which is replaced by the result when it is ready.

emacs-jupyter allowed for asynchronous code execution (with sessions), but it's great to have a solution that doesn't require Jupyter kernels, and is part of Org.

Font lock for inline export snippets

Now, this isn't necessarily a significant change, but I don't think many people know about this feature so I'll take the opportunity to go over it 🙂.

If you want to include a snippet of HTML/LaTeX etc. when exporting to that format, you can use a #+begin_export html block which simply includes the enclosed content verbatim. This doesn't really work for small inline snippets though --- but never fear, Org has inline export snippets which simply follow the form @@format:content@@. For example:

  I love using Org to export to @@html:<abbr title="Hyper Text Markup Language">HTML</abbr>@@ @@latex:\LaTeX{}@@ documents.

which will export to HTML as,

  I love using Org to export to <abbr title="Hyper Text Markup Language">HTML</abbr> documents.

and then in LaTeX will be,

  I love using Org to export to \LaTeX{} documents.

isn't that neat!

Now you'll find the @@ parts using the comment face and the format: bit using the Org tag's face. It's a small change, but it makes it easier to see what's going on.

No mode-specific syntax highlighting yet, but that may come in the future 😉.

#+plot your #+results

Org-plot has been getting some more love as of late (see last month's post), and that hasn't stopped yet. This month there's been a fairly minor change that I'm quite a fan of. If you have a source block that produces a table of #+results, you can now put a #+plot statement immediately above to get a visualisation of those results!

  #+begin_src python
    # pretend this is some profound source of information
    return [[i, i^3 - 4*i^2 - 2*i] for i in range(5)]

    #+plot: ind:1
  | 0 |  1 |
  | 1 | -2 |
  | 2 |  7 |
  | 3 |  8 |
  | 4 | 13 |

As usual, this relies on gnuplot being present. You can read more about it in the manual.

Fancier LaTeX verses

With the use of verse.sty you can now export fancier verses from Org, as verse blocks now support four new attributes: :lines for the numbering interval. :center which can be set to t and works as long as, :versewidth, the longest line in the verse as a text string is set. You can also easily add arbitrary LaTeX code to be included with :latexcode.

  #+latex_header: \usepackage{verse}

    #+latex: \poemtitle{A Dream Within a Dream}
    #+attr_latex: :lines 3 :center t
    #+attr_latex: :versewidth Through my fingers to the deep,
    Take this kiss upon the brow!
    And, in parting from you now,
    Thus much let me avow —
    You are not wrong, who deem
    That my days have been a dream;
    Yet if hope has flown away
    In a night, or in a day,
    In a vision, or in none,
    Is it therefore the less gone?
    All that we see or seem
    Is but a dream within a dream.

    I stand amid the roar
    Of a surf-tormented shore,
    And I hold within my hand
    Grains of the golden sand —
    How few! yet how they creep
    Through my fingers to the deep,
    While I weep — while I weep!
    O God! Can I not grasp
    Them with a tighter clasp?
    O God! can I not save
    One from the pitiless wave?
    Is all that we see or seem
    But a dream within a dream?
org-verses-example-poem-dream-within-dream.png Figure 11: A short Poe-em

Easy zero-width spaces with Org

Occasionally you may run into annoyances when you wish to have two different Org elements right next to each other (no space) --- for example, emphasising part of a word or putting a currency symbol immediately before an inline source block.

The best solution to this in Org is zero-width spaces. As such, I've found it rather nice adding insertion of a zero-width space to the org-mode-map in my config. Perhaps some of you might find this solution useful too 🙂.

  (define-key org-mode-map (kbd "M-SPC M-SPC")
  (lambda () (interactive) (insert "\u200b")))

Should you want to keep zero-width spaces out of exports, that's easy enough to accomplish with an export filter.

  (defun +org-export-remove-zero-width-space (text _backend _info)
  "Remove zero width spaces from TEXT."
  (unless (org-export-derived-backend-p 'org)
  (replace-regexp-in-string "\u200b" "" text)))

  (add-to-list 'org-export-filter-final-output-functions #'+org-export-remove-zero-width-space t)

Org's repos have moved contrib/ is now at for Org 9.5, and it will be available on Non-GNU ELPA. Worg is now at Org itself is moving to Savannah Other improvements Add support for HHhMM date formats (e.g. 13h20) Gustavo Barros Make tangling faster and more robust Sébastien Miquel Allow importing tables from files that don't end in .txt, .tsv, or .csv Utkarsh Singh Add an SVG-specific post-export ob-plantuml step: org-babel-plantuml-svg-text-to-path for running Inkscape text-to-path replacement Nick Daly Refactor JavaScript in ox-html Anthony Carrico Set org-html-head-include-scripts to nil by default (was t) Bastien Guerry Remove LaTeX-environment type #+results TEC New capture templates parameter, :refile-targets Richard Garner Merge org-speed-commands-default and org-speed-commands-user into a new variable, org-speed-commands Bastien Guerry URL recognition regex now handles up to two levels of nested brackets, and is tested Ihor Radchenko Cache parent heading positions for faster movement up buffers. Significantly improves Org queries involving inheritance (15-50x improvement) _Ihor Radchenko_ New command ~org-refile-reverse bound to C-c C-M-w Adam Spiers Allow inline tasks to be dragged up/down Bastien Guerry LaTeX export, allow arbitrary :float values Thomas S. Dye Org attach git, new option org-attach-git-dir to use the attachment dir as a git repository Juan Manuel Macías Use a write-back buffer in Org src Sébastien Miquel Add the :environment and :options LaTeX attributes to Quote blocks Juan Manuel Macias Surround LaTeX :options attribute with curly braces when it contains square braces Markus Huber Recognise the specific contributions of Kyle Meyer, Ihor Radchenko, and TEC in the manual Bastien Guerry Improve test coverage Ihor Radchenko, Kévin Le Gouguec A bikeshed of new maintainers New maintainer for ox-html --- TEC New ob-ledger maintainer --- Eric S Fraga New ob-awk maintainer --- Tyler Smith New ob-calc maintainer --- Tom Gillespie New ob-asymptote and ob-coq maintainer --- Luc Pellissier General code cleanup Bastien Guerry Documentation improvements Bastien Guerry, Eric S Fraga, Samim Pezeshki, Nicolar Goaziou Bugfixes Make ob-gnuplot work on remote systems Ihor Radchenko Stop M-x org-toggle-link-display from affecting emphasis markers Bastien Guerry Inserting a heading before a headline Bastien Guerry Perform org-entry-put in a read-only buffer Ihor Radchenko Emacs 24 compatibility for ob-C and org-agenda-show-new-time Kyle Meyer Maintain Org's keybindings when visual-line-mode active Bastien Guerry Keep track of start of region beginning in org-table-wrap-region Bastien Guerry Ensure correct visibility when unfolding subtree Bastien Guerry Corner case in org--backwards-paragaph-once Bastien Guerry Some byte compiler silencing Kyle Meyer Make tags filtering case-sensitive Bastien Guerry C-c C-c on a #+plot line can no longer cause an error Bastien Guerry Ensure consistent position-translation in org-src by using point for position instead of column TEC Prevent ob-sql from getting stuck on an error Ivan Sokolov Make org-columns respect global-visual-line-mode, and simplify tag scanning Nick Savage Don't fontify :: in headlines as description item Ihor Radchenko Handle a few corner-cases in ob-R Jeremie Juste Many fixes to org-indent-line Bastien Guerry Make headline numbering consistent with TOC Mingkai Dong Allow read-only tangling again, and ensure the correct filename is used Sébastien Miquel Fix edge case when converting durations to minutes Nicolas Goaziou Make org-refile work in non-file-visiting buffers Bastien Guerry Be more rigorous in org-sort-remove-invisible Nicolas Goaziou Don't update checkbox stats when heading has todo COOKIE_DATA Bastien Guerry Don't recognise a lone :END: to be forming a drawer Nicolas Goaziou Allow new footnotes in empty table cells Nicolas Goaziou

-1:-- May 2021 (Post TEC ( 01, 2021 04:00 PM

Meta Redux: Meta Reduce 2021.1: Summer Time

It’s been quite a while since my last “Meta Reduce” post. I’m happy to report that since writing it in April, I got vaccinated against COVID-19, and the cases in Bulgaria have dropped down significantly. One can never know what life has in store for us next, but the summer has been pretty pleasant and almost normal so far.

I finally did a bit of international travel for the first time since the pandemic started:

  • In June I’ve spend a couple of weeks in Ukraine, visiting the family of my wife.
  • In early July I finally managed to go to Venice, after a couple of failed attempts (the second one was in March 2020).
  • In mid July I spent some quality time in Greece on the islands of Zakynthos and Santorini. If you’re into peaceful vacations, I can’t recommend the northern part of Zakynthos highly enough!

Clearly I really missed traveling, as I think I overdid it in the past couple of months. Now it’s time for a quiet month at home. I love Sofia in August, as it’s almost totally empty and very peaceful. I also hate traveling to the seaside during the high season. I guess I don’t have a lot of fondness for big groups of humans. Go figure!

There’s not much I can report on the OSS front. I took a 1 month vacation from work in mid-July and I’ve been trying to unwind a bit and stay away from programming for a while. Things are pretty quiet on the RuboCop and CIDER fronts. UNIX socket support for nREPL was finally merged a couple of days ago and I expect that relatively soon we’ll release nREPL 0.9 (e.g. early September).

We’ve also made some headway with the new library enrich-classpath, that makes it easy to download the sources and the javadoc for Java libraries. That’s extremely handy for CIDER (Orchard) users, as it makes it possible to navigate to the sources and javadoc of Java libraries. That has always been possible in CIDER, but the setup process was admittedly somewhat complex (you had to meddle with the classpath manually) and enrich-classpath makes this simple. Kudos to vemv (I don’t know his real name) for his work on the new library, and his recent efforts to improve cider-nrepl and refactor-nrepl!

Another cool recent development is the launch of nrepl-cljs-sci, created by Kimmo Koskinen. People have wanted an nREPL server for Node.js for a very long time, and now they have one. The project is still in its infancy and will require a lot of polish and some documentation, but it’s off to a very promising start.

I’ve used the extra time on my hands during my vacation to do some reading (I’m currently re-reading “A Wizard of Earthsea”), play StarCraft 2 (I totally suck there and random kids wipe the floor with me), watch “Better Call Saul”, migrate my personal email from Gmail to Fastmail, and provide technical support for my parents (that requires a lot of time!).

I also plan to do a bit of extra blogging in the next couple of weeks, but with all the heat here, and my excessive laziness, there’s no guarantee that this is going to happen. At least I finally finished the article I started to write last summer about the brief return to Linux. I’ve got plenty of ideas for articles, though, and I’m optimistic that at least 20% of them are going to become actual articles eventually. Of course, there’s always the possibility that I’ll actually learn how to play StarCraft II, become a pro gamer and put programming behind me.1

That’s all I have for you today. Short and sweet. Enjoy the summer (winter)! May it be as normal and delightful as possible! Keep chilling!

  1. Don’t worry, the chances of this happening are lower than those of England winning a major football trophy. 

-1:-- Meta Reduce 2021.1: Summer Time (Post Bozhidar Batsov)--L0--C0--August 01, 2021 11:08 AM

Jonas Bernoulli: Magit 3.2 released

I am excited to announce the release of Magit version 3.2, consisting of 84 commits since the last feature release one month ago.
-1:-- Magit 3.2 released (Post)--L0--C0--August 01, 2021 10:20 AM

Meta Redux: CIDER is Now on Discord

Over the past few months I’ve been trying to find better ways to support the community around CIDER (and my other bigger OSS projects), that’s why I was more focused on documentation and exploring new communication channels, instead of new features and fixes. Over the years I’ve tried a lot of different support channels with varying degrees of success:

  • Mailing List (Google Groups) - never gained any traction. I’ve noticed the Clojure mailing list hasn’t been that active in recent years as well, so I think mailing lists are losing popularity in general. A pity, if you ask me. At any rate - given that no one uses the mailing list I definitely considering to shut it down completely.
  • Gitter chat - never gained any traction. Gitter was somewhat popular a few years ago, but that’s no longer the case.
  • GitHub Discussions - it’s still new, but there’s not much traction there.
  • StackOverflow - never gained much traction either, although it’s certainly more used for CIDER than any of the above options.
  • Slack (Clojurians) - the #cider, #emacs and #nrepl channels there are quite active. CIDER’s channel alone has over 1700 users, which probably makes it one of most popular channels on Clojurians. Seems that Slack was a big success for Clojure in general, and for CIDER in particular.

A lot of support also happens in GitHub issues, but I consider this accidental rather than intended and now I can easily convert all issues that should have been discussions into discussions.

So, it seems that Slack is the solution for support/discussions/etc, right? It’s big, it’s active, so it must be great, right? Unfortunately, I don’t think that’s exactly the case. Sure, it has a lot of users, but it’s really painful for me to use Slack because of several things:

  • The logs disappear fairly quickly on the free plans that the Clojurians Slack is using. Often by the time I see something, all the context for it has disappeared. I know the logs are stored somewhere else, but I don’t really want to have to dig for them. I prefer them in chat.
  • There’s not enough granularity in the conversations as they happen in just a couple of channels and support requests, feature requests, etc quickly get intertwined. I could have created more channels like cider-support, cider-beginners, etc, but experience with Slack has taught me that most people probably won’t bother to use them (unless constantly prodded by someone). And Slack’s threads are notoriously easy to miss. In our company we had even forbidden them for a while, as so many people hated how they were implemented.
  • Slack has been betting progressing more enterprise and less hackerish every year. I still remember it when it was hip, simple and cool. Now it’s something very different.
  • It uses a ton of RAM.

All this means that I don’t really enjoy using Slack much. Frankly, the only reason that I still frequent the Clojurians Slack is that I’m using Slack for work anyways. I’ve been pondering about alternatives of Slack for a while now, but I couldn’t find something compelling. Until I did. At the end of last year I stumbled upon Discord, the famous chat app for gamers, and I was shocked to realize that it’s a pretty general purpose chat app, that fits my needs way better than Slack:

  • It’s simpler (less features, less hassle). It actually reminds me of the early days of Slack in some ways.
  • It uses way less resources.
  • The history doesn’t disappear on the free plan. That’s big!
  • I can run my own Discord “server” where I get to define the channel structure and how channels can be used. Probably not very important for you, but quite important for me.
  • It does threads better.

I know that some people don’t like Discord for various reasons (mostly related to some privacy fiasco in the past), but from my perspective it’s better than Slack in every way (at least for my CIDER/OSS projects use-case).

CIDER’s Discord server has been up for a few months and has the following channel structure:

  • #general
  • #support
  • #ideas
  • #nrepl
  • #orchard
  • #clojure-mode
  • #clj-refactor
  • #inf-clojure

A bunch of CIDER-related channels (the first 3), plus a few extra channels for my CIDER-related projects. Pretty simple, and super focused, at least from my perspective.

The Discord server is not particularly active yet (it has only a 110 users), but I haven’t advertised it much, so I’m optimistic about the future. My plan is to gradually reduce my presence in Slack and focus entirely on Discord. It’d be cool if more people adopted Discord (not just for CIDER, there’s a pretty big Clojure community on Discord in general), but I totally understand everyone who’s happy with Slack and wants to stay there. I have a feeling that part of its popularity is coming from the fact that so many companies are using Slack today as the official company chat, so adding one extra workspace there is not much hassle for many people. Given the size of CIDER’s Slack community, I think it’s going to continue being helpful even without me there. You can join CIDER’s Discord server here and decide for yourself if it’s better than Slack.

That’s all I have for you today. Keep chatting!

-1:-- CIDER is Now on Discord (Post Bozhidar Batsov)--L0--C0--August 01, 2021 05:30 AM

TAONAW: EWW, Wordnick, and Emacs Satisfaction

I wrote before about EWW, the text-only browser built into Emacs. Last night I’ve implemented a quick lisp function to have it search certain words in Wordnik.

I got some help on the Emacs channel on IRC (My lisp gets rusty, I forgot that “let” in lisp lives only in the instant of the function, it doesn’t implement a permanent change). There, I also learned of Abo-abo’s define-word, which seems promising. However, this function only shows partial definitions in the minibuffe and any key press exists that buffer, making it hard to copy-paste definitions.

There are more options for this function (abo-abo is an amazing Emacs packages contributor) but I couldn’t find more thorough documentation on GitHub or the web. I also wanted something quick and vanilla-Emacs as possible, so I decided to go with my original solution.

To have EWW search a certain word in Wordnik:

(defun wordnik-search ()
(let ((eww-search-prefix "")) (eww-search-words)))

This function uses the built in EWW function eww-search-words, which searches a highlighted word in EWW (M-x M-s). In itself, this is also very useful1.

To understand why you’d want a full page of a definition, you need to use Worknik for a while and get familiar with it. The website is not a mere dictionary like many others, it’s an index of several dictionaries, some of which are rarer to find. My favorite is the century dictionary, though I like to have the “quick and easy” word definition from American Heritage or similar as well.

Each definition in Wordnik also follows with tables of synonyms, rhymes and more. In EWW, there’s also the helpful eww-readable (simply “R”) which:

“View the main “readable” parts of the current web page. This command uses heuristics to find the parts of the web page that contains the main textual portion, leaving out navigation menus and the like.”

This makes reading the word definitions in Wordnik clean and distraction-free. Oh, and while I’m mentioning known-but-forgotten tricks: to highlight a word under the mark, use M-@, which will highlight from where the mark is located. Stand on a word you want to define, hit M-@, and then C-arrow to move to the start of the word (I never got used to M-b or M-f, which are placed awkwardly under the left palm).

Here’s how it looks like on my Emacs:

Wordnik definition for the word "definition" in Emacs

To have these word definitions at your fingertips while you write a post such as this one without ever switching a program or a Window… this is why Emacs is a magical writing machine to me.


  1. EWW uses Duck Duck Go by default, so your searches will come up there. Duck Duck Go is an excellent and privacy-oriented search engine, but it doesn’t stop there. It comes with Bangs, which means you can search certain terms in websites like wikipedia and yes, also wordnick, directly from EWW. ↩︎

-1:-- EWW, Wordnick, and Emacs Satisfaction (Post)--L0--C0--August 01, 2021 04:00 AM

Irreal: More on Writing Academic Papers with Org-mode

The other day, I wrote about Wouter Spekkink’s Org-mode setup for writing academic papers and promised to followup with Jonathan Bennett’s post on the same subject from a couple of years ago. As I started to prepare my post on Bennett’s post, though, things seemed vaguely familiar.

A little checking revealed that I’d already written about Bennett’s post back in 2019. It’s a good post and worth revisiting—especially in view of Spekkink’s post—so I’m linking to it again. If you have to produce papers in an academic environment—or anywhere, actually—you should take a look Bennett’s post.

-1:-- More on Writing Academic Papers with Org-mode (Post jcs)--L0--C0--July 31, 2021 04:42 PM

Meta Redux: Hasta la Vista Gmail


I’ve been a Gmail user pretty much since day 1, when it was still an invite-only service in 2004.1 Not anymore. Over the past month I’ve migrated most of my email to Fastmail and I’m extremely happy with the result.

Why bother? Well, I guess it won’t come to you as a shock that I’ve felt progressively more uncomfortable with how Google (and the like) are handling my personal data. I’ve also been getting quite frustrated with attempts to make email/my inbox “smarter”. I never needed a “priority inbox”, auto-categorization of email, etc. Simple is good. Just put the newest emails on the top and I’ll sort it out from there.

On the other hand, Gmail is really hard to replace/compete with:

  • It’s free and you get a lot with the free plan (e.g. 15GB of storage).
  • It ties perfectly with Google’s productivity suite (e.g. Google Docs, Google Drive, etc) and I’m a heavy user of it.
  • It’s fast, secure and really sleek. Clearly Google’s vast resources have been put to good use here.

That’s not easy to give up. I’ve tried a few other e-mail providers over the years, but I never found someone compelling enough to make me do a real switch. HEY was pretty close to making the cut, but it’s still missing some features that I deem essential (e.g. you can’t have multiple domains attached to your account, there’s no way to use HEY without its apps, there’s no calendar). Enter Fastmail.

Moving to Fastmail

I’ve never heard of Fastmail, until I started to explore more actively Gmail alternatives in the past 3 months. At first I had quickly discarded it, because of its ancient looking UI, but once I got past this superficial stuff I realized it’s a fantastic service:

  • It packs all the features I needed (e.g. custom domains, aliases, calendar, IMAP/JMAP)
  • It has great customer support
  • They are working towards improving the global email standards (check out JMAP)
  • It’s half the price of HEY

Sure, it doesn’t look fancy, I’ve ran into a couple of bugs, and it doesn’t have the best search in the world, but it gets the job done. I’ve been a happy customer for over a month now and I can heartily recommend it to everyone. Here’s a nice comparison between Fastmail and Gmail, even if it’s bit biased.

I won’t write here about the actual migration process from Gmail, as there wasn’t much of it. I just forwarded both my Gmail accounts to my new Fastmail account, and I updated many services to use the Fastmail addresses directly. My domain is tied to a legacy free Google Apps plan, that’s also used by other members of my family, so I couldn’t just move the domain to Fastmail, as I would have done normally. Instead I bought the domains and and decided to gradually make them my primary email addresses. You can now also write to at first name at metaredux dot com.

I’ve also opted not to import my Gmail contacts and mails into Fastmail, even though the process is trivial. I rarely need to check something in the archives and I decided to go for a clean start. Jason Fried and HEY thought me about the value of that. By the way, I’m still going to use HEY as well. Even though the service doesn’t quite match my needs, there’s a certain charm to it that I really like. I’ve been using it mostly as a newsletter reader and to write occasional emails to close friends, like in the pen pal era. You should try this! If nothing else - HEY taught me to favour top posting, instead of inline responses. Seems weird at first, but that’s how real mail works. :-)

Fastmail Alternatives

I guess by now this article might look like a Fastmail advertisement. I want to mention that I certainly don’t think it’s the only game in time, as there are plenty of solid mail providers to choose from. I considered several Gmail alternatives before deciding on Fastmail. They all have their pros and cons and I guess for some of you they might be a better choice.

  • ProtonMail - a privacy-centered mail service, hosted in Switzerland. I liked ProtonMail a lot (it has all the essential features for me, plus a very sleek web UI), but because of the end to end encryption they use, you’re stuck with their clients or a clunky IMAP bridge. I like open standards, that’s why I went with Fastmail in the end.
  • - another privacy-centered mail provider, this time hosted in Germany. It offers pretty similar features to Fastmail and it’s a bit cheaper. I picked Fastmail over it, mostly because of JMAP.
  • HEY - I already covered it above.

Fastmail, Proton and allow you to have multiple users attached to one account, which is pretty handy if you want to create email accounts for your entire family or your business.

I never considered one of the other big players (Outlook, Hotmail, Yahoo, etc), as I think they suffer from the same problems as Gmail (you pay for them with your privacy). Probably there are other cool services that I didn’t try out. Feel free to mention those in the comments.

The important thing to note is that there are plenty of good Gmail alternatives, and most of them are not particularly expensive either. ProtonMail has a free plan, Fastmail starts at $3/month and starts at only 1 EUR/month. From my perspective our privacy is worth a lot more than this.


We now live at a time where more and more people consider email obsolete and rely mostly on chat apps like Slack, FB Messenger, Whatsapp, Telegram, etc. Many applications claim to be the email killer, but due to their walled garden approaches no one really succeeds in this endeavor. For some reason email has this horrible reputation of something that’s always messy and causes a ton of stress, but I think that’s just a side effect of how most people use (abuse?) email. Email can be a lot of fun, and no stress at all. You just have invest a bit of time in organizing and streamlining your inbox. For me the migration to Fastmail was a great opportunity to do this and I’m truly having a lot of fun with email right now. It’d be cool if some of you shoot me an email or two! :)

I hope I managed to convince a few of you that Gmail has viable (and fun) alternatives. I regret a bit not doing the switch earlier, but better late than never, right? For a long time privacy was an afterthought for me, but as I’ve been growing older I’ve learned to appreciate it more. I’ll assume this means I’m getting both older and wiser.

Anyways, that’s all from me for now. Time to go back to having more fun with my new inbox. Keep hacking!

  1. Damn, that’s 17 years! Almost half my life (I’m 36 as I write this). 

-1:-- Hasta la Vista Gmail (Post Bozhidar Batsov)--L0--C0--July 31, 2021 11:08 AM

Meta Redux: Back to Linux


Note: I’ve started writing this article about one year ago (September 2020), but I dropped it at some point. Its final version is way less ambitious than my original plans for it, mostly because I forgot some of things that were on mind back then. Still, better than nothing.

A long time ago (in 2011) I wrote about my frustrations with Linux that led me to abandon the OS after having spent quite a lot of time on it.

After this article I made one failed attempt to convert to Windows and eventually I settled on macOS for almost a decade. While I was reasonably happy with macOS for most of the time, it never felt like home and I kept longing to revisit Linux. I was also missing having a custom-built desktop PC for a while, so I was very tempted to get one and run Linux on it. For various reasons (e.g. a lot of work-related travel and excessive laziness) I never got to doing so. Until now.

2020 has been a horrible year on many levels, but it presented me with an unique opportunity to follow through with my Linux PC plans, as I was finally grounded at home and had some extra time on my hands. In this article I’ll share my experience revisiting Linux and rediscovering the joy of being in control of your operating system and your hardware.

The Downfall of macOS for Software Development

I won’t go into much details here, as I hope everyone has noticed the shift in macOS to be something more like iOS. That’s good for most users, but not really for software engineers.

Apple used to spend a lot of time courting developers to their OS some 15 years ago, but now they only seem to care about macOS and iOS devs. They rarely update the Unix tools that ship with macOS, they still haven’t created a package manager (everyone’s basically using homebrew), etc.

At this point it’s clear to me that macOS is not meant to be an OS for tinkerers, but rather for consumers. That’s not a bad thing, it just doesn’t sit very well with me.

On a more practical note, here are a few things that have bothered me with macOS in recent years:

  • Pushing aggressively for the use of the App Store, which limits what applications can do. The OS tries hard to dissuade you from using any externally procured applications.
  • Bringing some applications and weird features from iOS to macOS (has anyone ever used the launchpad?).
  • The need to reinstall XCode after each macOS upgrade.
  • Almost every major OS upgrade breaks Homebrew or some tool that I use (like Karabiner, a keyboard remapping utility).
  • macOS ships by default with Emacs 22. That’s not a typo. As noted above there are plenty of outdated Unix tools that ship with macOS.
  • Cheap tricks to obscure some problems, like hiding the remaining battery life estimation.

I can go on, but I’ll stop at this point. I hope you get the idea.

The New Hardware

Here’s the hardware that I got in early July 2020 (it took me almost 3 months to settle on all the parts):

Motherboard AORUS X570 ULTRA
SSD 960GB M.2 2280 Corsair Force Series MP510
RAM 32GB (2x16GB) DDR4 3200MHz Corsair Vengeance LPX
Case Fractal Design Define 7
PSU Fractal Design Ion+ 660W Platinum

As you can see there’s nothing fancy about it. I wanted to build a decent workstation, not a gaming rig. Still, I opted to get a decent discrete GPU, as there were a few PC games that I was hoping to eventually play (StarCraft II, Tomb Raider, Diablo III, etc). I went for the Radeon mostly because of the AMD’s (supposedly great) open-source GPU driver for Linux. In hindsight this was a big mistake, but I’ll expand on this topic later.

Note: I knew that an Intel CPU with built-in GPU was the safest option in terms of driver support, but I really wanted a Ryzen CPU and a reasonably powerful discreet GPU.

I have to say that this 1,600 EUR desktop completely blew out of the water my way more expensive MacBook Pro. Of course, desktops always offered better value/performance than most laptops, but in recent years we’ve all became completely obsessed with laptop/tablets. While portability is definitely a problem with desktops, they also have some cool advantages like:

  • They don’t overheat
  • They don’t run out of juice
  • You can actually fix/upgrade them
  • They force you to work on desk (meaning the ergonomics are usually better)

End of this slight lyrical detour on the merits of ancient technology from more sophisticated times.

The Distro

I decided to play it safe and I went with Ubuntu 20.04, which was the latest release at the time. Historically I preferred Arch Linux and Fedora, but I wanted to minimize the setup efforts.

When I was younger I loved spending lots of time to tweak every aspect of my setup (e.g. building a custom kernel, tuning the compilation flags for my packages, obtaining proprietary drivers from third-party repos, etc), but now I’m older, lazier and more practical. I still enjoy tinkering with my setup a lot, but I don’t want to be forced to tinker (the Gentoo way).

One general trend I’ve observed is that Linux distros are now more complex than they used to be. Life seemed pretty good and simple in the days of System V init, but today systemd dominates everything and makes it harder to comprehend. At least to someone like me, who completely missed the transition to systemd.

systemd is a software suite that provides an array of system components for Linux operating systems. Its main aim is to unify service configuration and behavior across Linux distributions; systemd’s primary component is a “system and service manager”—an init system used to bootstrap user space and manage user processes. It also provides replacements for various daemons and utilities, including device management, login management, network connection management, and event logging.

So much for the single-responsibility principle.

The Drivers

Everything worked out of the box, but unfortunately not everything worked well. I was getting some intermittent issues with my wi-fi and kept crashing due to some issues with the GPU drivers. A quick Google search revealed I wasn’t the only person facing these GPU issues.

No matter what I tried (and I tried a lot of things - updated kernels, Mesa, random patches I found here and there, etc) I couldn’t solve the GPU issue and my computer kept crashing 1-2 times per day. As you can imagine this was quite frustrating. Funny enough, after each change the crashes would get more frequent or less frequent. Never completely disappear, though.

The wi-fi problem was much easier to address - I just switched to ethernet and never bothered to investigate it.

In the past I also struggled with getting my printer to work properly, but I no longer have a printer, so that’s one of those problems that solved itself.

Hardware support was the main reason I left Linux a decade ago and sadly the situation there hasn’t improved much. Perhaps the situation is better with Nvidia GPUs, but I was hoping avoid dealing with a proprietary driver.1

The Apps

Little has changed in the past 10 years, not to mention I don’t use that many apps - mostly a browser (Chrome and Firefox), Emacs and a terminal (Guake). In short - everything was better than I remembered it, but nothing was fantastic. GNOME and its apps (e.g. Nautilus) still have plenty of rough edges, but they get the job done.

Albert was a great alternative to Alfred (one of my favorite macOS tools). That’s probably the only new app that I used this time around. Some proprietary apps that I need for work (like Zoom, Slack and Dropbox) didn’t work/look great (especially when compared to their macOS/Windows versions), but this is what I expected anyways. Still, they were working better than I remembered them to. Given the small market share that desktop Linux has, I never expected big corporations to start investing heavily in Linux support. I recall that 5 years ago Zoom kept crashing constantly on Linux (colleagues using Linux were often dropping out of Zoom calls, that’s how I know this), but at least it was working reliably for me.

Back in the day I complained about how bad Skype for Linux was, but fortunately I no longer have to use Skype, so this is a problem that solved itself. I also complained about the quality of OpenOffice - another application I no longer needed, as I’m using mostly Google Docs these days. In general the trend to move from native desktop applications to web based applications is definitely a benefit for Linux users. In some cases I actually preferred the web versions of applications that have a Linux desktop version as they seemed to work better to me (e.g. Slack and Spotify). Skype also has a nice web app these days, if you happen to need it.

One more thing - I was happy to see that there were a lot of games (by Linux standards) in Steam, despite the failure of Valve’s Steam Machine project (a gaming console running Linux). I tried out a couple of older games and they worked fine, apart from the video crashes I was getting because of the GPU driver issues.

The Development Experience

Absolutely divine. Proper package manager. Proper service management. Emacs in all its GTK glory! All the fantastic GNU utils. Docker at its home. No more XCode installations. It doesn’t get better than this.

I’m 100% certain that Linux offers the best development experience for most software engineers. When there aren’t hardware issues to affect it negatively, that is.


“Back to Linux” is a bit of a misnomer, because of the long period in which this article stayed on my backburner. By the time I wrapped it, I’m no longer using Linux, at least not natively.

Due to the GPU driver issues, in the end I’ve opted to switch to Windows 10 and WSL (basically a Linux VM running in Windows). One year later I’m still a happy camper. With Windows 10 I got the best of both worlds:

  • no driver issues
  • proper Linux development experience

As a bonus - I also got the opportunity to play a lot more games.2

Windows still has its quirks, but the experience with it certainly beats the experience I had with Linux. All proprietary apps work great, the drivers are solid and I’m essentially working in Linux all of the time. The only thing from macOS I’m really missing is the nice collaboration/sync between all Apple devices - e.g. you take a picture on your phone and it immediately goes to your computer. You get an SMS on your phone and it’s also on your computer. Not a big deal, but this walled Apple garden kept me on macOS even though I was getting more and more frustrated with it. I hate walled gardens!

In short, hardware support remains the biggest weakness of Linux as desktop operating system, just as always. It’s super disappointing that even after carefully choosing hardware for Linux compatibility I still ended up with a GPU that didn’t work reliably. I’m reasonably sure that if I had opted for an older GPU it would have worked better, but I didn’t really want to make too many compromises. Who knows, probably by now the problems that plagued me have been fixed, although I’m not sure eager to check this.

On the bright side - it was a ton of fun to assemble a new PC, after all those years. You should have seen how happy I was when the thing booted from the first try! And it was nice to check in on the progress made in the world of Linux and to find a reason to give Windows another chance.

That’s all I have for you today. Keep hacking!

  1. And I happen to be a huge AMD fan. 

  2. Not sure if that’s really a bonus though. 

-1:-- Back to Linux (Post Bozhidar Batsov)--L0--C0--July 31, 2021 09:38 AM

Manuel Uberti: A dictionary in Emacs

I explained my need for an English dictionary when I wrote about my own helm-wordnut. To sum it up: my English is good but it’s not David Foster Wallace good, so a dictionary is mandatory.

Last October Torsten Hilbrich added dictionary-el to Emacs master so, in my quest for a Vanilla Emacs appreciation, I decided to give it a try. According to the first line of dictionary.el this library is a client for RFC 2229 dictionary servers, which as the RFC says, rely on the DICT protocol:

The DICT protocol is designed to provide access to multiple databases. Word definitions can be requested, the word index can be searched (using an easily extended set of algorithms), information about the server can be provided (e.g., which index search strategies are supported, or which databases are available), and information about a database can be provided (e.g., copyright, citation, or distribution information). Further, the DICT protocol has hooks that can be used to restrict access to some or all of the databases.

This is very useful because it means that one can collect different definitions from various dictionary and possibly compare synonyms.

This is how I set up dictionary.el in my init.el:

(global-set-key (kbd "C-c d") #'dictionary-search)
(setq dictionary-server "")

dictionary-search cleverly picks up the word at point which means that when I hit C-c d RET on a word I don’t know I get a *Dictionary* buffer with entries coming from:

  • The Collaborative International Dictionary of English
  • WordNet
  • Moby Thesaurus II

There is much more in dictionary.el, though. I counted 17 defcustoms for starters, so go on and tweak it like any Emacs hacker would do. As for me, the couple of ELisp lines above are adequate.

-1:-- A dictionary in Emacs (Post)--L0--C0--July 31, 2021 12:00 AM

Irreal: Writing Academic Papers With Org-mode

Wouter Spekkink has an interesting post on his workflow for writing academic papers using Emacs and Org-mode. It’s a long post because he wrote it for several different audiences. He starts with what Emacs and Org-mode are and why someone not familiar with them might find it worthwhile to learn them. He considers the question of why one would want to “do this.” He mentions things like version control and the advantages of working with plain text but I doubt it will convince anyone. Either you embrace plain text with all its upsides and downsides or your prefer to live in—what I consider—the dystopia of Word and its evil siblings.

The most useful part of his post, for me, discusses his setup for actually writing papers. That includes both the boilerplate in the document itself and his configuration. He’s a Doom Emacs user so it may not be completely transparent if you worship in a different sect of the Emacs church but it’s reasonably easy to make the translation.

Spekkink also discusses how he integrates Org-roam and bibliography processing into his workflow. He uses the excellent org-ref to handle his citations and bibliography and org-roam and org-noter to organize his notes.

Much of Spekkink’s workflow is informed by a post from 2019 by Jonathan Bennett, which is also excellent. I’ll probably write about Bennett’s post later. In the mealtime, take a look at Spekkink’s post if you’re interested in writing academic papers with org-mode.

-1:-- Writing Academic Papers With Org-mode (Post jcs)--L0--C0--July 29, 2021 04:47 PM

Philip K.: Emacs 28 has a global mode line

Emacs 28 has a global mode line

Emacs 28 has a global mode line

A complaint I have often heard raised amongst Emacs users is that the mode line can get cramped, quickly. Enable display-time-mode and perhaps rcirc-track-minor-mode, start compiling something and depending on your window configuration, you might not be able to see everything – and that despite information duplication! E.g. display-time-mode adds the current time to every mode line, even though there is no need for that.

One way to solve this, an idea that I head of a few times, was to add a “global mode line”. A bar at the top of an Emacs frame just for this kind of information that doesn’t belong to any specific buffer. There have been attempts at solving this, including hacking this information into the minibuffer, but nothing real – until now.

A few months ago, support was added for just this kind of a functionality, to be released with the next version of Emacs (28.1). And all you need is this1:

(setc tab-bar-format '(tab-bar-format-global)
      tab-bar-mode t)

As indicated, it makes use of the tab-bar, a space added in 27.1 initially intended for tabs, that can just as well represent any string.

This is particularly useful for people who don’t use tabs, but if someone does, it is no problem either, one just has to adapt tab-bar-format (see it’s documentation string for more info).

As for Emacs 27.1/2 and earlier, one can try to hack together something like this:

(defun local/global-mode-line ()
  "Generate a global mode line."
  `(keymap (global . (menu-item
		      ,(format-mode-line global-mode-string)

(advice-add 'tab-bar-make-keymap-1 :override #'local/global-mode-line)

The functionality isn’t perfect, but it does some version of the job for now. Someone interested in this could try to improve it.

Either way, this is yet another much appreciated addition to the next release of Emacs, that I think many people will be looking forward to. My issue now is that I don’t even know what to do with all the space in the new global mode line.

  1. setc here is a macro that calls customize-set-variable↩︎

-1:-- Emacs 28 has a global mode line (Post)--L0--C0--July 29, 2021 10:23 AM

Emacs NYC: Lightning Talk Wrapup - May 2021

Original Etherpad source:

Ben Bass - Beorg (iOS Org Mode App)

Org interface from iOS. Scripted in biwascheme ( ) Uses different capture templates from Org(maybe?) Can sync via Dropbox, iCloud, WebDAV, Box References Getting Things Done methodology(

Zachary Kanfer(Transient Key Maps)

Maintain a certain state After calling set-transient-map something Any keypress that is within the map will call the function associated It will work until a non keymap key is pressed


  • Free Lisp Meetup:
  • scimax - Awesome editing for scientists and engineers:
-1:-- Lightning Talk Wrapup - May 2021 (Post)--L0--C0--July 28, 2021 04:20 PM

Alex Schroeder: Browsers

The browsers I use…

Most of the time I use Firefox. I’m happy Mozilla exists. I’m happy there’s an alternative to Google Chrome. I’m super concerned that they are basically being propped up by Google as a shield, and a tool. They can claim that they’re not a monopoly, and Mozilla cannot be too outspoken about them. I think Aral Balkan is right: the big companies are everywhere, even sponsoring their competittion, thus keeping them weak and malleable.

So, in light of the overwhelming support for surveillance capitalism by generally well-respected organisations that say they work to protect our human rights, privacy, and democracy, I have decided that I must be the one who’s wrong. – Aral Balkan criticising Google and Facebook and their corrupting influence

So yes, I use Firefox. I also change many of the defaults, and install a handful of extensions to make it work. There are a gazillion defaults, and they change every now and then, so this helps keep us all confused and our defences weak. I hate that. Having to install extensions is also problematic as they increase our attack surface, make us more vulnerable. How easy it must be to bully, bribe or buy the small fries extension authors. I dislike this very much.

Basically I search for telemetry*enabled and switch it all too false, because I don’t understand why we need a bewildering plethora of options when almost all people will be either “I don’t care” or “fuck this shit”. This is false choice designed to confuse the unwary, if you ask me. – My Firefox Setup page keeps growing and growing

So what else should I be using, if I can? Not any of the Firefox-derivatives, that’s for sure.

I have qutebrowser installed but hardly ever use it. The lack of a menu make it very difficult to discover; you’re immediately faced with a terrible wall.

qutebrowser is a keyboard-focused browser with a minimal GUI – Qutebrowser

I recently compiled and installed netsurf. We’ll see whether that gets used more often.

Small as a mouse, fast as a cheetah and available for free. NetSurf is a multi-platform web browser for RISC OS, UNIX-like platforms (including Linux), Mac OS X, and more. – NetSurf

I’ve used Eww a lot; the browser inside Emacs. It’s text only, no Javascript, so you can’t use it for many links, but it definitely works well when following links from mails or social media, where you’re not sure where they’re taking you. Having a text-only browser without Javascript at your fingertips is great. And it has a reader mode integrated that I keep forgetting about because it’s already close to ideal. Use R, for “readable.”

Actually, I have started writing a little something that allows me to use Elpher for the web. Elpher is a Gopher and Gemini browser for Emacs. I mean, I’m just hooking existing stuff up: url-retrieve to fetch stuff via HTTP; HTTP header parsing using code I copied from Eww; HTML rendering using shr, the same library that Eww is using. The benefit I’m hoping to see is that it’s easier to follow HTTP links from Elpher without accidentally switching from Elpher to Eww. When that happens, things still look OK, but the keybindings are different, and you can’t go “back” to Elpher because now you have both Elpher and Eww buffers, so you have to quit or bury Eww in order to get back to Elpher. It confused me for a while.

One interesting side effect: Emacs has its own bookmarks, mostly for positions in files, but with a framework that lets us extend them to other uses. Eww has its own bookmarks. Elpher used to have its own bookmarks. But I recently managed to switch Elpher bookmarks to the Emacs bookmarks backend, so now I can visit websites using Elpher, and bookmark them, and they end up in Emacs bookmarks where I can edit and annotate them, bypassing the Eww bookmarks. It’s going to be part of the next official Elpher release, apparently. 😁

Fighting the urge to add Emacs bookmarks as a back-end to Eww bookmarks… Nooo!

-1:-- Browsers (Post)--L0--C0--July 28, 2021 08:28 AM

Irreal: Some Custom Commands from Prot

Protesilaos Stavrou (Prot) has another video up in which he discusses a few of the commands he’s implemented to make his workflow easier. There’s no overriding theme, just some functions he’s written that ease his work in various ways.

For example, his first command deals with inserting comments. It puts the comment in the proper place using a heuristic based on where the point is but also adds a prefix consisting of a keyword and the date or a keyword and a date/time stamp. It is, as Stavrou says, not a big deal but it does make it easier to add comments as you code.

Next he considers diffing the current buffer. If the buffer has been modified, it diffs the buffer with the underlying file. If the current buffer is clean (has not been modified) it diffs it with the version in version control (if any). Again, this is pretty simple but very useful. When called with the universal argument, the function will highlight word-wise changes.

His next bit of Elisp is concerned with narrowing. Stavrou says it’s a simplification of some code by Bozhidar Batsov but I find Artur Malabarba’s code more useful.

The next bit of code involves escaping URLs and email address for Markdown. They’re nice but we Org mode users probably won’t find much use for them.

Finally, he presents some code to ease grepping. It uses the built-in grep function but puts a wrapper around it so that you don’t have to input all the information the standard implementation requires.

He has a sort of coda to the video that mentions a few things that he doesn’t discuss at length but that he finds useful.

There’s a lot of material in the video but it’s only 31 minutes, 27 seconds long. That short enough that you can probably fit it in easily but long enough that you’ll still have to schedule some time for it.

-1:-- Some Custom Commands from Prot (Post jcs)--L0--C0--July 27, 2021 03:58 PM

Emacs Redux: GNU ELPA Devel Package Repository

GNU ELPA is one of the most well-known package repositories for Emacs (and the only one enabled by default).1 Recently I learned there’s also a GNU ELPA repository for pre-release versions of the ELPA packages called elpa-devel/gnu-devel. You can add it to your Emacs config like this if you want to install the development version of some package (e.g. for test purposes or to get a bug fix early):

(add-to-list 'package-archives '("gnu-devel" . ""))

You can think of this repository as something similar to the popular MELPA repository, but limited only to the packages part of GNU ELPA. It seems that the repository is not mentioned anywhere in Emacs’s documentation, that’s why I decided to write this short article about it. I doubt that most of you will ever need it, but I guess it doesn’t hurt to know about its existence.

That’s all I have for you today. Keep hacking!

  1. In Emacs 28.1 another package repository is going to be available by default - NonGNU ELPA

-1:-- GNU ELPA Devel Package Repository (Post Bozhidar Batsov)--L0--C0--July 27, 2021 07:05 AM

Andrea: What if we cannot make it? A less optimistic view on climate change

Are we parasites or gardeners?
-1:-- What if we cannot make it? A less optimistic view on climate change (Post)--L0--C0--July 27, 2021 12:00 AM

Andrea: Moldable Emacs: finding examples of Clojure functions (with tests)

-1:-- Moldable Emacs: finding examples of Clojure functions (with tests) (Post)--L0--C0--July 27, 2021 12:00 AM

Irreal: Ten More Emacs Tips

A couple of weeks ago, I wrote about the Ten Useful Emacs Tips video from the Emacs-Elements YouTube channel. Now there’s a new video, 10 More Helpful Emacs Tips. Like the last video, you will probably be familiar with some of the tips but others may be new so it’s worth spending a few minutes on it.

Here’s a list of the topics from the video notes:

Tip 1: Delete empty directories in Dired
Tip 2: Recenter Positions
Tip 3: Minibuffer commands
Tip 4: Insert lines of a single character
Tip 5: Change encoding system for a file
Tip 6: Cycle org lists
Tip 7: Autoexpand without an external package
Tip 8: Cycle org-agenda files
Tip 9: Add a package manually
Tip 10: Xah file backup

Irreal talked about Tip 2 previously. First to change the sequence as recommended in the video and then to recant my apostasy and return to the default. This seems like something you wouldn’t need that much but I find myself using it several times a day. It’s so easy to change the sequence that it’s essentially free to experiment.

The last tip is about Xah Lee’s functions to make a backup of the current file. Lee doesn’t like the default Emacs way of doing this. If you agree, his bit of Elisp is an excellent alternative.

Tip 1 on deleting empty directories was new to me. So was Tip 8 on cycling through the files that go into your agenda summary. I’m not sure how often I’d use either of those tips but they’re nice to know.

The video is 10 minutes, 18 seconds long so it should be easy to fit it into your schedule.

-1:-- Ten More Emacs Tips (Post jcs)--L0--C0--July 26, 2021 05:33 PM

Phil Jackson: Export an environment variable to Emacs

Handy function to export environment variables to Emacs from the command line:

function export-emacs {
    if [ "$(emacsclient -e t)" != 't' ]; then
        return 1

    for name in "${@}"; do
        value=$(eval echo \"\${${name}//\\\"/\\\\042}\")
        emacsclient -e "(setenv \"${name}\" \"${value}\")" >/dev/null

Use it like this:

export BLAH="Some value"
export-emacs BLAH

And in emacs:

(getenv "BLAH") ; => "Some value"

update: A very kind soul updated the function to handle quoting properly. Thanks, @pcrama!

-1:-- Export an environment variable to Emacs (Post)--L0--C0--July 26, 2021 03:04 PM

Marcin Borkowski: Binding a command to every key bound to another command

For today, I have an extremely specific Emacs Lisp tip – this is definitely not something you would use every day, but when you need it, it’s there. Assume that you are writing a mode (call it cool-mode), which should support some general Emacs command (call it do-something) – only the workings of this mode are so specific that this command should be basically written from scratch instead of using Emacs’ own do-something. You could (of course) advise do-something, but it seems cleaner to define cool-do-something instead. How do you bind it to the same keys it is normally bound to in Emacs? For bonus points, the user might have its Emacs customized (with global-set-key, for example) to bind do-something to a key of their choice.
-1:-- Binding a command to every key bound to another command (Post)--L0--C0--July 26, 2021 06:10 AM

Sacha Chua: 2021-07-26 Emacs news

Links from, r/orgmode, r/spacemacs, r/planetemacs, Hacker News,, YouTube, the Emacs NEWS file, Emacs Calendar and emacs-devel.

-1:-- 2021-07-26 Emacs news (Post Sacha Chua)--L0--C0--July 26, 2021 12:00 AM

Phil Jackson: Using yadm via magit

Yadm’s an amazing dotfile manager that’s basically a thin wrapper around git and a bare repo. With it being a bare repo, you’ll not be able to manage it directly with Magit so here’s a really smart tip I found that will let you access it via Tramp:

(use-package tramp
  (add-to-list 'tramp-methods
                 (tramp-login-program "yadm")
                 (tramp-login-args (("enter")))
                 (tramp-login-env (("SHELL") ("/bin/sh")))
                 (tramp-remote-shell "/bin/sh")
                 (tramp-remote-shell-args ("-c")))))

(defun yadm ()
  (magit-status "/yadm::"))
-1:-- Using yadm via magit (Post)--L0--C0--July 25, 2021 05:22 PM

Irreal: Logging mbsync Errors

I’ve been using mu4e and mbsync for the last four years and love it. One of the things you discover early in your use of mbsync is that it loves spew messages into the minibuffer. That would be okay except that sometimes it overwrites something that you’re looking at.

A first hack at fixing this is to simply redirect those messages to /dev/null but then you might miss something that requires action so the second try at a fix is to redirect the output to a file. But then you discover that mbsync can emit the same error message on every invocation. For me that began with a message about an illegal message number. I fixed that but now Apple mail, I guess, is sending some flag that mbsync doesn’t know about so I get the error “IMAP warning: unknown system flag Junk”. That happens every time mbsync downloads new email messages so it would quickly fill up the log file.

A third iteration in fixing this is to send the messages to a filter that deletes any messages that you’re not interested in. My simple filter for this is

#! /bin/zsh
read LINE
if [ $LINE != 'IMAP warning: unknown system flag Junk' ]
    echo  $(date): \\c
    echo $LINE

Obviously you can easily add additional messages to ignore.

The next problem is that mbsync sends these messages to STDERR instead of STDOUT so you have to figure out someway of piping STDERR to the next process’s STDIN. That turns out to be a bit fussy but the TD;DR is

  1. Redirect STDERR to STDOUT
  2. Disappear STDOUT

Here’s what this looks like for mu4e.

(setq mu4e-get-mail-command "mbsync -q icloud 2>&1 > /dev/null | (~/bin/mbsyncfilter) >> ~/.mbsync.log")

Something similar, I’m sure, would work for notmuch or whatever else you’re using mbsync with.

I get about five to ten error messages a week. They’re mostly things like the system couldn’t resolve the IP address of the Apple mail server or that the server had some problem or another. This solution works really well for me. I check the log file once a week to make sure no action on my part is required. I clear the log at that time so there’s never a huge number of messages to deal with.

-1:-- Logging mbsync Errors (Post jcs)--L0--C0--July 25, 2021 04:33 PM

Emacs APAC: Notes from Emacs Asia-Pacific (APAC) virtual meetup, July 2021

These are the notes from Emacs Asia-Pacific (APAC) meetup happened on July 24, 2021. Managing music queue with Emacs [Yuchen] download the media files, delete them once played. [bhavin192] [meain] [Sean O’Byrne] EMMS can be used as a player. Python code to Toot/Tweet and post on LinkedIn. [shrini] A demo of above script, using mastodon.el to compose the post. And using M-| to send the region to Python code.
-1:-- Notes from Emacs Asia-Pacific (APAC) virtual meetup, July 2021 (Post)--L0--C0--July 25, 2021 04:12 PM

James Cash: Emacs Completes Me

New Things

For no particular reason other than wanting to try something new, I’ve migrated away from Helm to a completion setup for Emacs based on Protesilaos’ latest config (see prot-minibuffer.el). That is, just using normal Emacs completion – albeit with some of the new goodies from Emacs 28 – along with Embark, Consult, and Orderless.

My Helm configuration was pretty well-honed and I’ve done a lot of stuff with custom actions, so I had a fairly high bar to be able to switch over. I’d want to easily be able to switch to buffers or files in a new window, controlling whether it would be a horizontal or vertical split; plus, I have a little package specifically for Helm to easily switch between multiple shells.

Splitting the Difference

It took a little bit, but I was able to replicate the open-in-split functionality I wanted with Embark. The one little wrinkle I encountered with writing my commands was handling being invoked from the minibuffer or the completion window. It took some experimentation, but I was ultimately able to put something fairly simple together:

(defun cogent--split-below (open-fn target)
  (select-window (split-window-below))
  (funcall open-fn target))
(defun cogent--split-right (open-fn target)
  (select-window (split-window-right))
  (funcall open-fn target))

(defun cogent--embark-act (fn &rest args) ;
  "Helper function to handle embark act events that can run from completion"
  (when (and (eq (selected-window) (active-minibuffer-window))
             (not (minibufferp)))
    (apply #'embark--quit-and-run fn args))
  (apply fn args))

(defun cogent/switch-to-buffer-horiz-split (buf)
  "Switch to buffer in a horizontal split"
  (interactive "BBuffer: ")
  (cogent--embark-act #'cogent--split-below #'switch-to-buffer buf))
(defun cogent/switch-to-buffer-vert-split (buf)
  "Switch to buffer in a vertical split"
  (interactive "BBuffer: ")
  (cogent--embark-act #'cogent--split-right #'switch-to-buffer buf))

(defun cogent/switch-to-file-horiz-split (file)
  "Switch to file in a horizontal split"
  (interactive "FFile: ")
  (cogent--embark-act #'cogent--split-below #'find-file file))
(defun cogent/switch-to-file-vert-split (file)
  "Switch to file in a vertical split"
  (interactive "FFile: ")
  (cogent--embark-act #'cogent--split-right #'find-file file))

(define-key embark-buffer-map (kbd "C-s") #'cogent/switch-to-buffer-horiz-split)
(define-key embark-buffer-map (kbd "C-v") #'cogent/switch-to-buffer-vert-split)
(define-key embark-file-map (kbd "C-s") #'cogent/switch-to-file-horiz-split)
(define-key embark-file-map (kbd "C-v") #'cogent/switch-to-file-vert-split)

The only wrinkle here is in the cogent–embark-act function. It has to detect if the minibuffer was active but the current buffer isn’t a minibuffer. From my fiddling, this seems to be the case when embark-act is invoked while scrolling in the *Completions* buffer.

Shell Games

The other big thing I needed to do replicate the functionality of my helm-switch-shell library, which is deep in my muscle memory now. I tend to have many *eshell* and *vterm* buffers in various project directories and this library makes it so I can usually switch to the one I want with just a keystroke or two. The idea is that it sorts the shell buffers by their distance from your current working directory, so the top of the list is usually the one you want. However, it also provides several helm actions on the candidates, to allow either switching to the buffer normally, switching in a horizontal or vertical split, or opening a new eshell or vterm in the same directory.

This was longer, but I was able to take much of the key code for sorting the candidates from my library and hack something together with normal completing-read, plus Marginalia and Embark, that gave me what I wanted. You can find that in my config here. I may eventually publish it stand-alone, since I already did so with my helm library, I suppose.

Jumping Around

The final thing that I wanted to share was a handy little helper function I wrote to make it easier to navigate the groups that are new to Emacs 28’s completion. Something that I got very used to with helm-rg was using the left and right arrow keys to skip through results by file, then use up and down to navigate through results for a single file and I wanted to be able to do that with this new system.

The following simple little function did it for me – I kind of expected something like this to already be built-in, but I suppose this is a fairly new addition, so the helper functions aren’t there yet.

(defun cogent/completion-next-group (&optional arg)
  "Move to the next completion group"
  (interactive "p")
  (while (and (not (eobp))
              (not (eq (point-max)
                       (save-excursion (forward-line 1) (point))))
              (get-text-property (point) 'completion--string))
    (next-line 1))
  (next-completion 1))

(defun cogent/completion-prev-group (&optional arg)
  "Move to the previous completion group"
  (interactive "p")
  (dolist (dir '(-1 1))
    (while (and (not (bobp))
                (not (eq 1
                           (forward-line -1)
                (get-text-property (point) 'completion--string))
      (next-line -1))
    (unless (eq 1
                  (forward-line -1)
      (next-completion dir))))

(define-key completion-list-mode-map (kbd "<right>") #'cogent/completion-next-group)
(define-key completion-list-mode-map (kbd "<left>") #'cogent/completion-prev-group)

Hopefully something here was interesting or useful to someone out there!

Update 2021-07-28: After a conversation with Protesilaos, I’ve updated my completions functions to use the text-property-search-* family of functions; they now look like this:

(defun cogent/completion-next-group ()
  "Move to the next completion group"
  (when-let (group (save-excursion
                     (text-property-search-forward 'face
                                                   t nil)))
    (let ((pos (prop-match-end group)))
      (unless (eq pos (point-max))
        (goto-char pos)
        (next-completion 1)))))

(defun cogent/completion-prev-group ()
  "Move to the previous completion group"
  (when-let (group (save-excursion
                     (text-property-search-backward 'face
                                                    t nil)))
    (let ((pos (prop-match-beginning group)))
      (unless (eq pos (point-min))
        (goto-char pos)
        (text-property-search-backward 'face
                                       t nil)
        (next-completion 1)))))
-1:-- Emacs Completes Me (Post)--L0--C0--July 25, 2021 12:00 AM

Andrea: Org Roam and Nyxt: taking Zettelkasten notes from the web

-1:-- Org Roam and Nyxt: taking Zettelkasten notes from the web (Post)--L0--C0--July 25, 2021 12:00 AM

Raimon Grau: Cypress, React and Emacs backup/lock files

 So I'm dealing with some javascript lately, and it took me a while to figure out that some of the javascript tooling ("cypress open", or "yarn start" a react app) fails to refresh correctly (in fact exits with an exception) every time you modify a file that it is watching.

So, if autorefresh is "on", you can't touch any file.  Not good.

Found out that the cause of those failures are both emacs lockfiles and backup files. They are created in the source directories, and then, js tries to load them, or to examine them somehow, and js falls flat on its face.

(setq make-backup-files nil  

         create-lockfiles nil)  

That should do it.

-1:-- Cypress, React and Emacs backup/lock files (Post Raimon Grau ( 24, 2021 11:12 AM