Irreal: Capturing the Current File Location

Marcin Borkowsi has a nice post on how to capture the current file’s location and copy it to the system clipboard. It’s just what you need for sharing information about data in a file with a colleague. By file location he means the path to the file and the line number within that file.

That doesn’t seem too hard but there are some wrinkles. First of all you want the absolute line number within the file not just the number of the line visible in the buffer. That’s pretty easy but the second problem is a bit trickier.

Sometimes, just the name of the file is not enough. It may be that two files within a project have the same name but lives under a different subdirectory. Your first thought is probably to capture the full path to the file but that isn’t optimal either. As Borkowski says, there’s no point in showing the full path on his machine. What’s needed is the path relative to the current project.

That means the path relative to the current VC repository. It’s pretty easy to get that with the vc-root-dir function. Borkowski has some code that captures the file path and line number and copies it to the system clipboard. It’s simple and can be copied and used as is or modified to meet your particular needs.

The post is definitely worth a read if only to discover how to deal with the various issues.

UPDATE [2022-06-26 Sun 14:40]: Added missing link to Borkowski’s post.

-1:-- Capturing the Current File Location (Post jcs)--L0--C0--June 26, 2022 02:47 PM

Irreal: Red Meat Friday: Notion

Romain Slootmaekers has his own take on the Notion app:

To be fair, Notion is a pretty nice app but as I’ve written before you can do the same things with Org-mode. If you’re an Emacs user, there’s no reason to be using Notion, especially since your data is held on their servers.

-1:-- Red Meat Friday: Notion (Post jcs)--L0--C0--June 24, 2022 04:09 PM

Kisaragi Hiu: git-zip-commit

Pack a commit's changed files into a zip file. Just a command to make it easier for me to submit KDE zh_TW translations.
-1:-- git-zip-commit (Post Kisaragi Hiu)--L0--C0--June 24, 2022 12:00 AM

scripter.co | Emacs: View GitHub Pull Requests in Magit

How to view GitHub Pull Request branches locally in the cloned repo, and more importantly, how to do that automatically from within Emacs.

I have a few public projects in git repos, but I don’t get that much traffic in Pull Requests (PR) Gitlab calls these Merge Requests or MRs. . So when I need to add additional commits to a PR, I would just add the PR author’s remote to my local repo, check out their PR branch, add my own commits and then merge that to my project’s main branch.

As these occurrences were few and far apart, I didn’t have a need to view the PR branches directly from within Emacs/Magit. Though, I somehow knew that each GitHub Pull Request’s HEAD got assigned a git reference. But I didn’t need to use that knowledge until today 😃.

Today, when discussing PR # 20 on Prot’s Denote package’s GitHub mirror Prot uses SourceHut as the primary git forge for his Emacs packages. But I am glad that he doesn’t mind the activity in Issues and Pull Requests on the GitHub mirror. , he wrote this comment:

Now I just need to figure out how best to incorporate your changes into the org-id branch so I can add the final bits. I am not too familiar with the PR workflow …

.. and that inspired this post today.

Locally creating a branch for a PR #

From the GitHub docs, the git command to create a local branch for a PR is this:

git fetch origin pull/ID/head:BRANCHNAME

I have the denote package cloned from its GitHub mirror. So the origin remote’s url is https://github.com/protesilaos/denote.

Make sure that the remote name used in this command is pointing to a GitHub repo, and not a mirror forge like GitLab or SourceHut.

When I ran the below command, I got a new branch pr-20 pointing to the latest commit of that PR:

git fetch origin pull/20/head:pr-20

Awesome!

.. But that wasn’t good enough
    .. Now I wanted more
        .. I didn’t want to manually create a branch for each PR.

Getting references to all Pull Requests #

