Andrea: Use test generators to assess Scala software performance

How to use ScalaCheck to evaluate performance of code
-1:-- Use test generators to assess Scala software performance (Post)--L0--C0--January 26, 2022 12:00 AM

Irreal: Combining Find and Grep in Emacs

One of the classic Unix idioms is to search all files in a file hierarchy for some regular expression with a find/grep pipeline. For example, to search the lisp directory and all of its subdirectories for file containing the mapcar function, one could use

find ~/lisp -name "*.lisp" -exec grep -H mapcar {} \;

That pipeline finds every .lisp file in the hierarchy and runs grep on it looking for mapcar.

I, at least, don’t do this type of thing very much anymore because there are so many easier ways of doing so, especially from within Emacs.

Nonetheless, it’s still possible to usefully combine find and grep from within Emacs to build a Dired buffer of all the files that contain the matching regex. This tweet by
Mickey tells you how:

There’s a bit more to the command so you should take a look at the on-line documentation if you have a use for it.

-1:-- Combining Find and Grep in Emacs (Post jcs)--L0--C0--January 24, 2022 05:25 PM

Marcin Borkowski: Journaling with Org-mode

OK, so let’s admit it. I’ve been journaling with Org-mode for more than 6½ years now. Every day (well, almost every day) I sit down and make notes of important things that happened that day.
-1:-- Journaling with Org-mode (Post)--L0--C0--January 24, 2022 04:26 PM

Bozhidar Batsov: Reader’s Block

Today I finished reading a book for the first time in a couple of months. As a matter of fact - I barely did any reading in the past couple of months. That rarely happens to me, as I’m the type of person who’s constantly reading something. It seems that lately I’ve been having a “reader’s block” - I’ve had almost no desire to read anything. Over the past week I’ve been pondering on the subject and I think I figured it out.

In early December 2021 I was probably reading simultaneously around 5 books. That’s bad by itself, because I’ve noticed that when I start reading more than a couple of books at the same time I rarely make equal progress on each front. Typically 1-2 books are way more interesting to me than all the rest and I just focus my attention on them. This time, however, I wasn’t particularly engaged with any of the books in progress. A couple of them were just painful to read. So, what did I do? I just picked up more books to read!

I guess it’s clear that the simple course of action here is to just abandon those books that I didn’t like and move forward, but the problem is that I’m not the kind of person who starts something and doesn’t finish it.1 You have no idea how many boring books and movies I’ve powered through over the years. This has made me very selective when it comes to reading (and many other things for that matter), but no matter how much background work you’ve done you can always run into a book that you thought would be great, but you don’t enjoy at all.

Anyways, in the end of the day, my reader’s block is quite easy to explain:

  • Focus is key. Less is more. Remember the teachings of Kanban. If you’re doing too many things at the same time you’re not going to achieve optimal results. Note to self - limit books in progress to 2.2
  • Sunk cost fallacy, reader edition. In other words - perhaps the book will turn around if I invest into it 2-3 more hours. That rarely happens. And some books even get worse the further you progress with them.

Being aware of the issues and being able to address them - those are two completely different things, though. We’ll see how well will I do. For now I’m simply glad I’ve managed to deal a blow to my reader’s block. Keep reading!

  1. Okay, admittedly as I grew older I stopped applying this rule to bad TV shows. 

  2. I generally aim to read one fiction and one non-fiction book at the same time. 

