Irreal: Annotating a Text File

Chewxy had a need to annotate a text file. He wanted to mark a rectangle of text, capture a classification type, and write the results to a JSON file. He thought about writing a Web app to do it but realized that as an Emacser, it would quicker and easier to write a little Elisp instead.

The result was a minor mode to annotate a text file. To make an annotation, he just highlights the text, captures the resulting rectangle and the annotation, and writes it to the JSON file. That’s all pretty straightforward but there are a few subtleties mostly involving writing the JSON file, and using the mouse to mark the region.

One thing that was not hard was turning his functions into a minor mode. It’s just a matter of adding a bit of boiler plate and a couple of functions to turn the mode on and off.

The source code for the project is here. Note that the link in Chewxy’s post is broken.

-1:-- Annotating a Text File (Post jcs)--L0--C0--September 18, 2021 06:37 PM

T. V. Raman: Snarfing String Within Delimiters With One Defun

Snarfing String Within Delimiters With One Defun

1 Executive Summary

I found that I frequently needed to snarf a string enclosed within delimiters, e.g., URLs in email messages <url>, bolded, italics and other styled text in org-mode etc. I first tried package ciel but found that it did not handle all the delimiters I wanted. However looking into it further revealed that emacs had all the tools needed to reduce the task to a single defun!

2 The Solution

Here is the solution I implemented at emacspeak-wizards-snarf-sexp. invoking this command with point on the opening delimiter snarfs the enclosed string into the kill-ring; an optional prefix arg clears it as well. The code below is the same as in the Emacspeak project, but with emacspeak-specific calls removed:

(defun snarf-sexp-contents (&optional delete)
  "Snarf the contents between delimiters at point.
Optional interactive prefix arg deletes it."
  (interactive "P")
  (let ((orig (point))
        (pair nil)
        (pairs ;;; The delimiter pairs:
         '((?< ?>)
           (?\[ ?\])
           (?\( ?\))
           (?{ ?})
           (?\" ?\")
           (?' ?')
           (?` ?')
           (?| ?|)
           (?* ?*)
           (?/ ?/)
           (?- ?-)
           (?_ ?_)
           (?~ ?~)))
        (char (char-after))
        (stab nil)) ;;; Syntax table we  use
    (unless (setq pair (assoc char pairs)) ;;; Not on a delimiter 
      (error "Point is not on a supported delimiter"))
    (setq stab (copy-syntax-table))
    (with-syntax-table stab
      (cond
       ((= (cl-first pair) (cl-second pair)) ;;;Like quotes
        (modify-syntax-entry (cl-first pair) "\"" ) 
        (modify-syntax-entry (cl-second pair) "\"" ))
       (t;;; Like parens 
        (modify-syntax-entry (cl-first pair) "(")
        (modify-syntax-entry (cl-second pair) ")")))
      (save-excursion;;; We have our sexp 
        (forward-sexp) ;;; Will error out if delims dont match
        (cond
         (delete ;;; Clear sexp contents 
          (kill-region (1+ orig) (1- (point))))
         (t ;;; Copy sexp contents
             (kill-ring-save (1+ orig) (1- (point)))))))))

2.1 Key Take-Aways

  • S-expressions are a key Emacs concept with extensive built-in support.
  • S-expressions are determined by matching delimiters.
  • Delimiters are defined by the syntax-table in effect.
  • Emacs-lisp primitives let us define and manipulate temporary syntax-tables.
  • Putting it all together, the underlying task of snarfing the contents within a pair of delimiters reduces to a few calls to the underlying primitives.
-1:-- Snarfing String Within Delimiters  With One Defun (Post T. V. Raman (noreply@blogger.com))--L0--C0--September 18, 2021 04:46 PM

Tim Heaney: rename command

Yesterday, the new Bad Bad Hats record was released, so I downloaded it from Bandcamp! cd ~/Music/BadBadHats mkdir Walkman cd !$ unzip -l ~/Downloads/Bad\ Bad\ Hats\ -\ Walkman\ \(pre-order\).zip Don't mind that pre-order bit, it's the full record. Let's unzip it! ❯ unzip ~/Downloads/Bad\ Bad\ Hats\ -\ Walkman\ \(pre-order\).zip Archive: /home/tim/Downloads/Bad Bad Hats - Walkman (pre-order).zip extracting: Bad Bad Hats - Walkman - 01 Walkman.flac extracting: Bad Bad Hats - Walkman - 02 Detroit Basketball.
-1:-- rename command (Post)--L0--C0--September 18, 2021 12:00 AM

Tim Heaney: Haskell

Debian supplies lots of packages for Haskell. Bullseye supplies version 8.8.4 of the compiler, which is new enough for me, so I'm just going to install haskell-platform. sudo apt install haskell-platform sudo apt install haskell-platform-doc haskell-platform-prof It suggested the docs and profiling tools too. ❯ ghc --version The Glorious Glasgow Haskell Compilation System, version 8.8.4 Now I want to get the Haskell language server so I can use it from Emacs.
-1:-- Haskell (Post)--L0--C0--September 17, 2021 12:00 AM

Tim Heaney: Photos

Shrink I wrote shrink to shrink images before using them on the web. It has a few options, but I usually just change to the directory with the new images in it and run shrink Exif As a side effect, it also removes the Exif data. That saves me the trouble of applying the mighty ExifTool as I normally do. exiftool -all= *.
-1:-- Photos (Post)--L0--C0--September 16, 2021 12:00 AM

Irreal: Time Tracking With Org-mode

I’m Bmax has a post about his journey to find the perfect way to track his time. Like almost everyone else, he started with a spreadsheet but if you’ve ever done that you know what a pain it is and how hard it is to keep it up. He tried a few other solutions before settling on Emacs and Org-mode.

The thing that makes tracking your time with Org-mode so easy is that you just put the point on a task and clock in. When you’re finished or clock into another task, Org records the start and end time so that the time spent on a task is easily available. It doesn’t end there, of course. Org can produce reports on the total time spent on various task with a single key sequence.

I’m Bmax seems happy with his Org solution. It’s just a matter of clocking in and out of the task Org entries he needs in any event. In my experience, the time tracking comes later. You start with recording tasks or some other item and then realize that you can easily track how much time you spend on them with a simple key sequence.

Lots of people use Org mode to track their time for billing purposes and even produce their bills from the Org data. The nice thing about using Org is that you can simply record the times or use it to produce reports or bills on the time you spent on various tasks.

-1:-- Time Tracking With Org-mode (Post jcs)--L0--C0--September 15, 2021 06:37 PM

Tim Heaney: exFAT

I'm done with the bootable thumb drive I used to install Debian 11 with, so now I want to reformat it. If you want to format a thumb drive, you probably want to make it exFAT. Debian 11 uses Linux kernel 5.10 $ uname -r 5.10.0-8-amd64 which has native support for exfat! There is a new package for it called exfatprogs sudo apt install exfatprogs So the exfat-fuse package is no longer required
-1:-- exFAT (Post)--L0--C0--September 15, 2021 12:00 AM

Eigenbahn: Graphing my External Brain with Org-Roam

org-roam-ui

An External Brain

I have a terrible memory…

And like most folks dealing w/ software architecture, I have to deal w/ a humongous amount of information.

So I take notes. Lots of them.

In fact I’ve extended this practice to every subjects I work on / study, with extensive cross-referencing.

The trick is not to remember stuff but to find it back quickly.

My current setup1 is pretty straightforward: I use Org mode inside Emacs. To quickly search a piece of information I use deft or sometimes deadgrep.

The combination of these tools + my collection of notes act like an external brain.

Digital Gardening & Zettlekasten

My notes are organized in a very specific way.

I organize them hierarchically under subfolders.

I like mid-sized files, only splitting them when they attain a critical mass in term of size or complexity.

This practice of building and maintaining a personal wiki, as old as the world itself, is now getting qualified of digital gardening2. Indeed, you just don’t add content but have to regularly reorganize it, like you would clear a patch of soil.

I also stumbled upon the Zettelkasten Method and liked its idea of bidirectional links3 but quickly rejected one aspect of its philosophy: creating many many small files, one for capturing each incoming thought.

Indeed, bidirectional links allow for a very fluid way to structure information (akin to what you may find in a graph database).

Still, I like to impose some structure, a taxonomy loosely based on how I mentally represent things. Having to deal with a gazillion files would not imped finding information back, but would discourage me from regularly gardening my notes.

So while I adhered to the digital gardening philosophy, I rejected (my understanding of) Zettelkasten.

Org-Roam

I discovered Org-Roam through its accompanying visualization tool: Org-Roam-UI.

It’s an extension to Org to provide it a similar feature set to Roam, the most famous Zettlekasten software.

Even if I didn’t buy to the Zettlekasten philosophy, the ability to graph all the notes relationships dynamically was tempting.

I took a quick look around and realized that the implementation isn’t too intrusive:

  • relies on the native org-id feature
  • uses a local SQLite DB, but it’s only a cache that is easy to prune and re-create4

Furthermore, in its latest iteration it supports:

  • recursive parsing of the notes directory
  • having note titles different from file names

So I didn’t see any reason not to try it.

Indexing Existing Notes

Things worked smoothly, but I was struggling to find a command to register existing notes in Org-Roam’s DB.

Calling org-id-get-create would allow generating an org id for current file / outline. But that wasn’t sufficient to make it appear.

Indeed, I also had to register it in the org-id-locations-file by passing the current file path to org-id-update-id-locations.

Finally, I needed to call org-roam-db-update-file for Org-Roam to update its DB entry for the current file.

This gives:

(defun prf/org-roam/add-index-current ()
  "Add index to file of currently visited buffer, if applicable."
  (interactive)

  (unless (and (buffer-file-name)
		       (file-exists-p (buffer-file-name)))
    (user-error "Current buffer is not visiting a file that exists on disk."))

  (unless (prf/org/file-path-indexable-p (buffer-file-name))
    (user-error "Current buffer is not visiting an indexable file."))

  (unless (org-id-get)
    (org-id-get-create)
    (call-interactively #'save-buffer))

  (org-id-update-id-locations (list (buffer-file-name)))

  (org-roam-db-update-file))

Forcing Index of All Files

Sometimes I like to massively rename / move / delete note files and Org-Roam doesn’t seem to be super happy about this.

Using the same logic as above, I came up w/ the following command:

(defun prf/org-roam/rescan ()
  "Force rescan of whole `prf/dir/notes'."
  (interactive)
  (prf/org/index-rescan-all)
  (org-roam-db-sync))

(defun prf/org/index-rescan-all ()
  "Populate `org-id-locations' by rescaning recursively all files in `prf/dir/notes'."
  (interactive)
  (let ((buffs-snapshot (buffer-list)))
    (org-id-update-id-locations
     (f-files prf/dir/notes #'prf/org/file-path-indexable-p t))
    ;; NB: `org-id-update-id-locations' opens all matching files, we close them after processing
    (mapc #'kill-buffer
          (-difference (buffer-list) buffs-snapshot))))

Conclusion

I’m pretty happy with this setup.

The Org-Roam-UI helps me visualize the current structure of my notes and has helped me discover patterns and anomalies I had no idea existed.

Notes

  1. I originally started w/ Tomboy, then moved to MediaWiki, Markdown and finally to Org as soon as I started using Emacs. 

  2. It’s more than an empty buzzword. Lots of effort has been put on studying and qualifying this phenomenon. Don’t hesitate to browse the rest of Maggie Appleton’s site to learn more. 

  3. Not supported natively by Org as of writting. I was circumventing this limitation by creating a link in each of the 2 cross-referenced files. 

  4. This DB is just a cache, a derived data systems (i.e. materialized view). The system of record are the org files themselves. Hence there is no risk of unrepairable corruption. 

-1:-- Graphing my External Brain with Org-Roam (Post)--L0--C0--September 15, 2021 12:00 AM

Irreal: Another Emacs Configuration

As you all know—at least if you’ve been around Irreal for a while—I like reading through other peoples Emacs configurations. It’s not just a matter of voyeurism; I almost always learn something from seeing how others use Emacs. The latest example is this post from Supratim Samanta.

It’s in the form of an Org file so there’s a bit of explanation included. Samanta has all the usual use cases

  • Coding
  • Documentation with Org-mode
  • Elfeed
  • Magit
  • Evil for the Vim experience

It’s a fairly extensive configuration so there may be ideas lurking in it that you’ll find useful. Take a look and see.

-1:-- Another Emacs Configuration (Post jcs)--L0--C0--September 14, 2021 05:53 PM

Tim Heaney: Bounce

One more thing to add to my new desktop computer. Bounce I wrote bounce to convert a bunch of sound files to mono by calling SoX. It requires LAME for MP3 support. sudo apt install sox libsox-fmt-mp3 go install github.com/oylenshpeegul/bounce@latest We also need wodim (formerly cdrecord) when we want to burn a CD. sudo apt install wodim cdrkit-doc
-1:-- Bounce (Post)--L0--C0--September 14, 2021 12:00 AM

Irreal: Two Mini Tutorials

Here are a couple of mini-tutorials on using two Emacs packages. They’re both pretty short so I’ve combined them into a single post. In the first, Yuri Tricys presents some configurations and packages to customize Olivetti-mode. He shows how to adjust the margins, toggle the fringe on and off, and configure wrap and fill columns, He also shows using the highlight-numbers and the stripes packages.

Unfortunately, Tricys doesn’t provide any examples of the output but most of his configurations are self explanatory. If you’re a writer who uses or is considering using Olivetti-mode, take a quick look at Tricys’ post.

The second tutorial is by Franco Pasut and considers using expand-region with LaTeX. Many Irreal readers are probably familiar with expand-region from using it with their programming buffers but it’s also useful for dealing with LaTeX source. Pasut has a series of animated GIFs that show it in action. Judging from the GIFs, expand-region has some shortcomings when used with LaTeX as compared to other languages. For example, I’d expect the highlighting to go from word to sentence and then to paragraph.

Of course, Magnar anticipated that people would want to add capabilities and made that easy. If you’re really interested in using expand-region with LaTeX, you should look into adding the features you need.

-1:-- Two Mini Tutorials (Post jcs)--L0--C0--September 13, 2021 03:33 PM

Sacha Chua: 2021-09-13 Emacs news

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

-1:-- 2021-09-13 Emacs news (Post Sacha Chua)--L0--C0--September 13, 2021 12:00 AM

Phil Hagelberg: in which not everything is static, but most things are

The Fennel programming language recently celebrated its fifth birthday, and we ran a survey to learn more about the community and what has been working well and what hasn't. Fennel's approach has always been one of simplicity; not just in the conceptual footprint of the language, but in reducing dependencies and moving parts, and using on a runtime that fits in under 200kb. In order to reflect this, the Fennel web site is hosted as static files on the same Apache-backed shared hosting account I've been using for this blog since 2005.

Of course, generating HTML from lisp code is one of the oldest tricks in the book[1], so I won't bore anyone with the details there. But what happens when you want to mix in something that isn't completely static, like this survey? Well, that's where it gets interesting.

I put the shotgun in an Adidas bag and padded it out with four pairs of tennis socks, not my style at all, but that was what I was aiming for: If they think you're crude, go technical; if they think you're technical, go crude. I'm a very technical boy. So I decided to get as crude as possible. These days, though, you have to be pretty technical before you can even aspire to crudeness.[2]

When I was in school, I learned how to write and deploy Ruby web programs. The easiest way to get that set up was using CGI. A CGI script is just a process which is launched by the web server in such a way that the request comes in on stdin and environment variables and the response is sent over stdout. But larger Ruby programs tended to have very slow boot times, which didn't fit very well with CGI's model of launching a process afresh for every request that came in, and eventually other models replaced CGI. Most people regard CGI as somewhat outmoded and obsolete, but it fits Fennel's ethos nicely and complements a mostly-static-files approach.

So the survey generates an HTML form in a static file which points to a CGI script as its action. The CGI script looks like this, but it gets compiled to Lua as part of the deploy process to keep the dependencies light.

(let [contents (io.read "*all")
      date (io.popen "date --rfc-3339=ns")
      id (: (date:read "*a") :sub 1 -2)]
  (with-open [raw (io.open (.. "responses/" id ".raw") :w)]
    (raw:write contents))
  (print "status: 301 redirect")
  (print "Location: /survey/thanks.html\n"))

As you can see, all this does is read the request body using io.read, create a file with the current timestamp as the filename (we shell out to date because the built-in os.time function lacks subsecond resolution) and prints out a canned response redirecting the browser to another static HTML page. We could have printed HTML for the response body, but why complicate things?

At this point we're all set as far as gathering data goes. But what do we do with these responses? Well, a typical approach would be to write them to a database rather than the filesystem, and to create another script which reads from the database whenever it gets an HTTP request and emits HTML which summarizes the results. You could certainly do this in Fennel using nginx and its postgres module, but it didn't feel like a good fit for this. A database has a lot of moving parts and complex features around consistency during concurrent writes which are simply astronomically unlikely[3] to happen in this case.

At this point I think it's time to take a look at the Makefile:

upload: index.html save.cgi thanks.html 2021.html
    rsync -rAv $^ fennel-lang.org:fennel-lang.org/survey/

index.html: survey.fnl questions.fnl
    ../fennel/fennel --add-fennel-path "../?.fnl" $< > $@

save.cgi: save.fnl
    echo "#!/usr/bin/env lua" > $@
    ../fennel/fennel --compile $< >> $@
    chmod 755 $@

pull:
    rsync -rA fennel-lang.org:fennel-lang.org/survey/responses/ responses/

2021.html: summary.fnl chart.fnl questions.fnl responses/* commentary/2021/*
    ../fennel/fennel --add-fennel-path "../?.fnl" $< > $@

So the pull target takes all the raw response files from the server and brings them into my local checkout of the web site on my laptop. The 2021.html target runs the summary.fnl script locally to read thru all the responses, parse them, aggregate them, and emit static HTML containing inline SVG charts. Then the upload task puts the output back on the server. Here's the code which takes that raw form data from the CGI script and turns it into a data structure[4]:

(fn parse [contents] ; for form-encoded data
  (fn decode [str] (str:gsub "%%(%x%x)" (fn [v] (string.char (tonumber v 16)))))
  (let [out {}]
    (each [k v (contents:gmatch "([^&=]+)=([^&=]+)")]
      (let [key (decode (k:gsub "+" " "))]
        (when (not (. out key))
          (tset out key []))
        (table.insert (. out key) (pick-values 1 (decode (v:gsub "+" " "))))))
    out))

The final piece I want to mention is the charts in the survey results. I wasn't sure how I'd visualize the results, but I had some experience writing SVG from my programmatically generated keyboard cases I had constructed on my laser cutter. If you've never looked closely at SVG before, it's a lot more accessible than you might expect. This code takes the data from the previous function after it's been aggregated by response count and emits a bar chart with counts for each response. Here's an example of one of the charts; inspect the source to see how it looks if you're curious:

Linux-based (43) MacOS (11) Windows (6) Other BSD-based (4) Linux-based: 43, MacOS: 11, Windows: 6, Other BSD-based: 4

I had never tried putting SVG directly into HTML before, but I found you can just embed an <svg> element like any other. The <desc> elements even allow it to be read by a screen reader.

(fn bar-rect [answer count i]
  (let [width (* count 10)
        y (* 21 (- i 1))]
    [:g {:class :bar}
     [:rect {: width :height 20 : y}]
     [:text {:x (+ 5 width) :y (+ y 12) :dy "0.35em"}
      (.. answer " (" count ")")]]))

(fn bar [i data ?sorter]
  ;; by default, sort in descending order of count of responses, but
  ;; allow sorting to be overridden, for example with the age question
  ;; the answers should be ordered by the age, not response count.
  (fn count-sorter [k1 k2]
    (let [v1 (. data k1) v2 (. data k2)]
      (if (= v1 v2) (< k1 k2) (< v2 v1))))
  (let [sorter (or ?sorter count-sorter)
        answers (doto (icollect [k (pairs data)] k) (table.sort sorter))
        svg [:svg {:class :chart :role :img
                   :aria-label "bar graph" :aria-describedby (.. "desc-" i)
                   :width 900 :height (* 21 (+ 1 (length answers)))}]
        descs []]
    (each [i answer (ipairs answers)]
      (table.insert svg (bar-rect answer (. data answer) i))
      (table.insert descs (.. answer ": " (. data answer))))
    (table.insert svg [:desc {:id (.. "desc-" i)} (table.concat descs ", ")])
    svg))

{: bar}

In the end, other than the actual questions of the survey, all the code clocked in at just over 200 lines. If you're curious to read thru the whole thing you can find it in the survey/ subdirectory of the fennel-lang.org repository.

As you can see from reading the results, one of the things people wanted to see more of with Fennel was some detailed example code. So hopefully this helps with that, and people can learn both about how the code is put together and the unusual approach to building it out.


[1] In fact, the HTML generator code which is used for Fennel's web site was written in 2018 at the first FennelConf.

[2] from Johnny Mnemonic by William Gibson

[3] If we had used os.time with its second-level granularity instead of date with nanosecond precision then concurrent conflicting writes would have moved from astronomically unlikely to merely very, very unlikely, with the remote possibility of two responses overwriting each other if they arrived within the same second. We had fifty responses over a period of 12 days, so this never came close to happening, but in other contexts it could have, so choose your data storage mechanism to fit the problem at hand.

[4] This code is actually taken from the code I wrote a couple years ago to handle signups for FennelConf 2019. If I wrote it today I would have made it use the accumulate or collect macros.

-1:-- in which not everything is static, but most things are (Post Phil Hagelberg)--L0--C0--September 12, 2021 04:51 AM

Tim Heaney: Debian bullseye

I got a new desktop computer a couplafew years ago and partitioned the hard drives and installed Debian 10 alongside the proprietary OS that came with it. Now Debian 11 has been released, but rather than upgrade I did a reinstall. I hadn't used the other OS much (at all?), so I decided to reclaim that disk space. Here are the things I did to install and configure Debian bullseye.
-1:-- Debian bullseye (Post)--L0--C0--September 12, 2021 12:00 AM

Irreal: Prot on Bookmarks

Protesilaos Stavrou has a new video out on the Emacs bookmarks system. If you don’t use bookmarks, you should give them a try. They’re really handy for files you use often but don’t want to keep loaded all the time. Where they really shine for me is hard-to-find nodes in the info system. For example, I always have a hard time finding the Emacs syntax class information so I set a bookmark to pop me right into the info page.

If you use bookmark+ you can even use bookmarks to call a function or load a page in your browser. I have a bookmark to load Irreal, which is useful when writing and posting to the site. I’ve been using bookmark+ for a long time so I’m no longer sure what functionality is also in the default bookmark package.

If you want to integrate bookmarks into your workflow, I can’t recommend stealing abo-abo’s workflow enough. He uses a hydra and his headlong package to make opening a bookmark every efficient. Here’s the hydra entry I use for opening bookmarks

("m" headlong-bookmark-jump "bmk")

I’ll let you read the details at the above link but the TL;DR is that you can specify a bookmark with a single key in most cases. Thus, to open the aforementioned syntax node, I simply type Hyper+w m s and the page opens. The Hyper+w invokes a hydra that I use for window and buffer related operations. The m says to jump to a bookmark and the s specifies the syntax class info node.

The video is 24 minutes, 20 seconds long so plan accordingly. As always with Prot’s videos, it’s worth spending a few minutes on.

-1:-- Prot on Bookmarks (Post jcs)--L0--C0--September 11, 2021 03:53 PM

Emacs APAC: Announcing Emacs Asia-Pacific (APAC) virtual meetup, Saturday, September 25, 2021

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

Irreal: Enabling Multiple Minor Modes

Timo Geusch has a nice quickie post on setting multiple minor modes for a buffer. Often it’s convenient to have several minor modes associated with a buffer. For example, when I’m writing blog or prose text I like to have

  1. visual-line-mode
  2. wc-mode
  3. flyspell-mode

turned on and auto-fill-mode turned of. That’s enough modes that it’s inconvenient to set them by hand. The normal solution is to turn them on in the local variables list at the top or bottom of the file.

# -*- eval: (visual-line-mode 1); eval: (auto-fill-mode -1); eval: (wc-mode 1); eval: (flyspell-mode 1;) -*-

That works well and is what I do for non-blog writing but you have to take some sort of action to get it into each buffer such as including it or copying it by hand.

Geusch has another solution. He wrote a simple function to turn on the minor modes he needs and then runs that function in a hook for the type of buffer he’s interested in. That’s really easy if you use the use-package macro to configure your packages because you can use its :hook keyword to cause the function to be called. See Geusch’s post for the details and sample code.

It’s a simple idea and easy to implement but it can make your workflow a bit easier. Definitely worth taking a look at.

-1:-- Enabling Multiple Minor Modes (Post jcs)--L0--C0--September 10, 2021 04:28 PM

Manuel Uberti: Grep's good rep

Look around this blog and you will find nice words about ripgrep. I especially enjoy how I can plug it into Emacs, like the time when I devised my own Helm commands for it.

However, roughly a year ago I started my journey to a more vanilla Emacs experience. During this time I have been slowly moving away from the niceties of ripgrep in order to stick to a couple of built-in tools: rgrep and vc-git-grep. Now, technically speaking, both this commands rely on external tools, grep and git grep. Why should I use these instead of ripgrep? Personal preferences, of course: grep is readily available on Ubuntu and git is the first tool I install when upgrading to a new LTS from Canonical1.

Furthermore, I rarely need the power of ripgrep. Your experience may be different on this, but the size of my projects does not scare neither grep nor git grep. For instance, I regularly use vc-git-grep on Emacs sources, which amounts to something like 2,755,361 lines of code2, and the performances are just fine for me.

The only thing I usually do not need from these commands is the prompt for the file types to look into.

(defun mu-recursive-grep (search-term search-path)
  "Recursively search for SEARCH-TERM in SEARCH-PATH."
  (interactive
   (progn
     (unless grep-command
       (grep-compute-defaults))
     (let ((search-term (grep-read-regexp))
           (search-path (expand-file-name
                         (read-directory-name
                          "Directory: " nil default-directory t))))
       (list search-term search-path))))
  (if (vc-root-dir)
      (vc-git-grep search-term "*" search-path)
    (rgrep search-term "*" search-path)))

I combined the two commands to make it simpler. When I am in a Git-versioned project (i.e., vc-root-dir is not nil) mu-recursive-grep runs vc-git-grep; otherwise, it’s time for rgrep to shine. As trivial as it might look, the fact that the last two lines of mu-recursive-grep look similar is what made it easier for me to devise a common wrapper. Emacs describe system is always invaluable for discoveries such as this.

One last thing. When in a project, if I want to find where the thing at point is used I do not need mu-recursive-grep. For this task project-find-regexp (C-x p g) is enough3, but mu-recursive-grep is still helpful when I want to narrow the search down to a specific path.

Notes

  1. I do it manually and I use Ansible Playbooks to set up the new system. 

  2. That’s what scc tells me today, anyway. 

  3. C-h v xref-search-program shows that ripgrep can be used instead of the default grep. Hence you can keep ripgrepping if that’s what you prefer. 

-1:-- Grep's good rep (Post)--L0--C0--September 10, 2021 12:00 AM

Philip K.: What I'd like to see done in Emacs

There are a few things I think would be good to see implemented in and around Emacs, but I don’t know if I will find any time soon to do so properly. There is no pride in hiding ideas one thinks might be worthwhile, so I’d like to share them here:


More deriving from prog-mode

Major modes can “derive” functionality from other modes, similar to how classes can inherit from one another in OOP.

For example: Customizing prog-mode-hook should affect all programming languages. I think this is a good thing, that makes maintaining Emacs easier: I want flyspell-prog-mode, abbrev-mode, display-line-numbers-mode, etc. to be enabled in every programming mode by default, but I don’t have to add it to every mode I might end up using manually.

The issue is this: The concept of deriving could go a lot further, and defining new major modes for programming languages could be a lot less repetitive.

So how about this: Instead of just deriving-prog-mode directly, further “abstract” modes are defined for different types of programming languages: interpreted-prog-mode, compiled-prog-mode, interactive-prog-mode. These define their own commands, such as complied-prog-mode-compile, interactive-prog-mode-eval, etc. that are used instead of custom commands for each actual mode. Their behaviour is generic, and depends on the actual mode deriving these intermediate modes.

The immediate advantage is that the user has less to learn. All interactive modes open a REPL the same way via C-z, all compiled modes compile a project using C-c C-k. Every programming mode has C-c C-f bound to a formatting command. Of course, if a functionality is not available for a certain language, a warning is issued.

It might even be possible to provide a macro that makes defining these modes even easier:

(define-interpreted-prog-mode python-mode
  :eval #'python-mode-eval
  :format #'python-mode-format
  ...)

that then expands to a define-derived-mode and finally a regular major mode definition.

Of course such a change might be very intrusive, especially when changing the keybindings, as no compromise can be found. I can imagine two mitigation strategies, assuming such a feature should even be included into the core:

  1. Generic major modes are enabled manually, either all at once or one-by-one. They will not interfere with existing definitions, unless the user expressly permits this.
  2. Different maps are provided, emulating exiting conventions in popular major modes. By default these might emulate the old mode, but this should be easily reconfigurable.

Something along these lines could also be done for markup languages.

(See also)

A forwards-compatibility library

Previously, I have expressed my lack of enthusiasm towards libraries such as dash, s, f, ht, …

Despite stylistic and other disagreements, one has to admit that even just a few years ago these libraries met a real need to simplify programming with Elisp. However, for a while now code Emacs has improved, and provides many functionalities it previously lacked.

The issue is that these have been added in successive versions of Emacs, and it is understandable that a package maintainer might not want to depend on the newest version, especially when older versions are still in circulation, e.g. by being packaged by Debian and CentOS.

So how about this: A library that provides at least strict subsets of functions and variables that have been defined in a more recent version of Emacs.

So while subr-x defines string-clean-whitespace in version 28.1, and the same version provides length< is written in C the motivation to use this code in a package is limited by the fact that it is not worth excluding most Emacs users for a little convenience.

Instead, one could depend on compat.el, the compatibility library. This would provide a copy of string-clean-whitespace and a reimplementation of length< that would only be loaded for versions older than 28.1.

The effect would hopefully be that packages can turn around: Instead of looking backwards at what was supported in version 24.1, they can look ahead and use what is new, without fragmenting the language.

(See also)

Local packages with package.el

An issue with package.el is that it is not easy to safely modify packages installed from an package archive. With each update, all your local changes can be overridden, and there is no way to store these changes in a VCS.

Most packages on the other hand are managed by some VCS (git, hg, CVS, …), but it requires some work OOTB to make that work. My workaround is a mix of this and the thread linked to below.

So how about this: package.el is added support for managing and initializing local packages. Maybe this means new packages can be installed by giving M-x package-install a URL, maybe this means packages can be installed by cloning them into ~/.emacs.d/elpa/. Either way, a local package should be automatically byte-compiled and autoloaded.

M-x list-packages might also be able to update these packages, by fetching new commits, and if possible merging them with local customizations.

The intention is to provide a low-maintenance method of managing packages the user might want to work on, and perhaps contribute their improvement upstream.

(See also; as far as I know a library called straight.el is comparable to what I am describing, but it rejects package.el instead of extending it. I have not tried it for this reason, so I cannot say.)

Semantic faces

Someone in my local Emacs user-group suggested this once, and I think it would be nice to see. The issue is this: Do M-x list-faces-display, and a buffer will appear. This buffer documents all the faces Emacs knows of, and shows you how they look like.

On closer inspection, especially the more packages a user might have installed, one might notice duplication. A lot of faces that indicate “good” things are green, a lot of faces that indicate “bad” things are red. Most markup modes also define similar faces, for similar concepts, that go beyond the basic bold, italic, bold-italic, …

So how about this: A package consisting mainly of face declarations, and uncontroversial/uncreative defaults. That’s it.

The effect would be that packages do not have to define as many faces, and instead can reuse the ones defined in such a package. My hope would be to see two effects:

  1. More consistent visual hints and design
  2. Less effort in defining new themes: Instead of adding support for every package, a theme just has to modify the semantic faces.

It could be discussed whether or not these faces should be used as they are, or if they should be derived. If I had to decide, I think the former would be preferable from a performance and consistency standpoint.

Package installation hints

I think it is good for packages to minimize their UI. Provide as little as possible, let something else do as much work as possible: Be lazy! For example: If implementing a syntax checker for some language Blub, don’t implement a minor mode that generates overlays, defines commands for introspection, etc. Instead, implement a Flymake backend. That way you have less to deal with, while users have less to configure.

But there might still be something to configure. add-hook, add-to-list, global-set-key, etc. might have to be used.

So how about this: A package can provide machine-readable hints, on how a package can be configured. It might for example want to express that all you need is to add

My idea (see below) was to use a list pacakge-configuration-suggestions like this

(add-to-list
 'pacakge-configuration-suggestions
 `(avy
   (key                             ; type of suggestion
     "Jump to a specific character" ; explanation
     ,(kbd "C-:")                   ; key to bind
     avy-goto-char)                 ; command to bind
   (key                             ; etc.
     "Jump to a specific word"
     ,(kbd "C-'")
     avy-goto-word)))

but it might also make sense to reuse the customize interface, and add an attribute to user options with hints. package.el could find these and inform the user about possible options when installing a package (or later when requested manually).

The question then remains if this should just set an option and hide what is being done, or if actual code should be generated? The first way is easier, The latter is preferable if you want to teach users how to configure Emacs. It might even be able to generate use-package and setup.el code from these hints all together.

(See also)

(Persistent and caducous) selection interface

I remember being charmed by completing-read and related functions. It was the missing abstraction that distinguished Emacs as a “shell” from the classical Unix shells. And it is true: completing-read provides an interface from both a programmer and user perspective, that can be used for a wide variety of cases. The popularity of “completion frameworks” such as Ivy, Helm, Vertico, … prove this point.

But the abstraction might have turned out to be leaky. Consider the “type” of completing-read: It maps a set (list, alist, hash table, …) of strings to a single string. OOTB this is clear, as pressing TAB just completes the user input as bash might do in a terminal session. The “completion frameworks” take the liberty of interpreting the interface differently. The focus is placed on narrowing and selecting elements of the set. Technically, both are interpretations are acceptable.

Issues emerge when developers assume more than the interface provides, and rely on specific front-ends. For example: “selection” makes it easier to choose in non-ascii text, “completion” handles multiple selections well.

From a developer perspective, the issue of being returned a string can be inconvenient. Especially when the intention is to select an item from a set, the text representation has to be mapped back on to the actual object. This is cumbersome, but also restrictive, because multiple objects might share a common representation (e.g. two buffer might have the same name).

So how about this: If we want selection, we do selection. A function, selecting-read, choose-selection, select-ephemeraly or whatever is created that maps a list to an element of the list. Each element has to be able to generate a text representation, that is used by the selecting function to represent it to the user.

I have tried implementing this, and it looked something like this

Selecting a city

As I was designing a new interface, I decided to add the ability to define hierarchies and attributes to items via cl-generic. The idea was that you could filter items by attributes, fold and show children, etc. In this example is also displays a buffer on the side, instead of the bottom of a frame as most completion frameworks do.

This might also be extended to a select-persistently function that doesn’t return an object, but attaches actions to objects that are executed on selection. Maybe select-consistently could be updated based on what the user is doing, and provide context sensitive options to suggest (In that case M-number key could be bound to easily select an option).

An older version of the code can be found here. I continued working on it, but my implementation was too slow and unstable.

(See also)

A cleaner Gnus, a more powerful Rmail

Gnus can be… unintuitive. But after using Rmail for a while, I still prefer it when it comes to functionality

Gnus it is not a mail client, it is a very extensible news reader. Rmail felt nicer when handling mail, not only because it is more light weight. But it lacks too many features I enjoy using, and the code is difficult to work on.

So how about this: A Emacs MUA that explicitly is written for Mail, yet extensible to handle multiple backends, while keeping configurations simple.

Again, I have sketched out a rough design based on cl-lib. Ideally the configuration should just consist of giving a list of mail sources:

(setq nmail-sources '((maildir "~/Mail/Personal")
                      (maildir "~/Mail/Professional"
                               :address "john@job.com")
                      (news "emacs.devel" :server "news.gmane.io")))

Where “Nmail” is a reference to “Rmail”, as I would like it to have a similar UI (message first, list second).

The user would then enter M-x nmail, select a inbox, and just do what they want to do.

Admittedly, this is not that creative of an idea. “What we have now, just better and a new name” is standard industry practice. Not only that, but there are a lot of MUAs in Emacs, and I haven’t tried them all. It might be that what I want already exists, at least to a close enough approximation.

Regular expression objects

(Note: This is the idea I am least sure about, because it involves the C-part of Emacs, and my experience with that part of the code is limited.)

I am not even sure if this is an issue, but I always wondered why regular expressions are always handled as strings. Couldn’t they be compiled to increase performance? Especially considering that they currently are used for a lot of highlighting.

So how about this: A new reader syntax for regular expressions.

#r<GNU \([eE]macs?\)*\'>

On the one hand, this should make quoting easier, and improve the highlighting of the syntax. But a the same time, they represent a compiled and perhaps optimised matcher object. All the functions that accept regular expressions (search-forward-regexp, string-match, looking-at, …) would have to support this addition, and handle these matcher objects properly.

Maybe this is premature optimisation, maybe might speed things up. I don’t really know.


This turned out to be longer than I initially though. I’m just glad I don’t have to keep remembering these ideas, and noticing that I still haven’t done anything.

My hope is that someone might pick up on these ideas up before I do, in which case I would be glad to discuss, collaborate and contribute. Just send me a message!

-1:-- What I'd like to see done in Emacs (Post)--L0--C0--September 09, 2021 09:29 PM

Irreal: Embedding Images in Text Files

Yuan Fu likes to take notes in which he can embed images. You can do that with Org, of course, but Fu doesn’t like that Org’s solution boils down to a link to a file. That means you have to keep the file paths in sync. He wanted a solution that embedded the image in the file and made it easy to resize the image on the fly.

To a first approximation, his solution is simple: Embed the image as a Base64 string at the bottom of the buffer and put an internal link to it at the point to where it is to appear. Of course, there are complications. First, there’s handling the resizing. That’s not too hard but there are also display issues such as having reasonable scrolling. Fu has some animated screenshots that show this in action. It appears to work well.

The code does not appear to be in Melpa and Fu doesn’t say whether he plans to submit it but it’s a single file and should be easy to load and try out. If you have a need to permanently embed images in a file and don’t want to have to worry about keeping file paths in sync, this is a good solution.

-1:-- Embedding Images in Text Files (Post jcs)--L0--C0--September 09, 2021 04:19 PM

Phil Jackson: Delta for Git & Magit

I was just introduced to a tool called Delta which is a pager you can use with Git to give you Github-esque diffs.

Magit and Delta

Tiny bit of elisp to configure:

(use-package magit-delta
  :ensure t
  :hook (magit-mode . magit-delta-mode))

Delta itself is incredibly configurable and from the command line has some nice features such as side-by-side diffs.

-1:-- Delta for Git &amp; Magit (Post)--L0--C0--September 09, 2021 01:58 PM

Emacs NYC: November 2020 Lightning Talks

Check out our previous post for our wrap up of November 2nd, 2020.

Raymond Puzio — emacs hypernotebooks

WebM (97 MB) | MP4 (549.6 MB)

Qiantan Hong – crdt.el, a collaborative environment

WebM (44.2 MB) | MP4 (267.1 MB)

Qiantan Hong – reflexive-music, an experimental music environment with Emacs as frontend

WebM (59.4 MB) | MP4 (413.3 MB)

Zachary Kanfer – Composing Electronic Music in Emacs

WebM (36 MB) | MP4 (180 MB)

-1:-- November 2020 Lightning Talks (Post)--L0--C0--September 08, 2021 04:09 PM

Jean-Christophe Helary: Building "vanilla" emacs on macOS, with brew, and more...


Table of contents

  1. Free software = build your software yourself
  2. Required dependencies for building emacs on macOS
  3. Extra dependencies that will add features to your emacs
  4. 8 lines of instructions
  5. emacs documentation
  6. To use emacs from the command line
  7. Updating the code requires 2 instructions
  8. Free Software = you can write code and contribute
  9. References

This is Free Software!

Lots of people seem to wonder, "what is the best emacs for macOS"?

Their criteria for "best" being not always clear, the answer I systematically give is: "Clone the repository and build it yourself. This is free software!"

Since I always forget the dependencies and the steps, this page is a memo for myself, and for curious people who want to try themselves.

Note: I am not a programmer. I just follow instructions. There is nothing magic in the 8 instruction lines that follow. Before, or after you've cloned emacs, you can read the INSTALL.REPO file where basically everything I write here is found, along with the README and the INSTALL files where you'll find additional or redundant information. It's basically all there. I am not making this up.

ToC

Required dependencies

The dependencies below are the minimum emacs requires, and you can find them by running ./autogen.sh first and then ./configure yourself before using brew to install them: the two scripts will just choke every time they don't find the required libraries.

What I did to come up with that list is just add dependencies until the scripts ran their course without error.

If this is your first "development" attempt, you will need the XCode command line tools, basically because you'll need gcc and git for the whole process.

brew will prompt you about that during its install process, and even if that does not happen, the first time you run git, for example to clone emacs, macOS will tell you that you need to install them and prompt you with a nice dialog.

The required dependencies are the following:

  • Autoconf
    "Autoconf is an extensible package of M4 macros that produce shell scripts to automatically configure software source code packages."
  • texinfo
    "Texinfo is the official documentation format of the GNU project."
  • GNU Mailutils
    "Mailutils is a swiss army knife of electronic mail handling. It offers a rich set of utilities and daemons for processing e-mail."
  • GnuTLS
    "GnuTLS is a secure communications library implementing the SSL, TLS and DTLS protocols and technologies around them."

ToC

Extra dependencies

I sent the link to this article to the emacs-devel mailing list for verification and Pankaj Jangid was nice enough to tell me about his own experiences and suggested a list of non-required but recommended packages that emacs would notice during the configuration process. Alan Third, the ns-port maintainer, also chimed in to indicate that some of Pankaj proposed libraries were in fact ignored since the image types they correspond to are handled by macOS proper.

The recomended dependencies are the following:

  • librsvg
    "This is librsvg - A small library to render Scalable Vector Graphics (SVG), associated with the GNOME Project."
  • libxpm
    "X11 pixmap library"
  • lcms2
    "Little CMS intends to be a small-footprint color management engine, with special focus on accuracy and performance."
  • jansson
    "Jansson is a C library for encoding, decoding and manipulating JSON data."

If you want to install the above recommended dependencies, you'll need to add a brew install instruction as shown below.

ToC

The instructions


# install brew
# URL: https://brew.sh
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# install required dependencies
# or jump to "configure, etc." below and install them one by one
brew install autoconf texinfo gnutls mailutils

# install recommended dependencies, but only after you've checked what they do by following the links above...
brew install librsvg libxpm lcms2 jansson

# clone emacs
# URL: https://savannah.gnu.org/projects/emacs
git clone -b master git://git.sv.gnu.org/emacs.git

# configure, build and install emacs
cd emacs
./autogen.sh
./configure
make install

Et voilà! Emacs.app now resides in emacs/nextstep/Emacs.app.

ToC

Documentation

I don't suppose you'd want to install emacs from scratch without knowing how to use it, but if that's the case, and that's totally OK, emacs comes with thousands of pages of manuals that are just a ctrl-h i away.

That shortcut means hit the control key, hold it pressed, hit the h key, release both, and hit the i key. That shortcut calls the info function, which bring up the list of manuals included in emacs.

You can also start a tutorial with ctrl-h t, which means hit the control key, hold it pressed, hit the h key, release both, and hit the t key. That shortcut calls the help-with-tutorial function.

The manuals are online, if you feel more confortable reading in a web browser: GNU Emacs Manuals Online

ToC

A few extra settings

If you need to use emacs from the command line you may need to update your .profile file with aliases like this:


alias emacs='path/to/emacs/nextstep/Emacs.app/Contents/MacOS/Emacs'
alias emacsclient='path/to/emacs/nextstep/Emacs.app/Contents/MacOS/bin/emacsclient'
alias ctags='path/to/emacs/nextstep/Emacs.app/Contents/MacOS/bin/ctags'
alias ebrowse='path/to/emacs/nextstep/Emacs.app/Contents/MacOS/bin/ebrowse'
alias etags='path/to/emacs/nextstep/Emacs.app/Contents/MacOS/bin/etags'

and that's basically it.

ToC

Updating the thing

The first time you build emacs, along with installing all the dependencies, etc. might take some time, maybe a good 30 minutes, maybe more. But then, you end up with a configuration where you just need to update the code once in a while, and make install the thing again to have the latest version running.

Basically, all is needed is to run this:


# inside the cloned emacs directory
# update the code
git pull

# build and install the new version
make install

And the next time to start emacs, you run the lastest master branch code.

ToC

This it Free Software! 2

The whole point of Free Software is that is gives you the tools necessary to understand what is going on, to learn how to do things yourself and to control your environement.

So, yes, emacs is free software, and now you're all set to play with the code and do your own thing, that will eventually lead to first contribute small things, and then bigger and bigger things to emacs proper.

For that, you just need to create your own development branch and code there:


# inside the cloned emacs directory
# update the code, just to have the latest one
git pull

# create your development/test branch, for example "myEmacs"
git checkout -b myEmacs

# open that new branch in Finder
open .

Everything you do there will never impact the master branch from which you have built emacs. You can always git checkout master back to go back to a clean slate (git will eventually ask you to git stash away your modifications before switching to master, so just follow the instructions).

ToC

References

Now, you may want to know a bit more about Emacs Lisp, about git, about how to contribute to emacs, so here are some references:

  • The "Introduction to Programming in Emacs Lisp" is the entry point for Emacs Lisp development. It is available from inside emacs (type ctrl-h i to find the list of manuals available right at your finger tips) and also online:
    An Introduction to Programming in Emacs Lisp
  • git comes with excellent documentation, and a free book too:
    Git Documentation
  • If you want to practice your Emacs Lisp skills, the "Exercism" site has a track for you:
    Emacs Lisp on Exercism
  • You will quickly find that you need to have a good Emacs Lisp reference to go further. emacs provides you with an excellent reference for pretty much everything you need to know, here again, just a ctrl-h i away, but it is also online:
    GNU Emacs Lisp Reference Manual
  • If you need general help, there is a help-gnu-emacs list and for development help there is the emacs-devel list, along with a lot of other emacs related lists, hosted on the emacs development site:
    emacs - Mailing Lists
  • And here is a tutorial about the procedure to follow if you want to propose your code for inclusion into emacs, by Colin Woodbury:
    Contributing to Emacs

ToC

-1:-- Building "vanilla" emacs on macOS, with brew, and more... (Post suzume (noreply@blogger.com))--L0--C0--September 08, 2021 05:48 AM

jao: a high signal to noise emacs command

Over the years, i've written perhaps hundreds of little emacs commands. Most of them looked useful at the time (why, i absolutely needed them!), but just faded away after a few weeks. There are a handful though that i use all the time, and i specially like it when their signal (features, usefulness) to noise (lines of code) ratio is above average. Here's one with a surprisingly high one:

(defun jao-buffer-same-mode (&rest modes)
  "Pop to a buffer with a mode among MODES, or the current one if not given."
  (interactive)
  (let* ((modes (or modes (list major-mode)))
         (pred (lambda (b)
                 (let ((b (get-buffer (if (consp b) (car b) b))))
                   (member (buffer-local-value 'major-mode b) modes)))))
    (pop-to-buffer (read-buffer "Buffer: " nil t pred))))
-1:-- a high signal to noise emacs command (Post)--L0--C0--September 08, 2021 12:37 AM

Protesilaos Stavrou: Primer on Emacs bookmarks

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

In this video I offer an introduction to the built-in bookmarking framework of Emacs. Bookmarks are compartments that store arbitrary data about files/contexts that we can retrieve on demand. They can potentially work with practically every major-mode inside of Emacs and can interface with other core features such as TRAMP to, e.g., restore an Eshell buffer over a particular file access protocol.

The video also briefly covers my custom extensions for the bookmarks’ list view as well as my handler function for making EWW compliant with the standard bookmark.el library instead of its own bookmarking facility.

All configurations and custom code are published on this website as part of my dotemacs: https://protesilaos.com/dotemacs. The link includes references to the Git sources.

-1:-- Primer on Emacs bookmarks (Post)--L0--C0--September 08, 2021 12:00 AM

Timo Geusch: Automatically enabling multiple Emacs minor modes via a major mode hook

In Emacs, I usually end up enabling the same set of minor modes when I use one of my “writing modes”, namely modes like markdown-mode and org-mode. Enabling a single minor mode automatically is generally pretty easy via the appropriate mode hook, but enabling more than one minor mode requires one more level of indirection. Of course it does, because everything in computer science requires one more level of indirection :).

-1:-- Automatically enabling multiple Emacs minor modes via a major mode hook (Post Timo Geusch)--L0--C0--September 07, 2021 07:15 PM

Irreal: Apropos Library

Recently a post by jao, who’s written a whole bunch of excellent software, popped up in my feed inbox. It’s just a very short (15 words) mention of apropos-library, a function that lists all the variables and functions in a library. It can also be configured to show the keybindings for the functions.

Apparently it’s been around since Emacs 23 but neither jao nor I were aware of it. It seems like a useful facility. Even though you won’t need it often, it’s easy to see how it could be really useful in certain circumstances. It’s already installed so give it a try to see how it works.

-1:-- Apropos Library (Post jcs)--L0--C0--September 07, 2021 05:26 PM

This Month in Org: August 2021

Dear readers, unfortunately I've been unusually busy as of late, and will continue to be for a bit over a month. As such, it's entirely likely that the next post or two may be late make use of creative dates too.

In terms of Org development, we've had a fairly slow month --- mostly tweaks and fixes, concentrated on the new org-cite functionality. However, there have been big developments with Roam as of late.

Org-roam v2

Pushed to the sidelines by last month's hugely significant citations announcement was the release of Org-roam v2 🎉. The project's author Jethro wrote a nice blog post outlining the major changes and motivations, and so I'll leave him to speak on that. Suffice to say, the idea of org-roam has been refined into a form that should better server tinkerers looking to build off Org roam, and make maintenance easier --- thus improving the user experience in the long term 🙂. Should you be worried that the v1 -> v2 upgrade will be painful, read Org-roam v2 doesn't hurt, relax, and try the upgrade wizard.

Org-roam-ui

Within a month of Roam v2's announcement, we were pleasantly surprised by the release of org-roam-server usurper --- org-roam-ui.

org-roam-graph-2d-overview.png Figure 1: org-roam-ui's 2D overview.

While org-roam-server remains incompatible with Roam v2, org-roam-ui is built around v2 from the ground up. With this shift comes a much more ambitious set of features. The graph view itself is now based on react-force-graph, which allows for both 2D and 3D views of the graph, with WebGL acceleration.

Using emacs-websocket, org-roam-ui establishes a two-way connection between Emacs and the Web visualisation. This allows for nifty features like syncing the graph view and the currently open roam file in Emacs. Furthermore, with xwidget-webkit you can even embed org-roam-ui inside Emacs![fn1]

org-roam-ui-in-emacs.png Figure 2: Embed org-roam-ui in Emacs using xwidget-webkit.

Beyond this, org-roam-ui also provides a number of other nice features, such as filtering and theme syncing, with more in the works. To see more, check out the README published on GitHub.

/github.com/org-roam/org-roam-ui

New ConTeXt exporter

We've long been able to export to LaTeX files with ox-latex, but now you can export to ConTeXt too with ox-context! While only just released, a lot of work has already gone into this --- with development starting almost a year ago by the commit history.

//github.com/Jason-S-Ross/ox-context

It's always nice to see more export options for Org, and I wish Jason all the best in developing ox-context.

Other improvements Refactor oc-natbib.el, oc-biblatex, oc-basic.el, org-compat.el to improve byte compilation Maxim Nikulin Nicolas Goaziou Marco Wahl Allow for selecting cite style with a citation argument Nicolas Goaziou Add support for Italian "smart quotes" DPDmancul Fix Spanish mistranslation in footnote Documentation Juan Manuel Macias Define \citeprocitem in oc-csl.el for use by citeproc-el TEC Fix error in org-export-define-backend docstring Zachary Kanfer Nicolas Goaziou Document the :results none option Yasushi Shoji Other documentation improvements: Jorge Neto Marco Wahl Bugfixes When tangling a certain language, be more careful about which blocks are matched DMG, Nicolas Goaziou Make q in org-agenda work even when debug-on-error is set Lars Ingebrigtsen Make org-attach work again for Emacs \(< 28\) Kyle Meyer, Marco Wahl Make rx usage in org-cite files compatible with Emacs \(< 27.1\) Max Nikulin Prevent ' from becoming a LaTeX active char in exports using oc-csl TEC Have org-colview dynblock match and mixlevel interact sensibly Nick Dokos Behave appropriately when ffap-url-regexp is nil, instead of throwing an error Peder Stray TEC Footnotes

[fn1] I have found the xwidget-webkit experience quite unstable until I started using Emacs 28 with the pure-GTK branch. So, if you're not getting a good experience now, there's a good chance you'll have a better experience in the future.

-1:-- August 2021 (Post TEC (tec@tecosaur.com))--L0--C0--September 07, 2021 04:00 PM

Marcin Borkowski: My experience with book writing

This is a rather atypical post in that it is just a bunch of thoughts about how to write a book, how not to write a book, how I’ve been writing my book on Emacs Lisp, what was easy, what was difficult etc. If you want to write a book, it might be useful to learn where a fellow author struggled – note however, that this post reflects my personal experiences and your situation, personality, experience, work style etc. may be similar or completely different. Also, this post is quite long, and – let’s say – not extremely structured. It is just a collection of thoughts, some of which might be useful, entertaining or interesting to someone – or not. You have been warned;-).
-1:-- My experience with book writing (Post)--L0--C0--September 06, 2021 06:31 PM

Phil Hagelberg: in which a laptop defies the trends

Over the years I've been a consistent[1] user of Thinkpads; early on because I liked the keyboards, but then later just because I wanted hardware that would last a long time rather than a machine with a soldered-in battery that's designed to be more disposable.

thinkpad x301

My most recent device was a Thinkpad X301 built in 2008 which I started using in 2016. While it's no speed demon, using Firefox with uBlock Origin configured to block 3rd-party scripts by default left it feeling quite usable for my purposes, and the physical design of the device was perfect. They used a rubberized coating for the chassis in the X301 that I haven't seen in any other model that feels really nice on the palm rest. Unfortunately while nearly every component of that machine has withstood the test of time, the battery has not. The original battery's charge is down to around 90 minutes, and while it's swappable, working new batteries in this form factor simply cannot be purchased for any amount of money. I bought from two separate vendors claiming to have original batteries, but both of them sold me a battery which ballooned up and became unusable after a month or two.

When I started to look for replacements I was dismayed. So many of the newer models had fallen into the Appleization trap—everything must be made as thin and as glossy as possible at the expense of every other concern. I don't want a thin laptop! I want a laptop where I can look at it and see what's displayed on the screen instead of my own face staring back at me. It seemed it was still possible to find a model with a replaceable battery, but even this basic feature was becoming increasingly rare.

mnt reform in a hammock

A couple years ago I became aware of the MNT Reform laptop, and it seems like the perfect antidote to the mistakes the entire industry seems dead-set on repeating. It's a laptop that's focused on open design with schematics freely available and all parts easily serviceable by the end user. Finding this was like a breath of fresh air; it's like someone was finally listening to my frustrations.

an Apple ][ computer with its case open

The MNT Reform has been described as "the anti-macbook" which I think is fitting, but ironically I prefer to think of it as the Apple ][ of laptops (in a good way). If you're like me and you're fed up with thin laptops, you will be pleased to see that this machine is chonky. It has to be in order to have room for its three most unique features: a mechanical keyboard, a trackball, and a standardized 18650-cell battery bay. Originally the batteries were what caught my attention after all the trouble I'd had buying replacements for my Thinkpad, but when I saw the mechanical keyboard I knew I had to have one. (But also: can we talk for a second about the audacity of producing a laptop with a trackball? Much respect.)

Part of having an open design is having everything documented. While you can get the schematics for everything from the motherboard PCB to the 3D printed trackball buttons, the part that nearly everyone will benefit from is the excellent Operator Handbook which describes the usage of the system in detail.

bottom view of reform with components and PCB visible

Other than the thick size, perhaps the most eye-catching feature of the Reform is its transparent bottom plate, which is laser cut from acrylic. Similar to the open lid of the Apple ][, it invites you to take a look inside and reminds you that this machine isn't magic: it's wires and capacitors and screws and connectors. It's physical parts you can understand and control.

This machine isn't perfect though; there are trade-offs. The four ARM Cortex A53 cores in the CPU do not perform any out-of-order or speculative execution, which means they are not vulnerable to attacks like Spectre and Meltdown, but at the cost of speed. (I'm using it mostly for chat, email, and developing the Fennel compiler, and it's plenty fast for that.) The lid closes with a satisfying magnetic snap, but it doesn't have a lid sensor, so you'll have to turn off the screen yourself. The stock wifi antenna's range is quite limited. (But you can easily replace it!) Suspend is currently not super reliable, but there are ongoing efforts to improve that.

reform kb

The keyboard is ... well, it's head-and-shoulders above any other laptop keyboard I've tried. Instead of a comically huge space bar, the bottom row is broken up into a reasonably-sized space bar plus several other useful keys. But it's still frustrating in a few ways. (Note that I'm a major keyboard nerd who has spent a lot of time getting my keyboard setup just right and I am far more picky about this kind of thing than most people!) While you can reprogram the keybord firmware to reassign keys with ease, the physical layout is very awkward. It has a conventional row-stagger which is not great but also not unusual. The problem is that in most row-staggered boards each row is offset from the one above it by 1.25 key widths or so, and on the Reform it's 1.5. Even 1.25 is too much (zero would be ideal), but 1.5 makes it so you have to contort your hand even more to hit keys on the "ZXCV" row.

Of course, it's a hackable laptop! Reprogramming the firmware to rearrange the keys can't fix problems with the physical arrangement, but I've built hundreds of keyboards by hand, so I planned to do design and construct one from scratch for my Reform when I got it. Unfortunately it's a little more complicated than I anticipated; the stock keyboard is integrated with the system controller which is involved with powering on the entire system and controls the OLED display containing the battery indicator, etc. I couldn't just adapt my existing design for a new form factor.

ortholinear kb mock-up in a reform

Luckily the folks at OLKB announced they were developing a kit for an improved keyboard with no row-staggering. I'd prefer an ergonomic design, but this is still a big improvement over the stock board, which is itself light years beyond anything I've ever used in a laptop before. I'm looking forward to building one out.

Overall I'm thrilled with this laptop. It's available both as a DIY set which needs some assembly (just screwing things together and plugging connectors; no soldering) and as a prebuilt laptop, but honestly if you're anywhere near the target market for the Reform, you're probably going to enjoy the assembly process and are best off skipping the pre-assembled option. In the end the Reform is a powerful antidote to the user-hostile trends which have prevailed in computing over the past decade or so, and if you're anything like me and you don't mind a little tinkering, I can't recommend it enough.


[1] Starting with a T60p in 2007 followed by an X61, then an X200s, and finally a X301. I took a brief detour with a Samsung ultrabook but the keyboard was so unpleasant that it didn't last long before I sold it.

-1:-- in which a laptop defies the trends (Post Phil Hagelberg)--L0--C0--September 06, 2021 02:18 AM

Sacha Chua: 2021-09-06 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 and emacs-devel.

-1:-- 2021-09-06 Emacs news (Post Sacha Chua)--L0--C0--September 06, 2021 12:00 AM

yuri tricys: Emacs Stripes, Visual Fill, Column Word Wrap

Olivetti Mode Centers the working area by adding margins you can adjust. Select Fringe-mode to show or hide the fringe. There are split window options that come into play when working in Olivetti…
-1:-- Emacs Stripes, Visual Fill, Column Word Wrap (Post)--L0--C0--September 06, 2021 12:00 AM

Andrea: Moldable Emacs: taking lispy notes that are easier to search!

Take notes via molds!
-1:-- Moldable Emacs: taking lispy notes that are easier to search! (Post)--L0--C0--September 05, 2021 12:00 AM

jao: apropos library

A gem introduced in emacs 23 that i've overlooked all these years:

M-x apropos-library
-1:-- apropos library (Post)--L0--C0--September 04, 2021 07:49 PM

Irreal: Melpa Reaches a Milestone

As regular readers know, I’m a big fan of Melpa and its proprietor Steve Purcell. It’s an extraordinary resource run strictly as a public service. The site is not monetized and yet Purcell devotes huge amounts of time to running it. Melpa is an unofficial repository so some GNU purists may spurn it but as a practical matter it’s the most important and useful repository and it’s hard to imagine configuring Emacs without it.

Recently, Melpa passed 5,000 packages, everyone of which is curated and kept up to date. It’s a pretty significant achievement so I say again: if we can coax Purcell out of New Zealand and you’re lucky enough to meet him, be sure to buy him a beer. Until then, I can only say, Thanks and well done.

-1:-- Melpa Reaches a Milestone (Post jcs)--L0--C0--September 02, 2021 04:26 PM

yuri tricys: Emacs Company-Mode Continued : The First Thing To Do When Developing With Emacs

Hello Emacs Enthusiasts Emacs enthusiasts can be terribly busy setting up an emacs dev environment. Emacs isn't an all in one off the shelf piece of software. It's a world unto its own. A fully complete, educational experience. Emacs enthusiasts, you are not forgotten. Others who walk the same path are here to help you along your way, for better or for worse (hopefully for better). Here at Reading World Magazine, behind the scenes, emacs enthusiasts are appreciated.
-1:-- Emacs Company-Mode Continued : The First Thing To Do When Developing With Emacs (Post)--L0--C0--September 01, 2021 12:00 AM

Manuel Uberti: Package report

I don’t know about you, but I like to monitor my Emacs configuration to see if it is growing out of control due to my penchant for experimenting with ELisp and new packages. This led me to a simple question: why not have a command that can produce a summary of the installed packages? Specifically, I want to know the total number of packages installed and I’d like to list the packages for every archive set up in package-archives.

(defun mu-package-report ()
  "Report total package counts grouped by archive."
  (interactive)
  (package-refresh-contents)
  (mu--display-package-report
   (let* ((arch-pkgs (mu--archive-packages))
          (counts (seq-sort-by #'cdr #'> (mu--archive-counts arch-pkgs)))
          (by-arch (seq-group-by #'car arch-pkgs)))
     (concat
      (format "Total packages: %s\n\n" (apply #'+ (mapcar #'cdr counts)))
      (mapconcat
       (lambda (archive)
         (concat "• "
                 (format "%s (%s)" (car archive) (cdr archive))
                 ": "
                 (mapconcat (lambda (ap-pair) (cdr ap-pair))
                            (alist-get (car archive) by-arch)
                            ", ")))
       counts
       "\n\n")))))

Now, let’s unpack it.

I want my report buffer to be displayed in a new window, so this is what mu--display-package-report does:

(defun mu--display-package-report (output)
  "Display OUTPUT in a popup buffer."
  (let ((buffer-name "*package-report*"))
    (with-help-window buffer-name
      (with-current-buffer buffer-name
        (visual-line-mode 1)
        (erase-buffer)
        (insert output)
        (goto-char (point-min))))))

Next, I want to know from which archive (e.g., GNU ELPA) a package is coming to my system:

(defun mu--archive-packages ()
  "Return a list of (archive . package) cons cells."
  (seq-reduce
   (lambda (res package)
     (let ((archive (package-desc-archive
                     (cadr (assq package package-archive-contents))))
           (pkg (symbol-name package)))
       (push (cons archive pkg) res)))
   (mapcar #'car package-alist)
   nil))

This is nice because now I can also have the number of packages for every archive.

(defun mu--archive-counts (arch-pkgs)
  "Return a list of cons cells from alist ARCH-PKGS.
The cars are package archives, the cdrs are the number of
packages installed from each archive."
  (seq-reduce
   (lambda (counts key)
     (cons (cons key (+ 1 (or (cdr (assoc key counts)) 0)))
           (assoc-delete-all key counts)))
   (mapcar #'car arch-pkgs)
   nil))

The rest of the code in mu-package-report deals with formatting the output. For example, I am using seq-sort-by to have the archive with the highest number of packages on top. As for the mapconcat producing the actual bullet points, the Emacs community came to the rescue on Emacs Stack Exchange.

Finally, this is how M-x mu-package-report RET looks like:

-1:-- Package report (Post)--L0--C0--September 01, 2021 12:00 AM

Protesilaos Stavrou: Emacs as a ‘second brain’ and mindfulness

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

In this recorded live stream, I offered a presentation that was divided in two parts:

  • In the first, I talked in general about how Emacs can boost one’s productivity through its sheer power, extensibility, and the interconnectedness of its environment.

  • While in the second I elaborated on the need to be mindful of our disposition towards knowledge and learning so that we give ourselves a chance to grow.

This ultimately is about how we go about maintaining an exomind with the help of Emacs while being mindful of the quality of what goes into it.

Below is the text of the presentation (in Org format):

#+TITLE: Live: Emacs note-taking and the mindful attitude
#+AUTHOR: Protesilaos Stavrou (https://protesilaos.com)
#+DATE: 2021-08-31

* Overview of how I plan to do live streams

Hello everyone!  My name is Protesilaos, also known as "Prot".

This is my first ever live stream.  I have never done one before nor
participated in any because my old computer could not handle it.  Now
that I have slightly better hardware, it is time to experiment with this
format.

[ I talked about my laptop woes in the last video:
  https://protesilaos.com/codelog/2021-08-29-emacs-community-new-pc/. ]

If there is anyone in the chat, feel welcome to send your questions and
I will reply to them once I conclude the presentation.  I am keeping the
chat here on the side though, so I might also answer some questions
while switching between chapters.

Today's topic and those of any live stream in the foreseeable future
will be about Emacs.  Though the connection may sometimes be tangential,
as I will be elaborating on broader themes as well.

What I will talk to you about today is the process of approaching a new
subject of sophistication or intellectual interest.  And I will link it
to Emacs' capacity to take notes with efficiency and, generally, help us
capture and then retrieve our thoughts.

If you wish to follow live streams that are exclusively about Emacs or
related technological topics, you can follow (A-Z):

+ Andrew Tropin :: https://www.youtube.com/channel/UCuj_loxODrOPxSsXDfJmpng
+ System Crafters (David Wilson) :: https://www.youtube.com/channel/UCAiiOTio8Yu69c3XnR7nQBQ
+ Xah Lee :: https://www.youtube.com/channel/UCXEJNKH9I4xsoyUNN3IL96A

There is also Sacha Chua, but I am not sure how often there are streams
there: https://www.youtube.com/channel/UClT2UAbC6j7TqOWurVhkuHQ.  Maybe
there is Twitch, but I am not familiar with it.

Perhaps there are other live streamers as well, but I am new to this, so
apologies if I have missed any.  Will include them next time.

Other useful Emacs-related videos:

+ Emacs Elements (Raoul Comninos) :: https://www.youtube.com/channel/UCe5excZqMeG1CIW-YhMTCEQ
+ Mike Zamansky :: https://www.youtube.com/channel/UCxkMDXQ5qzYOgXPRnOBrp1w

[ In my dotemacs, I maintain a section about other people's work.  The
  aforementioned and others are included: https://protesilaos.com/dotemacs. ]
* Taking notes in general

We document our ideas all the time, be it with pen and paper or by using
our software of choice.  It helps us clarify our thoughts and elucidate
concepts that would otherwise be hard to grasp.  We may also retrieve
information we have stored for later use.

When it comes to software, Emacs is a powerhouse for taking notes and
staying organised.  Apart from all its text-editing capabilities, its
ability to search recursively through files and edit the results
directly, its superb keyboard macros, and so on, the Emacs milieu has
the highly acclaimed Org mode.

At its core, Org is a lightweight markup language similar in spirit to
Markdown.  What makes Org special though is the ecosystem of Emacs Lisp
that has grown organically around it.  Users have been writing and
sharing code which let's you do practically everything with Org and the
'magic' of Emacs Lisp (Elisp).  For example:

1. Devise your own "Getting Things Done" workflow.
2. Organise your agenda, by scheduling tasks, adding appointment
   notifications, determining what should be tracked as a habit, etc.
3. Write a journal (org-journal).
4. Maintain a personal knowledge base using the zettelkasten method or
   some variant thereof (org-roam, zetteldeft).
5. Publish a website entirely with Org or, at least, by exporting
   specific documents to HTML (among numerous other formats).
6. Do literate programming.
7. Learn something new with flashcards and spaced repetition
   (org-drill).
8. Draw linkages between various contexts, such as by connecting a
   particular email message to a to-do item.

It seems that the possibilities are only limited by one's imagination.
Of course, all of the above can be achieved without using Org, provided
one is willing to experiment with alternatives and some custom code,
perhaps for educational or recreational purposes.

The point is that Emacs is all about choice.  It does not enforce a
specific workflow, nor does it come with stringent requirements of how
data should be stored and organised.  In other words, there isn't a
canonical way of using Emacs: that is always up to the user.

This is all possible because Emacs is programmable and extensible.  You
just write some ELisp and it can evaluate it live.  Though chances are
that there already exist packages which provide you with everything you
need to accomplish your goals.  In fact, you might never have to write
any code yourself and still be very effective with your Emacs usage.

* Emacs can help you develop a second brain

By using Emacs and Org with all of its accoutrements we can have the
basic components we need to set up our very own exomind or second brain.
This is a state where the distance between our mind and what the
software renders possible is reduced and where we can both add and
extract information in a near-frictionless fashion.  The second brain is
a higher state of efficiency.

What exactly goes into one's exomind will depend on their particular
requirements and how much time and effort they are willing to invest in
integrating their computing experience inside of Emacs.  I think it is
worth bringing everything into Emacs because of the innate
interconnectedness of its environment.

Some common tasks that can be done with Emacs:

1. Read RSS/Atom feeds (e.g. Elfeed).
2. Handle email correspondance (Gnus, Notmuch, Mu4e...)
3. Browse the Internet in a text-centric browser (EWW, Elpher).
4. Perform context-sensitive actions on the thing-at-point (Embark).
5. Seamlessly open your PGP/GPG-encrypted files (many built-in tools).
6. Bulk rename your files as if they were regular text, using ordinary
   text editing, keyboard macros, multiple cursors, and the like
   (Dired/Wdired).
7. Gain easy access to your ~pass~ store, where all your passwords are
   stored (pass, password-store).
8. Jump to any heading or "point of interest" in a file using ordinary
   search or more advanced patterns (built-in Imenu and extensions like
   Consult, and several completion frameworks such as Vertico).
9. Play back your music collection (Bongo, EMMS).

For all those and many others, you are always working in the same
environment, where it is trivial to either go from one place to the next
or to connect different packages in emergent workflows.  For example, to
have Elfeed interface with Bongo so that you can add the feed entry of
some music channel you are following directly to your playlist queue.

This is where Org comes in to play.  Specifically ~org-capture~ and
~org-store-link~.  These two commands can be used to quickly store any
kind of structured note and to create a direct link to the context it
was taken from.  A typical example is to read an important email and
capture it as a task that should appear in the Org agenda.

All those can be pieced together into a bigger system to reach that
higher state of productivity; that second brain.  But there is a catch!
Unlike the first brain, the second one does not think things through.
Its output will be as good or bad as your input.  And so there arises a
general problem of the state of mind one must have while documenting
their ideas about some newfound knowledge or piece of information.

* Remaining open to new ideas

As I said in the introduction, we want to be mindful of our attitude
when we are engaging with a new subject of sophistication or
intellectual pursuit.  Because even the most efficient text-editing
setup will not be able to affect our mindset, our dispotition towards
learning.

Maybe you have done this before or are aware of others who have done it:
you start reading a book and as you go through its pages you take
notes.  Maybe you will draw an underline under the text as you go
through it, or add some paper note there.  If the medium is digital, you
will be doing that with Emacs or something along those lines.

The point is that you are taking notes while still trying to parse new
information.  And that can prove problematic.  Sometimes the book, or
the resource more broadly, provides profound insights that require some
time to be fully understood and internalised.  You may have to read and
re-read the text before you are in a position to assess its content.

What happens then, is that if you write notes upon first encounter with
some new material, your input essentially codifies your previous
self---the one who was not yet aware of the book's teachings.  In other
words, those notes are not as useful as you would like to believe,
because they unconsiously embed your prior opinions.

When you engage with a new source that you consider worthy of your time,
at least based on first impressions, you want to give it some room to
grow or some time to sink in.

It is like how fermentation occurs over time.  Take wine production, for
example.  You start with grape juice that you store in a vessel, a
barrel perhaps.  After a few days, the liquid starts developing alcohol.
If you take out a portion of it, what you are getting is some unfinished
product.  Either some bad grape juice or something akin to the cheapest
plonk you can get on the market.  It is not good.  To truly appreciate
it, you have to let the fermentation process run its course.

Incoming ideas are just like that.  If you wrestle with them right away
and take a snapshot of your thoughts at the moment, you are effectively
consuming the unfinished article.  Whereas what you want is to refrain
from passing judgement upon first contact and allow the ideas the time
they need to come together.  This means that you may have to think about
them many times over.

No second brain will do that for you.  No second brain will prevent you
from storing notes that capture your unrefined or immature views.  No
second brain can tell you whether your inconsiderately captured notes
condition your current thought processes.  It is up to the first brain
to be mindful of the potential pitfalls.

* Avoid the dogma of self-identification through mindfulness

To take notes effectively with the intent of growing out of our mould,
we have to rely on our first brain, not the one that Emacs or some other
program/method may provide us with.  When we take notes, or generally
when we encounter something new, we essentially face a dilemma of either
(i) clinging on to our position or (ii) remaining open to the
possibility of refashioning ourselves.

If you hold firm in your views, such as when you read a new book and
comment on it in parallel, you are effectively implying that what you
already knew before reading the book is all you ever needed to know.
Put differently, you are developing a certain brand of dogmatism, of
insistance on the narrative you have about who you are and what it is
that you are doing.  Let me call this the "dogma of self-identification"
in which we do not recognise, tacitly or otherwise, the possibility of
not knowing something and where we claim to be capable of more than what
we actually are.

This is a trap that anyone who wants to flourish as a person should
actively try to avoid.  When we engage with new material, we want to be
mindful of our condition.  We must admit that we are not omniscient,
that we are fallible.  And we have to unequivocally tell ourselves how
our sense of self is a work-in-progress that remains open to influences
of all sorts.

There is no scope for pretense here.  No need to fake being tough or
smart or whatnot.  The open mind, the inquisitive spirit, has no trouble
acknowledging its inadequacies because it understands that it can only
improve by surfacing them, scrutinising them, and working towards
circumventing them.

And so, when we take notes---when we learn---our goal must be to always
keep open a window into the unknown.  Take as much time as you need to
think things through.  Give ideas the space they need to grow and become
fecund.  Then, just like the farmer who respects the land, reap the
fruits in a spirit of sustainability, in a way that allows ideas to grow
again perhaps by means of exposure to yet newer concepts.

What matters then is the attitude we have before implementing the
methodology.  The second brain may be powerful and extremely useful.
But it cannot think for itself and it cannot support the first brain in
rectifying its errors; errors which stem from a position of dogma.

Through such a mindful attitude we can expand our awareness of things
simply by being more considerate, more careful, more deliberate.  It is
not the volume or the efficiency.  It is not about productivity per se,
measured in some dubious unit of output.  This is about how we enrich
the quality of what goes into our mind and what eventually gets codified
into some note-taking system.

* Closing thoughts

As I mentioned in the introduction, I am new to the live-streaming
world.  Perhaps this format is the wrong one, but I just had to start
with something and see how it goes.

If there are any questions in the chat, I will answer them now.  They
can be related to what I just covered, or maybe to something else.  I
will try my best to be helpful.

In short:

+ Emacs can boost one's productivity through its sheer power,
  extensibility, and the interconnectedness of its environment.

+ The second brain is a good idea.  But it is not omnipotent.  You still
  have to put some serious effort into what you are doing.

  - This is true for Emacs in general and for every other field that
    involves some degree of sophistication.
  
+ We grow when we learn to let go.  And we are at our best when we are
  prepared to let go of our most cherished beliefs, such as our sense of
  self once taken as a snapshot.

+ Dogmatism, even one which is latent in what we do, is an impediment to
  our intellectual growth.  Without being mindful of our condition, we
  are forever trapped in a web of predispositions where we pretend to
  know more than we do.

As you could tell, part of this is tangentially about Emacs and even
about taking notes.  The emphasis is on our disposition, the attitude we
ought to maintain.  The rest follows from there and falls right in
place.

That's all.  Thank you for your attention!  Now let's check the chat for
any feedback, otherwise I am concluding this show.
-1:-- Emacs as a ‘second brain’ and mindfulness (Post)--L0--C0--August 31, 2021 12:00 AM

Phil Jackson: Save all mu4e attachments

To save all attachments from an mu4e email to a particular directory, you can use this handy snippet for older versions of the client. For more modern mu4e versions, use the elisp by @sj30.

-1:-- Save all mu4e attachments (Post)--L0--C0--August 30, 2021 07:14 PM

Marcin Borkowski: How I avoid deleting large parts of Org buffers accidentally

For today, I have a kind of obvious trick, but one that saved me a lot of trouble at least once. As many Emacs users, I am a heavy Org-mode user. However, one of the strengths of Org-mode is also one of its weaknesses. By default, it hides a lot of stuff from the user, in the sense of rendering them invisible (property drawers, folded parts of the tree etc.). This means that if I e.g. clock in and then accidentally call undo (effectively deleting my clock entry), it’s possible that I won’t notice that something is missing. Another thing I happen to press accidentally is C-c ;, which toggles the COMMENT keyword of the current entry – when I’m editing a long section of my book on Elisp, for instance, pressing C-c ; instead of C-c , (which is used to e.g. edit a source block) is pretty easy. Almost a year ago I decided to do something about it, and I came up with a primitive but working solution.
-1:-- How I avoid deleting large parts of Org buffers accidentally (Post)--L0--C0--August 30, 2021 04:14 AM