Protesilaos Stavrou: Emacs: cursory version 1.0.0

Cursory provides a thin wrapper around built-in variables that affect the style of the Emacs cursor on graphical terminals. The intent is to allow the user to define preset configurations such as “block with slow blinking” or “bar with fast blinking” and set them on demand. The use-case for such presets is to adapt to evolving interface requirements and concomitant levels of expected comfort, such as in the difference between writing and reading.

Below are the release notes.


Cursory has been in a stable state for a long time. I use it daily and am happy with what it does. This version refactors parts of the code in the interest of legibility/hackability, while providing a quality-of-life feature for users.

A preset can now inherit from another

In the interest of defining multiple presets while avoiding duplication, the user option cursory-presets now accepts an :inherit property. For example:

(setq cursory-presets
      '(
        ;; Sample code here ...

        (bar
         :cursor-type (bar . 2)
         :cursor-in-non-selected-windows hollow
         :blink-cursor-mode 1
         :blink-cursor-blinks 10
         :blink-cursor-interval 0.5
         :blink-cursor-delay 0.2)

        (bar-no-other-window
         :inherit bar
         :cursor-in-non-selected-windows nil)

        ;; More sample code here ...
        ))

Presets were already capable of getting properties from a default t preset. Now they can be controlled with greater precision.

The value of cursory-presets is updated accordingly to benefit from this mechanism and to showcase how it is done:

(defcustom cursory-presets
  '((box
     :blink-cursor-interval 0.8)
    (box-no-blink
     :blink-cursor-mode -1)
    (bar
     :cursor-type (bar . 2)
     :blink-cursor-interval 0.5)
    (bar-no-other-window
     :inherit bar
     :cursor-in-non-selected-windows nil)
    (underscore
     :cursor-type (hbar . 3)
     :blink-cursor-blinks 50)
    (underscore-thin-other-window
     :inherit underscore
     :cursor-in-non-selected-windows (hbar . 1))
    (t ; the default values
     :cursor-type box
     :cursor-in-non-selected-windows hollow
     :blink-cursor-mode 1
     :blink-cursor-blinks 10
     :blink-cursor-interval 0.2
     :blink-cursor-delay 0.2))
  ;; Omitting the doc string for demo purposes...
  )

In the above sample, we notice both the :inherit property and the default t preset with all its properties. Presets beside t act as overrides of the defaults and, as such, need only consist of the properties that change from the default. In the case of an :inherit, properties are first taken from the inherited preset and then the default one.

-1:-- Emacs: cursory version 1.0.0 (Post)--L0--C0--June 09, 2023 12:00 AM

Irreal: SICP and Emacs

As you all know by now, I really love SICP and consider it among the best—if not the best—books on computer science of all time. I didn’t read it until fairly late in my career and yet I can’t overstate how much I learned from it and how much it changed the way I think about our craft. There are those—including Abelson and Sussman—who say that the approach employed by SICP is no longer applicable but I disagree vehemently. If you don’t understand its lessons then you don’t understand computer programming no matter how many robots you program.

You won’t really understand those lessons unless you work most of the problems. I mostly skipped over them on my first reading but later went back to reread SICP and work the problems. Again, I learned new things and deepened my understanding of what I thought I already knew.

Getting, finally, to the point, Konstantinos Chousos has just started reading SICP and is working the exercises as he goes along. He has a blog post that describes his workflow for studying the book. His is by no means to only such workflow possible but it’s a good one and worth emulating if you, too, want to become enlightened by SICP.

The TL;DR is that he installed SICP as an Info file so he can read it in Emacs and then installed Racket as his Scheme environment because it offers an SICP extension that recreates the original MIT Scheme that SICP uses. He also installed the emacs-ob-racket package for working with Racket from within Emacs.

He describes in detail how to install all these so it’s pretty easy to duplicate his setup. If you want to study SICP, and you should, Chousos’ workflow is an excellent way of doing so. And, you’ll end up with SICP installed in Emacs as an Info file. What’s not to like?

-1:-- SICP and Emacs (Post jcs)--L0--C0--June 08, 2023 04:58 PM

James Dyer: Magit Status To Show Tracked Files

While currently piecing together my git repositories and figuring out which files to commit I am invariably going to have some Untracked files but I also would like to see the Tracked files in magit-status

Well emacs being emacs this can be easily achieved, I added the following to my use-package magit declaration.