-1:-- Reader’s Block (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 24, 2022 07:39 AM

Sacha Chua: 2022-01-24 Emacs news

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

-1:-- 2022-01-24 Emacs news (Post Sacha Chua)--L0--C0--January 24, 2022 05:26 AM

yuri tricys: How to Use EWW Browser in Emacs [and What it Isn't Good For]

Spoiler Alert: It isn’t good for animation. That’s right, you can’t view this post in emac’s eww browser and get the benefit of the matrixy animation. If you want to see the animation, use a regular browser, or Emacs Application Framework EAF.
-1:-- How to Use EWW Browser in Emacs [and What it Isn't Good For] (Post)--L0--C0--January 24, 2022 12:00 AM

Irreal: Adding To a Keyboard Macro

Wilfred Hughes’ Emacs Command of the Day Twitter feed has a useful tip:

I’ve seen this before and may even have written about it before but I always forget about it. I’m not sure why; it could hardly be simpler: just prefix the start macro command with the universal argument.

In any event, it’s a useful reminder for me and may be for you too.

-1:-- Adding To a Keyboard Macro (Post jcs)--L0--C0--January 23, 2022 06:07 PM

Protesilaos Stavrou: Re: add the Modus themes to base16?

I have received a variant of this a few times already:

Why don’t you add modus-operandi and modus-vivendi to the base16 project? It will give you free access to all the templates it supports. There is no need to manually port them over from Emacs.

For context, base16 is a collection of colour palettes and template files to generate so-called ‘themes’ for a variety of applications. I put the themes in quotes because I think there is an important distinction to be made between a colour scheme and a theme. Read the manual for the technicalities, while I use the remainder of this entry to explain some not-so-obvious issues with procedurally generated ‘themes’:

The origins of the 16-colour palette

base16 is fine in its own right, though it is not the right tool for porting the Modus themes to other apps. The base16 project inherits a constraint from terminal emulators where it expects a palette to consist of 16 colour values. These represent the {0..15} ANSI escape sequences that map to the following terminal colours (termcol for short):

ANSI sequence Colour name
termcol0 black
termcol1 red
termcol2 green
termcol3 yellow
termcol4 blue
termcol5 magenta
termcol6 cyan
termcol7 white
termcol8 bright black
termcol9 bright red
termcol10 bright green
termcol11 bright yellow
termcol12 bright blue
termcol13 bright magenta
termcol14 bright cyan
termcol15 bright white

For terminals such as XTerm, URxvt, Alacritty, Kitty, and the like, a 16-colour palette is perfect: it does exactly what it is supposed to, which is to define the colour value for termcol{0..15}. Those will usually produce good results in shell output, but become problematic in ncurses-based programs that want to apply background colours. The reason stems from the very design of the 16-colour palette, where you need to know the base background in order to establish the relationship (i.e. contrast ratio or overall looks) between it, each variant of coloured text, and all coloured texts in tandem. Put differently, the 16-colour palette has implicit rules on its possible combinations where termcol{0,7,8,15} are the de facto backgrounds and all the rest are the nominal foregrounds.

For themes that target an accessible contrast ratio in relative luminance, the actual usable base backgrounds are reduced to two: either termcol{0,8} for dark variants or termcol{7,15} for light ones. Which means that any CLI tool that hardcodes combinations such as termcol0+termcol2 will not look good on a light variant (and the inverse for dark variants).

The 16-colour palette does not grant full control

We can already grasp the implications of this constraint, which are encapsulated in the insight that the designer does not exert full control over their design. The 16 ANSI escape sequences are, at best, a colour scheme which does not determine how values are mapped to constructs in each context.

I state as much from a position of experience, having developed the tempus-themes, which are the spiritual ancestor of the Modus themes for Emacs (also check the tempus-themes-generator for an alternative to base16). My woes with colour inconsistencies stemming from the fragmented landscape of CLI and ncurses-based programs is one of the reasons I switched to Emacs in the summer of 2019 (in previous publications I have explained at length how Emacs furnishes the means for an integrated computing experience).

A practical example with the colouration of diffs

To return to the technical constraints of a 16-colour palette, consider for example, the case of diffs. You have removed lines in red, added lines in green (there can also be yellow lines and other things that need to be colourised, but let’s keep it simple). Check out how Magit (a top-tier Emacs package) displays diffs as sets of hunks that can be acted upon, where the hunk-at-point uses different colours to achieve a highlight effect. In such a context, we need distinct shades red/green (and others) to make the hunk-at-point stand out and/or to dim the other hunks. This cannot be achieved with 16 colours for two reasons:

  • We already explained how values like termcol{1,2,9,10} are conceived as foregrounds. They should work well side-by-side when they colour text against the main backgrounds (those being termcol{0,8} or termcol{7,15}). When you use the foregrounds as backgrounds, the original assumption no longer holds, because the red and green colours were not designed for the express purpose of looking good side-by-side as backgrounds. By the same token, the pairs termcol1+termcol9 as well as termcol2+termcol10 are not necessarily distinct enough when they are used as backgrounds, or their distinction does not look good in the context of diffs.

  • If the designer were to decide on defining some termcol entries as backgrounds, say termcol9 and termcol10, then they would encounter other problems in the output of CLI or ncurses-based programs that would continue to map those values to text, not the text’s background. In short, we return to what I already stated regarding the designer’s lack of control over their design.

Despite these constraints, it is common to have terminal emulators colourise diffs. They will either use red/green as foregrounds, which looks okay, or they will invert the colours with red/green working as backgrounds which might look usable though it likely is too intense. Even so, we are dealing with a scenario where we are forced to make the compromise of using colours that are not optimised for their given context. Things get worse when we factor in the need for the visuals of interactivity, à la Magit.

No theme must force itself to the 16-colour palette

There is no technical reason why we should cling on to the legacy of terminal emulators. Programs like Emacs can use colour with greater precision, which helps add much-needed nuance to each interface. We are losing the nuance, the context-specific optimisations, when we force ourselves to conform with the constraints of base16 or the tempus-themes. (Remember to read the entries in the Modus themes’ manual I linked to regarding the distinction between colour schemes and themes, as well as the prospect of a port of the themes to other platforms.)

To illustrate the point of not using a 16-colour palette, consider the differences between the original Solarized by Ethan Schoonover and how it compares to its Emacs port by Bozhidar Batsov, Thomas Frössman, and others. Like base16, Schoonover’s Solarized was also designed with terminal emulators in mind, although it semantically does not provide what terminals expect as termcol{10,11,12,14} since those are shades of gray instead of “bright {green, yellow, blue, cyan}”. Whereas the Emacs port is not a faithful one, as it does not limit itself to the original palette—and that is the right thing to do. Here is a sample from solarized-palettes.el:

(defvar solarized-dark-color-palette-alist
  '(;; solarized-dark palette
    (base03      . "#002b36")
    (base02      . "#073642")
    (base01      . "#586e75")
    (base00      . "#657b83")
    (base0       . "#839496")
    (base1       . "#93a1a1")
    (base2       . "#eee8d5")
    (base3       . "#fdf6e3")
    (yellow      . "#b58900")
    (orange      . "#cb4b16")
    (red         . "#dc322f")
    (magenta     . "#d33682")
    (violet      . "#6c71c4")
    (blue        . "#268bd2")
    (cyan        . "#2aa198")
    (green       . "#859900")
    (yellow-1bg  . "#273532")
    (yellow-1fg  . "#af8f41")
    (yellow-2bg  . "#433e20")
    (yellow-2fg  . "#b39a5e")
    (yellow-d    . "#866300")
    (yellow-l    . "#e1af4b")
    (orange-1bg  . "#2b2d2e")
    (orange-1fg  . "#ca6f48")
    (orange-2bg  . "#4d2c1f")
    (orange-2fg  . "#c47c5d")
    (orange-d    . "#992700")
    (orange-l    . "#fb7640")
    (red-1bg     . "#2d2c31")
    (red-1fg     . "#d66556")
    (red-2bg     . "#532725")
    (red-2fg     . "#ce7667")
    (red-d       . "#a7020a")
    (red-l       . "#ff6849")
    (magenta-1bg . "#272d3c")
    (magenta-1fg . "#cc6791")
    (magenta-2bg . "#4c2942")
    (magenta-2fg . "#c47896")
    (magenta-d   . "#a00559")
    (magenta-l   . "#ff699e")
    (violet-1bg  . "#0c3144")
    (violet-1fg  . "#8085c0")
    (violet-2bg  . "#1a365a")
    (violet-2fg  . "#888dbc")
    (violet-d    . "#243e9b")
    (violet-l    . "#8d85e7")
    (blue-1bg    . "#003547")
    (blue-1fg    . "#5c93c5")
    (blue-2bg    . "#003f5e")
    (blue-2fg    . "#709bc3")
    (blue-d      . "#0061a8")
    (blue-l      . "#74adf5")
    (cyan-1bg    . "#013841")
    (cyan-1fg    . "#54a099")
    (cyan-2bg    . "#00464a")
    (cyan-2fg    . "#6ba8a2")
    (cyan-d      . "#007d76")
    (cyan-l      . "#6ccec0")
    (green-1bg   . "#1d3732")
    (green-1fg   . "#8c9a43")
    (green-2bg   . "#2f4321")
    (green-2fg   . "#97a35f")
    (green-d     . "#5b7300")
    (green-l     . "#b3c34d")
    ;; palette end
    )
  "The solarized color palette alist.")

These are not all the effective colours of the Emacs Solarized port, as it also has code for colour blending. Still, it is clear that the notion of 16 colours is discarded because it is unsuitable for the demands of a fully fledged theme.

Colour mapping needs attention to detail

Now let us return to the problems with procedurally generated ‘themes’ from base16 and specifically the idea of getting ports to all those other apps “for free”. Are those templates good for our purposes? With the exception of terminal emulators, which will simply map the colour values to the termcol entries, the answer is negative because each of those templates tries to force a colour palette that was intended for terminal emulators to work as a general-purpose theme. Each of those templates does not consider the contextuality of any given combination of colours. This is not because the people who wrote those templates are careless: it has to do with the fact that the 16-colour palette is not appropriate for all those cases. One size does not fit all.

The quality of ports is something I take very seriously (again, check the links to the Modus themes’ manual). base16 has a port for Emacs, which can help us shed light on another aspect of the design: the overall rhythm of the applicable colours in each context. Compare those two screenshots, which I got from Peach Melpa:

base16-atelier-heath sample

https://peach-melpa.org/themes/base16-theme?lang=js&variant=base16-atelier-heath

modus-vivendi sample

https://peach-melpa.org/themes/modus-themes?lang=js&variant=modus-vivendi

The specific variant of base16 does not matter, as the colour mapping is constant. You will notice that they use in this context purple, orange, red, and yellow. I find this presentation awkward because there is no need to use complementary colours (purple+orange) to amplify the distinction between constructs of the same code. You have those colours effectively shouting at you “hey I am here”. For a theme with subtle colour values, this might not be a major problem, but it would look horrible if we were to apply the intensity of the Modus themes.

Now check how Modus Vivendi uses colour: blue, cyan, purple. We do not have wide differences in hueness because we do not need to exaggerate the distinction between the various constructs. There is no competition at play, nothing to call unwarranted attention to itself. I only use complementary colours (e.g. blue VS yellow) in contexts where the distinction is significant.

Then we have the aspect of colour psychology: the inconsiderate use of red/yellow makes it more difficult to make errors or warnings call attention to themselves.

Anyhow, this is not to imply that the Modus themes are perfect because each major-mode in Emacs will have its own ideas on how faces apply to any given construct. Still, we try our best to optimise the effective colours in their context and thus we do not impose an arbitrary limit on how many colours the palette must have. Without knowing the context, we cannot say anything about the propriety of any given colour combination even if it satisfies the minimum 7:1 contrast ratio that we target.

Some more entries from my themes’ manual:

No quick-and-dirty ports

To recapitulate:

  • Colour schemes are not themes.
  • The 16-colour palette is not appropriate for fully fledged themes.
  • What mostly works for terminal emulators does not necessarily apply to other programs. One size does not fit all.
  • I have no faith in base16, the tempus-themes-generator, or equivalent, to deliver high quality themes for any type of program because of the inherent limitations of the 16-colour palette.
  • Colour mapping cannot be done on a whimsy.

To be clear: this is not a critique of base16 as the same applies to my own tempus-themes. Read it as the distillation of years of experimentation or, rather, as a warning not to take theme development lightly.

You are still free to use whichever port you want, though I will never debase the quality of this project by supporting ports that are simply not up to our standards (and we haven’t even covered the customisability of the Modus themes and the power it gives to the end-user—again, read the manual).

-1:-- Re: add the Modus themes to base16? (Post)--L0--C0--January 23, 2022 12:00 AM

Christian Tietze: Closing Circe IRC Buffers in Emacs Without Leaving the Room

It’s a hack but it works:

To stay in a room (or rather: let the bouncer stay there) and still close the buffer locally, it helps to change the major mode of the circe buffer: M-x fundamental-mode RET. If you change the buffer’s mode to any text mode, the circe-mode specific teardown hooks won’t be triggered and you can close the buffer without leaving the room.

You don’t know what an IRC bouncer or circe is? Here’s some context.

circe is an Emacs package to connect to IRC servers. Unlike the built-in erc package, circe supports logging into bouncers with SASL authentication. That’s quite useful for some bouncers that require this.

A job of an IRC bouncer is to stay in an IRC room on your behalf and e.g. record messages that were sent while you were actually logged-out. When you set up a bouncer to stay in a room for you, if backlog replay works, that’s basically re-creating the experience you know from Slack and Discord.

So unless you want to always be online in chat, you will want to close the Emacs buffers that correspond to IRC rooms. After all, the bouncer will stay there for you. The idea is similar to closing Slack/Discord to focus on something else to return later and catch up.

By default, circe will not allow closing an IRC room’s buffer without leaving it. (Without a bouncer, that’s the default: you close the IRC client and leave all rooms.)


Receive Christian’s new posts via email

-1:-- Closing Circe IRC Buffers in Emacs Without Leaving the Room (Post)--L0--C0--January 22, 2022 08:35 PM

Irreal: MELPA Surpasses a Quarter Billion Downloads

From Steve Purcell:

I’ve said this before but it bears repeating: We all owe Purcell our thanks and, if we happen to meet him, a beer. He has, virtually single-handedly, run the most important Emacs package repository. It’s a lot of work that Purcell donates to the our community and more often than not his only feedback is complaints when the rare glitch isn’t resolved quickly enough.

A quarter of a billion downloads is a lot for a community the size of ours and underscores again the tremendous amount of work required to keep things ticking along. There are currently 5,077 packages in MELPA and each one has been curated and validated by Purcell or one of his helpers.

So again, let’s all raise to toast to Purcell and if you happen to be where he is, buy him a round.

-1:-- MELPA Surpasses a Quarter Billion Downloads (Post jcs)--L0--C0--January 22, 2022 06:11 PM

Bozhidar Batsov: How to Find Which Package a File Belongs to in Debian/Ubuntu

Occasionally I need to figure out which Debian package some file comes from (e.g. because I want to remove a redundant package or find related packages). There are a couple of ways to do this in Debian, with the simplest being the following:

$ dpkg -S /usr/bin/ag
silversearcher-ag: /usr/bin/ag
$ dpkg -S /usr/bin/gcc
gcc: /usr/bin/gcc

dpkg is a built-in command, so it’s always around. -S stands for --search:

-S, --search filename-search-pattern...
Search for a filename from installed packages.

Note, that it’s best to use absolute paths if you want to get a concrete package as the result. Observe the difference here:

$ dpkg -S /bin/ls
coreutils: /bin/ls
$ dpkg -S bin/ls
kmod: /sbin/lsmod
pciutils: /usr/bin/lspci
util-linux: /bin/lsblk
util-linux: /usr/bin/lsns
usbutils: /usr/bin/lsusb
e2fsprogs: /usr/bin/lsattr
util-linux: /usr/bin/lsmem
util-linux: /usr/bin/lslogins
initramfs-tools-core: /usr/bin/lsinitramfs
util-linux: /usr/bin/lsipc
kmod: /bin/lsmod
util-linux: /usr/bin/lslocks
gnupg-utils: /usr/bin/lspgpot
lsof: /usr/bin/lsof
coreutils: /bin/ls
util-linux: /usr/bin/lscpu
klibc-utils: /usr/lib/klibc/bin/ls
lshw: /usr/bin/lshw
lsb-release: /usr/bin/lsb_release

Here you can stop reading, as 99% of the time that’s probably the best option for you. Still, there’s one more way to approach the problem, namely by using apt-file. You’ll need to install apt-file and initialize its database first:

$ sudo apt install apt-file
$ sudo apt-file update

Using apt-file is quite simple:

$ apt-file search /usr/bin/gcc
gcc: /usr/bin/gcc
gcc: /usr/bin/gcc-ar
gcc: /usr/bin/gcc-nm
gcc: /usr/bin/gcc-ranlib
gcc-10: /usr/bin/gcc-10
gcc-10: /usr/bin/gcc-ar-10
gcc-10: /usr/bin/gcc-nm-10
gcc-10: /usr/bin/gcc-ranlib-10
gcc-7: /usr/bin/gcc-7
gcc-7: /usr/bin/gcc-ar-7
gcc-7: /usr/bin/gcc-nm-7
gcc-7: /usr/bin/gcc-ranlib-7
gcc-8: /usr/bin/gcc-8
gcc-8: /usr/bin/gcc-ar-8
gcc-8: /usr/bin/gcc-nm-8
gcc-8: /usr/bin/gcc-ranlib-8
gcc-9: /usr/bin/gcc-9
gcc-9: /usr/bin/gcc-ar-9
gcc-9: /usr/bin/gcc-nm-9
gcc-9: /usr/bin/gcc-ranlib-9
gcc-opt: /usr/bin/gcc-3.3
gcc-opt: /usr/bin/gcc-3.4
gcc-opt: /usr/bin/gcc-4.0
gcc-python3-dbg-plugin: /usr/bin/gcc-with-python3_dbg
gcc-python3-plugin: /usr/bin/gcc-with-python3
gccbrig: /usr/bin/gccbrig
gccbrig-10: /usr/bin/gccbrig-10
gccbrig-7: /usr/bin/gccbrig-7
gccbrig-8: /usr/bin/gccbrig-8
gccbrig-9: /usr/bin/gccbrig-9
gccgo: /usr/bin/gccgo
gccgo-10: /usr/bin/gccgo-10
gccgo-7: /usr/bin/gccgo-7
gccgo-8: /usr/bin/gccgo-8
gccgo-9: /usr/bin/gccgo-9
pentium-builder: /usr/bin/gcc
xutils-dev: /usr/bin/gccmakedep

As you can see by default it provides all possible matches from its database. One advantage that apt-file has over dpkg is that it will search through all available packages as opposed to all installed packages. That might be handy sometimes when you know you need to have some file installed, but you don’t know which package contains it. Admittedly, I didn’t know about apt-file until very recently myself, which is part of the reason I’ve decided to put together this short article.1

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

  1. When I write about something I just learned, the likelihood of retaining the new knowledge increases significantly. Still, nothing beats applying the new knowledge in practice all the time. 

-1:-- How to Find Which Package a File Belongs to in Debian/Ubuntu (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 22, 2022 08:55 AM

Bozhidar Batsov: Cheating at Wordle Like a Hacker

These day almost everyone on Twitter seems to be playing the word game Wordle, including me. You’ve probably seen many people around you sharing images like this one:

wordle.png

Most of the time the 5-letter words you have to guess are pretty easy, but occasionally there are words that are quite uncommon (at least for non-native speakers like me), that encourage to cheat in order to figure them out.

While there are all sorts of ways to cheat at Wordle, I think the most hackerish approach is to simply use a tool like grep on your English dictionary. Imagine that we’re looking for words that start with r and end with t. Now we can quickly find all such words to come up with our next guess:

$ grep ^r...t$ /usr/share/dict/words
react
rebut
refit
remit
reset
right
rivet
roast
robot
roost

That’s some pretty basic grep usage here - we’re basically using a regexp that will match all whole 5-letter words starting with r and ending with t. And that’s it.1 No more googling for queries like “5 letter words that end with t”. The Unix tools are the Way! Keep hacking!

  1. I think that dictionary file is installed by default on most Linux distros. 

-1:-- Cheating at Wordle Like a Hacker (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 22, 2022 08:28 AM

Bozhidar Batsov: Farewell, G Suite legacy free edition

Today I saw the news that Google are pulling on the plug on the G Suite legacy free edition (a.k.a. Google Apps for custom domains). If you don’t recall the story - originally the service was free for up to 50 users (making it quite popular with small companies), then up to 10 users, then up to 5 users, and finally it was made paid for everyone. The people who started to use the service before the terms were changed were kept on what Google called “G Suite legacy free edition”. I am (was?) one of them.

Nothing in life is truly free, however, and it seems that Google has decided to forcefully convert the last holdouts:

To maintain your services and accounts, review the information below and upgrade by May 1, 2022. Upgrading to Google Workspace takes just a few steps with no disruption to your users. After you upgrade you can use your new subscription at no cost until at least July 1, 2022.

If you choose to wait, Google will begin upgrading subscriptions automatically on May 1, 2022. We will upgrade your organization to a new Google Workspace subscription based on the features you currently use.

To complete the upgrade, set up Google Workspace billing before July 1, 2022. If you don’t provide your payment information, your Google Workspace subscription will be suspended until you set up billing.

After 60 days in suspension, you will no longer have access to Google Workspace core services, such as Gmail, Calendar, and Meet. You may still retain access to additional Google services, such as YouTube and Google Photos. Enter a valid form of payment to restore your suspended account.

TLDR; You’ve got 6 months to pay up or we’ll terminate the service for you. What exactly you’ll need to pay is unclear right now. (pretty weird)

I’ve been using the G Suite for over a decade for batsov.com, so normally I’d be a bit upset about this turn of events, even if I always expected it. And I’d pay up most likely, of course. Now that probably won’t be the case, as I’ve been a happy user of Fastmail for the past half a year and I’ll likely nudge my family members who are still on the G Suite to move over as well, together with the domain. We were only using it for email, anyways.

In the end of the day - I’m actually happy about this development as it gives me an incentive to cut one more tie with Google. I’ve been progressively less fond of the company in recent years and I’m happy to take my (tiny) business elsewhere.

Farewell, G Suite legacy free edition. You won’t be missed.

-1:-- Farewell, G Suite legacy free edition (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 21, 2022 06:02 PM

Andrea: Moldable Emacs: query your Org Roam notes by tag

-1:-- Moldable Emacs: query your Org Roam notes by tag (Post)--L0--C0--January 21, 2022 12:00 AM

Lars Ingebrigtsen: 13×10%

Lucky for some.

So that’s another 10% of the bugs in the Emacs bug tracker closed, so let’s natter on a bit.

So the most striking thing here is, of course, that we started with 2550 open bugs, and we’re now at… 2605.

That’s not much of a reduction!

Yeah yeah. This stretch took two months, and instead of hacking away at the bugs, I’ve been hacking away at implementing stuff, and… then I took three weeks off. Oops!

See if you can identify the weeks I was chillin’.

But it’s been pretty productive anyway. There’s been 1778 commits in the period, and among the bigger things is that we now support the Haiku OS, and we’ve merged the PGTK (pure GTK) branch (both things courtesy of developer Po Lu, but the PGTK branch was originally written by Yuuki Harano).

And one internal Emacs development thing I appreciate is that Stefan Kangas has fixed all the warnings in the Emacs test suite. I mean, you’d normally only look at the test results, but without any byte compilation warnings, it’s a more… calm… experience.

Zen.

But of the time I’ve spent typing myself, it’s been mostly three things:

Multisession variables are variables that get saved to disk automatically, so that they’re restored when you restart Emacs. Emacs has many ways of persisting session state, of course, and has always had, but it’s all so… manual. I mean, you pick a file name, and then write some code to write the data out, and then read it in, and then you get it wrong and the data disappeared, and then you fix it and then aaaargh!

So people only bother with the larger things. But with small things, like saving the recently used emojis, it’s just too much work for too little utility, so few programmers bother.

But with this interface, hopefully it’ll allow people who make packages to do easier persistence for smaller stuff. And one advantage of centralisation of this sort of data is that you can make a command that allows Emacs to list the data, and then edit/remove it:

It’ll work out OK, I think. (Note that this is for session state only — configuration stuff is still handled by Customize.)

Semi-related, Emacs now comes with built-in support for SQLite. This is based on Syohei Yoshida’s Emacs module, but has been somewhat rewritten. I think it’s a shame that Emacs hasn’t had built-in support for a database for years — Emacs is used to handle large amounts of data, but has been hampered by how slow it is to write that data out naively, and then reading it back in again to work with it.

Having SQLite built in will open up new vistas, and make some things (like the Gnus registry and some Org databases) much more performant. We should probably add something Linq-like for interacting with SQLite, though, because writing SQL as strings is yucky.

Finally, there’s been a lot of chatter (over the last few years) about the interesting attack surfaces that have opened up fot confusing people by using homoglyphs and bidirectional text for various fun things. Emacs has stuff to deal with those on various levels, but hasn’t really implemented the recommendation in Unicode® Technical Standard #39 for identifiers.

For “identifiers” read “URLs and email addresses”, basically. Well, there’s more, but that’s the most important bits — if you can fool people into thinking you’re sending an email to somebody by using shenanigans in the email address, that’s not cool.

(As an aside, I was amused to see that the main editor of that document has a Phd in Philosophy, but it explains so much about the way the document is written. Here’s the typical start of a description of an algorithm:

Consider Q, the set of all strings that are confusable with X.

And here’s how it ends:

The logical description above can be used for a reference implementation for testing, but is not particularly efficient. A production implementation can be optimized as long as it produces the same results.

I appreciate the attempt to be precise, and they’re using maths to be precise, but I’m a programmer, so: Herp derp, I eat paste while considering Q.)

So I’ve typed away at a library that ended up being called “textsec”, and it has a bunch of functions like “textsec-url-suspicious-p”, and after typing supscious approx. nine million times for that library, I can now spell it correctly 100% of the time.

and it’s true:

And so on and on and on. But after importing about 14K lines worth of data from Unicode, and writing… fewer lines of Emacs Lisp code, eww can now tell you about sus links:

Err… Perhaps the visual look should be… tweaked… a bit…

Hovering over the warning will tell you what’s suspicuos about the link.

And there are similar things in Message and Gnus, and will eventually find its way throughout all bits of Emacs that deal with these sort of things.

(And users can disable it, of course. This is Emacs, after all.)

Anyway!

This is what’s going on in the bug sitch more long term. Next stretch should go faster, I hope, because I don’t really have anything bigger planned (implementation wise) this time.

Thank you for attending my TED talk.

-1:-- 13×10% (Post larsmagne23)--L0--C0--January 20, 2022 03:40 PM

Mickey Petersen: Bad Emacs Advice

I have been using Emacs since 2004 which, measured in Emacs-ontological terms, barely counts as much experience at all. But since I started using Emacs I have spent a large part of that time learning, just like everyone else, and helping others do the same — and perhaps more to the point: watching other people dispense advice on how to learn Emacs or get started with it.

We’ve all spent a large amount of time learning, and reaching proficiency in, Emacs. So, the sage advice that most people dispense to new Emacs users is usually just that: sage advice. But just like pizza with pineapple, people do occasionally give out downright bad advice.

A lot of the bad advice – and it’s really just a few things that crop up again and again – that I see repeated all over the place seems to stem from the idea that Emacs’s own builtin facilities are immovable barriers, or cumbersome impediments, to achieving True Enlightenment, and that you can only achieve this Zen of Emacs through self-flagellation.

So I’m quickly going to go over the things that I really wish people wouldn’t tell new users, even though they do so with an abundance of good faith.

Disabling the Menu Bar

This is perhaps the most common “advice” of all: that you must disable the menu bar, tool bar, and scroll bar. In the case of the menu bar, you stand to gain 1 row of text in console Emacs, and a handful of pixels in GUI Emacs, at the cost of hiding the first thing any computer user would look to for help, features and guidance: a menu bar full of curated, context-sensitive menu options.

The menu bar is contextual: it will change depending on the major, and sometimes minor, modes you have enabled in the active buffer. And the selection of default menu bar features is vast. You can do an awful lot of Emacs work with nothing but the menu bar; better still, it’s got a human-friendly name for each option, and the keyboard shortcut (if any) next to it, as well. When I was learning Emacs (XEmacs, actually!) I found it invaluable myself.

And if you type M-`​ you get a keyboard-friendly version in the minibuffer that works in Terminals (and in the GUI) without the need for a mouse.

So it’s got features and it’s contextually aware of what you’re doing. That makes it an easy place to point beginners at if they want to do any number of common activities, like: customizing Emacs’s many features; changing the default font; or learning more about a major mode they frequently use. It’s also got a list of buffers and frames; you can access the package manager; the calculator; spell checker; search and replace; enable CUA mode; and much, much more.

But most importantly of all: it has the “Help” menu! Why someone would encourage newbies to disable something that can credibly help them learn Emacs is a mystery to me.

(Oh, and, by the way, you can type C-h k and click on a menu bar item to get its function description. I bet you didn’t know that!)

Not directing users to the Emacs Manual

Emacs is very well documented. It’s got the self-documenting parts, thanks to elisp and all that machinery, and a set of hand-curated manuals that ship with it. I find it surprising when people remark not to bother with it; it should be the first port of call for most people. I use it frequently to find commands and functions adjacent to what I am doing, or to learn about complex internals in Emacs.

I would encourage everyone, regardless of skill level, to sit down and read the Emacs manual in C-h i from start to finish. You’ll learn a lot, and gain a much greater appreciation for what Emacs is capable of, and how much care and attention is lavished on an area that most consider unsexy.

Not sure how to find things in the manual? Use the apropos tool.

Turning people away from the Tutorial

In a similar vein to the above, the builtin tutorial is short, simple, and to the point: but it’s there for a reason! It helps new users get acquainted with Emacs terminology and concepts — and they’ll need it, especially when you told them to turn off the menu bar so they can’t find things.

The Customize Interface

I use it, it’s useful, and it has its place. Especially if you’re new to Emacs. You can configure large swathes of Emacs core to your liking (and many third-party packages), and you can temporarily enable your changes for the current session only, ensuring you’ll never break something permanently.

It should again be the first port of call for people to configure their Emacs, if they are not yet comfortable with elisp. And they may not be for years, if at all.

Customize has its place, and so does configuring stuff with elisp. You can do infinitely more with the latter, but you can still accomplish a large amount with the former.

So here’s a challenge to people who say the Customize interface is useless: try launching a blank-slate Emacs and manually set up your font faces with pure elisp the way you like them without M-x customize-face and themes to guide you.

Conclusion

Telling beginners to disable helpful features in Emacs is not good advice. The confluence of customizing Emacs with Customize; discovering features with the menu bar; and knowing how to learn and get help is foundational stuff in Emacs. And it’s something everyone needs to know to get ahead in Emacs, even if you’re an expert.

-1:-- Bad Emacs Advice (Post)--L0--C0--January 20, 2022 12:29 PM

Bozhidar Batsov: Bad Ruby: Hash Value Omission

Ruby 3.1 was recently released and it features one major syntax addition - you can now omit values in hash literals and keyword arguments in certain cases.1 The release notes give the following examples:

  • {x:, y:} is syntax sugar for {x: x, y: y}.
  • foo(x:, y:) is syntax sugar for foo(x: x, y: y).

Note that x and y are local variables that are in scope. My first reaction was “WTF???”. My second reaction was to check how this made it to the language.

The feature request ticket has a few more usage examples:

x = 1
y = 2
h = {x:, y:}
p h # => {:x=>1, :y=>2}

def login(username: ENV["USER"], password:)
  p(username:, password:)
end

login(password: "xxx") # => {:username=>"shugo", :password=>"xxx"}

What it doesn’t have, however, is any rationale behind the proposed change. Weird. I get that the idea is to emulate the syntax of JavaScript’s object punning, but I find this to be quite misguided if the end result is reduced code readability.2 What’s the point in copying features from other languages if they don’t add value to Ruby itself? What’s the point of shaving off a few characters/keystrokes if the reader of the code might struggle to understand it?

I’ve noticed that everyone reacted negatively to the proposal initially, including Matz:

I prefer this syntax to #11105, but this introduces a Ruby-specific syntax different from ES6 syntax.

Besides that, I don’t like both anyway because they are not intuitive (for me).

– Matz

This was in 2018. 4 years later, however, he changed his mind:

After the RubyKaigi 2021 sessions, we have discussed this issue and I was finally persuaded. Our mindset has been updated (mostly due to mandatory keyword arguments). Accepted.

Oh, well… Sadly, no one bothered to share those convincing arguments in the ticket itself. I’m disappointed that in the end of the day the result is more complexity in the core language that serves mostly to allow writing shorter, but harder to read code. We should never forget the following words of wisdom:

Programs must be written for people to read, and only incidentally for machines to execute.

– Harold Abelson, Structure and Interpretation of Computer Programs

So, why do I feel that the new syntax makes things harder to read?

  • at a glance {x:, y:} seems like a hash without values. Simple as that. Yeah, when I know about the new syntax I’ll infer that there are some locals with the same names as the keys that are currently in scope, but why bother with all of this? Explicit is (almost always) better than implicit when it comes to code readability/maintainability!
  • modern editors and IDEs are already quite smart - if you want to type less, such a problem can be solved at this level (e.g. IDEs would infer that you probably want to put x after x:).
  • how can I jump the local variable at point (e.g. I want to inspect it) if there’s no local variable at point?
  • there are also some “fun” cases to consider:
# the shorthand somewhat surprisingly works with methods without params
def destroy (); puts "surprise"; end

{destroy:} # this will print "surprise"

# do you think this code behaved the same way before Ruby 3.1 and in Ruby 3.1?
# see - https://github.com/rubocop/rubocop/issues/10359
def some_method(token)
  user = double :user, id: 42, token:
  described_class.build(user)
end

Not to mention that this complicated further Ruby’s already complicated parsers and created a boatload of work for me and the other members of RuboCop’s team. Observing some of the interactions of the new syntax with other Ruby code (e.g. method calls using the new syntax followed by conditional modifiers) left me believing that the full implications of this were not carefully thought out.

I’m left pondering if I’d feel differently about the feature if it was implemented in terms of a different syntax, that’s not so ambiguous. Probably yes. Still, I’ve decided to give this syntax the benefit of the doubt and not discourage it in the default RuboCop configuration (RuboCop introduced support for Ruby 3.1 in version 1.24). As usual I’ll leave it to the broader community to figure out if something will become a Ruby idiom in the long run or not.

Adopting new syntax is usually the least effective productivity improvement.

And a language where the most easy path of change is such syntax additions is not providing the evolutionary path for meaningful improvements.

– Markus Schirp

This episode is just a continuation of the all the language changes in Ruby in recent years that I’ve found detrimental and that eventually prompted me to write my short essay Ruby’s Creed in 2019. It’s clear to me at this point that Ruby’s direction hasn’t changed and is unlikely to change. That makes me sad. I thought Ruby was all about programmer happiness.3

I can only hope that I’m in the minority and the hash punning syntax makes the majority of the Ruby programmers happy. Be happy!

  1. The feature is officially named “hash value omission”. It’s also known as “hash punning” after the similar “object punning” in JavaScript. 

  2. There is a bit more rationale in another ticket

  3. I have no doubt this change made someone happy, but I also wonder how many people did it leave as frustrated as me. 

-1:-- Bad Ruby: Hash Value Omission (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 20, 2022 12:09 PM

Bozhidar Batsov: Unix Sockets are Now Supported on Windows

I was surprised to learn that Windows has added support for Unix sockets (AF_UNIX) a few years ago (in 2017). From the announcement article:

Beginning in Insider Build 17063, you’ll be able to use the unix socket (AF_UNIX) address family on Windows to communicate between Win32 processes. Unix sockets allow inter-process communication (IPC) between processes on the same machine.

In practice that means that all recent builds of Windows 10 support Unix sockets, plus Windows 11, of course. It’s really great to see the evolution of Windows in the past few years - it becomes more developer-friendly every day.

-1:-- Unix Sockets are Now Supported on Windows (Post Bozhidar Batsov (bozhidar@batsov.net))--L0--C0--January 20, 2022 08:57 AM

Meta Redux: Weird Ruby: Heredoc Delimiters

Remember how I thought that the syntax for single-quoted heredocs was weird? I’ve got something even weirder for you today!

Turns out that when using single-quoted heredoc delimiters you can have pretty much anything in them, including spaces!

<<'END HTML'
  <html>
    ...
  </html>
END HTML

<<'\n!"£$%^&*()-=_+[];#{}:@~,./<>?|`\'
hello
\n!"£$%^&*()-=_+[];#{}:@~,./<>?|`\

It never crossed my mind that something like this would be possible until I came across this RuboCop ticket, asking for spaces in delimiters to be allowed. As most editors are unlikely to handle this properly1, and it looks pretty… weird, I think that you should restrain yourselves from using such heredoc delimiters.

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

Articles in the Series

  1. Clearly rouge (the code highlighter my blog uses) doesn’t handle such delimiters properly as well. 

-1:-- Weird Ruby: Heredoc Delimiters (Post Bozhidar Batsov)--L0--C0--January 20, 2022 06:49 AM

Manuel Uberti: Handling wildcards in paths

My recent experiments with Eglot and Java led me to figure out how to speed up the connection to Eclipse JDT Language Server. Basically I wanted a simpler version of eglot--eclipse-jdt-contact to avoid any prompt and just do the right thing for me.

Looking at Eglot’s bug tracker, there is an issue with some tips: #424. I followed the instructions and added the relevant code to my init.el:

(with-eval-after-load 'eglot
  (defconst mu-jdt-launcher
    (concat "/home/manuel/jdt/plugins"
            "/org.eclipse.equinox.launcher_1.6.400.v20210924-0641.jar"))

  (defun mu-eglot-jdt-contact (_interactive)
    "See `eglot--eclipse-jdt-contact'."
    (let ((cp (or (getenv "CLASSPATH") path-separator)))
      (setenv "CLASSPATH" (concat cp path-separator mu-jdt-launcher))
      (unwind-protect (eglot--eclipse-jdt-contact nil)
        (setenv "CLASSPATH" cp))))
  (setcdr (assq 'java-mode eglot-server-programs) #'mu-eglot-jdt-contact))

However, I do not like the hard-coded path to the JDT jar file, mainly because I have to manually update it every time I install a new version of the language server. Fortunately, Emacs has what I need right under the hood: file-expand-wildcards.

(defconst mu-jdt-launcher
  (let ((path "~/jdt/plugins/org.eclipse.equinox.launcher_*"))
    (car (file-expand-wildcards path 'full))))

If you check the documentation of file-expand-wildcards you will notice that it returns a list of file names matching the given pattern. In this case, there is only one element in that list, so car can safely grab it. Again, the documentation will also explain the meaning of that 'full argument, but I am sure it is pretty clear already.

-1:-- Handling wildcards in paths (Post)--L0--C0--January 20, 2022 12:00 AM

Irreal: Corner Quotes

John D. Cook has a useful post on using “corner quotes” (⌜ ⌟) to delimit regular expressions in text. As Cook says, it makes a lot of sense especially when the regular expression begins or ends with a space. Cook’s port deals with using Unicode for the corner quotes but it’s also easy to do in Emacs.

In vanilla Emacs, the way to do it is to specify TOP LEFT CORNER and BOTTOM RIGHT CORNER with insert-char through the Ctrl+x 8 binding. If you have Ivy installed, you can also use the lceil and rfloor entities through ivy-insert-org-entity a handy function that I stole from John Kitchin’s Scimax.

(defun ivy-insert-org-entity ()
  "Insert an org-entity using ivy."
  (interactive)
  (ivy-read "Entity: " (loop for element in (append org-entities org-entities-user)
                             when (not (stringp element))
                             collect
                             (cons 
                              (format "%10s | %s | %s | %s"
                                      (car element) ;name
                                      (nth 1 element) ; latex
                                      (nth 3 element) ; html
                                      (nth 6 element)) ;utf-8
                              element))
            :require-match t
            :action '(1
                      ("u" (lambda (element) (insert (nth 6 (cdr element)))) "utf-8")
                      ("o" (lambda (element) (insert "\\" (cadr element))) "org-entity")
                      ("l" (lambda (element) (insert (nth 1 (cdr element)))) "latex")
                      ("h" (lambda (element) (insert (nth 3 (cdr element)))) "html"))))

The latter method uses left and right floor and ceiling entities (⌈ ⌋) rather than the corner entities but the results are almost the same. At least they are if the regular expression doesn’t contain a floor or ceiling operator.

I usually just set the regular expression in a constant width font but as Cook notes that doesn’t work as well when the regex begins or ends with a space. This seems to me to be a good convention that we should consider adopting.

-1:-- Corner Quotes (Post jcs)--L0--C0--January 19, 2022 07:17 PM

Protesilaos Stavrou: Emacs: mct version 0.4.0

Below are the release notes. If you have no idea what mct is, it is a very thin layer of interactivity on top of the default completion user interface. Watch the video demo of the initial release.


This entry outlines the changes to the “Minibuffer and Completions in Tandem” (mct package) since the release of version 0.3.0 on 2021-11-19. There have been more than 120 commits in the meantime.

For further details, please consult the manual online: https://protesilaos.com/emacs/mct. Or evaluate the following expression if you already have mct installed:

(info "(mct) Top")

As most changes pertain to optimisations in the code base, we limit this log to what is of interest to the end-user.

Minibuffer Confines Transcended (aka mct-region-mode)

Emacs distinguishes between two types of completion: one that involves the minibuffer and another for text expansion inside regular buffers. MCT has supported the former case since its inception, as hinted by its original name (“Minibuffer and Completions in Tandem”), but would not work as intended for in-buffer completion.

This changes with the introduction of a new global minor mode: mct-region-mode. What once was mct-mode is now defined as mct-minibuffer-mode to better denote the scope of the given functionality.

With mct-region-mode enabled, users get a simplified subset of the familiar MCT functionality when typing TAB or C-M-i to complete the text-at-point in any major-mode that supports completion-at-point-functions (e.g. programming modes or Org).

mct-region-mode is considered experimental and unstable. Users are encouraged to report any bugs as well as recommend ways to improve its functionality or interaction model. The manual has been updated to cover all the relevant details.

Daniel Mendler, who is the developer of the vertico and corfu packages (alternatives to mct-minibuffer-mode and mct-region-mode, respectively), was intstrumental in making mct-region-mode happen. Daniel’s patches helped with everything from (i) the proper functioning of mct-region-mode, (ii) the separation between mct-minibuffer-mode and mct-region-mode, (iii) the overall setup of the minor modes, and (iv) lots of other crucial details of the overall design of MCT. In short: there would be no mct-region-mode without Daniel’s contributions. Any remaining errors or omissions are my own.

Given this new functionality, we can now joke that “MCT” stands for “Minibuffer Confines Transcended”.

-1:-- Emacs: mct version 0.4.0 (Post)--L0--C0--January 19, 2022 12:00 AM

Marcin Borkowski: Making code snippets in Org-mode easier to type

From time to time people tend to discuss the Org markup – some people want to extend it in one way or another, some people want to make it more Markdown-ish. I tend to agree that the selection of the tilde (~) to denote code is a bit inferior than Markdown’s choice of the backtick (`). But keep in mind this: I don’t have a problem with looking at my Org file and seeing (lots of) tildes. After all, font-lock does a good job of telling me that this is code. I have a problem with typing these tildes, since they require me pressing the shift key – and if I have a lot of small code snippets, this is not very comfortable. Add to this the fact that I happen to write in Markdown pretty often (when I use Markdown-based tools, like Slack or Jira), and I started wondering: why couldn’t I press the backtick in Org-mode to type a tilde (and vice versa so that I don’t lose the ability to type a backtick)?
-1:-- Making code snippets in Org-mode easier to type (Post)--L0--C0--January 17, 2022 08:12 PM

Jeremy Friesen: Switching from Company to Corfu for Emacs Completion

Thinking Through the Principle of Discovery

Both Company and Corfu are completion packages for Emacs 📖. Corfu’s README outlines alternatives, one of which is Company.

Why Corfu?

There are three considerations:

Corfu’s package is one .el file at 1220 lines of code and comments. Whereas Company’s package is many .el files, the company.el file alone is 3916 lines of code and comments.

That’s not to say that that is intrinsically bad, but Corfu’s narrow focus and adherence to the Emacs API 📖 means that the long-term maintenance of Corfu is likely easier.

But that is somewhat ideological. I primarily write Ruby on Rails software; a gigantic code-base. So as with all things ideological, I look towards pragmatism.

The actual “killer” feature of Corfu, which I’m sure I could implement in Company, is the export the popup completion candidates to the mini-buffer.

Embark on a Tangent

I spend quite a lot of time in Emacs’s mini-buffer: searching a project, invoking M-x (e.g., execute-extended-command) to look for Emacs commands, searching for matching lines via consult-line, etc.

Based on my configuration of Emacs, I annotate the mini-buffer with Marginalia. This helps me better understand the context around the candidates.

Throughout the day, I often rely on Embark’s embark-export for exporting those mini-buffer candidates to another buffer, the Embark Export Occur buffer; a buffer I the further search, edit, and manipulate.

Stay on Target

With Corfu, I can send the “pop-up” completion to the mini-buffer. And once in the mini-buffer I can use embark-export.

Below is the code, from the Corfu wiki for transferring the in region popup to the mini-buffer.

(defun corfu-move-to-minibuffer ()
  (interactive)
  (let (completion-cycle-threshold completion-cycling)
    (apply #'consult-completion-in-region completion-in-region--data)))
(define-key corfu-map "\M-m" #'corfu-move-to-minibuffer))

This means I can more thoroughly inspect the candidates recommended by the completion-at-point functions. See their marginalia, and if applicable export each one to an Embark Export Occur buffer for even further interaction.

Back to Principles

ago I wrote Principles of My Text Editor. As I’ve worked with Emacs, I’ve grown to appreciate it’s discoverability.

And Corfu’s ability to move a completion popup to the mini-buffer is a wonderful discoverability feature.

In moving from Company to Corfu I do lose out on the spiffy company-org-block package; which provides a nice convenience method.

In my mental rubric, I would rather have the ability to more thoroughly explore the completion candidates than a convenience function regarding source code in org files.

-1:-- Switching from Company to Corfu for Emacs Completion (Post Jeremy Friesen (jeremy@takeonrules.com))--L0--C0--January 17, 2022 06:27 PM

Sacha Chua: 2022-01-17 Emacs news

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

Also, thanks to Andrés Ramírez for some links to emacs-devel posts!

-1:-- 2022-01-17 Emacs news (Post Sacha Chua)--L0--C0--January 17, 2022 05:44 PM

Irreal: Exporting Variables From Org-mode to LaTeX

Franco Pasut has posted on exporting variables from Org to LaTeX. The TL;DR is that you can define LaTeX macros defining a variable value in #+LATEX_HEADER: entries at the top of the Org file and then interpolate the variables in the text by including \variable_name{} in the body of the document. That’s nice because it makes it easy to change the value of those variables, if needed, in one place and have the results reflected in the whole document.

The problem with this method is that it’s not portable. It’s great if you’re only exporting to PDF but if you want to also export to HTML, say, it won’t work. The proper way of handling the general case is to define the variables at the Org level as described by Mike Hamrick in his excellent video Consistent Technical Documents Using Emacs and Org Mode that I wrote about wrote about previously.

In either case, the idea of defining variables in one place and using their values throughout the document makes a lot sense precisely because it makes it easy to change those values when needed without scanning the entire document. Take a look Hamrick’s video to see how powerful the method can be.

-1:-- Exporting Variables From Org-mode to LaTeX (Post jcs)--L0--C0--January 16, 2022 05:05 PM

Emacs TIL: Idea: Get AI to write lisp!

After playing OpenAI and writing some elisp at the same time, I come up with this crazy idea: We can "outsource" the mechanical part of function/macro writing to AI.

We have seen how accurate Github Copilot helps autocomplete code in VSCode.

The interesting bit about lisp is that, it has powerful macros, which allows defining DSLs easily and create new programming languages. On the other hand, AI knows all programming paradigms as well as natural language texts.

Given a task, 1) we can define a function skeleton and get AI autocomplete a bunch of mundane functions, or 2) generate a list of steps in natural language, map them to lisp code (the structure should be close to natural language), and then AI writes macros & functions to "implement" that language!

The 2) idea is more interesting because AI is trained from existing code corpus. In a sense, we are crowd-sourcing the DSL generation with the help of AI.

Of course, I'm not an expert in AI or programming languages, and I have not yet tried to implement it. so take the idea with a grain of salt.

Thoughts? Feel free to leave me a comment.

-1:-- Idea: Get AI to write lisp! (Post Junji Zhi)--L0--C0--January 16, 2022 03:24 PM

Andrea: Moldable Emacs: translate string at point in multiple languages!

-1:-- Moldable Emacs: translate string at point in multiple languages! (Post)--L0--C0--January 16, 2022 12:00 AM

Irreal: Source Block Executors

Isa Mert Gurbuz (isamert) has a very interesting post on using Org Babel to interactively deal with Web APIs. Starting with Zweifisch’s ob-http, he queries a site and gets some JSON returned. The ob-http code even allows you to pipe the results through the jq binary to slice and filter the JSON results.

That’s pretty neat but what’s better is he shows us how to make the JSON results “executable”. It’s probably not clear what it means to “execute” JSON but the idea is simple: use can specify source block header parameters to specify filtering or other manipulation. The code to do this is simple and isamert gives an example of such code.
There are several examples in his post so take a look to see how it all works.

But wait! There’s more. JSON is an existing Emacs major mode but it’s possible to extend the idea to custom modes as well. The example isamert uses is for the Couchbase database. There’s no mode for Couchbase, so isamert created one by simply extending sql-mode. Then he wrote a function to take an SQL statement and send it to the Couchbase server. Again, that’s simple because Couchbase provides a command line tool. Finally, he wrote an executor for the Couchbase source block thereby providing an interactive Org-mode based tool to manipulate the database. Here’s an example of the its use (n1ql is the name of the mode):

#+begin_src n1ql :host DB_HOST :username DB_USERNAME :password DB_PASSWORD
  SELECT * FROM SomeTable LIMIT 10;
#+end_src

When he executes this block, the database is queried with the SELECT statement and the results are returned in a #+RESULTS: block as usual.

This is good stuff and has application outside of Web APIs so it’s well worth spending some time to read and understand isamert’s post even if you don’t routinely deal with Web APIs.

-1:-- Source Block Executors (Post jcs)--L0--C0--January 15, 2022 06:56 PM

Daniils Petrovs: Creating universal Emacs Lisp packages and scripts

A few weeks ago, I decided to create a dedicated Emacs package for work, which contains helpful commands specific to our team’s workflow. Of course, not everyone in the company uses Emacs as their editor (and you cannot expect them to). This problem got me thinking - how can I create a fantastic DevX for the Emacs users, but at the same time without leaving out non-Emacs users?

Emacs as a Lisp interpreter

Modern Emacs allows to not only byte compile (and even natively compile) packages, but also still interpret Emacs Lisp scripts in a completely headless way. This means that you can use the full power of a high level, homo-iconic language like Elisp to automate common chores, and also use all of the benefits of the highly productive Emacs development workflow. However, we also want to use this script as a normal Emacs package. This leads us into the next section.

How to make a package behave like a script

Unfortunately there are barely any guides on how to implement this polymorphic behavior, which is why I am writing this guide.

First, let’s create a minimal Emacs package and call it foo.el:

;;; foo.el --- Foo development and productivity utils  -*- lexical-binding: t; -*-

;;;###autoload
(defun bar ()
  "Print foo bar."
  (interactive)
  (message "Foo Bar!"))

(provide 'foo)

Next, to allow us to simply call the script as if it was a regular shell script, we need to add this shebang to the first line of the file:

#!/usr/bin/env emacs --script

This should locate emacs on almost any system, as well as switch on batch mode to interpret the script.

Next, let’s make a special “CLI” section at the end of the file, and also create a small predicate function to easily tell when the file is running as a script or not:

;;;; CLI

(defun foo-running-as-script-p ()
  "Return truthy if running as Elisp script."
  (member "-scriptload" command-line-args))

Finally, we need to define an entrypoint (think of it like a main in mainstream languages). I found that the simplest way is to create a main function and run it when the script is being interpreted:

(defun main ()
  "Entrypoint for foo"
  (pprint command-line-args-left)
  (message "Do stuff here"))
  
(when (foo-running-as-script-p)
  (main))

The best part is that you can use the same message and yes-or-no-p as you would with an Emacs package, and they will behave in an interactive way, even when executed from the command line.

One final thing to note: you might have to explicitly require some Elisp modules if you are using certain functions (e.g. cl-defun from cl-lib). The easiest way to tell which ones, is to try to execute your script interactively and add any missing modules like so:

(require 'cl-lib)

The full example looks like this:

Make the script executable with chmod +x foo.el and call it like so:

$ ./foo.el somearg
("somearg")
Do stuff here

Congratulations! You now have a universal Emacs package + script. Hopefully this guide has been helpful.

Honorable mentions

https://leancrew.com/all-this/2008/04/emacs-lisp-as-a-scripting-language/

https://kitchingroup.cheme.cmu.edu/blog/2014/08/06/Writing-scripts-in-Emacs-lisp/

-1:-- Creating universal Emacs Lisp packages and scripts (Post Daniils Petrovs)--L0--C0--January 15, 2022 04:40 PM

D.V.F.P.: Variables in LaTeX documents exported from Emacs Org Mode

Table of Contents

The usual introduction to Emacs, Org Mode and LaTeX

This is the usual introduction to Emacs, Org Mode and LaTeX: if you already know everything you can skip it.

Org Mode under GNU Emacs is a very powerful tool for organizing ideas.

An excellent features of this tool is its ability to directly export documents from Org Mode to LaTeX, the absolute excellence for pagination, as well as to other languages such as Markdown and HTML.

When exporting to LaTeX, you can add commands in the preliminary part of the documento in Org Mode, to customize the output in the final PDF document.

Variables are useful commands that allow LaTeX to automatically replace placeholders fields with names, numerical strings or any other combination of text and numbers.

You can find information on this topic in my previous article.

In the actual article I suggest some solutions for generating variables when exporting documents from Org Mode to LaTeX.

Preamble section in Org Mode for essential export to LaTeX with variables generation

Let’s see the following simple preamble into an Org Mode document:

#+LANGUAGE: en
#+AUTHOR: Name of the Author
#+TITLE: Title of the document
#+LATEX_HEADER: \newcommand{\myname}{Franco}
#+LATEX_HEADER: \newcommand{\mysurname}{Pasut}

The first line configures the english language (default), the line the author’s name and the third line the title of the document.

In the exported LaTeX document you will, then, automatically find the author’s name and the title in the front page.

Of course, other preliminary settings can be added, but this is not the subject of this article.

The lines dedicated to the export of the variables

It is, however, the last three lines that I would like to highlight.

The fourth line #+LATEX_HEADER: \newcommand{\myname}{Franco} creates a new variable called “myname” that will be replaced, in the exported LaTeX document, with the name “Franco”.

The fifth line #+LATEX_HEADER: \newcommand{\mysurname}{Pasut} creates a new variable called “mysurname” that will be replaced, in the exported LaTeX document, with the name “Pasut”.

Now you can scatter the variables \myname{} and \mysurname{}, or any other variable you want to create, in the Org Mode document and, then, get the automatic replacement in the document exported to LaTeX with the names you set, in this case Franco and Pasut.

Be careful not to use variable names that are reserved for the system Emacs: you will soon realise this because the variables will not be transformed correctly.

As you can notice above, variables are followed by a the blank space {}: it’s used to distance the names generated by the variables from the words immediately following them.

If, on the other hand, there is a punctuation mark after the variable, there is no need for such an addition.

Now, to export the Org Mode document to LaTeX you have to press C-c C-e ll or, if you want the automatic opening of the exported document in a PDF reader, C-c C-e lo.

Why variables?

But what’s the purpose of creating variables instead of names? Wouldn’t it be enough to write the content directly in the document?

Very simple: if in the document exported to LaTeX it is necessary to replace the names generated by variables with others, it will be enough to modify the variable assignment in the preamble and you won’t run the risk of leaving some “old” name all over the orginal Org Mode document.

It’s a solution particularly useful if you need to reuse the exported LaTeX document.

Thank you for your attention.

-1:-- Variables in LaTeX documents exported from Emacs Org Mode (Post)--L0--C0--January 15, 2022 12:00 AM

TAONAW: Punching in/out the org-mode way

One of org-mode’s features I started to use more frequently is the clocking of tasks. “Punching the clock” for each task I do was tedious at start, but with time it became a habit. This is a small addition to my workflow, but it comes with significant advantages.

There’s an option to start a running clock with org-capture (to automatically “punch in” whenever I create a task) but I don’t work that way. I often look at a large list of tasks and projects on my agenda, pick what I need to do next, and then start a clock as I work on it.

Sometimes I check in a project that is not scheduled for that day. This happens if I have extra time or if I’m doing something related to it. I leave the task scheduled for the original date but clock in. At other times, I clock in for tasks that are already done or canceled if I’m asked to review something. Whatever the case, it’s a way to navigate an otherwise organic and chaotic day. C a a l brings up the agenda buffer with the logged tasks, and it shows me what I’ve been working on and how many “chunks” I put into it1. It’s not always possible to be exact with the length of time I worked on a certain task. Sometimes I forget to clock in, so I add an approximate time duration after the act; at other times there might be a conflict between the org file on my phone and the desktop which I need to correct. What’s important to me is that I know I worked on the task that day.

Since I record notes and separate the entries with an inactive timestamp, there’s also a rough correlation between the logs and the notes. For example, say I have a task called “plan a trip”. I punch in, and then go online to look for hotels. I create an inactive timestamp inside the task under the properties drawer (C-u C-c C!) and type down notes about the prices of different locations and their availability. When I’m done, I punch out. Later I can review my agenda and I see that I was working on “plan a trip” and if I want to know what I did I can check my notes and refer to that time stamp as well. The timestamp is so easy to include, it just comes naturally as a log entry to me.

Using the clock like that adds another layer of “doing stuff”. I use the scheduled tasks as a reference of importance, which also roughly translates to when I want to do it in the day. This keeps the clock logs as a record that I actually did get to the scheduled task and did some work on it, since I often reschedule my tasks as well.

Footnotes


  1. I sometimes have something I call a “boomerang” task. This is usually a bigger task or a project which I want to work on for a large amount of time. Since I know I’m going to get interrupted and can’t just keep working on one thing, I “boomerang” it: I keep returning to it and punching in and out of the clock throughout the day. This allows me to keep track of projects and chisel my way at larger undertakings. ↩︎

-1:-- Punching in/out the org-mode way (Post)--L0--C0--January 14, 2022 05:00 AM

Jeremy Friesen: Emacs Packages to Get Stuff Done

Recording and Replaying Keystrokes

, I was working on the Forem codebase. Part of the toolchain at Forem 📖 is that we run Rubocop auto-correct on any files we commit. We use Husky to manage our pre-commit hook.

With auto-correction, we sometimes might get a surprise change. To avoid that surprise change, when we our linters, we try to remember to run the linters against the entire repository. That is not always something we do.

And I got one of those surprises. I wrote a pull request that helped avoid future sneaky auto-corrects.

But I want to write about what I did via Emacs 📖 and the command line.

The Steps in the Process

I took the following steps:

  1. Run Rubocop Auto-Correct.
  2. Run Rspec on a Directory.
  3. Use Emacs to Quickly Remove the Specs.

Run Rubocop Auto Correct

Rubocop—a Ruby 📖 code style checking and code formatting tool— has numerous “cops” that each check the code for one conceptual thing.

You can run Rubocop on a subdirectory and specifying a single “cop” to run. Below is the “cop” I ran on the app/models directory, I specified to auto-correct any offenses:

$ rubocop app/models \
  --only "Rails/RedundantPresenceValidationOnBelongsTo" \
  --auto-correct

There output was as follows:

102 files inspected, \
27 offenses detected, \
27 offenses auto-correctable

With the --auto-correct switch, the above call to rubocop changed the code.

Run RSpec on a Directory

At Forem, we use RSpec. With rubocop changing the models, I wanted to see how this impacted their specs.

$ rspec spec/models

There were 22 failures, which is less than the number of auto-corrects. Looking at the failures they all had the following form:

Failure/Error: it { is_expected.to \
  validate_presence_of(:author_id) }

Excellent, these appear to all be consistent in structure. There were two of the form it { is_expected.to validate_presence_of(:relation) }. I found those when I re-ran the specs. And I quickly remediated them by hand.

Use Emacs to Quickly Remove the Specs

I ran the following commands:

consult-ripgrep
Limiting to files in spec/models, I search for validate_presence_of _id). My consult-ripgrep configuration uses fuzzy finding. In essence, my find will look for lines that have both validate_presence_of and _id) in the same line.
embark-export
Export the search results to a new buffer.
kmacro-start-macro
I recorded, by typing, the following key sequence RET 2*C-k C-d M-o n, more on that later.
kmacro-end-macro
End the recording of the macro.
kmacro-call-macro 21 times
Run the just recorded macro 21 times (one for each of the remaining specs to adjust).
M-x save-some-buffers
Write the changes made in the embark buffer to their corresponding files.

For purposes of explaining what’s happening, I said I called kmacro-start-macro, kmacro-end-macro, and kmacro-call-macro. That’s not quite true, I used kmacro-start-macro-or-insert-counter and kmacro-end-or-call-macro. Those are mapped (by default?) to F3 and F4. But from a writing and explaining standpoint, the underlying functions make a bit more sense.

The Keyboard Sequence

The key sequence for kmacro-start-macro assumes:

  • I’m starting in the search results buffer.
  • I have two windows open, one for the search result buffer and one for “work”.

Below, I write about the key macro and what it does:

RET
Open the source file and line for selected search result.
Ctrl + k twice
Delete to the end of line and delete that now blank line. See jnf/kill-line-or-region for more details.
Ctrl + d
Delete the leading blank space.
Alt + o
Jump back to the search result buffer. See ace-window for more details.
n
Move to the next line in the search results buffer.

While recording keyboard macro, I could see what I was changing. I took my time to type and think what I wanted to do.

I recorded the macro, felt comfortable with it, and told Emacs to run it 21 more times. I could have instead mashed on the F4 key twenty one (21) times.

Conclusion

First, I did all of this from a clean Git 📖 repository state. This allowed me to make potentially sweeping changes with confidence of being able to revert.

I often use Embark’s embark-export; creating a buffer with a list of candidates. I can interact with the candidates, save the buffer for later, or further narrow those candidates with a different command.

What’s the list of candidates? In the above example, it’s search results. But it can be more than that. I often pair embark-export with wgrep. Wgrep allows you to edit a grep buffer and apply those changes to the file buffer like sed 📖 interactively. Wgrep’s functionality is now a must have for my text editor.

It took me over a year of using Emacs to even start recording and using keyboard macros. In I wrote Principles of My Text Editor.

Nowadays, I’m usually recording a disposable macro every other day. The more I use Emacs the more I learn and adjust how I can tell Emacs to do more work for me.

-1:-- Emacs Packages to Get Stuff Done (Post Jeremy Friesen (jeremy@takeonrules.com))--L0--C0--January 13, 2022 03:38 PM

Irreal: The Second Emacs 28 Pretest

Some more splendid news from the Emacs front: the second Emacs 28 pretest is out. There’s a lot of great features coming in Emacs 28 so please give it all the testing you can.

It always seems as if progress is excruciating slow but this is the developers making sure that when Emacs 28 is released, it will be rock solid. As always, I want to thank all the developers donating their time and energy to help bring this latest release to us.

-1:-- The Second Emacs 28 Pretest (Post jcs)--L0--C0--January 12, 2022 05:56 PM

Jeremy Friesen: Resolving an Unable to Resolve Link Error for Org Mode in Emacs

Documenting to Share a Solution

I’ve been dabbling with the org-transclusion package. But I encountered an odd behavior somewhere in my Org-mode 📖 and Org-roam 📖 configuration.

What Worked and What Didn’t

I had a source org file. I linked to the target org file in another directory via the target’s id property. In my source I had the equivalent of [[id:org-id-get-create][Name of Target]]. The org-id-get-create is a placeholder (and the name of the function I used to generate the target’s ID).

When I would open the target link in my buffer, I would jump to the target document. As expected.

However, when I attempted to use the org-transclusion functions or export (via org-export-dispatch) the org document to another format, I got the following error:

Unable to resolve link: org-id-get-create

I thought this had something to do with my directory structure. But it worked to link to other files in the same directory as the target.

Poking Around Through Source Code

I tried rebuilding my org-roam database (e.g., M-x org-roam-db-clear-all then M-x org-roam-db-sync) but that didn’t work.

In the source file, I ran org-lint. That generated reported what looked to be the same error message.

So I dug further into the org-lint method. There I learned about the org-lint--checkers variable. The registered functions that are called to lint a document. I went looking through that list and found a likely culprit: org-lint-invalid-id-link.

The org-lint-invalid-id-link function lead me to the org-id-find function. Which in turn called org-id-find-id-file id. And there I found the following code bit of code: (unless org-id-locations (org-id-locations-load)).

Huzzah! Org-mode was generating a cache! Somewhere there must be a cache invalidation or update function.

So I went looking for functions like the org-id-locations-load. I found org-id-update-id-locations and org-roam-update-org-id-locations.

I ran the org-id-update-id-locations and it reported processing several files, but certainly not enough. I thenorg-roam-update-org-id-locations; that function call reported a lot of processed files.

Hoping that this update of a cache would resolve my problem, I went back to the previously broken source document. Both org-transclusion and org-export-dispatch worked.

Capturing the Knowledge

I wrote a function that is now part of my Emacs 📖 configuration; the purpose of the function is to help remind me how to fix this problem if it shows up again.


;; I encountered the following message when attempting
;; to export data:
;;
;; "org-export-data: Unable to resolve link: FILE-ID"
(defun jnf/force-org-rebuild-cache ()
  "Rebuild the `org-mode' and `org-roam' cache."
  (interactive)
  (org-id-update-id-locations)
  ;; Note: you may need `org-roam-db-clear-all'
  ;; followed by `org-roam-db-sync'
  (org-roam-db-sync)
  (org-roam-update-org-id-locations))

I don’t envision running that function all that much, but it will be a bit of written memory of this debugging.

Conclusion

First, navigating Emacs functions is amazing. Emacs provides powerful introspection.

I used helpful.el to jump to the documentation of a function, and kept jumping deeper. I used M-x paired with marginalia.el to look for similar named functions.

Pairing helpful.el and marginalia.el (and many other packages), I could do ever narrowing work and when I needed to expand my focus.

In fact, it was so easy to navigate I did it twice. First when debugging and then when writing this blog post.

Second, taking the time to write this up, I hope I help other folks (including my future self).

-1:-- Resolving an Unable to Resolve Link Error for Org Mode in Emacs (Post Jeremy Friesen (jeremy@takeonrules.com))--L0--C0--January 12, 2022 03:37 AM

Alain M. Lafon: Configuring default applications for xdg-open

-1:-- Configuring default applications for <code>xdg-open</code> (Post Alain M. Lafon (munen@200ok.ch))--L0--C0--January 12, 2022 12:00 AM

Irreal: Emacs Calc Video

Over at the Calculator Culture Youtube Channel they have a nice Introductory video on the GNU Emacs calculator otherwise known as Calc. The thing about Calc is that’s it’s gigantic. It’s not Mathematica but it seems like it can do practically anything mathematical that you need.

The problem with Calc is neatly captured by Karthink in a reddit comment:

“The problem with Calc is that it’s got a big learning curve for anything more than simple arithmetic, and it doesn’t stick in the head because of the terse and arcane UI (even for Emacs) for the higher level functions. I have to relearn how to access most of the above every time I fire it up.”

This is exactly what I find. Calc does so much that I find it impossible to remember most of the advanced features unless I’m using one of them constantly. As soon as I stop that constant use, I forget the more abstruse parts.

The video is only 13 minutes, 21 seconds long so it doesn’t begin to cover all of Calc but it does give you an idea of some of what it can do. The good news is that it’s easy to learn and remember the basic functions so you always have a useful calculator at hand when you’re in Emacs. I use it as my desktop calculator and couldn’t be happier with it.

-1:-- Emacs Calc Video (Post jcs)--L0--C0--January 11, 2022 05:50 PM

Eric MacAdie: 2022-01 Austin Emacs Meetup

Last week there was another meeting of EmacsATX, the Austin Emacs Meetup.

I discovered that the two most recent write-ups were included in Sacha Chua’s Emacs news roundup. I guess that makes me the unofficial scribe.

If you have read any of these recent write-ups, you will not be surprised to read there was no set agenda. Do not make this a drinking game. However, The Organizer [Note 1] did ask for topics at the beginning rather than at the end.

Member #1 [Note 2] spoke about sockets and domain sockets for about ten minutes. When we decided to start talking about Emacs, there was some silence.

Member #2 started talking about projects in Doom Emacs. Their Org file had different level in different font sizes. Their Emacs terminal looked like a tag cloud. I do not know much about projects in Emacs. I will add that to my ever-growing to-do list in my ever-growing Org file. I have worked with projects before (Maven, Gradle, Rails, etc), but I am just not sure what Emacs has to offer. Perhaps there is an EmacsConf video that talks about projects. I just started going through the EmacsConf videos; I am on the third for 2013.

Member #2 also talked about circadian. It is a mode that changes your theme based on the time of day.

Members #2 and #3 started talking about themes. Both of them worked on themes. Member #3 pointed out that many themes do things differently, and if you switch themes that some of the attributes of the first theme are still in the system. Perhaps something could be done about the process of making themes.

Lastly people started comparing Clojure to Emacs Lisp. The consensus was most people liked Clojure better, mostly due to its data structures and destructuring abilities. The Organizer implemented the Clojure comment macro in Emacs Lisp.

Note 1: “The Organizer” does sound like it could be a cool nickname if you know how to work it. “I am here to kick ass and run through our agenda, and as usual we don’t have an agenda.”

Note 2: I give people numbers since I do not know if they want their names in this write-up. Think of it as the stoner’s version of the Chatham House Rule. I figured that numbers are a little clearer than “someone said this, and someone else said that, and a third person said something else”. For the record, there were about seven people there.

Image from Gospels Codex 56, a 9th century manuscript of the  Archbishop’s Diocesan and Cathedral Library in Cologne, Germany, assumed allowed under Public Domain.

-1:-- 2022-01 Austin Emacs Meetup (Post Eric MacAdie)--L0--C0--January 11, 2022 07:52 AM

Isma: Emacs for Rust Development

Emacs > Visual Studio Code There's a good chance I'm a hater or that I don't know what I'm doing.
-1:-- Emacs for Rust Development (Post)--L0--C0--January 11, 2022 12:00 AM

Marcin Borkowski: Simple tmux scripting revisited

Some time ago I wrote about my (very simple) tmux script. Since then I started to like tmux even more, and in fact I tend to create a similar script for every major project I work on. Last time, however, I noted how the sleep part is very fragile (and less than elegant). Since then I realized that I do not need any advanced scripting to run command Y in tmux window B when command X in window A finishes its job. In fact, this is very simple, and I’m ashamed I didn’t think about it earlier.
-1:-- Simple tmux scripting revisited (Post)--L0--C0--January 10, 2022 09:59 PM