Now that I was on that quest of “I want more”, it didn’t take me long to re-discover this 7-year old nugget by Oleh Krehel. Here are the relevant bits from that post:

  1. Open the local repo’s .git/config file.
  2. Find the [remote "origin"] section
  3. Modify it by adding this one line with pull refs. This is the same for all GitHub repositories.
    [remote "origin"]
        url = https://github.com/USER/REPO.git
        fetch = +refs/heads/*:refs/remotes/origin/*
        fetch = +refs/pull/*/head:refs/pull/origin/*
    

With that edit in place, when I did l a (show the log for all git references), followed by f a (fetch all the remotes) in the Magit, I could see the references to the denote repo’s PRs!

Figure 1: Viewing PR references from denote package’s GitHub repo

Figure 1: Viewing PR references from denote package’s GitHub repo

.. But that still wasn’t good enough
    .. I didn’t want to manually edit the .git/config in each repo.

Automatically adding PR refs #

Of course, I wasn’t the first one to think of this!

Another Emacs veteran Artur Malabarba had already had this covered also around 7 years back. Coincidentally, that post was written as a response to that same blog post by Oleh where he shared the above .git/config tip.

In that post, Artur shares an Emacs Lisp function that uses Magit functions like magit-get, magit-get-all and magit-git-string to auto-add the fetch = +refs/pull/*/head:refs/pull/origin/* line in the .git/config. This magic happens after checking that the origin remote points to a GitHub repo, and if that line doesn’t already exist.

Here, I am lightly modifying the function shared in that post so that the origin remote name is not hard-coded The reason is that sometimes, I name the original remote as upstream and my fork as fork, and I might have no remote named origin. . Credit for the main logic in this code still goes to Artur.

(defun modi/add-PR-fetch-ref (&optional remote-name)
  "If refs/pull is not defined on a GH repo, define it.

If REMOTE-NAME is not specified, it defaults to the `remote' set
for the \"main\" or \"master\" branch."
  (let* ((remote-name (or remote-name
                          (magit-get "branch" "main" "remote")
                          (magit-get "branch" "master" "remote")))
         (remote-url (magit-get "remote" remote-name "url"))
         (fetch-refs (and (stringp remote-url)
                          (string-match "github" remote-url)
                          (magit-get-all "remote" remote-name "fetch")))
         ;; https://oremacs.com/2015/03/11/git-tricks/
         (fetch-address (format "+refs/pull/*/head:refs/pull/%s/*" remote-name)))
    (unless (member fetch-address fetch-refs)
      (magit-git-string "config"
                        "--add"
                        (format "remote.%s.fetch" remote-name)
                        fetch-address))))
(add-hook 'magit-mode-hook #'modi/add-PR-fetch-ref)
Code Snippet 1: Function to auto-add GitHub PR references to the repo's .git/config

Summary #

With the above snippet added to your Emacs config and evaluated, each time you visit a repo cloned from GitHub in the Magit Status buffer (M-x magit-status), the PR refs will get auto-added to that repo’s .git/config if needed.

After that, you can easily view the commits from all the PRs by doing l a f a.

References #

-1:-- View GitHub Pull Requests in Magit (Post Kaushal Modi)--L0--C0--June 23, 2022 09:51 PM

Irreal: Hiding Some Org Subtrees

The other day I wrote about Kaushal Modi’s post on Advice Combinators. Modi has another post that uses that information but the post is interesting in its own right. The problem is to fold (or collapse) headings having a certain property. His use case for this involves the file of his blog posts. Take a look at his post for the details.

The method Modi employs is pretty simple. He loops through all the headings with org-map-entries calling outline-hide-subtree whenever the property EXPORT-FILE-NAME is set. All that is handled by the single call to org-map-entries so it’s easy. Modi makes another pass also collapsing subtrees that are Footnotes or COMMENTS. That’s even easier being a simple re-search-forward.

Since Ctrl+c Tab does something similar in plain Org-mode, Modi decided to call his function with the binding Ctrl+u Ctrl+c Tab. He accomplished that by advising the Ctrl+c Tab function using the :before-until combinator.

To be sure, collapsing only certain headings isn’t something most of us most to do very often but it’s nice to see how to do it as well as see a nice application of an advice combinator.

-1:-- Hiding Some Org Subtrees (Post jcs)--L0--C0--June 23, 2022 04:21 PM

Irreal: Advice Combinators

A really powerful Emacs feature for those who know a bit of Elisp in the ability to advise functions. Historically, the defadvice macro allowed the specification of code to run before, after, or around a function call. It’s really handy for modifying the action of a function without changing the function itself or getting into the details of how a function works. I have advice for 7 functions in my init.el, an indication that it’s more useful than you might think.

The defadvice macro has been obsoleted by the newer and more flexible advice-add and add-function macros. You’ll usually want to use advice-add because it works in more situations. The new macros support a finer grained specification of where the advice is to be applied.

Kaushal Modi over at A Scripter’s Notes has an excellent post that explains all the methods of specifying where the advice will operate. These methods are called “advice combinators”. Modi has what are essentially railway diagrams that illustrate the operation of each of the combinators. They’re an easy way of understanding what each of them does. He also has a summary table that describes in words how each of them works.

You should also take a look at the built-in add-function documentation that shows the new function that is created for each of the combinators.

Modi’s post is the best explanation of using advice that I’ve seen. You should definitely take a look at his post to see what’s possible.

-1:-- Advice Combinators (Post jcs)--L0--C0--June 21, 2022 04:23 PM

Mickey Petersen: Mastering Emacs is now available in Japanese

If you’re a Japanese speaker, you can now read my book, Mastering Emacs, in Japanese. I owe all this hard work to AYANOKOJI Takesi and USAMI Kenta, two legendary Emacs hackers and writers in the Japanese Emacs community. There’s a large Emacs community in Japan but, unless you speak Japanese, you probably wouldn’t know that!

It’s easy to miss, but Emacs owes its superb Unicode and multilingual support to the Japanese National Institute of Advanced Industrial Science and Technology (AIST) who created (and maintained) a separate fork of Emacs called Nihongo (“Japanese”) Emacs, first created in 1987. Later it was wrapped up into a separate package called MULE (M-x find-library mule.)

MULE was merged into Emacs 20.1 in 1997 (C-u 20 C-h n to open the NEWS file from then and search for MULE), and it’s one of the few exceptions Richard Stallman and the FSF made to their ironclad rule that copyright must be assigned to the FSF. So there’s a bit of trivia for you.

So, once again, thanks to Takesi and Kenta for their hard work. If you own my book, you can download the translated version for free.

-1:-- Mastering Emacs is now available in Japanese (Post)--L0--C0--June 21, 2022 09:55 AM

Marcin Borkowski: Copying the current location

Continuing the trend of playing around with copying stuff from Emacs to the system clipboard, today I’d like to talk about a command I wrote a few days ago.
-1:-- Copying the current location (Post)--L0--C0--June 20, 2022 05:53 PM

Sacha Chua: 2022-06-20 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, emacs-devel, and lemmy/c/emacs. Thanks to Andrés Ramírez for emacs-devel links!

-1:-- 2022-06-20 Emacs news (Post Sacha Chua)--L0--C0--June 20, 2022 02:33 PM

Meta Redux: Compliment 0.3.13

I haven’t written anything here in ages, mostly because of the war in Ukraine. Today I’m changing this, with the announcement of a new release of the ultimate Clojure code completion library - compliment.1 The “fatal” 0.3.13 version bundles the following small improvements:

  • #82: Offer completions for quoted/var-quoted symbols (e.g. 'some.ns/symbol and #'some.ns/symbol).
  • #83: Complete local bindings declared in map destructuring with namespaced keywords.
  • #83: Fix completion of local bindings when a context contains namespaced keywords.
  • #84: Enable locals completion for defmethod form.

The new version of compliment has already been integrated in cider-nrepl 0.28.5 and it’s being used by CIDER’s 1.5-SNAPSHOT builds. That’s probably the easiest way to take it out for spin. I hope you’ll love this release and I hope I didn’t mess anything up!

You might be wondering why I’m doing the release announcement this time around instead of compliment’s author and all-star Clojure hacker Alex Yakushev. Well, sadly Alex has been impacted much more by the war than me. He’s from Ukraine and is now fighting for the freedom of his country. In the mean time I’ll be helping Alex out a bit with the maintenance of compliment until he’s back home safe and sound.

Alex is a great Clojure hacker and a great person all around, and these days he’s in my thoughts quite often. I’m looking forward to the day when we’d be able again to chat about Clojure over beers and hot dogs in downtown Kyiv. Remember Ukraine and all its heroes! Glory to the heroes!

  1. You might not know its name, but it powers the code completion functionality of most Clojure editors and IDEs these days (e.g. CIDER, Calva, vim-fireplace, iced-vim, etc). 

-1:-- Compliment 0.3.13 (Post Bozhidar Batsov)--L0--C0--June 20, 2022 05:45 AM

Emacs Notes: How to create a Table with multi-paragraph content & spanned cells using Emacs Org mode

Good Bye! List Tables; Hello! Transcluded Tables In an earlier post, I talked about how to Create tables with paragraph-like content in Org mode, with the least amount of hassle. In that post, I recommended using a List Table. A List Table is essentially a two-level Org list which gets transformed in to a Table. … Continue reading How to create a Table with multi-paragraph content & spanned cells using Emacs Org mode
-1:-- How to create a Table with multi-paragraph content & spanned cells using Emacs Org mode (Post Emacks)--L0--C0--June 20, 2022 02:52 AM

Irreal: Emacs and the Lindy Effect

Vivek Haldar has an observation about the expected lifetime of Emacs:

The Lindy Effect postulates that the longer some (nonperishable) entity has existed, the more likely that it will continue to exist. It’s a bit more technical so follow the link to Wikipedia if you want the details.

Nothing lasts forever, of course, so even the mighty Emacs will eventually fade away but not, if you believe in Lindy’s law, anytime soon. It make sense if you think about it: the fact that Emacs has lasted as long as it has means that it’s meeting the needs of its users and continuing to adapt to new needs so its chances for continued support from its current users and its being embraced by new users is good.

-1:-- Emacs and the Lindy Effect (Post jcs)--L0--C0--June 19, 2022 04:49 PM

scripter.co | Emacs: Gujarati fonts in Emacs

Setting a different font for a specific script or language in Emacs.

All Emacs versions ship with a nifty HELLO file that you can quickly open using M-x view-hello-file or its default binding C-h h. This file lists “Hello” written in dozens of languages to demonstrate some of the character sets supported by Emacs.

Figure 1: “Hello” buffer in Emacs

Figure 1: “Hello” buffer in Emacs

Born and raised in the Gujarat state in India, I grew up speaking the Gujarati (ગુજરાતી) language India officially recognizes 22 languages (as of <2022-06-19 Sun>) and Gujarati is one of them. and so it’s also the language closest to my heart. So I was pleasantly surprised to see a representation of Gujarati in the “Hello” buffer! In the above screenshot, in the “South Asia” section, the script after the yellow cursor is Gujarati, and it reads namaste.

Setting a “fontset” font #

It was on <2018-08-13 Mon> that I discovered the presence of Gujarati script in that “Hello” buffer, and the reason I know that exact date is because I had asked a question regarding that on the help-gnu-emacs mailing list 😃.

This was the time when Emacs was using the m17n library for multi-lingual font rendering by default. The question was regarding a font rendering issue I was seeing. As I learn later in that thread, it was because I didn’t have the m17n database installed on my machine At least in 2022, the harfbuzz library is the recommended library for text shaping and font rendering. Someone please correct me if that’s wrong. In any case, I have switched to using harfbuzz instead of m17n for a while now and haven’t found any font-rendering issues with non-English scripts. . But it’s in that support thread that, thanks to Andy Moreton, I learned that you can change the font for the Gujarati script using set-fontset-font.

This applies in general to any script. You can read more details about this function in Emacs Info: Modifying Fontsets, but here’s the gist:

(set-fontset-font "fontset-default" 'gujarati "<FONT NAME>")
Code Snippet 1: Setting default font for Gujarati script using set-fontset-font

That led me down the path of exploring the available Gujarati fonts out there ..

Gujarati fonts #

After looking around for a bit, I found a wonderful collection of Gujarati fonts in this GitHub repository: github.com/samyakbhuta/chhapkaam The repo name is chhapkaam (I would have spelled it as chhaapkaam) which is the Gujarati word છાપકામ, meaning “printing”. .

Below is my further curated list of fonts from the above list:

Table 1: Gujarati Fonts
Font Name Namaste Category Homepage Download
Shruti serif wfonts.com
Mukta Vaani serif Ek Type – Mukta Vaani GitHub
Lohit Gujarati sans serif Pagure – Lohit pagure releases

To use these fonts, after downloading and installing them on your system, evaluate Code Snippet 1 above with the correct “FONT NAME”. For example, to set the Gujarati text to use the Shruti font, evaluate (set-fontset-font "fontset-default" 'gujarati "Shruti").

Thanks for reading (વાંચવા બદલ આભાર) 🙏!

-1:-- Gujarati fonts in Emacs (Post Kaushal Modi)--L0--C0--June 19, 2022 05:31 AM

jao: simple note taking

I was just watching Prot's explanation of his new package denote, a very elegant note-taking system with a stress on simplicity and, as the author puts it, low-tech requirements. Now, those are excellent qualities in my book, and i think i'd quickly become a denote user if it weren't for the fact that i already have a homegrown set of utilities following a similar philosophy. Inevitably, they differ in some details, as is to be expected from software that has grown with me, as Prot's with him, during more than a decade, but they are similar in important ways.

I've had in mind writing a brief note on my notes utilities for a while, so i guess this is a good time for it: i can, after showing you mine, point you to a polished package following a similar philosophy and sidestep any temptation of doing anything similar with my little functions :)

consult-recoll.png

As you'll see in a moment, in some ways, my note taking system is even simpler than Prot's, while in others i rely on more sophisticated software, essentially meaning that where denote is happy to use dired and filenames, i am using grep over the front-matter of the notes. So if you loved the filename-as-metadata idea in denote, you can skip the rest of this post!

These are the main ideas around which i built my note-taking workflow:

  • Personally, i have such a dislike for non-human readable identifiers, that i cannot even stand those 20221234T142312 prefixes (for some reason, i find them quite hard to read and distracting). When i evolved my notes collection, i wanted my files to be named by their title and nothing more. I am also pretty happy to limit myself to org-mode files. So i wanted a directory of (often short) notes with names like the-lisp-machine.org, david-foster-wallace.org or combinator-parsing-a-short-tutorial.org.1
  • I like tags, so all my notes, besides a title, are going to have attached a list of them (denote puts them in the filename and inside the file's headers; i'm content with the latter, because, as you'll see in a moment, i have an easy way of searching through that contents).
  • I'm not totally averse to hierarchies: besides tagging, i put my notes in a subdirectory indicating their broad category. I can then quickly narrow my searches to a general theme if needed2.
  • As mentioned, i want to be able to search by the title and tag (besides more broadly by contents) of my notes. Since that's all information available in plain text in the files, grep and family (via their emacs lovely helpers) are all that is needed; but i can easily go a step further and use other indexers of plain text like, say, recoll (via my consult-recoll package).
  • It must be easy to quickly create notes that link to any contents i'm seeing in my emacs session, be it text, web, pdf, email, or any other. That comes for free thanks to org and org-capture.
  • I want the code i have to write to accomplish all the above to be short and sweet, let's say well below two hundred lines of code.

Turns out that i was able to write a little emacs lisp library doing all the above, thanks to the magic of org-mode and consult: you can find it over at my repo by the name of jao-org-notes.el. The implementation is quite simple and is based on having all note files in a parent directory (jao-org-notes-dir) with a subfolder for each of the main top-level categories, and, inside each of them, note files in org mode with a preamble that has the structure of this example:

#+title: magit tips
#+date: <2021-07-22 Thu>
#+filetags: git tips

The header above corresponds to the note in the file emacs/magit-tips.org. Now, it's very easy to write a new command to ask for a top-level category and a list of tags and insert a header like that in a new file: it's called jao-org-notes-open-or-create in my little lib, and with it one can define a new org template:

("N" "Note" plain (file jao-org-notes-open-or-create)
 "\n- %a\n  %i"
 :jump-to-captured t)

that one can then add to org-capture-templates (above, i'm using "N" as its shortcut; in the package, this is done by jao-org-notes-setup, which takes the desired shortcut as a parameter). I maintain a simple list of possible tags in the variable jao-org-notes--tags, whose value is persisted in the file denoted by the value jao-org-notes-tags-cache-file, so that we can remember newly-added tags; with that and the magic of emacs's completing read, handling tags is a breeze.

Now for search. These are text files, so if i want to search for contents, i just need grepping, for instance with M-x rgrep or, even better, M-x consult-ripgrep. That is what the command jao-org-notes-grep does.

But it is also very useful to be able to limit searches to the title and tags of the notes: that's what the command jao-org-notes-open does using consult and ripgrep by the very simple device of searching for regular expressions in the first few lines of each file that start with either #+title: or #+filetags: followed by the terms we're looking for. That's something one could already do with rgrep alone; what consult adds to the party is the ability of displaying the matching results nicely formatted:

org-notes.png

Links between notes are simply org file: links, and having a simple "backlinks" command is, well, simple if you don't want anything fancy3. A command to insert a new link to another note is so boring to almost not meriting mention (okay, almost: jao-org-notes-insert-link).

And that's about it. With those simple commands and in about 160 lines of code i find myself comfortably managing plain text notes, and easily finding contents within them. I add a bit of icing by asking Recoll to index my notes directory (as well as my email and PDFs): it is clever enough to parse org files, and give you back pointers to the sections in the files, and then issue queries with the comfort of a consult asynchronous command thanks to consult-recoll (the screenshot in the introduction is just me using it). It's a nice use case of how having little, uncomplicated packages that don't try to be too sophisticated and center on the functionality one really needs makes it very easy to combine solutions in beatiful ways4.

Footnotes:

1

I also hate with a passion those :PROPERTIES: drawers and other metadata embellishments so often used in org files, and wanted to avoid them as much as possible, so i settled with the only mildly annoying #+title and friends at the beginning of the files and nothing more. The usual caveat that that makes it more difficult to have unique names has proven a non-problem to me over the years.

2

Currently i use work, books, computers, emacs, letters, maths, and physics: as you see, i am not making a great effort on finding the perfect ontology of all knowledge; rather, i just use the first broad breakdown of the themes that interest me most at the moment.

3

Just look for the regular expression matching "[[file:" followed by the name of the current file. I find myself seldom needing this apparently very popular functionality, but it should be pretty easy to present the search results in a separate buffer if needed.

4

Another example would be how easy it becomes to incorporate web contents nicely formatted as text when one uses eww as a browser. Or how how seamless it is taking notes on PDFs one's reading in emacs, or even externally zathura (that's for a future blog post though! :)).

-1:-- simple note taking (Post)--L0--C0--June 19, 2022 03:36 AM

Irreal: Highlighting

This week there were two excellent posts on highlighting in Emacs. The first was Marcin Borkowski’s post, Highlighting and de-highlighting things. He covers most of highlighting commands but not their default keybindings.

When I first saw Borkowski’s post I thought I’d write about it if only to have a handy guide to the commands. Before I could do that, Mickey Petersen published his post on the same subject matter. That post, Highlighting by Word, Line and Regexp covers a few more commands and includes their bindings. Mickey also explains how to make a set of highlightings persist in a file.

It turns out that even Irreal has plowed this ground but it was so long ago (over a decade) that I’d forgotten all about it. One nice thing about that post is that I provided a table of keybindings at the end but I didn’t cover all the commands. Below is a new table based on Mickey’s list of bindings. The purpose of many of them is obvious from the command name but take a look at Mickey’s post for what all these commands do. If you can remember the Meta+s h part, the commands are pretty mnemonic but, of course, if you use them regularly they’ll get burned into your muscle memory.

Key Sequence Command
Meta+s h . highlight-symbol-at point
Meta+s h l highlight-lines-matching-regexp
Meta+s h p highlight-phrase
Meta+s h r highlight-regexp
Meta+s h u unhighlight-regexp
Meta+s h w hi-lock-write-interactive-patterns
Meta+s h f hi-lock-find-patterns
-1:-- Highlighting (Post jcs)--L0--C0--June 18, 2022 04:32 PM

scripter.co | Emacs: Emacs Lisp: Advice Combinators

My diagrammatic take on summarizing all the Emacs advice combinators.

If you have read some of my earlier posts, you would know that I really enjoy using the Emacs Advice system 😃.

The “advice” feature lets you add to the existing definition of a function, by advising the function. This is a cleaner method than redefining the whole function, because it’s easier to debug and if you don’t need it, you can just remove the advice.

You can jump to the References section below if you need to look at the related sections in the Emacs Lisp Manual.

Overview on using advices #

I do not plan to write a tutorial on how to write advices in Emacs-Lisp, but here’s a 3-second primer:

To add an advice
(advice-add 'original-fn <combinator> #'advising-fn)
To remove an advice
(advice-remove 'original-fn #'advising-fn)

This article attempts to briefly describe different ways of advising a function, using 10 different combinators. If you have never used advices in your Emacs config, don’t worry. I am hopeful that the diagrams in this post and the examples linked for some of the combinators in the Summary section makes this concept a bit easier to assimilate.

Diagram Legend
  • Initial black circle: Original Fn input arguments
  • Yellow box: Original Fn
  • Gray box: Advising Fn
  • Black circle inside a white circle: Return values

1 :before #

Figure 1: :before advice

Figure 1: :before advice

2 :after #

Figure 2: :after advice

Figure 2: :after advice

3 :override #

Figure 3: :override advice

Figure 3: :override advice

4 :around #

Figure 4: :around advice

Figure 4: :around advice

5 :before-while #

Figure 5: :before-while advice

Figure 5: :before-while advice

6 :before-until #

Figure 6: :before-until advice

Figure 6: :before-until advice

7 :after-while #

Figure 7: :after-while advice

Figure 7: :after-while advice

8 :after-until #

Figure 8: :after-until advice

Figure 8: :after-until advice

9 :filter-args #

Figure 9: :filter-args advice

Figure 9: :filter-args advice

10 :filter-return #

Figure 10: :filter-return advice

Figure 10: :filter-return advice

Summary #

Here’s a concise summary of what each advice combinator does. For brevity, the advising function is called A and the original function is called O.

Once you click on any of the example posts, search for advice-add on that page to find the code example.

Table 1: Summary of what each advice combinator means
Combinator Description Example
:before A is called before O. O args and return values are not modified.
:after A is called after O. O args and return values are not modified.
:override A is called in lieu of O. A gets the same args as O. Zero HTML Validation Errors!
:around A is called in lieu of O. A gets O fn + O args as args. Using Emacs advice to silence messages from functions
:before-while A is called first. If it returns non-nil, O is called.
:before-until A is called first. If it returns nil, O is called. Org: Show only Post subtree headings
:after-while O is called first. If it returns non-nil, A is called.
:after-until O is called first. If it returns nil, A is called.
:filter-args A is called first. O is called next with return value from A as input. Narrowing the Author column in Magit
:filter-return O is called first. A is called next with return value from O as input. Zero HTML Validation Errors!

If you have any feedback on how these diagrams can be made easier to understand, please let me know.

References #

-1:-- Emacs Lisp: Advice Combinators (Post Kaushal Modi)--L0--C0--June 18, 2022 12:51 PM

Protesilaos Stavrou: Emacs: demonstration of my Denote package (simple note-taking)

Raw link: https://www.youtube.com/watch?v=mLzFJcLpDFI

Denote is a new package that I am developing for Emacs. Its first stable release will be avaible in the coming days from the official GNU ELPA.

Denote is the culmination of methods and code I have been relying for several years now (including from my pre-Emacs days).

Here is the official manual which includes links to the Git sources and the mailing list: https://protesilaos.com/emacs/denote.

And here is the page that outlines all my Emacs-related public work: https://protesilaos.com/emacs.

-1:-- Emacs: demonstration of my Denote package (simple note-taking) (Post)--L0--C0--June 18, 2022 12:00 AM

TAONAW - Emacs: Another look at my Journal Capture Templates

More than anything else in my Emacs settings, my org-mode capture templates evolve with my understanding of Emacs, as I learn to do more wonderful things I didn’t know existed. Since I’ve been discussing my writing recently, it’s a good time I want to talk about the journal-related those, where all my writings begins.

If you’re new to Emacs org-mode, this code might not make sense, so please look up org-mode capture in the manual to get a better idea of what these are, and then come back here to get an idea of how these are put to use. Then, if you get stuck trying to connect the dots, ask me about it (see below in comments) and I’ll be happy to explain.

Here it is:

("j" "Journal Related")
("jj" "Journal: Event" entry (file+datetree+prompt "~/Personal/journal.org") "**** About: %? %^G \n\n %U:\n" :tree-type week)
("je" "Journal: Elements" entry (file+datetree+prompt "~/Personal/journal.org") (file "~/Personal/temp-elements.org") :tree-type week :jump-to-captured t)

What this bit of elisp does is to call an org capture sub-menu with two options: j and e. The key sequence will look like this:

  1. Hit C-c to call up org-mode capture
  2. From the menu that shows up, press “j” for the “Journal Related” option (that’s the part you actually see here).
  3. From that sub-menu, press “j” again for an event or “e” for elements.

To learn more about these sub-menus (the manual is very brief about those) look at this post.

I want to expand on the journal elements options here (“je”). I explained what my are elements before, but briefly, these are my foundations of self-care throughout the day. As you can see from the code above, I use a template file, temp-elements.org, to call in further information. Here is the content of this file:

**** Yesterday's Elements :elements:
%^{Sleep}p %^{Exercise}p %^{Food}p %^{Meditation}p
- Total: %?
%U
***** Of Note:

Every morning, I write about the previous day. The elements are a good starting point that help me remember what happened and when. For example, I think of what I ate for lunch, and recall I had to take money out for the ATM around that time to get cash for an even later in the day. At that point, I create a footnote (for the event I remembered) and expand on it under the “Of Note:” section at the bottom of the template.

Later in the day, I open my journal file (I discussed my daily writing process a few days ago) and try to build a post around these notes, as I’m doing this very moment.

I recently realized two things:

  1. I only need one journal entry per day, which I can expand later. There’s no reason to attach a journal entry to my events on my agenda as I did previously; the events often contain all the notes in the body of the task already, under a timestamp.

  2. Reinforcing the second point: There’s no conflict of where to write notes. All notes relating to a task or an event are under those in the week’s org file. It’s more useful to link to these using a unique IDs from the journal, because then I also have the context of the whole project, including the other tasks, the time it happened, how long I worked on it, and other projects the task may link to. It’s all right there neatly for me.

Because the journal file has been going strong since 2018 (when I started using Emacs), I can always use my journal entries as a good reflection point on what happened in what day. When I need more details, these are just a link away1.

Comments?

Reply to this post on Mastodon, or you can always email me: taonaw<at>protonmail<dot>ch (for GPG, click the lock icon on the navbar to the left).

Footnotes


  1. I only keep 10 weekly files connected to my agenda at a given time for speed purposes. If I find something in the journal that happened more than 10 weeks ago, I use Dired to go to my “Old archive” folder which is not indexed by org-mode agenda, and use rzgrep to find the term I’m looking for. rzgrep finds a list of words along with the weekly org-files they are in.

    If a certain link is broken (because these files' unique ID is not loaded to org-agenda anymore) I can look at the ID itself, which is a date (check the post I linked above explaining that), to know which week I’m looking for and which date exactly. ↩︎

-1:-- Another look at my Journal Capture Templates (Post)--L0--C0--June 17, 2022 12:00 AM

Kisaragi Hiu: info-variable-pitch.el

Like org-variable-pitch but for Info.
-1:-- info-variable-pitch.el (Post Kisaragi Hiu)--L0--C0--June 17, 2022 12:00 AM

scripter.co | Emacs: Org: Show only Post subtree headings

How to define a custom org-global-cycle-like command that collapses only the Org subtrees with specific properties.

I start this post by introducing what the Org mode global cycling command does, what kind of subtree folding I actually need, and then share the solution with code snippets.

Org Global Cycle #

Org mode has a built-in org-global-cycle command that you might be familiar with. It’s bound by default to the S-TAB key. Each time this command is called, the Org buffer will cycle through these states:

  1. Overview: Show only the Level 1 headings and collapse everything underneath.
  2. Contents: Show only the Org headings and collapse all the content.
  3. Show All: Expand all the headings and show their contents too.

If a numeric prefix N is used with this command, it will show only the Org headings up to Level N. For example, C-2 S-TAB will show only the headings up to Level 2.

This is a really helpful command, but I needed something different ..

Skeleton of only Post headings #

I maintain most of this website’s content in a single Org file. I have dozens of blog posts organized in Org subtrees, which I further organize under “category” headings .. It kind of looks like the below mock-up: It’s amazing how many features PlantUML has. If you are interested in creating diagrams like these, check out the PlantUML Salt syntax.

Figure 1: Post Subtrees at arbitrary heading levels

Figure 1: Post Subtrees at arbitrary heading levels

As we can see,

  • All the post subtrees are not at Level 1 headings.
  • They are also not at a fixed Level N.
  • The heading level of the post depends on how many parent categories that post has (and that will also change over time).

I needed to basically show everything leading up to a post subtree heading, and then collapse all the content under that post; even the sub-headings.

The “Collapse All Posts” function #

The modi/org-hugo-collapse-all-posts function defined below meets the above requirement:

  1. It first widens the whole buffer and expands all the headings.
  2. Then it loops through all the headings and collapses all the post subtrees i.e. all the subtrees that have the EXPORT_FILE_NAME property set. This is where I use the org-map-entries magic.
  3. Finally it looks for Org headings that begin with “Footnotes” or “COMMENT” and collapses them as well.

I am using the development version of Org mode (version 9.6, yet to be released as of <2022-06-15 Wed>) which has the new org-fold library. This library obsoletes the use of outline.el library and other code-folding related functions in Org mode. So cl-flet is used to create function symbol aliases that use the org-fold-* functions if available, otherwise they fall back to the legacy functions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
(defun modi/org-hugo-collapse-all-posts ()
  "Collapse all post subtrees in the current buffer.
Also collapse the Footnotes subtree and COMMENT subtrees if
present.

A post subtree is one that has the EXPORT_FILE_NAME property
set."
  (interactive)
  (cl-flet ((show-all (if (fboundp 'org-fold-show-all)
                          #'org-fold-show-all
                        #'org-show-all))
            (hide-subtree (if (fboundp 'org-fold-hide-subtree)
                              #'org-fold-hide-subtree
                            #'outline-hide-subtree)))
    (widen)
    (show-all '(headings))
    ;; Collapse all the post subtrees (ones with EXPORT_FILE_NAME
    ;; property set).
    (org-map-entries #'hide-subtree "EXPORT_FILE_NAME<>\"\"" 'file)
    ;; Also hide Footnotes and comments.
    (save-excursion
      (goto-char (point-min))
      (while (re-search-forward "^\\(\\* Footnotes\\|\\*+ COMMENT\\)"
                                nil :noerror)
        (hide-subtree)))))
Code Snippet 1: Function that collapses all the post subtrees in the current buffer

Binding with C-u C-c TAB #

The function is ready, but let’s now add a bit of convenience to it.

If a point is under a subtree, C-c TAB will collapse that subtree while showing only Level 1 headings, and if a numeric prefix is used, it will show only those many levels of headings. I decided to bind the above function to C-u C-c TAB because,

  1. The behavior of modi/org-hugo-collapse-all-posts falls in the same category as that of C-c TAB.
  2. The C-u C-c .. binding rolls off the fingers pretty nicely 😃.

This binding is achieved using one of my favorite Emacs features .. the advice system. The :before-until Advice Combinator is used here, which means that if the advising function (below) returns a nil, the advised or the original function org-ctrl-c-tab is not called.

The advising function below detects if the C-u prefix argument is used. If it is, the modi/org-hugo-collapse-all-posts function is called, otherwise the original org-ctrl-c-tab function is called.

1
2
3
4
5
6
7
8
9
(defun modi/org-ctrl-c-tab-advice (&rest args)
  "Run `modi/org-hugo-collapse-all-posts' when
doing \\[universal-argument] \\[org-ctrl-c-tab]."
  (let ((do-not-run-orig-fn (equal '(4) current-prefix-arg)))
    (when do-not-run-orig-fn
      (modi/org-hugo-collapse-all-posts))
    do-not-run-orig-fn))

(advice-add 'org-ctrl-c-tab :before-until #'modi/org-ctrl-c-tab-advice)
Code Snippet 2: Bind C-u C-c TAB to call modi/org-hugo-collapse-all-posts

Result #

After evaluating the above two snippets, when I do C-u C-c TAB in my “blog posts” Org buffer, I see this:

Figure 2: My “blog posts” Org buffer showing only the Post subtree headings

Figure 2: My “blog posts” Org buffer showing only the Post subtree headings

It matches that earlier mockup — Mission accomplished! 💯

-1:-- Org: Show only Post subtree headings (Post Kaushal Modi)--L0--C0--June 16, 2022 04:21 AM

Magnus: Power-mode in Spacemacs

I just found the Power Mode for Emacs. If you want to try it out in Spacemacs you can make sure that your ~/.spacemacs contains the following

dotspacemacs-additional-packages
'(
  ...
  (power-mode :location (recipe
                         :fetcher github
                         :repo "elizagamedev/power-mode.el"))
  )

After a restart Power Mode can be turned on using SPC SPC power-mode.

Unfortunately I found that it slows down rendering so badly that Emacs isn't keeping up with my typing. Even though I removed it right away again it was fun to try it out, and I did learn how to add package to Spacemacs that aren't on MELPA.

A useful resource is this reference on the recipe format.

-1:-- Power-mode in Spacemacs (Post)--L0--C0--June 15, 2022 06:08 AM

Irreal: Elfeed-tube

As regular readers know, I’m a huge fan of RSS and of using elfeed to read and curate my feeds. If you’re an Emacs user and not using elfeed, you’re really missing out. It’s the absolute best feed reader I’ve ever used.

You may not know it but you can add YouTube channels to your elfeed feeds. If you follow one or more channels on YouTube, elfeed is a nice way of keeping up with them without a lot of fuss. Things just got a lot better.

Karthink has a new package, elfeed-tube, that makes following YouTube channels even better and easier. The package is so versatile that I won’t even try to cover everything it does; you should head over to the elfeed-tube GitHub repository for a long and thorough description of everything it’s capable of.

I found the link to elfeed-tube on reddit. The comments were uniformly positive, saying among other things, that the package “just worked” out of the box. This looks like a really great package for Emacs users who follow YouTube channels.

-1:-- Elfeed-tube (Post jcs)--L0--C0--June 14, 2022 04:50 PM

Sacha Chua: 2022-06-13 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, emacs-devel, and lemmy/c/emacs.

-1:-- 2022-06-13 Emacs news (Post Sacha Chua)--L0--C0--June 14, 2022 12:47 AM

Marcin Borkowski: Highlighting and de-highlighting things

From time to time I want to perform a kind-of “human search” on a file. For example, there is some keyword – or maybe something describable by a regex – and I want to be able to easily spot all of its occurrences in some file. For some reason, isearch or Swiper won’t work for me. (This may happen if, for instance, I don’t exactly know what I’m looking for. Imagine going through some file and deciding to search for some keywords only when I actually see them for the first time. So, I’m skimming a buffer and once I see the word “banana”, I go “hey, bananas are good, let’s find more of them” and then I want to easily see every line containing the word “banana”. Skimming further, I can see the word “apple” and I suddenly have a craving for apples, so I want to add apples to things that should be easily seen. And so on.) It turns out that Emacs has a few commands which can help with that.
-1:-- Highlighting and de-highlighting things (Post)--L0--C0--June 13, 2022 07:14 PM

Kisaragi Hiu: Download packages without fetching repositories when using Straight*

straight.el is awesome as it clones the source repositories of each package being installed. This makes it easy to install packages not submitted to a package archive, make changes and perhaps contribute to packages, etc. However, sometimes this is not desirable and you really just want what the package archives offer, without cloning repositories: for example, you might be installing packages like protobuf-mode which live in a much larger repository and would take ages to download, even with shallow clone enabled via setting straight-vc-git-default-clone-depth to 1.
-1:-- Download packages without fetching repositories when using Straight* (Post Kisaragi Hiu)--L0--C0--June 13, 2022 04:48 PM

Irreal: How To Create A Missing Directory

If you’ve been around Emacs for a while, you probably know that Emacs has you covered if you call find-file (Ctrl+x Ctrl+f) and specify a path with a missing directory. You simply get asked if you want to create the missing directory and give your assent with a simple Return Return.

That’s pretty simple and convenient but Bozhidar Batsov is committed to eliminating as much friction as possible and doesn’t want to have to do anything to create those missing directories. He just wants it to happen. Of course, being Batsov, he made it happen. It turns out to be pretty easy and he gives two solutions for doing it.

Almost every time I get the missing directory error it’s because I mistyped the path. That means that automating the creation of missing directories would almost always be a fail for me. But that’s me. Others, like Batsov, view it as a win. If you fall on Batsov’s side of the question, take a look at his post to see how easy it is to do.

The final, obvious, oft repeated, but mandatory observation is how easy Emacs makes it to fine tune it to each individual user’s workflow.

-1:-- How To Create A Missing Directory (Post jcs)--L0--C0--June 13, 2022 04:23 PM

Emacs Redux: Auto-create Missing Directories

Every now and then I’d do something like C-x C-f /path/to/new/dir/some-file.el. As the new folder doesn’t exist Emacs will prompt me to press RET twice to create it. It’s not a big deal, but it always annoys me a little bit and I’m always looking for ways to optimize my workflow.

At first I thought I’d have to advise find-file and just add some check in the advice whether the destination folder exists. Here’s how this typically works:

(defun er-auto-create-missing-dirs (orig-fun &rest args)
  (let* ((filename (car args))
         (target-dir (file-name-directory filename)))
    (unless (file-directory-p directory)
      (make-directory directory t))
    (apply orig-fun arg)))

(advice-add 'find-file :around 'er-auto-create-missing-dirs)

That gets the job done, but I’ve never been super fond of using advices as they add some complexity to the process of debugging something. Turns out there’s a much simpler solution, though - the hook find-file-not-found-functions. According to the docs:

List of functions to be called for find-file on nonexistent file. These functions are called as soon as the error is detected. Variable buffer-file-name is already set up. The functions are called in the order given until one of them returns non-nil.

This means all we need to do is write a simple hook function:

(defun er-auto-create-missing-dirs ()
  (let ((target-dir (file-name-directory buffer-file-name)))
    (unless (file-exists-p target-dir)
      (make-directory target-dir t))))

(add-to-list 'find-file-not-found-functions #'er-auto-create-missing-dirs)

Basically we just need to extract the destination folder from the file we’re trying to create and invoke make-directory with its second param instructing it to create all the non-existing folders along the way. The advice example shown earlier is doing exactly the same thing.

Place one of the above snippets in your Emacs configuration and that’s it. I can never get enough of such small productivity improvements!

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

-1:-- Auto-create Missing Directories (Post Bozhidar Batsov)--L0--C0--June 12, 2022 08:02 AM

TAONAW - Emacs: To Modus or Not to Modus?

At some point yesterday I stumbled upon this video from David of System Crafters explaining how to customize the famed Modus themes. I want to use these themes Ebecause they are so detailed and thoughtful, but I disagree with the main idea behind them: the sharply contrasting colors.

On the other hand, the video demonstrated the depth of detail these themes go into. I haven’t checked all the themes available for Emacs, but I don’t doubt that there are no other themes that come close in terms of attention to detail and customization as the Modus themes. They are in a league of their own.

After watching parts of the video and browsing the Modus themes manual, I came to the same conclusion I have before. I already have my preferred colors, and I adjusted my theme according to these and my soft-contrast principles.

The Modus theme did inspire me and made me consider modifying my theme further and including a light mode as well. This is a good idea especially on the laptop in well-lit rooms. Then again, the rest of my Linux theme is set to dark mode. Emacs’s bright theme will stand out like a flashlight.

So do I really need it? If a certain yellow is too close to the orange somewhere in org-mode or if an emphasis somewhere is not good enough, I tweak the theme’s el file to my liking. It’s not pretty and the code is broken by my comments everywhere, but it works.

Comments?

Reply to this post on Mastodon, or you can always email me: taonaw<at>protonmail<dot>ch (for GPG, click the lock icon on the navbar to the left).

-1:-- To Modus or Not to Modus? (Post)--L0--C0--June 12, 2022 12:00 AM

Emacs APAC: Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, June 25, 2022

This month’s Emacs Asia-Pacific (APAC) virtual meetup is scheduled for Saturday, June 25, 2022 with BigBlueButton and #emacs on Libera Chat IRC. The timing will be 1400 to 1500 IST. The meetup might get extended by 30 minutes if there is any talk, this page will be updated accordingly. If you would like to give a demo or talk (maximum 20 minutes) on GNU Emacs or any variant, please contact bhavin192 on Libera Chat with your talk details:
-1:-- Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, June 25, 2022 (Post)--L0--C0--June 11, 2022 12:01 AM

Irreal: Red Meat Friday: Who’s Next?

As most of you have probably heard by now, the Atom editor is being discontinued in December. That’s sad, of course, especially for Atom users but there are some lessons to be drawn.

Eric Fraga has the TL;DR:

It’s a good point. You devote considerable effort into mastering an editor and perhaps
writing extensions for it only to have it jerked out from under you. Fraga says that with Emacs he doesn’t have to worry about that. Bozhidar Batsov explains why that is in his Forever Emacs post. The short version is that Emacs is a community driven open source project1.

The demise of Atom shows that open source is not enough. After all, Atom was open source too but it wasn’t community driven. It was, rather, commercially driven by GitHub and GitHub, like every commercial entity, is mostly concerned with pursuing projects that they perceive will benefit them. Apparently, they no longer felt that Atom was a worthwhile investment in time and resources.

Now for the red meat. As the post title suggests, a natural question to ask is, “Which editor is next?” A reasonable candidate is VS Code. Like Atom, it’s an open source, commercially driven product. Furthermore, Microsoft has historically shown itself more than willing to dump any product that they felt was no longer meeting their needs.

If your PDF reader is discontinued it might be a little annoying but, really, who cares? There are plenty of them out there and they all work pretty much the same. If your editor goes away, it’s a much bigger deal. Most of us have put considerable effort into mastering our editor and making it an integral part of our workflow. If Microsoft does decided to sunset VS Code, what will all those users who flocked to it do?

Footnotes:

1

Yes, yes. Of course I know that Emacs is Free software. I’m merely making the point that the same principal applies to the larger universe of open software.

-1:-- Red Meat Friday: Who’s Next? (Post jcs)--L0--C0--June 10, 2022 04:41 PM

Christian Tietze: Prioritize hl-line Highlight Over Neotree Faces

In hindsight, it looks like my quest to tweak how Emacs looks and feels is to make it more Mac-like. No wonder, because I really like the OS X-era UI. So I’m still using the system default selection highlight colors and want these everywhere.

For example in neotree.

The hl-line current line highlight, combined with lin.el (which I use for half a year) to make it act as a prominent selection instead of a subtle hint in that mode, did lose over neotree’s own face settings.

Before and after the face's priority change.

Inspecting why that looked the way it looked via C-u C-x = to see the character and face information, I got this:

There are 2 overlays here:
 From 565 to 598
  face                 hl-line
  priority             -50
  window               nil
 From 578 to 597
  button               [Show]
  category             default-button
  face                 neo-file-link-face
  follow-link          t
  help-echo            [Show]
  keymap               [Show]
  neo-full-path        [Show]

Never saw this before, but “priority: -50” sounded like the way to go. Raise the priority, then maybe the hl-line face would override the neo-file-link-face of the file “button” at point.

But there’s no face property called ‘priority’. Searching the web for this, I found out about show-paren-priority on Emacs.StackExchange, so it looks like this is commonly a variable, and yes, there is a hl-line-overlay-priority and its value is -50. I don’t know what other priorities there are, so I’m just flipping it to +50 for good measure.

Update 2022-06-10: Setting this in neotree still makes sense, but setting this globally only looked good for a while – until I ran into color issues with selections. If the priority is not negative, it will override the region selection colors. So I couldn’t see when I was selecting file names or file sizes in dired. Here’s a fixed version.

The updated code just enables this for neotree buffers:

(defun my/neotree-hook ()
  (hl-line-mode -1)  ;; Disable if it's on, see explanation below.
  (setq-local hl-line-overlay-priority +50)
  (lin-mode))
(add-hook 'neotree-mode-hook #'my/neotree-hook)

The important part is to set the priority buffer-locally before entering hl-line-mode or lin-mode. So you cannot use lin-mode-hooks to auto-enable lin, but have to do it this way instead. Make sure to remove neotree-mode-hook from lin-mode-hooks so it isn’t enabled early.

But neotree has a neo-hide-cursor setting that auto-enables hl-line-mode before calling any hooks:

(define-derived-mode neotree-mode special-mode "NeoTree"
  "A major mode for displaying the directory tree in text mode."
  (setq indent-tabs-mode nil            ; only spaces
        buffer-read-only t              ; read only
        truncate-lines -1
        neo-buffer--show-hidden-file-p neo-show-hidden-files)
  (when neo-hide-cursor
    (progn
      (setq cursor-type nil)
      (hl-line-mode +1)))
  ...

Geez! So we either have to:

  • not use neo-hide-cursor, which would be a surprise setting to accommodate for the way I configure lin;
  • add an advice to hl-line-mode limited to a neotree buffer instead and change the priority before enabling hl-line-mode;
  • just keep the quick fix to disable hl-line-mode before resetting the priority.

Disable and re-enable hl-line-mode or neotree, and then it looks good!

The next nit I want to pick is to enable horizontal scrolling with the mouse for long filenames, and removing the block cursor when LIN is active (which you don’t see on the screenshots because I timed the picture with its blinking).


Receive Christian’s new posts via email

-1:-- Prioritize hl-line Highlight Over Neotree Faces (Post)--L0--C0--June 10, 2022 12:41 PM

Christian Tietze: Free Cmd-W in Magit to Close the Buffer

Magit binds M-w to magit-copy-buffer-revision. On my Mac, I use the left Command () key as the Meta key, though, and wired M-x, M-c, M-v to cut/copy/paste, leaving M-w aka +W to close the current buffer.

Magit defines this key binding in a lot of modes, though. The status mode has its own key map, the log mode has its own key map – so I did the only sensible thing and removed this from all maps I could find.

Update 2022-06-10: Magit author Jonas Bernoulli pointed out I’m doing everything wrong, there’s just 1 key-map, all the others derive from it. So the actually sensible thing to do is just this:

(unbind-key "M-w" magit-mode-map)

In my defense I would like to complain that this fact isn’t very obvious from the built-in Emacs help!!1

Old approach before Jonas showed the true way

Here’s the previous code to unbind M-w from all Magit mode key maps:

(let ((all-magit-mode-maps
       '(magit-status-mode-map
         magit-mode-map
         magit-log-mode-map
         magit-blob-mode-map
         magit-diff-mode-map
         magit-refs-mode-map
         magit-blame-mode-map
         magit-stash-mode-map
         magit-cherry-mode-map
         magit-reflog-mode-map
         magit-process-mode-map
         magit-section-mode-map
         magit-stashes-mode-map
         magit-repolist-mode-map
         magit-revision-mode-map
         magit-log-select-mode-map
         magit-todos-list-mode-map
         magit-merge-preview-mode-map
         magit-submodule-list-mode-map
         magit-blame-read-only-mode-map)))
    (dolist (mode-map all-magit-mode-maps)
      (unbind-key "M-w" mode-map)))

To get there, I filtered all bound variables for “magit -mode-map”. That produced a list of 20 results.

Thanks to Embark, I ran C-, S ((embark-collect)) to produce a more permanent buffer from the minibuffer’s resuls. There, I copied the variable names with a rectangular selection and concatenated the 20 lines into one via xah-reformat-lines that ships with my modal input of choice, Xah Fly Keys mode. (I could’ve probably also have used fill/unfill shortcuts, I just realize.)

Collected results in a dedicated buffer to edit

Wrap that in a quoted list and loop over it to call unbind-key for each map.

It’s likely that some of these key maps didn’t even bind M-w, but that’s not a problem, it’s just a no-op.


Receive Christian’s new posts via email

-1:-- Free Cmd-W in Magit to Close the Buffer (Post)--L0--C0--June 10, 2022 12:12 PM

Bozhidar Batsov: Zed Editor

Yesterday the demise of Atom was a very hot topic for many programmers.1 One thing I noticed in the comments here and there was that the original team behind Atom is now working on a new editor, named Zed.

I assume the name alludes to something like “Zed is going to be the last editor you’ll ever need”. It’s a good name. Zed hasn’t had any public releases yet, so relatively little is known about it at this point:

  • It’s written in Rust and supposedly it’s very fast
  • It has some built-in collaboration features for software engineers
  • It uses TreeSitter for syntax highlighting and code navigation
  • It’s in a private alpha right now.

You can learn more about Zed from this intro presentation.

It does look like an interesting project, but I assume it’s going to be another proprietary editor (like TextMate in the past and Sublime Text), so I doubt it will have a major impact on the editor landscape. Those projects typically start strong and quickly fade away. Still, I’m always curious about the new ideas a new editor will bring along. Perhaps we’ll adapt some of them to Emacs down the road…

I still believe that Emacs is the last editor you’ll ever need.

  1. I wrote a short commentary on Emacs Redux. 

-1:-- Zed Editor (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--June 10, 2022 06:05 AM

Irreal: Proced

Bhaskar Chowdhury has a nice video on using proced in Emacs. He covers many, but not all of the things you can do with it. As Chowdhury says, proced is best thought of as a top substitute built into Emacs. I don’t think it’s quite a full blown top substitute but it does have many of the same capabilities and does move us closer to never having to leave Emacs.

As most of you know, I do most of my work on my MacBook laptop and for a long time proced didn’t really work on a Mac. But at least since 2018 it’s been working fine on the Mac. After watching Chowdhury’s video, I fired up proced to see if I could find any shortcomings—I couldn’t. Everything that Chowdhury showed worked fine on my MacBook.

Proced is perfect for a quick check on things when you don’t want to have to context switch out of Emacs. It’s just another example of how Emacs provides a nearly complete operating environment. It is as I’ve often said a light weight Lisp Machine. Most of us will never have to opportunity to work on a Lisp Machine but Emacs does provide a hint of what it was like.

Proced gives you top-like information in an Emacs buffer. That’s nice because you can use all the usual Emacs searching and navigation commands in that buffer. You many not use proced all that often but it’s perfect when you need it.

-1:-- Proced (Post jcs)--L0--C0--June 09, 2022 04:33 PM

Emacs TIL: Editing Efficiency and Emacs Serendipity

Squeezing the tiny editing efficiency

I used to bind Super and another key with the commands / functions that I repetitively use. It works well for the actions like counsel-buffer-or-recentf which I just press Command + T keys in my Mac keyboard.

It is a bit efficient than pressing M-x and type the command name.

Is it worth it if I can’t remember the keys?

I seem to have overdone it and ended up with lots of keybindings. When I actually need to use it occasionally, my first instinct was to try to remember what my keybinding was, and often forgotten.

Later I realized it is better to not bind the keybindings at all. Instead, just give the command or function a descriptive name, like jz/copy-relative-path, and always use M-x.

Yes, I lose a little editing efficiency, but I form a better long-term memory about the editing operations, and the functions available for me to use.

M-x and serendipity

Using M-x also comes with another unexpected benefits: With autocomplete, I sometimes learn about better commands in the drop-down and use them instead.

Example:

When I want to replace something inside a repo, I vaguely remember projectile has something like that, so I type: M-x proj replace.

Some commands show up. One is projectile-replace and the other is project-query-replace-regexp.

At that moment, I can slow down and ask myself if I want to use regex instead. If yes, I should pick the regex one instead.

Most Emacs commands are name meaningfully, and based on autocomplete and string fuzzy match, we could discover the relevant commands. We should take advantage of that.

Even if you spell brokenly, like typing partial words proj and repla, Emacs still finds the right spell for you and does its magic.

During the process I felt calm. I let Emacs teach me something new, and enhance my memory about Emacs verbiage along the way.

That's my Emacs serendipity.

-1:-- Editing Efficiency and Emacs Serendipity (Post Junji Zhi)--L0--C0--June 09, 2022 03:44 PM

Emacs Redux: Forever Emacs

Operating systems, GUI toolkits and competing editors come and go, but Emacs is forever!

– Unknown

Yesterday it was announced that the once popular Atom editor is going to be discontinued at the end of this year.

I’ve often said that one of the great advantages of Emacs is that it has stood the test of time1 and will likely be with us for a very long time to come. During the 25 years I’ve been into computers and programming I’ve seen a lot of editors and IDEs rise and fall:

  • Komodo
  • Eclipse
  • NetBeans
  • TextMate
  • LightTable

And now Atom. Any investment you’ve made to master those tools and build additional plugins for them has been mostly wasted in the end.

This list also serves to illustrate that just being an open-source project doesn’t mean much, if there’s no real community around the project and the bulk of the development is driven by commercial interests. The moment when such projects lose their backing they typically stagnate and die. It’s not like community project don’t meet their demise from time to time as well, but they are definitely much more resilient than the typical company-driven OSS project.

Emacs is a true community-driven project and I’m certain that it will outlive many more trendy editors until all is said and done.2 If you’re playing the long game, you better pick the right tools for it.

In Emacs we trust! M-x forever!

  1. It first appeared way back in 1976! 

  2. Same goes for our evil nemesis vim

-1:-- Forever Emacs (Post Bozhidar Batsov)--L0--C0--June 09, 2022 12:51 PM

Bozhidar Batsov: Modern Emacs: Redux

New is always better.

– Barney Stinson

My recent article Who Needs Modern Emacs? generated a bit of controversy. I’ve received a lot of feedback over email, Reddit, and Lobsters and I feel the need to address some of that feedback.

Let’s start with some comments that caught my attention:

The difficulty with posts like this and the responses is that it all comes from the same echo chamber of established, long time, respected Emacs users/devs who already have a vested interest in keeping the status quo and having others adapt rather than face adapting themselves. I’m not saying they’re wrong necessarily, but I think it’s worth seriously exploring the positive effects of modernizing aspects of Emacs. And I think to see how it can help all us grey beards, we need look no further than the effects that Doom had on the Emacs community.

I totally loved this comment! To set the record straight - I’m not opposed to modernizing Emacs, but rather to a particular notion of what modernization is about. I’m concerned about meddling with the essence of Emacs (e.g. its Elisp core) to chase after potential users that might never materialize. I’m also tired of non-stop comparisons with editors like Sublime Text and VS Code and all the people urging Emacs to try to emulate them.1 There’s a popular saying that always comes to my mind when I hear something like this:

If we all think alike then nobody’s thinking at all.

It is fine to have editors that deviate from the established norms. The fact that something is very popular doesn’t make it great. Having diverse alternatives is not a bad thing.

There’s also the point that I’ve never seen an editor make a big comeback, which makes me fairly confident that no amount of changes will likely make Emacs super popular down the road. The narrative for modernization is always that this is going to bring Emacs a lot of new users (and hopefully more contributors) and change its fortunes, but I never bought this and I’m still not buying it.

Here’s a bit more food for thought - how much resources have Microsoft, one of the biggest companies in the world, invested in making VS Code a success? Is it realistic to expect that any community of volunteers can match those?

I’m also fairly certain that if our definition of innovation gets reduced to “copy features/behavior from the popular editors of the day” we would never see new ground-breaking tools like org-mode, magit, SLIME, CIDER, etc.2

So, instead of chasing wild geese, I’d rather focus on improvement efforts that make Emacs better, while preserving its essence.

Doom (and before it Spacemacs) brought forth a ton of new (likely Vim) users willing to try out Emacs, and created a lot of momentum in new content that the whole Emacs community benefitted from. But before Doom existed, we had naysayers just like this post claiming that something like Doom wasn’t necessary or needed. What we need is some visionary thinking that moves beyond this. We can continue to debate changing (or configuring) terms like buffer/kill/yank vs file/cut/paste or which themes are included or which keybindings - but in the end, to me it comes down to one thing - how do we continue to see Emacs grow and increase adoption?

True that. I’ve long been a believer that the Emacs distros are the most viable way to cater to the needs of different groups of Emacs users. That’s why I’ve spent years working on Emacs Prelude. Distros provide us a good way to validate some ideas that might make it all the way to vanilla Emacs (e.g. new defaults, additional packages bundled and enabled by default, etc) and they make it possible to do things that will likely never make it in vanilla Emacs (packages depending on proprietary software, vim keybindings by default, etc).

It seems that many people have missed that particular point of mine - given how flexible Emacs is (being in essence editor building material), you don’t need to push all changes you want to Emacs itself; you can achieve quite a lot externally in the form of a reusable configuration.

For my $.02, I’d love to see a bit more movement from the devs in this arena, but more importantly a ton more movement from the Emacs distro community in this arena, to create something that feels a bit more out-of-the-box like Sublime Text or VSCode. We have some good starts with NANO, but that’s not quite enough. I think a lot more people would be willing to try and stick with Emacs with a stater kit geared toward those users that simply had a file browser and file tabs, more familiar keybindings, modern terminology, more sane behaviors (stop unselecting regions all the time!!!), and some better default options. Learning to configure from there with elisp isn’t the issue to adoption - the issue is how much elisp you have to start with to get to something that feels familiar.

No argument from me on this point as well, although I do think that unless you know Elisp you’re unlikely to ever unlock the full potential of Emacs. Learning Elisp was definitely game-changing for me as an Emacs user and I allowed me push Emacs much further than I ever thought was possible. If I can’t truly bend Emacs to my will and I’m just an user of some configuration than a lot of it appeals just disappears for me.

Emacs needs to be as easy to use out of the box as atom. Then, you can configure it endlessly. Just because it’s building material doesn’t mean it needs to arrive in shambles.

This comment made me smile in light of the news from yesterday that Atom’s development is coming to an end. Clearly being as modern as Atom is no recipe for long-term success. And yeah - the defaults can always be better and they typically get a bit better with each new Emacs release. It’s a slow process, but it’s already taking place.

And maybe. The fact that emacs isn’t modern isn’t a feature. It’s an indication that it hasn’t kept up with the times, that bugs and slowness persist over decades, that there is truly a rotten broken core inside emacs that requires serious changes.

I think that once again people conflate being unfamiliar/different with being familiar/modern. I can think of no editor with Emacs’s long history that has “kept up with the times” and ended up being more or less the same as VS Code. Yeah, a lot of problems in Emacs have lingered, but also a lot of problems have been addressed. Emacs is much better in many ways than it used to be just 10 years ago. People tend to ignore small improvements (because they quickly get used to them), but if you compare Emacs 22 with Emacs 28 I think you’ll agree that the difference between them is night and day.

I feel like many of the folks offering opinions here are outsiders to emacs. That is not a bad thing as we’re discussing defaults and its impacts on usage of emacs. It might be good to view these criticisms as perceptions on the barriers to entry instead of from an experiential basis, however.

Spot on. People are constantly conflating concepts like “newcomer experience”, “barrier to entry”, “simplicity”, “familiarity” and “modernity”. It’s quite possible for a tool to be modern in a way, yet so foreign to you that you’d consider it complex and dated. It’s also quite possible for a tool to have great onboarding experience and still feel challenging and foreign.

I’ve used emacs for about 4 years now so I have a bit of a different perspective than the folks that have been using it for 20+ years, but I also feel like I’ve invested enough time in the community and ecosystem to have a better vantage point than that of a new or curious user.

I’ve seen a lot of progress in emacs and its ecosystem in my time using it. Emacs has gotten faster and many of the core features of popular packages have been incorporated into the main distribution (tabs, projects, advanced completion, etc). NonGNU Elpa has lowered some barriers for package developers to contribute to an official repository. I’ve seen a renewed focus on rediscovering and leveraging built-in functionality within emacs to simplify packages and benefit from the integration that provides. This is opposed to some of the more heavyweight packages that would largely re-implement built-in fuctionality. Take a look at packages like vertico, corfu, orderless, embark, consult, modus-themes, eglot, etc. The authors of these packages seem to be the next generation carrying the emacs torch forward. They have a great respect for what already exists, but are incorporating functionality that is influenced by modern UX and capabilities.

I do not feel like emacs is declining. Since I’ve used emacs, I actually feel like it has become more popular. I think Doom emacs has had a big impact on bringing in new users. I personally use vanilla emacs so I do not necessarily believe that a big configuration package like Doom or Spacemacs is required to enjoy emacs. That said, I do feel like configuration packages are very useful and I would like to see more minimal versions. If a configuration could be based on emacs 28 or greater, I believe that a very capable and polished emacs configuration could be created with minimal or no extra packages beyond those that are built-in. Maybe some config(s) could catch on so much that it would make sense to provide them as an official option sometime in the future?

Yes! One thing I’ve been thinking for a while now is the idea of bundling some “configuration profiles” with Emacs, so that people can select one when they start Emacs for the first time. This seems to me like the most realistic way to appease the major groups demanding some changes in Emacs (e.g. you can have “traditional profile”, “modern profile”, “vim profile”, etc). With most popular packages available in the official Emacs repos these days this should be fairly easy to achieve. Some mechanism to access 3rd party configurations (e.g. Doom & Prelude) directly would be a nice addition as well.

Epilogue

Broadly speaking, all the feedback my original article received was in one of 3 categories:

  • Agreement (mostly from experienced Emacs users)
  • Partial agreement (mostly from experienced Emacs users)
  • Strong disagreement (mostly from people who (I guess) don’t use Emacs)

I’ve noticed that the people in the second and the third group have a very different idea about what needs to be modernized. The second group cares mostly about improvements to Emacs’s internals (make it faster, better handling of long lines, more robust syntax highlighting, better garbage collector, fix some bugs, etc)3, while the third group mostly wants Emacs to offer defaults and behaviors more aligned with what they consider to be “modern editors”.

I definitely felt that many people completely missed the message I was trying to convey in the original article. Many readers started to dissect the random examples of “points of modernization” that I had listed, or argued that Emacs has to be more newcomer-friendly, which for me is something completely orthogonal to Emacs being “modern”. I still have to find an editor with a better built-in tutorial for newcomers (C-h t) or better built-in documentation (C-h r). They are great, but they still require people to go through them and learn something new and it seems for many people that’s a very tall order.

There were plenty of strange (to me) comments I got like this one:

The fact that emacs is in such a sorry state doesn’t help anyone. It’s bad for new users that need to do so much work. It’s bad for existing users because it drives so many people away and makes the community smaller.

“Sorry state” is obviously quite subjective, but I really doubt we’re losing much of our existing userbase because of some lacking “modern” features from other editors. Funny enough just a month ago there was a popular discussion titled “Are we living in the Golden Age of Emacs?” and there a ton of people were praising the recent advancements that Emacs has made.

I think Emacs has never been better and the recent pace of improvements and innovation makes me very optimistic about its future. The amount of Emacs-related packages & activity on GitHub has been constantly growing for at least a decade. A few new Emacs blogs are born every year. The number of Emacs distros tailored for pretty much every taste keeps growing and growing. Emacs is not perfect, but it’s definitely not some dying editor with a rotten core. It’s the One True Editor and it keeps getting better and better every day.

So are we living in the Dark Age of Emacs or the Golden Age of Emacs? I know the answer for myself. M-x forever!

P.S. Btw, I’m never giving up Meta, Super and Hyper!

  1. I’m never tired of comparisons with vim, though. 

  2. That being said, I don’t mind tastefully copying some really great features of other editors and adapting them to Emacs. 

  3. Supposedly some of those problems are addressed by Commercial Emacs

-1:-- Modern Emacs: Redux (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--June 09, 2022 07:29 AM

Protesilaos Stavrou: Emacs: lin version 0.4.0

Lin is a stylistic enhancement for Emacs’ built-in hl-line-mode. It remaps the hl-line face (or equivalent) buffer-locally to a style that is optimal for major modes where line selection is the primary mode of interaction. In concrete terms: (i) let your theme use a subtle gray to highlight the current line in text-editing buffers like Org, and (ii) render the current line with a more prominent colour in Dired, Ibuffer, et cetera. Why? Because the two types of interaction have different requirements about how intensely the current line should be highlighted.

Sample configuration:

(require 'lin)

(setq lin-face 'lin-blue) ; check doc string for alternative styles

;; You can use this to live update the face:
;;
;; (customize-set-variable 'lin-face 'lin-green)

;; This is the default value
(setq lin-mode-hooks
      '(bongo-mode-hook
        dired-mode-hook
        elfeed-search-mode-hook
        git-rebase-mode-hook
        grep-mode-hook
        ibuffer-mode-hook
        ilist-mode-hook
        ledger-report-mode-hook
        log-view-mode-hook
        magit-log-mode-hook
        mu4e-headers-mode
        notmuch-search-mode-hook
        notmuch-tree-mode-hook
        occur-mode-hook
        org-agenda-mode-hook
        proced-mode-hook
        tabulated-list-mode-hook))

(lin-global-mode 1)

Below are the release notes.


-1:-- Emacs: lin version 0.4.0 (Post)--L0--C0--June 09, 2022 12:00 AM

Andrea: Make adding a Clojure require more interactive with Cider and Cljr

Use Cider to find the namespace to require
-1:-- Make adding a Clojure require more interactive with Cider and Cljr (Post)--L0--C0--June 09, 2022 12:00 AM

Irreal: Emacs Buffers

Mickey from Mastering Emacs has a post, Why Emacs has Buffers, that considers why Emacs makes the buffer concept one of its signal concepts. After all, he says, the natural construct when a programmer thinks of an editor is the string. The lines that you see on the screen are just strings and (text) files can be viewed as just a collection of strings.

Buffers, on the other hand, seem more abstract and unnatural. Mickey says they don’t evoke the same familiar associations as terms like “file” or “document” do. Of course, that’s a little overwrought. Any Emacs user, let alone programmer, who has a hard time with the concept of a buffer probably needs to find another occupation. Still, it’s worth considering why bringing the buffer concept to the forefront instead of burying
it in the internals as most editors do is the right thing and that’s what Mickey does.

One of the things the “modernize Emacs” nebbishes want to do is replace buffers with tabs. Not because tabs are better but just because they’re used to them. Of course, buffers are a much more general concept that includes things that are not files. You could, I suppose, make a tab for each buffer but that’s not want the nebbishes want: they want one tab per file just like they’re used to. I know I’m waving my cane at the kids on my lawn but—really—if you aren’t willing to put in a little effort to learn the Emacs way, please go away. If you are willing to put in that effort, welcome. There are plenty of people here willing to help you learn.

As always, any post from Mickey is worth spending a few minutes reading. Spend a few minutes to check it out.

-1:-- Emacs Buffers (Post jcs)--L0--C0--June 08, 2022 07:16 PM