:config
(magit-add-section-hook
  'magit-status-sections-hook 'magit-insert-tracked-files nil 'append)
-1:-- Magit Status To Show Tracked Files (Post James Dyer)--L0--C0--June 08, 2023 10:05 AM

Protesilaos Stavrou: Emacs: ef-themes version 1.1.0

The ef-themes is a collection of light and dark themes for GNU Emacs whose goal is to provide colourful (“pretty”) yet legible options for users who want something with a bit more flair than the modus-themes (also designed by me).

Below are the release notes.


This release introduces several minor refinements to the project, while adding support for more third-party packages or built-in face groups.

Tabs have their own semantic colour mappings

The Ef themes are designed to abstract away common patterns based on the semantics of the elements involved. For example, all strings in programming modes use the string colour that each theme defines in its palette. This allows the themes to share the same code base yet remain distinct from each other.

Colours used for tab-bar-mode, tab-line-mode, and related are now part of this design. The new semantic mappings are bg-tab-bar, bg-tab-current, bg-tab-other.

[ A theme palette can have user-defined overrides (e.g. tweak the main background). Consult the manual for the technicalities or contact me if there is any doubt. ]

Added support for the centaur-tabs package

The aforementioned semantic colours are applied to the faces of the centaur-tabs. Using it with the themes now works as expected, instead of defaulting to its own dark background colour (a default that doesn’t work with most themes, anyway).

Thanks to Amo DelBello for bringing this matter to my attention in issue 21 on the GitHub mirror: https://github.com/protesilaos/ef-themes/issues/21.

Covered the nerd-icons, nerd-icons-dired, nerd-icons-ibuffer packages

These are a new family of packages that are gaining traction in the Emacs milieu (for instance, the doom-modeline now uses the Nerd icons, which must be installed with M-x nerd-icons-install-fonts).

Their colours are now consistent with all the Ef themes.

Tweaked the colouration of the all-the-icons glyphs

I refined some of the colours in use to introduce greater variety and amplify certain values while avoiding exaggerations. In short, they should look nice and pretty.

The whitespace-mode indicators are much more subtle

The previous style involved the use of a dim grey background. While this is good to spot invisible characters quickly, it is bad for users who want to run whitespace-mode at all times (e.g. for Python which is space-sensitive).

We thus remove the backgrounds by default but provide the option to reinstate them via palette overrides (as documented at length in the manual). To this end, we have new semantic colour mappings for ordinary negative space and its invisible characters:

  • bg-space
  • fg-space
  • bg-space-err

Ediff faces no longer have an implicit dependency on diff-mode

I made a mistake where the Ediff faces would inherit the styles of their diff-mode counterparts. This usually works, such as when ediff is invoked from magit, though it will not do the right thing if the user invokes some Ediff command directly without first loading diff-mode.

This no longer happens. Ediff always works. Stylistically, everything looks the same.

The git-gutter and git-gutter-fr packages are supported

These now use the appropriate colours defined by the Ef themes. This is especially important for themese that do not use the generic red-green colour coding scheme.

image-dired marked items are easier to spot

With image-dired the user can apply selection or deletion marks to image thumbnails. Those marks are colour-coded the same way they are in Dired (the exact hues depend on the theme to account for accessibility, e.g. for deuteranopia or tritanopia). Sometimes the colour of the mark is obscured by the same colour found in the thumbnail. To make the mark stand out, a border is drawn around it, making the selection unambiguous.

Holidays and diary entries are more distinct and have no background

The holidays and diary entries that are found in the M-x calendar or M-x diary buffers no longer use a subtle background colour. The old design was not consistent with similar patterns established by the themes, such as how a date/timestamp should be represented.

Furthermore, the given constructs are assigned to contrasting hues to stand apart from each other and also be easy spot in their context (especially holidays in the Calendar view).

The mood-line is covered by the themes

This is a package that refashions the Emacs mode line. It is conceptually similar to the doom-modeline.

Miscellaneous

  • Added links in the Custom User Interface to the ef-themes web pages for the manual and sample pictures, respectively. Those links are visible when perusing the various M-x customize buffers where entries related to the Ef themes are present.

  • Made ef-themes--load-theme return the THEME argument it operates on. The intent is to allow other functions that call this one to capture the return value for their purposes.

  • Extended support for the built-in ERT faces, which are used in regression tests of Emacs Lisp code.

-1:-- Emacs: ef-themes version 1.1.0 (Post)--L0--C0--June 08, 2023 12:00 AM

Andrea: A little exploration of Go from a Clojure perspective

A little exploration of Go from a Clojure perspective

I have been looking into Go recently and I decided to find out how to do things that I usually do in Clojure. These are (a cleaned up version of) my notes.

First let's start from iterations. Clojure (as any good Lisp language) focuses on sequences. So changing a sequence into a new one is key (and super easy):

(map inc [1 2 3])

(2 3 4)

While Clojure focuses on immutability to keep things simple, Go focuses on performance. The easiest way to achieve the same is with a for loop:

list := []int{1,2,3}
for i, value := range list {
        list[i] = value + 1
}
list
[]int{
  1,
  2,
  3,

..... 
 []int{
  2,
  3,
  4,

Next Clojure focuses on data transformation and the most used data structure is the map. So let's iterate over a map's values:

(into {} (for [[k v] {:a 1 :b 2}] [k (inc v)])) 
; (update-vals {:a 1 :b 2} inc) ; clojure 1.11

{:a 2, :b 3}

In the above we use a Clojure for loop to create a new vector of key-value pairs, where they value in the pair was increased by one.

Go also comes with a map data structure which is super easy to write. Again the for loop will let us modify things:

theMap := map[string]int{"a": 1, "b": 2}
for key, value := range theMap {
        theMap[key] = value + 1
}
theMap
map[string]int{
  "a": 1,
  "b": 2,

..... 
 map[string]int{
  "a": 2,
  "b": 3,

And to complete our little exploration, I would say polymorphism is a must. In Clojure we can make interfaces via protocols:

(defprotocol StringMyself
  (who-am-i [x]))

(deftype Duck []
  StringMyself
  (who-am-i [x] "I am a duck!"))

(deftype Octopus []
  StringMyself
  (who-am-i [x] "I am an octopus!"))

(who-am-i (Octopus.))
StringMyself
user.Duck
user.Octopus
"I am an octopus!"

In Go is beautifully simple as well:

type StringMyself interface {
        WhoAmI() string
}

type Duck struct {}
func (d Duck) WhoAmI () string {
        return "I am a duck!"
}
type Octopus struct {}
func (d Octopus) WhoAmI () string {
        return "I am an octopus!"
}

var o StringMyself = Octopus{}
o.WhoAmI()
..... 
  main.Octopus{
 \"I am an octopus!\""

Not bad as a first go at go. And it seems to be pretty succinct!

Happy Going!

-1:-- A little exploration of Go from a Clojure perspective (Post)--L0--C0--June 08, 2023 12:00 AM

Irreal: The Real Emacs Advantage

After yesterday’s post I started thinking about what the real advantage of Emacs is. There are, as I’ve said many times, plenty of advantages but if you had to choose the most important one, what would it be?

My recent experience with elfeed-webkit crystallized this for me. It started with Christopher Wellons feeling that he needed a better RSS reader and that he’d like it to run in Emacs. The result of that itch was what I consider the best RSS reader in any environment: elfeed. The point here is that Wellons is just a guy with a problem but Emacs made it easy for him to solve that problem and make the result available to all of us.

But wait. There’s more. Fritz Grabo was an Elfeed user and liked it but many times he had to switch to his browser to read a post and then switch back to Elfeed. That was a pain so he started wondering if there was some way of faithfully rendering the HTML directly in Emacs. It turned out that of course there was. You can compile Emacs with XWidget support and then use Webkit to render HTML accurately directly in an Emacs buffer. Grabo used that to make elfeed-webkit and suddenly reading your RSS feed is even easier and more pleasant than it was before.

That’s the thing about Emacs: everything is available for you to extend it in any way you like, sometimes in surprising ways. Reading RSS feeds is, after all, only marginally related to text editing but as I’ve written so many times before, Emacs is much more than an editor so it has us covered.

For me, therefore, the most important advantage of Emacs is its extensibility. If it isn’t quite what you want, Emacs makes it possible to make it exactly what you want.

-1:-- The Real Emacs Advantage (Post jcs)--L0--C0--June 07, 2023 05:05 PM

Unwound Stack: Hosting indie-org.sh on S3

Bringing your own domain to Route 53 is easy, once you know how

-1:-- Hosting indie-org.sh on S3 (Post Michael (sp1ff@pobox.com))--L0--C0--June 07, 2023 07:00 AM

Thomas Fitzsimmons: firefox-javascript-repl

Read-Evaluate-Print Loops are great for doing quick experiments. I recently released two new REPL packages for Emacs to GNU ELPA. This is the first in a two part series.

I wanted something along the lines of SLIME or CIDER’s REPL (just the REPL part) but for JavaScript. There have been many options for this over the years, MozRepl, skewer-mode, jsSlime 1, and more recently dap-mode. I tried all of these existing options but all except for dap-mode are no longer maintained. The Firefox Remote Debugging Protocol has evolved over the past decade, and it has not always maintained backward compatibility. It is not meant to be an API, I guess, but more a reflection of Firefox internals.

I did try dap-mode, but I couldn’t install it on my development version of Emacs; there seemed to be Elisp compatibility problems with some of its many dependencies. It also seemed to require on the Firefox side a JavaScript extension from the repository for an unrelated proprietary IDE, which I found strange.

I just wanted a simple Emacs mode to communicate with Firefox directly, for small JavaScript experimentation. It seemed like everything was already available in Emacs and Firefox to do that.
I started with the Mastering Emacs Comint guide, and for the Firefox side, the geckordp project does a great job of documenting the Firefox Remote Debugging Protocol. Firefox needs to run in a special debug mode for the protocol to be available, so I added that logic to the new Emacs command.

The result is firefox-javascript-repl, available in GNU ELPA. I tested it on GNU/Linux. I would like this to work on other operating systems too, patches accepted.

I made sure this mode works on Emacs versions 26.1 (released in 2018) and newer 2. I’ve also tested on the most recent Firefox (113.0.2) and Firefox ESR (102.11.0esr). I’ll strive to keep up with changes in the Firefox Remote Debugging Protocol, to minimally keep firefox-javascript-repl working for the latest Firefox and Firefox ESR releases (though if the FRDP breaks compatibility, firefox-javascript-repl will also break compatibility with older browser versions, to avoid a large test matrix).

I was going to do a video of this working but it’s easy enough to try yourself. It creates a new temporary Firefox profile, so it doesn’t mess with any of your existing profiles. Try M-x package-install RET firefox-javascript-repl RET; M-x firefox-javascript-repl RET. If Firefox starts and everything succeeds, you should see an interesting JavaScript quirk-of-the-day, courtesy of the wtfjs project.

  1. I wish jsSlime were still maintained, in which case I wouldn’t need to write this post or this REPL.^
  2. I welcome patches to make it work on older versions of Emacs, but I can’t build anything older than Emacs 26.1 to test against.^
-1:-- firefox-javascript-repl (Post Thomas Fitzsimmons)--L0--C0--June 07, 2023 02:11 AM

Irreal: Is Emacs Slow?

What do you think? Is Emacs slow or is that just another instance of Emacs hater FUD? The most frequent complaint I see about Emacs—with the possible exception of its lack of bling—is that it’s too slow.

I don’t understand that. Maybe that’s because I’m old enough to have used some genuinely slow tools but I’m pretty sure it’s just that I have more sensible standards. Sure, other editors may be faster at one task or another but I have always found the differences in speed essentially undetectable by human beings in their normal workflows. In other words, Emacs is fast enough where it counts.

Corwin Brust over at Corwin’s Emacs Blog examines this question in his blog post, The Turtle and the Snail. The title comes from a joke involving a turtle and snail that has application to the question of Emacs’ speed. I’ll let you check out the joke on Brust’s post but the TL;DR is that speed—at least if we aren’t speaking of light—depends on the observer.

Brust mentions a related complaint: “[I]t consumes too much of my time, to understand and configure, and to enhance it.” That’s just plain silly. Unless you’re one of those people who demands instant gratification and are unwilling to expend any effort to attain it, the complaint is frivolous. When I started, I printed out the cheat sheet and was using Emacs reasonably productively on the first day. To be sure, I wasn’t as fast as I was with Vim but that came fairly quickly.

As for understanding and configuring it, we all know that that’s a lifetime journey. Like every other Emacs user, I’m still learning new things about Emacs and my init.el is a lifelong project. If this idea of a lifetime commitment bothers you, perhaps Emacs is not for you.

-1:-- Is Emacs Slow? (Post jcs)--L0--C0--June 06, 2023 04:21 PM

Will Schenk: Setting up emacs re-re-dux

Can we ever stop setting up emacs? I don't think it's possible, no. Lets do it again, with a nice clean setup using Nano Emacs. Compiling emacs First lets get ourselves a clean emacs from d12frosted/homebrew-emacs-plus. 1 2 3 $ brew tap d12frosted/emacs-plus $ brew install emacs-plus --with-imagemagick --with-native-comp --with-modern-sexy-v2-icon --with-xwidgets $ ln -s /opt/homebrew/opt/emacs-plus@28/Emacs.app /Applications This will take a nice little while. Also, some fonts: 1 2 3 4 $ brew tap homebrew/cask-fonts $ brew install font-roboto $ brew install font-roboto-slab $ brew install font-roboto-mono Installing straight.
-1:-- Setting up emacs re-re-dux (Post)--L0--C0--June 06, 2023 12:00 AM

Andrea: ob-gore: literate Go run via the Gore REPL

-1:-- ob-gore: literate Go run via the Gore REPL (Post)--L0--C0--June 06, 2023 12:00 AM

Irreal: Simple Extensions in Emacs

Robert Johnson has a useful post on Everyday editor extensions in Emacs. Most Emacs n00bs and even many seasoned Emacers assume Elisp is too obscure and hard for “normal” users so they avoid it. Of course, that’s not true at all. As Johnson shows, it’s pretty easy to get started making simple extensions without having to know much about Elisp.

He demonstrates this by making a very simple Emacs function that simply opens the browser at some fixed site—github/spacemacs in his case. From there, he adds the ability to enter parameters, first by having the user enter them, then by using thing-at-point, and finally by using a prompt if thing-at-point fails.

At that point Johnson has a useful function that anyone could customize for their own workflow. Next he considers calling a shell command rather than the browser and having the results put in an Emacs buffer. That’s great, of course, because you can stay in Emacs and don’t have to switch out to the browser.

All of this uses only a minuscule fraction of the Elisp language, of course, but still manages to produce useful extensions. The important, unstated, advantage, though, is that once you get comfortable with this tiny portion of Elisp, it’s much easier to move on to the rest of the language. Developing even a minimal working knowledge of Elisp will open up a whole new dimension of Emacs to you.

-1:-- Simple Extensions in Emacs (Post jcs)--L0--C0--June 05, 2023 04:53 PM

Sacha Chua: 2023-06-05 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, lobste.rs, lemmy, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

-1:-- 2023-06-05 Emacs news (Post Sacha Chua)--L0--C0--June 05, 2023 01:14 PM

Corwin Brust: The Turtle and the Snail

People are always talking about how fast they work, either because Emacs or because Not Emacs. That reminds me of this joke…

-1:-- The Turtle and the Snail (Post)--L0--C0--June 05, 2023 10:00 AM

Corwin Brust: The Turtle and the Snail

People are always talking about how fast they work, either because Emacs or because Not Emacs. That reminds me of this joke… For me, the idea "getting things done faster" hits a little funny. I attempt all sorts of crazy things in my own technology (particularly coding) projects. Moreover, as a general rule, I don't strive to "get stuff done fast" so much as struggle to get things done, at all.
-1:-- The Turtle and the Snail (Post)--L0--C0--June 04, 2023 10:00 AM

James Dyer: Quickly Deleting Duplicate Blank Lines

20230603114025-emacs--Quickly-Deleting-Duplicate-Lines.jpg I am currently hacking around with my org files and in fact macro removing quite a few unnecessary lines. However this has had the side effect of leaving some significant holes in the form of blank lines. Sometimes just two duplicate blank lines and sometimes more!

I found that I can quickly trim them down by using delete-duplicate-lines and making sure the identical lines must be adjacent argument is set by passing in a C-u C-u prefix.

So the process is:

  • open the org file
  • mark-whole-buffer
  • C-u C-u delete-duplicate-lines

and that’s it!, the key here is the prefix argument otherwise all the blank lines will be deleted which is not what I want.

Of course this method would delete all duplicate adjacent lines and not just the blank ones so I guess you would generally need to be a little careful, but I know I don’t have any of these and if I am not too sure then I can just inspect a git diff.

-1:-- Quickly Deleting Duplicate Blank Lines (Post James Dyer)--L0--C0--June 03, 2023 08:38 PM

Irreal: Warp Refactoring With Emacs

Ashton Wiersdorf has a very interesting post on refactoring in Emacs. His problem is a simple one: we wants to replace all occurrences of set_XXX_config! (where XXX varies) to config_XXX! for all files in a directory. He uses several packages to support this but the only one really necessary is wgrep, which make a search results buffer writable and saves the changes to it back to the original files.

His strategy is to

  1. grep for the appropriate regex,
  2. put the search results in a separate buffer
  3. make the buffer writable with wgrep
  4. use something like replace-regexp to change the identifiers
  5. save the results back to the original files

If you’ve been around Irreal for a while, this probably seems familiar. In abo-abo’s original post, he used rgrep so he didn’t need to worry about getting the results into another buffer but my process uses counsel-rg so I need a Ctrl+c Ctrl+o to move the results from the minibuffer to a separate buffer. After that, things are mostly the same. The nice thing is that Ivy handles all this for me and I don’t need any other packages besides wgrep.

This is a great way to refactor. The process, Wiersdorf says, is better than trying to do it from within an IDE using some sort of language server because it finds and changes all occurrences of the target identifiers including those in, say, documentation files that a language server is not going to find. It’s my favorite way of solving this problem. After you try it, it will probably become yours too.

-1:-- Warp Refactoring With Emacs (Post jcs)--L0--C0--June 03, 2023 06:49 PM

Marcin Borkowski: Org agenda clock check

Some time ago (well, a long time ago) someone posted an interesting discovery in Org mode agenda: “clockcheck mode”. I stored the link to that message with the intention of blogging about it and forgot about it. I rediscovered it some time ago and decided to take a look.
-1:-- Org agenda clock check (Post)--L0--C0--June 03, 2023 05:30 AM

Protesilaos Stavrou: Emacs: my new ‘spacious-padding’ package

I just published a new project called spacious-padding. This is yet another package of mine for GNU Emacs. It increases the padding or spacing of frames and windows on demand.

The idea with this package is to provide the means to easily toggle between terse and spacious views, depending on the user’s needs.

Below are a couple of pictures to show what I mean.

Default spacing 😒

GNU Emacs with default spacing

M-x spacious-padding-mode 🤩

GNU Emacs with spacious-padding-mode enabled

Coming soon

There will be no widely available GNU ELPA package for the first days of spacious-padding. Only those who track the GNU ELPA-devel archive or pull directly from source can get it right now. I want to test this for a while longer before tagging version 0.1.0. Expect the formal release some time next week.

Inspiration for this package comes from Nicolas Rougier’s impressive designs and Daniel Mendler’s org-modern package.

-1:-- Emacs: my new ‘spacious-padding’ package (Post)--L0--C0--June 03, 2023 12:00 AM

Manuel Uberti: Ghost in the Machine

Whenever I think of artificial intelligence, Ghost in the Machine, the seventh episode of the first season of The X-Files, comes to my mind.1 Almost thirty years have gone since that episode first aired, but it has always been one of my favourites. The plot is fairly straightforward: the Central Operating System (a.k.a. the AI) of a software company develops both survival instinct and morbid care for its creator; killings ensues; Mulder and Scully manage to stop the evil technology. Or do they? As a teenager I loved the openness of The X-Files, always leaving room for unsolved dilemmas episode after episode. I also wanted to believe as Mulder did, but that is a different story.

Today it is not uncommon to laugh at the overtly pessimistic views of shows such as this, casting aside wrongly perceived assumptions with an indulgent smirk. Beside the fact that usually the characters who never doubt common sense are the first ones to die in these tales, this sort of cynicism reveals more than it conceals.

My firm belief is that the outcomes of and the concerns about the recent developments in artificial intelligence are nothing more than the inevitable consequence of the society we have built. We have been putting our faith in technology for so long by now that it is nearly impossible to look at it from a rather different perspective. The one who does so is generally ridiculed. This is even more interesting when we think about the distinction between science and technology and how we relate to them. Think of the pandemic. What COVID-deniers’ reactions highlighted is how easily we can criticise science for its shortcomings while at the same time relying on the technology that science itself made available for our rants to be out in the public.

Technology says as much of our times as fiction does. It mirrors points of view, it asks questions, and offers problems just as it looks for answers and tries to offer solutions. Like telling a story, developing a specific technology is an effort situated in a precise place at a particular time, and we can understand more of that time and that place if we read them through the stories and the technology that were born within their constraints.

However, we do not want to look at technology as we look at fiction, because we cannot believe technology to live in the realm of the uncertain, the implausible or the unreal. Technology is tangible, its immediate effects readily perceivable in our lives. Technology fixes problems, creates comfort, enables people to do things that seemed impossible. And yet, like fiction, this is a story told from a narrator who, like us, is a finite human being. A story makes sense when it ends, but we cannot make sense of our lives because we do not know when they will end and, just as well, we can never know the whole that constitutes other people’s lives. Being a finite product of finite beings, how do we make sense of technology then?

One possible answer, or at least the only answer I can think of, is critical thinking. We may never find reliable replies to metaphysical doubts, but we can still stop ourselves from mindlessly consuming technology and pause for a moment, a moment long enough to figure out whether the full impact of new technology is clear and understood. It is fairly obvious to me that this was not the case for mobile technology. Have we ever stopped to think about how a smartphone could change the life of a teenager? Do we not see what happened to the attention span of people after years of push notifications? My university has already issued a statement warning that papers will be proof read to avoid misuses of ChatGPT, which is telling of how little to zero thought has been put into the pivotal transformations artificial intelligence will bring upon us.

Lost in our market-driven technological bubble we please ourselves by being concerned about the dangers of AI during lunch breaks or between rounds of beer. I know we are still capable of critical thought, but I am not sure for how long we will be. I cannot help but think that the smarter technology becomes, the dumber end users might get.


  1. Along with Kill Switch from Season 5, yes, but only when I am in a deeply apocalyptic mood that usually drives me to watch The Terminator one more time. 

-1:-- Ghost in the Machine (Post)--L0--C0--June 03, 2023 12:00 AM

Andrea: FS2 vs ZIO streams with Ammonite: a syntax comparison

-1:-- FS2 vs ZIO streams with Ammonite: a syntax comparison (Post)--L0--C0--June 03, 2023 12:00 AM

Michal Sapka: Literate configuration of Elfeed

Recently I’ve been toying with a literate configuration1 of Emacs. My init.el took a straightforward form: 1 (org-babel-load-file "~/.emacs.d/config.org") And all of my configuration lives in an org-file. This alone gives me very little benefit for now, but in the future, it will make it easier to have it as a dedicated page on this site. However, one thing completely surprised me: the elfeed configuration. Until now, I used the standard way of configuring feeds with Elisp.
-1:-- Literate configuration of Elfeed (Post)--L0--C0--June 02, 2023 08:26 PM

Irreal: Org Remark

If you’re the type of person who likes to annotate files but keep your notes external to the file itself, you may be interested in nobiot’s org-remark. There are a couple of videos [1, 2] that show how it works and some of the features. There’s also a user manual that describes its features and how to use them in detail.

The TL;DR is that you simply select some text and org-remark highlights it and opens a separate window in which you can make notes. You can also open existing notes corresponding to an already highlighted area. There are different colored “pens” available for highlighting text and you can define others if you need them.

All of this is demonstrated in the videos and explained in the users manual so take a look if you’re interested. I have no need for this capability but lots of people do. If you’re one of them, take at look org-remark. It’s available from the GNU ELPA repository or, if you’re adventurous, the GNU-devel ELPA repository for the development releases.

-1:-- Org Remark (Post jcs)--L0--C0--June 02, 2023 07:10 PM

Tory Anderson: Why does straight sometimes rebuild org?

The problem: rebulding packages This was discussed in an issue on straight1 With the notorious orgmode updates and breakages, combined with the amount that I depend upon orgmode, I am trying to just stick with the built in version and not ever build it. As such, my Straight orgmode invocation looks like this: (use-package org :straight (:type built-in) Nonetheless, some packages seem to cause org to “build” and use a straight version.
-1:-- Why does straight sometimes rebuild org? (Post)--L0--C0--June 02, 2023 12:00 AM

Lambda Land: Warp Factor Refactoring in Emacs

Here’s a nifty Emacs workflow for doing a project-wide search-and-replace on steroids. While I do use refactor tools that come with language servers,1 sometimes those aren’t enough. Consider the case where you not only need to change the name of a function, but also e.g. need to swap the order of two of its arguments. Or you’ve broken one function out into two that need to be chained together. Whatever—there are plenty of ways where the IDE won’t be able to do everything that you need.
-1:-- Warp Factor Refactoring in Emacs (Post)--L0--C0--June 01, 2023 12:00 AM

Irreal: The Emacs Help System

Over at the Emacs Elements Channel there’s another useful video up. This time it’s about the Emacs Help system. The majority of experienced Emacs users will already be familiar with most of the material but if you’re a learn-as-you-go user, there may be some information new to you.

The first thing is that Ctrl+h Ctrl+h will show you a list of all the help commands. If you’re like me, you know this but always forget it when you’re trying to remember a help command. There are a lot more commands then the ones you use everyday so it’s worth your while to type Ctrl+h Ctrl+h to see what’s available.

For example, I’d completely forgotten about Ctrl+H w to discover the shortcut for a given command. My usual procedure is to bring up the documentation for the command and get the information there but I’m going to try to remember to use Ctrl+h w instead.

Another thing that I learned from the video is the difference between scrolling up and down with Space and Delete versus the <PgUp> and <PgDn> keys. I’ll let you watch the video to see what that difference is.

The video is 14 minutes 52 seconds long so it shouldn’t be too hard to find time but you may have to plan ahead.

-1:-- The Emacs Help System (Post jcs)--L0--C0--May 31, 2023 04:10 PM

Irreal: PSA: Elisp Has Builtin Threading Macros

I’ve written about Clojure’s threading macros and their implementation in Elisp before [1, 2, 3, 4, 5]. I like them but almost always use the traditional composition of functions instead. That’s probably because being a mathematician it seems natural to me. Still, the threading macros are easier to read and understand.

Most people who care about such things know about Magnar Sveen’s implementation of these macros in his Dash library. They have the advantage of using the same names, ->, ->>, etc. as clojure. Of course, you have to install Dash to use them. That’s not much of a problem because so many packages use Dash that it’s probably already installed.

But what if you don’t want the dependency? It turns out that Elisp has the most important of these macros built in and has since at least Emacs 25. The first, thread-first corresponds to -> and the second, thread-last, corresponds to ->>. They live in the sub-x.el file if you want to check out there definition.

Ruslan Bekenev has a page that explains all this and even gives a short explanation of how to use the macros. If you’re interested in the threading macros, take a look at his post.

-1:-- PSA: Elisp Has Builtin Threading Macros (Post jcs)--L0--C0--May 30, 2023 05:42 PM

Ryan Rix: Making my NixOS system deploys as simple as possible with Morph, a hosts.toml file, and my Morph Command Wrapper Nix

Making my NixOS system deploys as simple as possible with Morph, a hosts.toml file, and my Morph Command Wrapper Nix

This weekend I tried setting up deploy-rs, and it and flakes are kind of not very good for what I am doing with my computers.

I spent some time today doing a think that I have wanted to do for a while, moving my "network topology" in to a data file which can be ingested by the tools themselves rather than declaring them in code.

This starts with defining a hosts.toml file whose topology maps more-or-less to the one that Morph uses; a network is a deployment entity which can have any number of hosts in it:

[endpoints]
description = "my laptops and desktop"
enableRollback = true
config = "../roles/endpoint"

[endpoints.hosts.rose-quine]
# target = "rose-quine"
# stateVersion = "23.05"
# user = "rrix"

There are reasonable defaults in the host configurations so that adding a new host is a single-line operation in the hosts.toml file.

With that file in place, Deploying from my hosts.toml defines a function that ingests the networks and spits out a Nix attrset in the shape that Morph wants to execute:

let
  pkgs = import <nixpkgs> {};
  allNetworks = pkgs.lib.importTOML ./hosts.toml;
  mkNetwork = import ./mkNetwork.nix { inherit pkgs; networks = allNetworks; };
in mkNetwork "endpoints"

and from there i could say morph build $file_defined_above and it would go off and do that. then another invocation of morph deploy with a grab-bag of arguments would actually roll the system out to the host.

Taking things a step further is fun though. Why not make a simple wrapper that can make this easier? Morph Command Wrapper does that and allows me to just type deploy to run a change out to the host i'm sitting at, or deploy -b to just build it, or deploy --all to run it out everywhere.

Invoking deploy-targets will print out a list of all the hosts that the system knows about, which can then be conveniently fed in to completing-read

(->> (shell-command-to-string "deploy-targets")
     (s-split "\n")
     (append '("--all"))
     (completing-read "Which host do you want to deploy to? "))

And that can be used by the interactive emacs function arroyo-flood to automatically tangle the systems' org-mode role files, dynamically extracting a list of server, laptop, desktop, etc, modules from a sqlite cache along the way, and then deploying those! I'm pretty happy with this.

-1:-- Making my NixOS system deploys as simple as
possible with Morph, a hosts.toml file, and my Morph Command Wrapper
Nix (Post)--L0--C0--May 30, 2023 06:40 AM

Protesilaos Stavrou: Emacs: modus-themes version 4.2.0

I just published the latest stable release of the Modus themes. The change log entry is reproduced further below. It is a long read. For any questions, feel welcome to contact me.

I will soon install the changes in emacs.git so please wait a little longer for the updates to trickle down to you.


I won a Google award for the Modus themes

Report here: https://protesilaos.com/codelog/2023-05-25-emacs-google-award/.

This is not a “change” per se, but it is worth documenting here. It shows how important accessibility can be in empowering people to use their computer and, in our case, to exercise their software freedoms.

The Modus themes tend to one aspect of accessibility. They do not exhaust the topic, though they should at least raise awareness about the significance of tending to the usability needs of everyone. The effort I put into documenting the themes (and my other packages) should be understood in this light as a means of helping people enjoy their software freedom by learning how to use and extend the program in question.

New tritanopia-optimised themes

I have created a pair of light and dark themes that are intended for people with blue-yellow colour deficiency (tritanopia). These are modus-operandi-tritanopia (light) and modus-vivendi-tritanopia (dark). Screenshots of all the Modus themes are available on my website: https://protesilaos.com/emacs/modus-themes-pictures.

The entire collection is now described in the manual as follows:

The Modus themes consist of eight themes, divided into four subgroups.

  • Main themes: modus-operandi is the project’s main light theme, while modus-vivendi is its dark counterpart. These two themes are part of the project since its inception. They are designed to cover a broad range of needs and are, in the opinion of the author, the reference for what a highly legible “default” theme should look like.

  • Tinted themes: modus-operandi-tinted and modus-vivendi-tinted are variants of the two main themes. They slightly tone down the intensity of the background and provide a bit more color variety. modus-operandi-tinted has a set of base tones that are shades of light ochre (earthly colors), while modus-vivendi-tinted gives a night sky impression.

  • Deuteranopia themes: modus-operandi-deuteranopia and its companion modus-vivendi-deuteranopia are optimized for users with red-green color deficiency. This means that they do not use red and green hues for color-coding purposes, such as for diff removed and added lines. Instead, they implement colors that are discernible by users with deueteranopia or deuteranomaly (mostly yellow and blue hues).

  • Tritanopia themes: modus-operandi-tritanopia and its counterpart modus-vivendi-tritanopia are optimized for users with blue-yellow color deficiency. The idea is the same as with the deuteranopia variants: color coding relies only on hues that are accessible to people with tritanopia or tritanomaly, namely, shades of red and cyan.

Recalibrated the “graph” colours in all themes

The new palette subset improves the contrast of all the relevant colours when presented side-by-side. These are most notably used by the org-habit consistency graph, which is displayed in the Org agenda. The deuteranopia and tritanopia themes have their own bespoke colours for this purpose, due to their specific requirements for colour coding (e.g. they cannot use green).

Faces or face groups

  • Introduced a subtle 3D effect for clickable buttons, replacing the previous 2D design. I realised the flat style creates ambiguity between the button and the text fields. This happens, for example, with M-x customize-variable for org-capture-templates which has lots of button and text field combinations. The added sense of depth helps with the usability of these buttons because it makes them unambiguous. Personally, I prefer the 2D approach, but here we have a trade-off between usability and aesthetics. According to what I state in the manual:

    If there arises an inescapable trade-off between usability and stylistic considerations, we will always opt for the former.

  • Refashioned the whitespace-mode to be much more subtle and added the concomitant semantic colour mappings.

    The previous style involved the use of a dim grey background for each invisible character. While this is was good to spot invisible characters quickly, it was a major hindrance for users who want to run whitespace-mode at all times (e.g. for the Python programming language which is space-sensitive).

    We thus remove the backgrounds by default but provide the option to reinstate them via palette overrides (as documented at length in the manual). To this end, we have two new semantic colour mappings for ordinary space, its invisible characters, as well as space errors.

    Thanks to Christian Tietze and Oliver Epper for their feedback in issue 80 on the GitHub mirror: https://github.com/protesilaos/modus-themes/issues/80.

  • Applied a more subtle background for faces menu-bar-mode, tool-bar-mode, scroll-bar-mode. They do not need to stand out so much because the toolkit already takes care of that. Also, we do not want to dillute the semantic value of either bg-tab-bar or fringe palette colour mappings that I was wrongly using before in this context. Note that those faces may not apply, depending on the underlying tool kit. For example, I encounter them with the Lucid build of Emacs, though not with the GTK one.

  • Fix the critical typo of ‘widget-buton’, which prevented the actual widget-button face from being affected by the themes. Thanks to Steve Downey for pointing it out in issue 73 on the GitHub mirror: https://github.com/protesilaos/modus-themes/issues/73.

  • Added support for the disk-usage package. It is made to look like Dired, to the extent possible. Thanks to Nacho Barrientos for the patch: https://lists.sr.ht/~protesilaos/modus-themes/patches/39822. The change is small and does not require copyright assignment to the Free Software Foundation.

  • Made the eglot-diagnostic-tag-unnecessary-face look like a warning. By default it inherits the shadow face, which makes it counter-intuitive as it dims the text instead of bringing it to our attention. The intent of eglot-diagnostic-tag-unnecessary-face is to highlight unused symbols, so this is better presented as a warning.

    Thanks to Augusto Stoffel for bringing this matter to my attention. This was done via a private channel and the information is shared with permission.

  • Changed the smerge-markers to inherit from diff-header instead of diff-heading. Thanks to Steve Downey for the contribution. This was done in pull request 74 on the GitHub mirror: https://github.com/protesilaos/modus-themes/pull/74. The change is small and does not require copyright assignment to the Free Software Foundation.

  • Added support for the jinx package. This was originally done by Tomasz Hołubowicz in pull request 71 on the GitHub mirror: https://github.com/protesilaos/modus-themes/pull/71. The change is small and does not require copyright assignment to the Free Software Foundation. I then modified it to make the underlines look like warnings instead of errors. This is because of how the package works: it automatically highlights misspellings in the visible portion of the buffer. There are cases where this results in a very intense presentation, which can be distracting. We want to reduce the overall intensity and not draw too much attention to those highlights.

  • Extended coverage of Org to the new org-agenda-calendar-daterange face (part of Org version 9.7). Thanks to Gautier Ponsinet for the patch, which I received via a private channel. The change is small and does not require copyright assignment to the Free Software Foundation. In addition to this, I introduced a new semantic colour mapping in the themes’ palette called date-range. This can be used with the palette overrides, which are documented at length in the manual (there are lots of copy-pastable examples as well).

  • Supported all of the new faces of the built-in proced package. These are part of Emacs 29 and make the proced buffers more colourful, subject to the user option proced-enable-color-flag. As always, the themes strive to avoid exaggerations, meaning that I apply colour with restraint: not all faces need to stand out.

  • Included the rst-mode in the list of explicitly supported packages, making its heading look like those of Org, Markdown, etc. Thanks to David Edmondson for the patch: https://lists.sr.ht/~protesilaos/modus-themes/patches/40625. I believe David has already assigned copyright to the Free Software Foundation, though this patch is small anyway.

  • Covered all the new faces of the built-in flymake package. These concern the inline feedback messages (Emacs 30) as well as those that appear in the echo area (Emacs 29). The former are subject to the user option flymake-show-diagnostics-at-end-of-line.

  • Reduced the intensity of the which-key prefix descriptions. Those are the keymaps that displayed by which-key to hint that typing the given key will open a new which-key page with more keys.

  • Configured new vundo-saved and vundo-last-saved faces of the vundo package. They are designed to be easy to read, without going over-the-top. Thanks to Nicolas Semrau for bringing this matter to my attention in issue 79 on the GitHub mirror: https://github.com/protesilaos/modus-themes/issues/79.

  • Removed the deprecated consult-preview-cursor face and made the requisite adjustments to the consult faces. This was done in commit 267b0c9 of the Consult Git repository. Discussed here: https://github.com/minad/consult/issues/764#issuecomment-1537491625.

  • Instructed the shr-selected-link face of the built-in shr package to use a “mark selection” style instead of the semantically incorrect “intense red” it had before. This change is helpful for those who override the palette of their Modus theme of choice, while it also allows us to have varied colours depending on the requirements of each theme (e.g. deuteranopia/tritanopia compared to the defaults).

  • Did the same as above, mutatis mutandis, for the faces transient-disabled-suffix, web-mode-error-face, erc-dangerous-host-face, aw-minibuffer-leading-char-face, binder-sidebar-highlight, binder-sidebar-missing, image-dired-thumb-flagged, image-dired-thumb-mark, info-menu-star, rainbow-delimiters-mismatched-face, evil-ex-substitute-matches, iedit-occurrence, iedit-read-only-occurrence, pgtk-im-0, dired-narrow-blink.

  • Enhanced the image-dired mark faces with a box border, as the use of a background alone can be obscured by the underlying image thumbnail, depending on its figures/colours.

  • Removed the backgrounds from the powerline-evil faces and simplified their overral presentation in the interest of maintainability. The old styles were hard to predict and test. There could easily be conflicts, such as if the user would override the colours of the mode line.

  • Ensured that diary and holiday colours are distinct and legible, without being too intense.

Changes to the manual or other documentation

  • Updated the doc string of the primary customisation group defined by the themes to reflect the support for the case of tritanopia.

  • Included links to the web page of the manual and the one with the sample pictures in the customisation groups. Those links appear in the various Custom UI buffers.

  • Introduced an annotation function for all commands that involve minibuffer completion. The annotations display the one-line description of each theme, making it easier for a user to pick their preferred choice (e.g. when using the modus-themes-select command).

  • Defined semantic colour mappings for “marks”. These are used by dired, trashed, proced, and others. These is no change to the default appearance of what users are already familiar with, though it is now possible to override those styles.

  • Complemented the subset of semantic colour mappings for errors/warnings with “prominent” variants. Those employ a background and foreground combination. They are used in all sorts of contexts, such as for fringe errors (flymake, flycheck, …), query-replace, isearch-fail, and others.

  • Wrote sample code on how to add “padding” to the Emacs frame and the space between the Emacs windows. This makes for a presentation that some users find easier to work with.

  • Corrected the sample code for git-gutter to use the appropriate symbols from the theme palette. Thanks to Christian Tietze for the patch: https://lists.sr.ht/~protesilaos/modus-themes/patches/40354. The change is small and does not require copyright assignment to the Free Software Foundation.

  • Removed moody from the list of packages explicitly supported by the themes. We stopped supporting it since version 4 that removed the relevant user option for the mode line. The idea is that the mode line is better handled by the user without interference from the theme, due to the number of options available (and how brittle those can be when interacting with unpredictable face definitions). Thanks to Nicolas De Jaeghere for reminding me to remove moody from the manual: https://lists.sr.ht/~protesilaos/modus-themes/%3Cypi9jzyclqxy.fsf%40gmail.com%3E#%3C87jzybdgg1.fsf@dejaeghe.re%3E.

Miscellaneous

  • Added two new preset palette overrides to make the overall presentation “warmer” or “cooler”. Those are called modus-themes-preset-overrides-warmer and modus-themes-preset-overrides-cooler, respectively. The manual explains how those presets can be used. I suggest the user does not add such overrides if they intend to load any of the deuteranopia or tritanopia themes, due to the specific requirements of their design.

  • Refined the deuteranopia yellows for warnings, errors, and comments. These otherwise slight adjustments make it considerably easier to tell apart distinct elements that may be positioned close together.

  • Tweaked the deuteranopia semantic colour mappings for emails. The subject line use a more appropriate colour value, while level 3 quotes stand out a bit more than they did before, without being needlessly intense.

  • Arranged for the modus-themes-load-theme function return the value of the THEME argument it accepts. The intent is to allow other functions that call this one to capture the return value for their purposes (such as with a let binding). Thank to Oliver Epper for the feedback in issue 78 on the GitHub mirror: https://github.com/protesilaos/modus-themes/issues/78.

-1:-- Emacs: modus-themes version 4.2.0 (Post)--L0--C0--May 30, 2023 12:00 AM

Irreal: Elfeed-webkit Update

The other day I wrote about installing elfeed-webkit to render my RSS feed as proper HTML. I was pretty impressed with it when I first tried it and now I’m even more of a fan. Before elfeed-webkit, I spent a lot of time switching between Elfeed and Safari so that I could read interesting posts that came up in the feed. It doesn’t seem like it would take that much time but since the change, my RSS workflow seems faster and easier.

A secondary advantage is that Emacs has more functionality now that I have XWidgets enabled. At first I wondered if I could get eww to do a better job rendering sites by using Webkit. That turned out to be a bust but I did discover xwidget-webkit-broswse-url that will render a site in decent HTML but it’s not a proper Browser so it’s pretty much restricted to viewing a specific URL. You can follow links and control videos but there are no bookmarks, content filtering, or other Browser amenities. Still, it does help keep me in Emacs and a lot of times I just want to visit a page from Emacs and it works perfectly for that.

In my original post, I noted a couple of problems. The first was the possibility of being inundated with ads because of the lack of content filtering. That’s basically a nonissue for the sites I read although occasionally a feed item will send me off to a “commercial” site that does have a lot of intrusive pop-up adds but it doesn’t happen often.

The second problem was that I couldn’t get t to toggle elfeed-webkit on and off. I thought maybe something else was grabbing the t binding to I changed it to w but that didn’t work either. I solved that by binding a global key to toggle elfeed-webkit and that worked fine (but see below).

Finally, I recently upgraded my email client mu/mu4e and a helper function I wrote to display the post in eww stopped working. While investigating that, I discovered that mu4e will display an email with webkit, which is what I really want so I’m now using that instead of eww.

While investigating the email issue I discovered that the XWidget library does indeed capture the t key as well as the w key. The t doesn’t appear to do anything useful as its definition

(define-key map "t" (lambda () (interactive) (message "o"))) ;FIXME: ?!?

shows. I don’t know how it was working for Grabo; perhaps he’s using the Emacs 29 pretest and it has removed the useless binding. In any event, I simple changed my toggle key to x and now it works perfectly.

That leaves only one small problem. One of the sites I follow, Daring Fireball, has the unusual property that its RSS URL is not the site itself but the site it’s linking to. That means that I miss the Daring Fireball commentary and go straight to the linked site. I’m considering adding code to implement a tag that inhibits rather than enables elfeed-webkit. In the meantime, I’m simply toggling elfeed-webkit off when I get to a Daring Fireball post.

All in all, I’m really happy with elfeed-webkit and recommend it wholeheartedly.

-1:-- Elfeed-webkit Update (Post jcs)--L0--C0--May 29, 2023 05:09 PM

Sacha Chua: 2023-05-29 Emacs news

Links from reddit.com/r/emacs, r/orgmode, r/spacemacs, r/planetemacs, Hacker News, lobste.rs, lemmy, planet.emacslife.com, YouTube, the Emacs NEWS file, Emacs Calendar, and emacs-devel. Thanks to Andrés Ramírez for emacs-devel links. Do you have an Emacs-related link or announcement? Please e-mail me at sacha@sachachua.com. Thank you!

-1:-- 2023-05-29 Emacs news (Post Sacha Chua)--L0--C0--May 29, 2023 01:44 PM

James Dyer: Insert Unique Log Message

I had tried to implement a debugging logging/print method myself using macros but hadn’t really achieved the level of elegance outlined in https://xenodium.com/sprinkle-me-logs/

I added a couple of programming modes to the function defined in the post above and have now incorporated it into my workflow:

((equal major-mode 'ada-mode)
  (cons (format "Ada.Text_Io.Put_Line (\"%s: \\([0-9]+\\)\");" word)
    (format "Ada.Text_Io.Put_Line (\"%s: %%s\");" word)))
((equal major-mode 'c++-mode)
  (cons (format "std::cout << \"%s: \\([0-9]+\\)\" << std::endl;" word)
    (format "std::cout << \"%s: %%s\" << std::endl;" word)))

For some reason I always seem to tend to ribald statements within my code, something like poop or some other unsavoury variant, I just need to remember to tidy these up later on!

Oh and I added an old fashioned emacs badge to the top of this blog just for fun! as technically it is kinda true as in this web page and of course as in me as a human 😀

-1:-- Insert Unique Log Message (Post James Dyer)--L0--C0--May 29, 2023 11:00 AM

Protesilaos Stavrou: Emacs: Denote can now automatically rename its buffers

I am working towards the next major release of denote. There already are lots of goodies in the works. A new one among them is the global minor mode denote-rename-buffer-mode. It automatically renames the buffer of a Denote file upon visiting the file. A buffer is renamed only when visiting the underlying file. This means that existing buffers are not renamed until they are visited again in a new buffer (files are visited with the command find-file or related).

For example, I enable the mode and then visit a file whose name is 20230507T084817--software-freedom-and-accessibility__linux_politics.txt. Normally, that would also be the name of the buffer. Whereas now the buffer is called Software freedom and accessibility.

[ If you are unfamiliar with Denote, consult the comprehensive manual or at least watch the video demo I did of its original version. Links below. ]

Customize the user option denote-rename-buffer-function to affect how buffers are renamed. Its value must be the symbol of a function. The default is the denote-rename-buffer-with-title, with an alternative of denote-rename-buffer-with-identifier.

The user option also accepts an arbitrary function. Refer to the implementation details of denote-rename-buffer-with-title or denote-rename-buffer-with-identifier for guidance on how to write a custom function.

Note that renaming a buffer is not the same as renaming a file (Denote can do both). The former is just for ease-of-use inside of Emacs. Whereas the latter is for writing changes to disk, making them available to all programs.

I don’t know when I will be able to release version 2.0.0. Hopefully soon.


Denote is a simple note-taking tool for Emacs. It is based on the idea that notes should follow a predictable and descriptive file-naming scheme. The file name must offer a clear indication of what the note is about, without reference to any other metadata. Denote basically streamlines the creation of such files while providing facilities to link between them.

Denote’s file-naming scheme is not limited to “notes”. It can be used for all types of file, including those that are not editable in Emacs, such as videos. Naming files in a consistent way makes their filtering and retrieval considerably easier. Denote provides relevant facilities to rename files, regardless of file type.

-1:-- Emacs: Denote can now automatically rename its buffers (Post)--L0--C0--May 29, 2023 12:00 AM

Irreal: Org Blk URI

Just a quickie. I stumbled across a post from Andrea that describes his package Org Blk URI. It’s pretty simple: it’s just a way of extracting the content at a URL into an Org source block.

That’s handy for capturing Web content that is apt to be ephemeral. The example Andrea gives is a job ad and, of course, we’ve all run across Web pages that might not remain available but that we’d like to retain. This package is a nice way of capturing them into an Org file that we control.

I haven’t installed yet but it seems like a handy tool to have.

-1:-- Org Blk URI (Post jcs)--L0--C0--May 28, 2023 03:56 PM

Ruslan Bekenev: Emacs has built-in thread macros

Intro

Surprisingly for me I just discovered that Emacs Lisp has equivalent of Clojure’s -> and ->> macros.

And I’m not talking about dash.el. I’m talking about built-in thread-first and thread-last.

What are these

If you’re not familiar with these beautiful macros, the main goal is to pipe a value through multiple functions and return the result.

-> passes a value as first argument of next function, then takes the result and passes it as first argument to next function, etc.
->> does the same except that it passes the result as next function’s last argument

Example

Instead of having this:

(+ (- (/ (+ 5 20) 25)) 40)

we can have this:

(->
  5
  (+ 20)
  (/ 25)
  -
  (+ 40))

It’s way easier to modify and which is even more important - to read.

Emacs lisp equivalent

There is dash.el library that provides us with similar macros (and many more) but emacs has built-in thread-first and thread-last.

(thread-first
  5
  (+ 20)
  (/ 25)
  -
  (+ 40))

will work for you if you’re on Emacs 25 or newer.

I don’t write much elisp but every time I do I feel like I miss those ->/->>.

Not anymore!

-1:-- Emacs has built-in thread macros (Post)--L0--C0--May 28, 2023 12:00 AM

Mickey Petersen: How to Get Started with Tree-Sitter

The next version of Emacs is around the corner, so I think it’s time to talk about how you can start using one of the more impressive additions to Emacs 29: tree-sitter. Briefly, tree-sitter is a library that transforms source code – or any other structured text, like Markdown – into a concrete syntax tree. I’ve written about tree sitter and the complications of parsing languages and why it’s a big deal: correct syntax highlighting; cleverer editing and movement; and better indentation are just some of the benefits of tree-sitter.

And in Emacs 29, support for tree-sitter is built in. Sort of. It’s an optional extra, so you must compile Emacs from source, or hope that someone else will do it for you. In my experience, unless you’re using a bleeding-edge Linux distribution, you’re in for quite a wait. So I’ve compiled a guide on how to get started with tree-sitter in Emacs: not just the compilation, but how to get started using it. You see, getting everything to work properly is a bit more involved than just compiling Emacs with tree-sitter support.

My package, Combobulate, adds advanced editing and movement using tree-sitter. This is Combobulate's expand region feature, bound to M-h.

Despite the high activation cost of getting tree-sitter up and running, I firmly believe it’s worth it. Here’s what you’ll need to do to get it set up.

Building Emacs with Tree-Sitter Support

Note that these compilation instructions cover Linux, and use Ubuntu/Debian as the example distribution. Tree-sitter will also work on other platforms, like Microsoft Windows. For compiling or installing the grammars on more platforms than just Linux, see below.

  1. Grab the latest Emacs sources from Savannah, Emacs’s official git repo. Once Emacs 29 is out you can use the official tarballs instead, but for now I recommend you check out the emacs-29 branch, or just master if you’re OK with living life on the bleeding edge. I always use master:

    $ git clone https://git.savannah.gnu.org/git/emacs.git -b emacs-29
  2. Next, you’ll need to install the prerequisites required for Emacs to compile. With Debian/Ubuntu-based systems, that is easy, as you can rely on apt-get build-deps to do the heavy lifting by having it install the dependencies for one of the Emacs versions it your distro does support.

    Building Emacs is not hard, and the simplest way to do this is to follow my existing guide where I detail how to do all of this, step-by-step, to get native compilation working:

    Speed up Emacs with libjansson and native elisp compilation

    If you’ve never bothered with native compilation, you should: it provides a significant speed boost. You may as well build Emacs with it also.

    I would urge you to get this step working first: we’ll amend it slightly to add tree-sitter support (and other optional goodies) next. The approach outlined in that article is the barebones version of Emacs, but once you get it building on your system, you can easily recompile Emacs from scratch with additional features, as needed.

  3. Next, you’ll need to check out tree-sitter’s source code:

    $ git clone git@github.com:tree-sitter/tree-sitter.git

    I, once again, stick to the master branch, but you can use a tagged release if you prefer a stable release.

    Your distro may already include tree-sitter as a package, as in the case of Debian:

    $ sudo apt-get install libtree-sitter-dev

    That is occasionally enough to install tree-sitter so it works with Emacs. However, given how easy tree-sitter is to install, having no real depencies of its own, and it being a rather fast-moving project, I recommend you just build it from source also.

  4. Time to build tree-sitter. Provided your Emacs builds, so should tree-sitter:

    $ cd tree-sitter/
    $ make
    $ make install

    That is all it takes. Note that make install normally requires root. It’ll install a shared library to (usually) /usr/local/lib.

    In theory, that’s all it takes for Emacs to compile with tree-sitter support. However, if Emacs complains during the build that it can’t find the shared library libtree-sitter.so, try this:

    $ export LD_LIBRARY_PATH=/usr/local/lib/

    And retry building Emacs.

  5. Now you can start building Emacs with tree-sitter. I’ll assume you followed my other tutorial and you’re now at a point where Emacs builds (without) tree-sitter. Now all you need to do is add --with-tree-sitter (technically, it should detect tree-sitter automatically, but I prefer being explicit) to the call to ./configure:

    ./configure --with-tree-sitter --with-native-compilation ... CC=gcc-10

    Now run make then make install. Everything should build and link and you’ll wind up with your own build of Emacs.

That takes care of Emacs. Unfortunately, that is not enough to reap the benefits of tree-sitter. We’ll have to install some language grammars also.

Installing the Language Grammars

Neither tree-sitter nor Emacs come installed with language grammars. Just like kids’ toys and batteries, they’re sold separately. So you’re required to download and compile the sources for each language grammar you want to use.

You must compile each language into a shared library and put in a place where tree-sitter can find them. It is not especially hard to do so, but it can be a frustrating experience as it’ll depend on: your platform; your choice of compilers; whether the grammar author chose C++ or just C, and so on. Furthermore, there is often no Makefile, so you have to tell the compiler yourself to build a shared library.

Luckily, there are two simpler ways than the manual way: the builtin method in Emacs, or relying on the kindness of strangers.

Before I explain both methods, I must point out that, at the end of the day, regardless of the method you choose – and especially if you’re compiling the grammars yourself – that you must put them in a directory where Emacs and tree-sitter can find them:

  1. Emacs will look in treesit-extra-load-path if you have it set;
  2. Then, in a subdirectory called tree-sitter under user-emacs-directory — e.g., ~/.emacs.d/tree-sitter/.
  3. And finally it’ll look in all the usual /lib locations scattered around your filesystem.

I prefer the Emacs directory approach myself. The grammars are small and, unless you make it a habit to swap between wildly different system architectures, you can safely commit the shared libraries to git and lug ’em around with you.

Anyway. Let’s install the grammar libraries. Onwards!

Compiling and Installing with the builtin method in Emacs

This is perhaps the simplest, but it’ll only work if you don’t have an exceptional setup (so it won’t work well unless you have GCC and run some flavor of Linux.) But if your Linux installation’s plain as day, expect this method to work fine if you successfully compiled Emacs and tree-sitter from scratch.

The command M-x treesit-install-language-grammar installs a language grammar by first cloning the git repo hosting it and then compiling it and storing the shared library in your .emacs.d directory.

In order to determine where – and what – it can install, you must first tell Emacs where to find the language grammars. The variable treesit-language-source-alist is a simple alist that expects a form in the format of (LANG . (URL REVISION SOURCE-DIR CC C++)). Where only LANG and URL are mandatory. Leave out the rest and Emacs will try to do the right thing. It is not customizable using the Customize interface, unfortunately, so you must set and edit it manually.

Here’s an example:

(setq treesit-language-source-alist
   '((bash "https://github.com/tree-sitter/tree-sitter-bash")
     (cmake "https://github.com/uyha/tree-sitter-cmake")
     (css "https://github.com/tree-sitter/tree-sitter-css")
     (elisp "https://github.com/Wilfred/tree-sitter-elisp")
     (go "https://github.com/tree-sitter/tree-sitter-go")
     (html "https://github.com/tree-sitter/tree-sitter-html")
     (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
     (json "https://github.com/tree-sitter/tree-sitter-json")
     (make "https://github.com/alemuller/tree-sitter-make")
     (markdown "https://github.com/ikatyang/tree-sitter-markdown")
     (python "https://github.com/tree-sitter/tree-sitter-python")
     (toml "https://github.com/tree-sitter/tree-sitter-toml")
     (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
     (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
     (yaml "https://github.com/ikatyang/tree-sitter-yaml")))

As you can see, there’s not much to it. A couple of the languages require a little path and branch fiddling as their directory structure differ from the accepted standard.

Once you’ve found the languages you like, you’ll need to install them. Call the command M-x treesit-install-language-grammar for each language and that’s usually all there is to it.

If that’s too much manual work, just bulk install all of ’em in one go. Evaluate this elisp form to do so:

(mapc #'treesit-install-language-grammar (mapcar #'car treesit-language-source-alist))

It can happen that LANGUAGE is named differently than the shared library. In the unlikely event that happens you can use treesit-load-name-override-list. You’re more likely to encounter this if you’re using competing grammars for the same language, or if the name does not match the shared library name.

Every language has a function entry point named tree_sitter_<LANGUAGE> in the library, and if the <LANGUAGE> does not match up with the filename (usually libtree-sitter-<LANGUAGE>.so), Emacs won’t load the module. This is not the case with the example I gave above, but you may run into it if you’re using niche language grammars or if you want multiple ones serving the same language (for some reason.)

Here is what that could look like:

(setq treesit-load-name-override-list '((js "libtree-sitter-js" "tree_sitter_javascript")))

Using pre-compiled language grammars

Before Emacs 29 added tree-sitter support, Tuấn-Anh Nguyễn created a third-party tree-sitter package that adds tree-sitter based font locking and support for tree-sitter in all modern versions of Emacs. It’s excellent, though it has a number of limitations (mostly due to Emacs’s dynamic module system more than anything else.) But if you want tree-sitter support in older Emacsen, you should check it out. It’s a MELPA package install away and it pretty much works out of the box.

Nevertheless, Tuấn-Anh also took the time to build a CI release system that tracks a large portion of the most common language grammars — complete with builds for Windows, Mac and various Linux architectures. Really superb work.

So if you’re on Windows or if you find the idea of building the grammars cumbersome, you should give his precompiled packages a shot.

You can find them on his Github releases page. You can also download the tree-sitter-langs package from MELPA, but I recommend you just download the shared libs directly instead, as you’ll in any event have to rename them and place the grammar libraries somewhere else.

The names of the files are <LANGUAGE>.so (or with your platform’s equivalent extension) which is not in keeping with the expected naming style in Emacs. You must first rename them so they’re named libtree-sitter-<LANGUAGE>.so. This is as good a time as any to learn how to bulk rename them with Emacs’s M-x dired and the editable dired buffers feature.

Once they’re named appropriately, put them in the directory called tree-sitter in user-emacs-directory. Or pick another place for them, as per the search path order I wrote about earlier. But for most of us, putting them in ~/.emacs.d/tree-sitter is good enough.

Check if a grammar is working

Determining if a grammar is available is not intuitive nor obvious unless you use elisp. You must call the treesit-language-available-p function to check:

ELISP> (treesit-language-available-p 'python)
t
ELISP> (treesit-language-available-p 'klingon)
nil

Emacs will return t if it’s a known language and nil otherwise. Use this to check if you’ve compiled, installed or copied (all depending on the method you chose) the grammars correctly.

The other thing to keep in mind with the grammars is that they are not versioned! There is no version tags beyond the git commit hash to help you determine which version of the grammar you have. That’s mostly of interest to major mode developers or people like me that build structured editing and movement packages on top of tree-sitter. I recommend you reinstall the grammars every now again to keep up with changes, for package authors have no easy way of checking.

How to use Tree-Sitter

Yep. This part needs a tutorial introduction also. Emacs now implements a very different way of font locking (syntax highlighting) than most – though not all! – major modes in Emacs, as most of them use regular expressions to feed Emacs’s font lock engine with syntactic information. Now that it’s using an actual syntax tree to extract information, Emacs is a lot more accurate.

Because of the complete 180-degree turn in, well, almost everything, the Emacs developers decided against wedging tree-sitter support into the existing modes. Instead it’s relegated to its own, “TS”-powered, major modes. I understand why – some of the major modes are complex and naively cramming tree-sitter-powered features into them will require more longer-term engineering effort to sort out than they can currently muster – but it’s still, well, they’re different modes, with all the drawbacks and benefits that bring.

Modes that use tree-sitter are all named <major-mode>-ts-mode. That’s the naming standard and it does mean you can quickly check if Emacs supports your pet major mode out of the box: typing C-h a -ts-mode$ should do the trick. The apropos window will list all known tree-sitter major modes.

Note that, just because you have installed a grammar, does not mean Emacs supports it. Someone still has to write the – admittedly, way easier – syntax and indentation logic and all that good stuff.

One interesting outcome of tree-sitter support is that Emacs has now gained new major modes it did not have before. Like dockerfile-ts-mode.

So to use tree-sitter you must activate the new major mode manually. Emacs will, by default, use the existing major modes, even if you have everything set up correctly.

To coax Emacs into using the new major modes by default, you’ll have to either:

  1. Edit auto-mode-alist, interpreter-mode-alist, etc. and change over all the references you care about to use new <LANGUAGE>-ts-mode major modes; or…
  2. Use major-mode-remap-alist, an icky hack that maps one major mode symbol to another behind-the-scenes. That feature, rather conveniently, debuted in Emacs 29 also.

Hacky though I think it is, I’d pick the major-mode-remap-alist for now: it’s easy to get started with, and you can always migrate everything to the harder, and more explicit, way once you’re happy with your new tree-sitter-enabled major modes.

Here’s an example, and this time you can instead use M-x customize-option to customize it to your liking, if you prefer the customize interface.

(setq major-mode-remap-alist
 '((yaml-mode . yaml-ts-mode)
   (bash-mode . bash-ts-mode)
   (js2-mode . js-ts-mode)
   (typescript-mode . typescript-ts-mode)
   (json-mode . json-ts-mode)
   (css-mode . css-ts-mode)
   (python-mode . python-ts-mode)))

As you can see there’s not much to it. Whenever Emacs is asked to activate css-mode, it’ll instead call css-ts-mode.

Despite the major mode switcheroo gimmick, it does not remove most of the obstacles and annoyances of having a new major mode.

At this point, I’d try out some of the major modes you want to use. Annoyingly, there’s no easy way to see if you’re using the normal or the TS-powered major mode: you can look at the lighter in the mode line, but it’s often the same text as the normal mode. The quickest way to tell is to type M-: major-mode and you’ll see which major mode you’re using.

I’ve heard tales of the TS-powered major modes being “temporary”, but… there’s nothing so permanent like a temporary solution. I understand why the distinction has to exist (for now), but it’s still awkward, and this approach does leave a number of unsolved problems you’ll still have to solve yourself:

  1. You must duplicate and/or change your mode hooks. python-mode-hook is distinct from python-ts-mode-hook, and you should ensure you copy over your settings.
  2. Your indentation customizations (if you have them) may not work. Indeed, any customizations you’ve applied to one mode won’t necessarily apply. They might, but there’s no guarantee they will. It comes down to the mode and the feature.
  3. Font lock faces are now more detailed and expressive than ever before. This is one area you probably definitely will and want to customize, if only to take advantage of better syntax highlighting.
  4. Third-party packages will blithely assume you’re using the default major mode and not your turbo-charged tree-sitter equivalent, and so they may not activate or work at all in the TS-powered one. It’ll take a while for this distinction to percolate, and for packages to check for one or the other.
  5. Most TS-powered modes ‘derive’ from the original major mode, with varying levels of overlapping customizations and features. The best way to see what your new major mode can (or cannot) do is, uh, well.. to read the source. Sorry.

Nevertheless, it’s worth the pain, as you’ll only have to do it once.

Tweaking the Font Locking

One of the benefits of having a concrete syntax tree is precision. Emacs is now capable of precisely highlighting things it couldn’t before: it can distinguish function calls from keywords or identifiers. To better support that, there’s now a host of new font lock faces.

Due to the large array of things you can color, Emacs now separates its font locking into font lock features. This feature’s akin to the long-existing font-lock-maximum-decoration that the chromatically averse can tweak to disable some or all of Emacs’s coloring if it’s too ostentatious. If you belong to that cohort – most of whom refer to this as “angry fruit salad” – then you’re in for a technicolor razzle-dazzle.

Every TS-enabled major mode will decide on its own list of features. The features are buffer-local and set in treesit-font-lock-feature-list, with each sub-list representing a level of highlighting. If you want to change it, you’ll need a mode hook to alter it properly.

For most, it’s enough to change the font lock feature level. To do so, customize treesit-font-lock-level. Every incrementation of the level will color more and more things: one you reach the higher echelons, it does become a bit much, even for me. But it’s great to have that flexibility and the power to decide which things should, and which things should not, be highlighted.

NOTE: treesit-font-lock-level has a special setter attached to it, so as to automatically recompute the font lock features in all your buffers when you change the level. If you use Customize, then you don’t have to do anything, but if you normally use setq, you’ll have to use customize-set-variable instead to ensure the setter is called properly.

It’s worth experimenting with the font lock level: the default is conservative and in line with what Emacs normally font locks. This is one of the capstone features of tree-sitter, and you should absolutely tweak it to your liking. To go along with each feature is an equivalent font-lock-<feature>-face. You can list all the pertinent faces with M-x customize-apropos-faces RET ^font-lock-. It’s very likely your theme (or your own face customizations if you maintain your own faces, like I do) is missing these customizations, so be sure to check, as their defaults make everything look rather samey.

The general intent behind the level is that you set it once and you get – approximately – the same general style of font locking in all TS-powered modes. I think that intent holds up rather well, even though what gets font locked, and how, is up to each major mode author.

Inspecting the Tree-sitter tree

One benefit of tree-sitter is access to the live concrete syntax tree of your source code. You can inspect the tree in a buffer with M-x treesit-explore-mode and M-x treesit-inspect-mode. There’s a lot more you can do with it, so I recommend you consult the manual, or stay tuned for more in-depth articles on this topic here!

“Fixing” the S-Expression Commands

Emacs has had s-expression-based commands for decades. They’re bound to keys like C-M-f, C-M-SPC, and C-M-k.

They work well in a wide range of languages because they’re delightfully dumb: they look for structured expressions – such as ( and ), " and ", and so forth – and treat them as cohesive, syntactic ‘unit’. In the absence of such structured units, they fall back and behave much like word-based movement and editing.

Not so in tree-sitter major modes. They’ve been “upgraded” to try and guess the syntactic units you probably want to move over or edit.

That sounds like a great idea until you realize that it is not possible to make one-size-fits all commands that do this. Believe me: I’ve tried. Every language is different, and even a modest language grammar will have hundreds of node types and millions of combinations. Whereas before you could predict where point would end up after calling these commands, now you probably can’t. Worse, the commands do not mirror the old behavior at all: they’re erratic and unpredictable.

If you already use these commands, and you also dislike this unwanted and unasked for change in behavior, then you can use this snippet to revert to the old way:

(defun mp-remove-treesit-sexp-changes ()
  (when (eq forward-sexp-function #'treesit-forward-sexp)
    (setq forward-sexp-function nil))
  (when (eq transpose-sexps-function #'treesit-transpose-sexps)
    (setq transpose-sexps-function #'transpose-sexps-default-function))
  (when (eq forward-sentence-function #'treesit-forward-sentence)
    (setq forward-sentence-function #'forward-sentence-default-function)))

(add-hook 'prog-mode-hook #'mp-remove-treesit-sexp-changes)

Structured Editing and Movement

Combobulate can insert multiple cursors (if you use it); move around your code structurally; insert syntax-aware code templates; and much, much more.

One of the tantalizing things that a library like tree-sitter offers is better and more correct editing and movement that understands the syntax of your code. That’s one of the things my package Combobulate sets out to do: to provide advanced editing and movement across a swathe of languages.

Now that you’ve gotten tree-sitter working, why not take my Combobulate package for a spin? It’s a work-in-progress still, so expect bugs, but it’s got a host of useful features that’ll speed up your day-to-day coding.

-1:-- How to Get Started with Tree-Sitter (Post)--L0--C0--May 27, 2023 08:29 PM

Protesilaos Stavrou: Guix: spontaneous live stream today (2023-05-27) at 09:30 Europe/Athens time

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

I got a new laptop: Lenovo ThinkPad X470 (EDIT 2023-05-27 11:39 +0300: it’s T470, not X470). This is a gift from Anush V, to whom I am thankful. I will be using this device to experiment with Guix, a distro I have been following since ~2017 but never had the hardware to test it on. These will be my first impressions.

The video is recorded and can be viewed at any time. No worries if you cannot make it. I am posting this on 09:08 +0300.

-1:-- Guix: spontaneous live stream today (2023-05-27) at 09:30 Europe/Athens time (Post)--L0--C0--May 27, 2023 12:00 AM

Michal Sapka: Input Completion in Emacs

Emacs consists of a massive set of tools with a long history. Therefore, whatever the problem is, someone likely has already created a package for it. In many cases, this package is already baked in Emacs. This is great for veterans but very confusing to newcomers - like me. The three modes Emacs comes with three modes for input completion: Icomplete, IDO, and FIDO. Input completion works with whatever you select in the Minibuffer section.
-1:-- Input Completion in Emacs (Post)--L0--C0--May 26, 2023 07:10 PM

Alvaro Ramirez: Deleting from Emacs sequence vars

25 May 2023 Deleting from Emacs sequence vars

Adding hooks and setting variables is core to customizing Emacs. Take a major mode like emacs-lisp-mode as an example. To customize its behaviour, one may add a hook function to emacs-lisp-mode-hook, or if you're a little lazy while experimenting, you may even use a lambda.

(add-hook 'emacs-lisp-mode-hook
          #'my/emacs-lisp-mode-config)

(add-hook 'emacs-lisp-mode-hook
          (lambda ()
            (message  "I woz ere")))

emacs-lisp-mode-hook's content would subsequently look as follows:

'(my/emacs-lisp-mode-config
  (lambda nil
    (message  "I woz ere"))
  ert--activate-font-lock-keywords
  easy-escape-minor-mode
  lisp-extra-font-lock-global-mode)

Maybe my/emacs-lisp-mode-config didn't work out for us and we'd like to remove it. We can use remove-hook for that and evaluate something like:

(remove-hook 'emacs-lisp-mode-hook #'my/emacs-lisp-mode-config)

The lambda can be removed too, but you ought to be careful in using the same lambda body.

(remove-hook 'emacs-lisp-mode-hook
             (lambda ()
               (message  "I woz tere")))

There are other ways to remove the lambdas, but we're digressing here… We typically have to write these throwaway snippets to undo our experiments. What if we just had a handy helper always available to remove items from sequences (edit: we do, remove-hook is already interactive, see Update 2 below)? After all, hooks are just lists (sequences).

removed-lambda.gif

While the interactive command can likely be simplified further, I tried to optimize for ergonomic usage. For example, completing-read gives us a way narrow down whichever variable we'd like to modify as well as the item we'd like to remove. seqp is also handy, as we filter out noise by automatically removing any variable that's not a sequence.

(defun  ar/remove-from-list-variable ()
  (interactive)
  (let* ((var (intern
               (completing-read  "From variable: "
                                (let (symbols)
                                  (mapatoms
                                   (lambda (sym)
                                     (when (and (boundp sym)
                                                (seqp (symbol-value sym)))
                                       (push sym symbols))))
                                  symbols)  nil t)))
         (values (mapcar (lambda (item)
                           (setq item (prin1-to-string item))
                           (concat (truncate-string-to-width
                                    (nth 0 (split-string item  "\n"))
                                    (window-body-width))
                                   (propertize item 'invisible t)))
                         (symbol-value var)))
         (index (progn
                  (when (seq-empty-p values) (error  "Already empty"))
                  (seq-position values (completing-read  "Delete: " values nil t)))))
    (unless index (error  "Eeek. Something's up."))
    (set var (append (seq-take (symbol-value var) index)
                     (seq-drop (symbol-value var) (1+ index))))
    (message  "Deleted: %s" (truncate-string-to-width
                            (seq-elt values index)
                            (- (window-body-width) 9)))))

Hooks are just an example of lists we can delete from. I recently used the same command on display-buffer-alist.

alist.gif

While this has been a fun exercise, I can't help but think that I'm likely re-inventing the wheel here. Is there something already built-in that I'm missing?

Update 1

alphapapa suggested some generalizations that would provide an editing buffer of sorts. This is a neat idea, using familiar key bindigs C-c C-c to save and C-c C-k to bail.

edit.gif

Beware, I haven't tested the code with a diverse set of list items, so there's a chance of corrupting the variable content. Improvements to the code are totally welcome.

 ;;;  -*- lexical-binding: t; -*-

(defun  ar/edit-list-variable ()
  (interactive)
  (let* ((var (intern
               (completing-read  "From variable: "
                                (let (symbols)
                                  (mapatoms
                                   (lambda (sym)
                                     (when (and (boundp sym)
                                                (seqp (symbol-value sym)))
                                       (push sym symbols))))
                                  symbols)  nil t)))
         (values (string-join
                  (mapcar #'prin1-to-string (symbol-value var))
                   "\n")))
    (with-current-buffer (get-buffer-create  "*eval elisp*")
      (emacs-lisp-mode)
      (local-set-key (kbd  "C-c C-c")
                     (lambda ()
                       (interactive)
                       (eval-buffer)
                       (kill-this-buffer)
                       (message  "Saved: %s" var)))
      (local-set-key (kbd  "C-c C-k") 'kill-this-buffer)
      (erase-buffer)
      (insert (format  "(setq %s\n `(%s))" var values))
      (mark-whole-buffer)
      (indent-region (point-min) (point-max))
      (deactivate-mark)
      (switch-to-buffer (current-buffer)))))

Update 2

So hunch was right…

"While this has been a fun exercise, I can't help but think that I'm likely re-inventing the wheel here. Is there something already built-in that I'm missing?"

juicecelery's Reddit commit confirmed it. Thank you! remove-hook is already interactive 🤦‍♂️. TIL 😁

juicecelery was kind enough to point out an improvement in the custom function:

"but I see your improvements, for instance that non list items are removed from the selection."

-1:-- Deleting from Emacs sequence vars (Post)--L0--C0--May 25, 2023 10:23 PM

Irreal: Elfeed-webkit

I just stumbled across a post by Fritz Grabo about his package elfeed-webkit. When I first saw it, I thought it was interesting and worth a look. After reading more about it, I knew I had to install it. That wasn’t entirely easy because I had to recompile my Emacs to support xwidgets. But I liked the idea of the package enough to press on and add xwidgets to my Emacs.

After that, it was simply a matter of installing elfeed-webkit from MELPA. When I toggled it on with Meta+x elfeed-webkit-toggle all my elfeed results were rendered directly in the Elfeed buffer. Sometimes—for example, when I want to save a page for an Irreal post—I need to go to the browser and rerender the page. That’s simply done by pressing the v key.

You’re supposed to be able to toggle elfeed-webkit on and off with a t after you configure it in your init.el but I can only get it to toggle on, not off. Doubtless, I have some misconfiguration but that’s research for another day. You can also add a tag to individual feeds to turn it on but I haven’t tested that yet (I installed it just before I started this post).

So far, I really like this package. It (mostly) keeps me in Emacs and renders the pages perfectly. A comment in the original reddit post complained that Webkit was going to deluge my feeds with dozens of ads but I didn’t notice that with my admittedly limited testing. The nice thing is that you’re not really committed. It’s easy to turn it off or even uninstall it if you don’t like it. The worst that happens is that you end up with support of xwidgets in your Emacs.

-1:-- Elfeed-webkit (Post jcs)--L0--C0--May 25, 2023 04:40 PM

Please note that planet.emacslife.com aggregates blogs, and blog authors might mention or link to nonfree things. To add a feed to this page, please e-mail the RSS or ATOM feed URL to sacha@sachachua.com . Thank you!