Irreal: Profoundly Ignorant And Proud Of It

It’s easy to be snarky about management—especially the suits—and Irreal has certainly indulged itself often. In case you think such snark is unwarranted, I offer this sad example for your consideration.

It demonstrates everything that can go wrong when people with no technical skills nevertheless feel inclined—and entitled—to make decisions that aren’t really any of their business and for which they are eminently unqualified. Take a look at their description of Emacs:

“An old fashioned and slow text editor created by Canonical for use with the Ubuntu operating system”.

There’s not a single part of that description that’s correct. You Vim guys can stop laughing now. Here’s the description of Vim:

“Developed by CentOS, an editor with a steep learning curve”.

I guess that’s a slightly better description than the one for Emacs in that “with a steep learning curve” might be said to be accurate. On the other hand, these same suits are happy to embrace Neovim so, again, they have no idea what they’re talking about.

I can’t imagine working for a company that would presume to tell developers what editor they should use let along one that justifies their decisions with such a complete lack of knowledge of what they’re talking about.

All I can say is that if you are working for this company or one like it you should start looking for other employment forthwith. Even if your preferred editor is on the approved list, management’s attitude and presumption will eventually reach out to bite you.

-1:-- Profoundly Ignorant And Proud Of It (Post jcs)--L0--C0--November 11, 2024 03:46 PM

Sacha Chua: 2024-11-11 Emacs news

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

View org source for this post
-1:-- 2024-11-11 Emacs news (Post Sacha Chua)--L0--C0--November 11, 2024 01:08 PM

New emacs org-mode category in place…! Actually, it was there for a while, but now it’s in the navigation bar, complete with my own AI illustration of what the Emacs GNU looks like. Check it out: taonaw.com/categorie…

-1:--  (Post)--L0--C0--November 09, 2024 09:43 PM

Thanos Apollo: RSS Mastery with RSS-Bridge & Elfeed [Video]

I’ve just published a short video covering the basics of RSS, RSS-Bridge & Elfeed, it’s currently available on YouTube.

Video notes

What is RSS?

  • XML-based web feed that allows users to access updates of websites, without “visiting” the website.
  • Hacktivist including Aaron Swartz contributed to the development of RSS

Why use it?

  • Having total control over information you consume
    • Filter/Prioritize content from various sources
    • Bypass algorithms
    • Ad-free reading
  • Offline Access
  • Time saving
  • Allows creation of a personalized & decentralized information hub

(+ Emacs RSS) ;; => ’elfeed

No matter what RSS reader you choose, they all get the same job done

  • Elfeed is a simple & highly customizable RSS client for Emacs
    • Developed by Christopher Wellons (skeeto)
  • It has a well designed database & tagging system

use-package installation example:

(use-package elfeed
  :vc (:url "https://github.com/skeeto/elfeed") ;; vc option is available on Emacs 30
  :config
  (setf elfeed-search-filter "@1-week-ago +unread"
        browse-url-browser-function #'browse-url-default-browser
        elfeed-db-directory (locate-user-emacs-file "elfeed-db"))
  ;; Feeds Example
  (setf elfeed-feeds
        '(("https://hackaday.com/blog/feed/"
           hackaday linux)))

  ;; Play videos from elfeed
  (defun elfeed-mpv (&optional use-generic-p)
    "Play video link with mpv."
    (interactive "P")
    (let ((entries (elfeed-search-selected)))
      (cl-loop for entry in entries
               do (elfeed-untag entry 'unread)
               when (elfeed-entry-link entry)
               do (start-process-shell-command "elfeed-video" nil (format "mpv \"%s\"" it)))
      (mapc #'elfeed-search-update-entry entries)
      (unless (use-region-p) (forward-line))))

  :bind (("C-x f" . elfeed)
         :map elfeed-search-mode-map
         ("v" . 'elfeed-mpv)
         ("U" . 'elfeed-update)))

What to do with websites that do not provide an RSS feed?

  • Utilize rss-bridge to generate one.
  • RSS Bridge is easy to self host using docker

Example guix service:

(service oci-container-service-type
         (list
          (oci-container-configuration
           (image "rssbridge/rss-bridge")
           (network "host")
           (ports
            '(("3000" . "80"))))))
-1:-- RSS Mastery with RSS-Bridge & Elfeed [Video] (Post)--L0--C0--November 09, 2024 12:00 AM

Aimé Bertrand: Mu4e - save attachments faster - an update

My Issue

In an older post I wrote down my solution for saving multiple attachements at once without a completion from Mu4e. The reason being that my the bulk of use cases are to save all attachments at once.

In the rare cases I want to select an attachments out of many I can still use mu4e-view-mime-part-action.

Now I have encountered a few breaking updates of Mu4e and for a while I have been dealing with another one. Granted, You are not supposed to use private function in an Emacs package/library in you own solution. So in this case I am the one to blame.

My solution

The default command mu4e-view-save-attachments provides a way of selecting multiple files in the completion list, but even this kind of grinds my gear. I do not need the completion at all. See above.

This is the reason, why I went ahead and modified the command. Simply put, this removes the completion for a files. Then it always ask for the directory to save to starting with the mu4e-attachment-dir.

(defun timu-mu4e-view-just-save-all-attachments ()
  "Save files from the current Mu4e view buffer.
This applies to all MIME-parts that are \"attachment-like\" (have a filename),
regardless of their disposition.

This is a modified version of `mu4e-view-save-attachments'.
It does not use `mu4e--completing-read' to select files, but just selects all.

Also it always prompts for the directory to save to."
  (interactive)
  (let* ((parts (mu4e-view-mime-parts))
         (candidates  (seq-map
                         (lambda (fpart)
                           (cons ;; (filename . annotation)
                            (plist-get fpart :filename)
                            fpart))
                         (seq-filter
                          (lambda (part) (plist-get part :attachment-like))
                          parts)))
         (candidates (or candidates
                         (mu4e-warn "No attachments for this message")))
         (files (mapcar #'car candidates))
         (default-directory mu4e-attachment-dir)
         (custom-dir (read-directory-name
                                    "Save to directory: ")))
    (seq-do (lambda (fname)
              (let* ((part (cdr (assoc fname candidates)))
                     (path (mu4e--uniqify-file-name
                            (mu4e-join-paths
                             (or custom-dir (plist-get part :target-dir))
                             (plist-get part :filename)))))
                (mm-save-part-to-file (plist-get part :handle) path)))
            files)))

Conclusion

This might be a quick and dirty way of solving my issue, however it works really good for me. You are always free to hit me up with a better solution however. I am not the Emacs Lisp magician, so I am thinking a proper wiz might use an advice or hook or something.

-1:-- Mu4e - save attachments faster - an update (Post)--L0--C0--November 08, 2024 11:00 PM

James Cherti: The compile-angel Emacs package: Byte-compile and Native-compile Emacs Lisp libraries Automatically

The compile-angel Emacs package automatically byte-compiles and native-compiles Emacs Lisp libraries. It offers two global minor modes:

  • (compile-angel-on-save-mode): Compiles when an .el file is modified and saved.
  • (compile-angel-on-load-mode): Compiles an .el file before it is loaded.

These modes speed up Emacs by ensuring all libraries are byte-compiled and native-compiled. Byte-compilation reduces the overhead of loading Emacs Lisp code at runtime, while native compilation optimizes performance by generating machine code specific to your system.

NOTE: It is recommended to set load-prefer-newer to t, ensuring that Emacs loads the most recent version of byte-compiled or source files. Additionally, ensure that native compilation is enabled; this should return t: (native-comp-available-p).

What is the difference with auto-compile?

This package is an alternative to the auto-compile Emacs package. Here are the main differences:

  • Compile-angel is lightweight: The compile-angel package is lightweight, with one-third the lines of code of auto-compile.
  • Compile-angel ensures more .el files are compiled: The compile-angel package, in addition to compiling the elisp files that are loaded using load and require, also handles .el files that auto-compile misses, such as those that are deferred (e.g., with :defer t and use-package) or autoload.

(Special thanks to Jonas Bernoulli, the creator of the auto-compile package, whose work inspired the development of compile-angel. This package was created to offer a lightweight alternative to auto-compile that also compiles deferred/autoloaded .el files.)

Installation using Straight

To install compile-angel using straight.el:

  1. It if hasn’t already been done, add the straight.el bootstrap code to your init file.
  2. Add the following code at the very beginning of your Emacs init file, before anything else:
(use-package compile-angel
  :ensure t
  :straight (compile-angel
             :type git
             :host github
             :repo "jamescherti/compile-angel.el")
  :config
  (compile-angel-on-save-mode)
  (compile-angel-on-load-mode))

Links

-1:-- The compile-angel Emacs package: Byte-compile and Native-compile Emacs Lisp libraries Automatically (Post James Cherti)--L0--C0--November 08, 2024 04:27 PM

Irreal: 🥩 Red Meat Friday: Emacs For Word

In what has to be the silliest question of the week, Kiiwyy, over at the Emacs subreddit, asks do you use Emacs as a substitute for Word. In particular, he’s wondering if people use Emacs for class or project notes. He says he uses Word for these and wonders what other people are doing.

In the first place, the concept of using Emacs as a replacement for Word seems backwards to me. Emacs can do so much more than Word that the question makes more sense the other way around.

The only real strength of Word is that all the normals use it so it’s sometimes necessary to produce a Word document for collaboration. The canonical example, and virtually the only one mentioned in the comments, is resumes. The other required Word use is in some publishing domains. A number of Journals, particularly in the humanities, insist that papers be submitted as Word documents. Similarly some book publishers really want Word documents—although they tend to be a bit more flexible—because it facilitates their production flow.

The commenters are, almost to a person, unsympathetic. They all note that—other than resumes—there really is no reason to use Word. Even if the final recipient requires a Word doc, you can always export an Org document to Docx so even for resumes you can maintain it in Org and export it to Word, PDF, or HTML as circumstances demand.

Sure, if you’re a secretary writing business letters for your boss, use Word. In most other situations, it’s hard to see why you would. Emacs has so much more to offer and, really, is just as easy to learn so why use word and worry about losing your document when Microsoft has a hiccup?

-1:-- 🥩 Red Meat Friday: Emacs For Word (Post jcs)--L0--C0--November 08, 2024 04:23 PM

Thanos Apollo: Why I Prefer VC Over Magit [Video]

I’ve just uploaded a short video on why I prefer VC over Magit, alongside a quick demo workflow with VC.

The video is available on youtube here.

-1:-- Why I Prefer VC Over Magit [Video] (Post)--L0--C0--November 08, 2024 12:00 AM

Irreal: Why Isn’t There An Emacs 2?

Over at the Emacs subreddit, Available-Inside1426 asks why there isn’t an Emacs 2. By that he means a rewrite of Emacs to address what he sees as problems with Emacs. Those problems include the usual silliness like a better GUI implementation, better mouse support, a client-server architecture, and so on. The only improvement he suggests that makes sense to me is implementing threads.

Of course, everyone would like Emacs to have a robust thread implementation but the problems are legion. Here’s an account of one brave soul’s attempt to implement them. The TL;DR is that in the end he gave up because there’s just too much shared state built into Emacs.

One thing you hear all the time and that Available-Inside1426 repeats is that “Emacs was made for a different world”. I don’t know what that means. Sure, Emacs was made in a different world but I don’t think it’s true that it was made for a different world. After all, it was made to edit text as efficiently as possible and in that it still performs better than any other editor. My cynical suspicion is that what “made for another world” really means is that it doesn’t have enough bling, and is not centered on point and click.

Emacs development is, in fact, proceeding apace and everyone with even a bit of software development experience knows that rewriting a mature system always ends in tears. Emacs doesn’t need to be rewritten. Sure, some things would benefit from improvement but that exact process is always underway. Your pet wish may not be as high on the list as you’d like but if it’s worthwhile, it will certainly be implemented eventually. Who knows? Maybe we’ll even get a good thread model.

-1:-- Why Isn’t There An Emacs 2? (Post jcs)--L0--C0--November 07, 2024 04:44 PM

Ryan Rix: Two Updates: Org+Nix dev streams, and my new DNS resolver

Two Updates: Org+Nix dev streams, and my new DNS resolver

I've started to stream on Thursdays where I'll explore salt dunes and arcologies

The last few weeks I have started to work in earnest on Rebuild of The Complete Computer , my effort to provide a distribution of my org-mode site publishing environment in a documented, configurable Concept Operating System . My "complete computing environment" will be delivered in three parts:

  • a set of online documents linked above that are explaining how I manage a small network of private services and a knowledge management environment using my custom web publishing platform, The Arcology Project .

  • a set of videos where I work through the documents, eventually edited down in to a set of video lectures where you are guided from complete fresh fedora VM to installing Nix and a bare-bones org-roam emacs, bootstrapping a NixOS systems management environment, and then use Org files to dynamically add new features to those NixOS systems.

  • a handful of repositories which i'll finally have to treat like "an open source project" instead of Personal Software:

    • The arcology codebase which you'll have a copy of on disk to configure and compile yourself

    • the core configuration documents that are currently indexed on the CCE page, a subset which will be required to run the editing environment, and a number of other bundles of them like "ryan's bad UX opinions", "ryan's bad org-mode opinions", "ryan's bad window manager", etc...

I hope that by reading and following along with the documents while utilizing the video resources, one can tangle source code out of the documents, write and download more and an indexing process will extract metadata from the files that can be later queried to say "give me all the home-manager files that go on the laptops", for example, and produce systems that use that.

https://notes.whatthefuck.computer/media/c71d50750dff59e4abdfdb788f87c1fa26190d6f0b2dc1b1fd4edf3679d58d35.png

Two weeks ago I produced a three hour video where I played Caves of Qud and then spent two hours going over some of the conceptual overviews and design decisions while setting up Nix in a Fedora VM, ending with the Arcology running in a terminal and being used to kind-of-sort-of clobber together a home-manager configuration from a half-dozen org-mode files on disk. It was a good time! This is cataloged on the project page, 0x02: devstream 1 .

This week I came back to it after taking a break last week to contribute an entry to the autumn lisp game jam, and it was a bit more of a chaotic stream with only two hours to get up to speed on the project; there are many implicit dependencies in the design and implementation of the system because it's slowly accreted on top of itself for a decade now. That was 0x02: devstream 2

This week I'll work on cleaning up things to smoothly bootstrap and next week we'll come back with a better way to go from "well home-manager is installed" to "home-manager is managing Emacs and Arcology, and Arcology is managing home-manager" and then from there we build a NixOS machine network...

I have probably a three or six month "curriculum" to work through here while we polish the Rebuild documents. I will be streaming this work and talking about how to build communal publishing networks and document group chats and why anyone should care.

With the news from the US this week, it feels imperative to teach people how to build private networks, if only because the corporatist monopolist AI algorithm gang are going to run rough-shod on what's left of the open web the second Lina Khan and Jonathan Kanter are fired if they haven't already begun today. We can host Fediverse nodes and contact lists and calendars for our friends for cheap and show each other how to use end-to-end chat and ad-blocking and encrypted DNS; we oughta.

I'll stream on twitch.com/rrix on Thursdays at 9am PT and upload VODs to a slow PeerTube server I signed up for. Come through if this sounds interesting to you.

I re-did my DNS infrastructure

Years ago I moved my DNS infrastructure to a pi-hole that was running on my Seattle-based edge host. It worked really nicely without thinking about it when I lived in Seattle, but I hesitated fixing it for the years since I moved a half a hundred milliseconds away. The latency finally got annoying enough lately so I finally got around to it this week.

On my devicies, I've been using Tailscale's "MagicDNS" because DNS is a thing that I think should just have magic rubbed on it, as it is i've already thought way more about DNS in my life than I'd like. If you enable MagicDNS and instruct it to use your pi-hole's address as the global nameserver, any device on your Tailnet will use the pihole for DNS. Neat.

Pi-hole isn't packaged in nixpkgs and I was loathe to configure Unbound etc and a UI myself so I put it off and fnord ed the latency for months. I finally got around to it this week by deploying Blocky on my LAN server which has the feature-set I need, and rather than shipping a UI it ships a minimal API and a Grafana dashboard:

https://notes.whatthefuck.computer/media/a4fad0c5daa7cf3773eaacce68a988286554f61c7c00abbba088393ffcddfccf.png

It's a neat little nice little thing, I hope it'll work out. I've started documenting this at Simple DNS Infrastructure with Blocky of course.

With the querying back on my LAN and managed by my Nix systems instead of a web GUI on an unmanaged host, I can list my blocked domains and block lists in a human-legible format, I can have different DNS results to route all my server's traffic direct over the LAN to my homelab instead of round-tripping to the SSL terminator, I can have custom DNS entries for local IPs. All this is managed in that one document which you'll soon be able to download from my git instance; that's the Concept Operating System promise.

If you're a content pihole user but never use the web UI and need to move, consider taking this thing for a spin.

-1:-- Two Updates: Org+Nix dev streams, and my new DNS resolver (Post)--L0--C0--November 07, 2024 05:45 AM

Sacha Chua: Excerpts from a conversation with John Wiegley (johnw) and Adam Porter (alphapapa) about personal information management

Adam Porter (alphapapa) reached out to John Wiegley (johnw) to ask about his current Org Mode workflow. John figured he'd experiment with a braindumping/brainstorming conversation about Org Mode in the hopes of getting more thoughts out of his head and into articles or blog posts. Instead of waiting until someone finally gets the time to polish it into something beautifully concise and insightful, they decided to let me share snippets of the transcript in case that sparks other ideas. Enjoy!

John on meetings as a CTO and using org-review

Today I was playing a lot with org-review. I'm just trying to really incorporate a strong review process because one of the things I started doing recently is that this [Fireflies AI]​ note taker that's running in the background. Now, it produces terrible transcripts, but it produces great summaries. And at the bottom of every summary, there's a list of all the action items that everyone talked about associated with the names.

So I now have some automation, that will all I have to do is download the Word document and then I have a whole process in the background that uses Pandoc to convert it to Org Mode. Then I have Elisp code that automatically will suck it into the file that I dedicate to that particular meeting. It will auto-convert all of the action items into Org-mode tasks where it's either a TODO if it's for me, or if it's a task for somebody else, tagged with their name.

Then, when I have a one-on-one with a person in the future, I now have a one-on-one template that populates that file, and part of the template is under the agenda heading. It uses an a dynamic block that I've written: a new type of dynamic block that can pull from any agenda file. And what it does is it [takes] from all of those meetings, all of the action items that are still open that are tagged with their name.

This has been actually really, really effective. Now, I don't jump into a one-on-one being like, "Well, I didn't prepare so I don't know what to talk about." I've usually got like 10 to 30 items to go through with them to just see. Did you follow up? Did you complete this? Do we need to talk about this more?

I want to incorporate org-review. Scheduling is not sufficient for me to see my tasks. What I need is something that is like scheduling, but isn't scheduling. That's where org-review comes in. I have a report that says: show me everything that has never been reviewed or everything that is up for review.

Then I have a whole Org key space within agenda for pushing the next review date to a selected date or a fixed quantity of time. So if I hit r r, it'll prompt for the date that I want to see that again. But if I hit r w, it'll just push it out a week.

Every day I try to spend 15 minutes looking at the review list of all the tasks that are subject for review. I don't force myself to get through the whole list. I count it as success if I get through 20 of the tasks. Because earlier I had 730 of them, right? I was just chewing on them day by day.

But now I'm building this into the Org agenda population, because in the dynamic block match query, I can actually say: only populate this agenda with the tasks that are tagged for them that are up for review. That way, if we're in the one-on-one and they say, "Oh I'm working on that but I won't get to it for a month," I'll say, "Let's review that in a month." Then next week's one-on-one won't show that tasks. I don't have to do that mental filtering each time.

This is something I've been now using for a few weeks. I have to say I'm still streamlining, I'm still getting all the inertia out of the system by automation as much as possible, but it's helping me stay on top of a lot of tasks.

I'm surprised by how many action items every single meeting generates. It's like, it's like between 5 and 12 per meeting. And I have 3 to 7 meetings a day, so you can imagine that we're generating up to a hundred action items a week.

In the past, I think a lot of it was just subject to the whims of people's memory. They'll say, "I'm going to do that," and then… Did they remember to do that? Nobody's following up. Three months later, somewhere, they'll go like, "Oh yeah we talked about that, didn't we?"

So I'm trying to now stem the the tide of lost ideas. [My current approach] combines dynamic blocks with org-roam templates to make new files for every meeting and it combines org-review to narrow down the candidate agendas each time appropriately, and it combines a custom command to show me a list of all tasks that are currently needing review.

Reviewing isn't just about, "Is the thing done?" It's also, "Did I tag it with the right names? Did I delegate? Did I associate an effort quantity to it?" (I'm using efforts now as a way to quickly flag whether a day has become unrealistically over-full.)

I only started using column view very, very recently. I've never used it before. But now that I'm using effort strings, it does have some nice features to it: the ability to see your properties laid out in a table.

Back to table of contents

John on making meaningful distinctions (semantic or operational)

Today's agenda has 133 items on it. I need ways to narrow that agenda down.

I've used a lot of different tasks management philosophies. We're always looking for more efficiency, and we're looking for more personal adaptation to what works for us. I've gone from system to system. What I'm starting to realize is that the real value in all of these systems is that they're different enough from whatever you're using today, that they will force you to think about the system you're making for yourself, that is their value.

That's why I think there should always be a huge variety of such systems and people should always be exploring them. I don't believe any one one system can work for everybody, but we all need to be reflecting on the systems that we use. Somebody else showing you, "Hey, I do it this way" is a really nice way to juxtapose whatever system you're using.

I discovered through reading Karl Voit's articles that there are three principal information activities: searching, filtering, and browsing.

  • Hierarchies assist with browsing.
  • Tagging assist with filtering and keywords.
  • Metadata assist with searching.

Those are the three general ways that we approach our data.

We have to do work to draw distinctions between that data. The whole reason that we're drawing distinctions between that data is to narrow our focus to what is important.

I have over 30,000 tasks in my Org Mode overall. 23,000 of them are TODOs. Several thousand of them are still currently open. I'm never gonna see them all. Even if I wanted to, I'm never gonna see them all. I don't know what to search for. I don't know what the query should be. I have to use tagging and scheduling and categorization and everything. I believe that that is the work of a knowledge worker is to introduce these distinctions. That takes time and it takes effort.

What's really important is to draw meaningful distinctions. Make distinctions that matter.

I could tag things with like the next time I go to Walmart, so that I could do a filtered query to show me all things that I might want to do at Walmart, but is that worth the effort or is just tagging it as an errand enough? Because that list will get within the size range that I can now eyeball them all and mentally filter out the ones that I need for Walmart.

What makes a meaningful distinction? I believe there are two things that make a distinction meaningful. One is semantic, and one is operational.

A semantic distinction is a distinction that changes the meaning of the task. If I have a task that says "Set up Zoom account", if that's in my personal Org Mode, that has one level of priority and one level of focused demand. If it's in my work list, that has a totally different importance and a totally different focused demand. It changes the nature of the task from one that is low urgency (maybe a curiosity) to high urgency that might impact many people or affect how I can get my work done. That distinction is meaningful or semantic. It changes the meaning of the task.

An operational distinction changes how I interact with the task. [For example, if I tag a phone call, I can] group all of my phone calls during a certain time of the day. That changes my nature of interaction with the task. I'm doing it at a different time of day or doing it in conjunction with other tasks. That helps narrow my focus during that section of time that I have available for making calls. It's an operational distinction. if it's changing how you interact with the task.

You're succeeding at all of this if on any given day and any given time, what's in front of your eyes is what should be in front of your eyes. That's what all of this is about. If an operational distinction is not aiding you in that effort, it's not worth doing. It's not meaningful enough to go above the bar.

Back to table of contents

John on examples of distinctions that weren't personally worth it

I'm trying to narrow and optimize down to the minimum distinctions necessary to remain effective. If I can ever get rid of a distinction, I'm happy to do it.

I used to have projects and have categories, or what PARA method calls areas. Projects are different from areas and that they have a definition of completion and they have a deadline, but that's the only distinction. I realized that distinction doesn't do me any good because if it has a deadline, that's the distinction, right?

Calling it an area or calling it a project… I can just have projects without deadlines and then that's good enough. I have a query that shows me all projects whose deadlines are coming up within the next month, and then I'm aware of what I need to be aware of. I don't need to make the distinction between the ones that have and don't have deadlines. I just need to assign a deadline so the deadline was sufficient discrimination. I didn't need the classification difference between area and project.

And then [PARA's] distinction between projects, areas, and archives. I realize that there's only one operational benefit of an archive, and it's to speed things up by excluding archives from the Org ID database or from the org-roam-dbsync. That's it. That's the only reason I would ever exclude archives, because I want to search in archives. org-agenda-custom-commands is already only looking at open tasks. In a way, it's by implication archiving anything that's done in terms of its meaning.

This is all just an example of me looking at the para method and realizing that none of their distinctions really meant something for me.

What was meaningful was:

  • Does it have a deadline?
  • Is it bounded or not bounded?
  • Do I want to included in the processing of items?
  • [Is it a habit?]
Back to table of contents

John on habits

I did decide to draw the distinction of habits. I want them to look and feel different because I'm trying to become more habit-heavy.

I read this really brilliant book called Atomic Habits that I think has changed my life more than any other. I've read a lot of really good time management books but this book far and away has made the biggest impact on my life. One of its philosophical points that it makes that is so profound is that goal-oriented thinking is less successful in the long run than behavior-oriented thinking or habit- or system-oriented thinking. Instead of having a goal to clean your office, have a habit to remove some piece of clutter from your office like each time you stand up to go get a snack. You seek habits that in the aggregate will achieve the goals you seek to do.

I'm trying now to shift a lot of things in my to-do lists that were goals. I'm trying to identify the habits that will create systems of behavior that will naturally lead to those goals. I want habits to be first class citizens, and I want to be aware of the habits I'm creating.

I think the other thing that Atomic Habits did is it changed my conception of what a habit is. Before, I thought of a habit as "using the exercise bike" or something like that, which always made it a big enough task that I would keep pushing it off. Then I would realize I'd pushed it off for six months and then I would unschedule it and give up on it because it was just it would just be glaring at me with a look of doom from my agenda list.

What's important is the consistency, not the impact of any one particular accomplishing of that habit. It's a habit. If I do it daily, it's doesn't matter how much of it I do. So even if it just means I get on the bike and I spin the pedals for three minutes, literally, that's successful completion.

Any time you have a new habit, one of the activities in mastering that habit is to keep contracting the difficulty of the habit down, down. You've got to make it so stupidly small and simple to do, that you do it just for the fun of marking it done in the agenda, right?

I have a habit to review my vocabulary lists for languages that I'm learning. I'm okay with one word. As long as I ran the app and I studied one word, that's success.

What you find happening is that you'll do the one word, and now because you're there, because you're in the flow of it, you're like, "I'll do two. You know, I'm already here. What's the big difficulty in doing two?"

So you make the success bar super low. You're trying to almost trick yourself into getting into the flow of whatever that activity is.

[org-habit org-ql list] So I have all of these habits here, and every single habit on this list is super easy to do. Five minutes is all that it would take, or even one minute for most of them. I use different little icons to group them. It also keeps the title of the habit really small. I found that when the titles were really long. I didn't like reading it all the time. It just was a wall of text. When it's these one word plus an icon, it just kind of jumps out.

Back to table of contents

Adam on the Hammy timer and momentum

I took that to a bit of an extreme sort of with my my package remote called Hammy, for hamster. It's for timers and ideas, kind of like being a hamster on a hamster wheel.

Anyway, one of the timers is called flywheel mode. The idea is: just do a little bit. Like, if I'm just having a mental block, I can't stand working on that test today, I'm going to do five minutes. I can spend five minutes doing whatever. Next time, we do 10 minutes in 15. Pretty soon, I'm doing 45 minutes at a stretch. Maybe when I sit down to do 5, I'll actually do 15. I'm just slowly building up that mental momentum. I'll allow myself to quit after 5 minutes, but I end up doing 20.

Back to table of contents

John on momentum and consistency

Momentum is key. There's a flip side to this whole concept of the value of iterative improvement. The opposite remains also true.

Consistent good is your best ally, and inconsistent bad is also your ally. It's when the reverse is true that you have inconsistent good and consistent bad, that's what leads you into roads of doom.

That never occurred to me before. I would always be one of those people who would set myself up with a goal, like, I want to lose 20 pounds. I would struggle to achieve it. I would be dismayed because of how hard it was to get there, and then you'd have a day when you're like, you get off the wagon and you're like, The game is lost. And then and then you can't get back on again. Whereas now it's like that wagon, it's not so easy to get off of. I have to really make a concerted effort to be consistently bad in order to make things horrible again.

I almost want to change org-habit to have a different kind of visualization, because streaks are not motivators for me. Streaks punish you for losing one day out of 200, right? I don't want a graph that shows me streaks. I want a graph that shows me consistency. If I have 200 days and I've missed five of them, I'm super consistent. Maybe I could do this with colors. Just show a bar with that color, and don't show individual asterisks to show when I did it or when I didn't do it, because I find streaks anti-motivating.

[Discussion about other ways to display habits]

Back to table of contents

John on Life Balance by Llamagraphics

The whole principle around Life Balance [by Llamagraphics]​ was: you take all of your tasks, you categorize them, you associate difficulty to them and priority and everything else. Then it tries to use heuristics to determine if your life is being balanced, [and it percolates certain tasks to the top of your list].

If the system's doing a good job, then your agenda list should always be A-Z pretty much the best order in which you ought to do things. It didn't just do category-based balance, it also did difficulty-based balance. You should only be doing super hard stuff once in a while. You do a hard thing, then you do lots of easy things, then you do a hard thing.

Now, I'm wondering… This idea of momentum is very similar to the idea of balance. "Have established momentum with a system of behavior" is similar to "Have an established balance with all of the tasks that I do related to different activities." Is there a data architecture that would allow me to do both of these things.

The whole idea of making the habits be colors and then sorting them according to the spectrum is literally just to achieve balance among how much attention I'm paying to different habits.

[Discussion about dynamic prioritization]

Back to table of contents

Adam on the structure of his TODO view

My fundamental system right now is there's like two org-ql views. There's the view of tasks that are scheduled for today or have a deadline of today, and then there's a view of tasks that I've decided that they need to be done, but I haven't decided when to do them yet.

[Top list]: I just pick the next task off the list or reschedule if it's not important enough now. But then when that's empty, if it ever gets that way, it's the second view. I decide, okay, there's something I need to do. I can do that on Tuesday. Then it disappears until I need to think about it again.

This separates deciding what to do from when to do. Then I can just switch into my own manager mode for a moment, and then switch into "just put your head down and do the work mode."

[More details]

The top view is basically tasks that have a deadline, that are relevant to now (either deadline today or in the past), or it's an item that I've scheduled to work on today or in the past.

The view below, that is items that have no planning date. I need to give them one, or maybe they can just sit in that list of projects that have no next task. I use a project heading to [note] something that needs to be subdivided if I don't have a next task for it, then that'll show up there to remind me to give it one. Once it has a next task, [that] task would appear instead of the project heading until I schedule it. Anything I've forgotten to schedule yet will show up in that list.

Below that I just have a small window that shows me things. I've completed or clocked in the past week.

And then, another small window shows me anything that's a project status so I can get an overview.

In the work file itself, I have a number of links to org-ql views, like "Show me all my top level projects," "Show me tasks I need to talk to my boss about" or somebody else.

Back to table of contents

John on Org and data consistency

Org Mode is really a database, right? It's a database of of highly structured data that has a lot of associated metadata.

The value of that data requires a certain level of consistency which is work that we have to do. In the same way we do work drawing distinctions, we need to do work to keep that data consistent. Am I using this [property]? Am I using this tag to mean the right thing or whatever? Karl Voit says that one of the most valuable things if you're going to use tagging to organize your data is a constrained tag vocabulary. Make a fixed list. Then it's an error if you tag something and it's not in that list, because you either need to expand the list or you need to choose a better tag. That's really valuable.

Even though I use org-lint on all my org files, I found serious data errors. [The newline before an initial star had been lost], and then Org wouldn't see the entry. I never knew that it wasn't even being a participant in any of my queries. I just didn't know stuff like that.

I created a whole bunch of Haskell libraries that allow me to parse Org Mode data. It's a very opinionated parser. It's a very strict parser. It will not parse data files that do not have the exact shape and text and taxonomy that I want.

I wrote a linting module that basically encodes every single rule that I have ever wanted to apply to my data. Like, in the title of an Org Mode heading. I don't want two spaces. I don't want extra excess white space. That should be a rule right?

[Multiple examples, including when a file had TODO entries but didn't have a TODO filetag.]

My linter makes sure that this rule is consistently maintained. Being able to have an aggressive, thorough, universal consistency throughout all of my org data has really put my mind at ease. I can't break my data because I just won't be able to commit the broken data into git. I find myself adding new linting rules on a weekly basis. The more that I add, the more value my data has, because the more regular it is, the more normal, the more searchable.

Back to table of contents

My takeaways

People:

Comments

TIL about column view in #orgmode thanks to this great post from @sacha

@donaldh@hachyderm.io

Qu’est-ce que ça fait plaisir de lire un article de @sacha (en l’occurrence link) et de découvrir que John Wiegley utilise org-review (https://github.com/brabalan/org-review), un petit truc que j’ai écrit il y a 10 ans…

@brab@framapiaf.org

Very interesting to see Adam and John's workflows. Org is so flexible and powerful. I always learn something new watching other people do org stuff.

Nice article, Sacha!

mickeyp on Reddit

View org source for this post
-1:-- Excerpts from a conversation with John Wiegley (johnw) and Adam Porter (alphapapa) about personal information management (Post Sacha Chua)--L0--C0--November 06, 2024 07:29 PM

Sacha Chua: Interactively recolor a sketch

I wanted to be able to change the colours used in a sketch, all from Emacs. For this, I can reuse my Python script for analyzing colours and changing them and just add some Emacs Lisp to pick colours from Emacs.

2024-11-05-14-15-55.svg
Figure 1: Selecting the colour to replace
2024-11-05-14-16-04.svg
Figure 2: Selecting the new colour
(defvar my-recolor-command "/home/sacha/bin/recolor.py")

(defun my-image-colors-by-frequency (file)
  "Return the colors in FILE."
  (with-temp-buffer
    (call-process my-recolor-command nil t nil (expand-file-name file))
    (goto-char (point-min))
    (delete-region (point-min) (1+ (line-end-position)))
    (mapcar (lambda (o) (concat "#" (car (split-string o "[ \t]"))))
            (split-string (string-trim (buffer-string)) "\n"))))

(defun my-completing-read-color (prompt list)
  "Display PROMPT and select a color from LIST."
  (completing-read
   (or prompt "Color: ")
   (mapcar (lambda (o)
             (faces--string-with-color o o))
           list)))

(defun my-image-recolor-interactively (file)
  (interactive (list (read-file-name "File: " (concat my-sketches-directory "/") nil t
                                     nil
                                     (lambda (file) (string-match "\\.png\\'" file)))))
  (save-window-excursion
    (find-file file)

    ;; Identify the colors by frequency
    (let (choice done)
      (while (not done)
        (let* ((by-freq (my-image-colors-by-frequency file))
               (old-color (my-completing-read-color "Old color: " by-freq))
               (new-color (read-color "New color: " t))
               (temp-file (make-temp-file "recolor" nil (concat "." (file-name-extension file))))
               color-map)
          (when (string-match "#\\(..\\)..\\(..\\)..\\(..\\).." new-color)
            (setq new-color (concat (match-string 1 new-color)
                                    (match-string 2 new-color)
                                    (match-string 3 new-color))))
          (setq color-map (replace-regexp-in-string "#" "" (concat old-color "," new-color)))
          (call-process my-recolor-command nil nil nil
                        (expand-file-name file)
                        "--colors"
                        color-map
                        "--output" temp-file)
          (find-file temp-file)
          (pcase (read-char-choice "(y)es, (m)ore, (r)edo, (c)ancel: " "yrc")
            (?y
             (kill-buffer)
             (rename-file temp-file file t)
             (setq done t))
            (?m
             (kill-buffer)
             (rename-file temp-file file t))
            (?r
             (kill-buffer)
             (delete-file temp-file))
            (?c
             (kill-buffer)
             (delete-file temp-file)
             (setq done t))))))))

It would be nice to update the preview as I selected things in the completion, which I might be able to do by making a consult–read command for it. It would be extra cool if I could use this webkit-based color picker. Maybe someday!

This is part of my Emacs configuration.
View org source for this post
-1:-- Interactively recolor a sketch (Post Sacha Chua)--L0--C0--November 05, 2024 07:23 PM

Jack Baty: A Doom Emacs status update after several days

Some quick notes on my move back to Doom Emacs after a few days.

After once again hitching my wagon to Doom Emacs, I have been both elated and frustrated. I’m elated because Doom adds so many nice little quality-of-life improvements that make using Emacs downright pleasant right out of the gate. On the other hand, it ruins a few things and sometimes breaks for no reason that I can understand. It’s nice having someone maintain the basics of my config, but it’s also frustrating when those someones do it “wrong”. And sometimes running ./bin/doom upgrade breaks things. I can usually recover, but don’t love that I have to think about it. This is a side effect of having others do things for me, and it’s a fair trade.

So far, I’ve resolved most of the little issues. One of those was with Elfeed. Elfeed is unusable for me when using Doom’s default configuration. Doom includes the elfeed-extras package, and I don’t like it. The split window is annoying. What’s worse is that there’s no date column in the list of articles and there’s no simple way to include it. That’s just dumb, imo. So I disable that package and modify a few little things and it’s much better.

The remaining problem is that I sync my entire .config/emacs and .config/doom directories, and this somehow breaks because Doom adds $TMPDIR to the .config/emacs/.local/env file. Apparently, my tmp directory is not the same on both the Mini and the MBP, so I get permissions errors every time I switch machines. The workaround is to run ./bin/doom env before starting emacs when switching machines. That’s not sustainable. I’ll figure it out, but it’s one thing that still bugs me.

And oh, the key bindings! Around six months ago, I moved back to my vanilla config and decided to stop using Evil mode. It was a painful transition, but I got used to it and now the stock key bindings feel normal. The problem was that I also use several tools that only offer Vim bindings. Switching between Emacs and Vim bindings has been chaotic, to say the least. I keep tripping over myself and there’s been a lot of swearing. Going back to Doom and Evil mode has been tricky, but the muscle memory is returning, and I like the consistency in the apps I use most.

Something I dislike is using Doom’s abstractions like after! and map!. It just makes things even less “normal”. Handy, but it will make moving out of Doom harder. Not that I’d ever do that, though, right? 😆.

Right now, I’m happy with the setup. I love when Doom does something and it makes me say, “ooh, nice!”. As long as that happens more often than me saying, “WTF?! That’s dumb.”, I should be fine in Doom.

-1:-- A Doom Emacs status update after several days (Post)--L0--C0--November 05, 2024 11:32 AM

Sacha Chua: Emacs: Extract part of an image to another file

It turns out that image-mode allows you to open an image and then crop it with i c (image-crop), all within Emacs. I want to select a region and then write it to a different file. I think the ability to select a portion of an image by drawing/moving a rectangle is generally useful, so let's start by defining a function for that. The heavy lifting is done by image-crop--crop-image-1, which tracks the mouse and listens for events.

;; Based on image-crop.
(defun my-image-select-rect (op)
  "Select a region of the current buffer's image.

`q':   Exit without changing anything.
`RET': Select this region.
`m':   Make mouse movements move the rectangle instead of altering the
       rectangle shape.
`s':   Same as `m', but make the rectangle into a square first."
  (unless (image-type-available-p 'svg)
    (error "SVG support is needed to crop and cut images"))
  (let ((image (image--get-image)))
    (unless (imagep image)
      (user-error "No image under point"))
    (when (overlays-at (point))
      (user-error "Can't edit images that have overlays"))
    ;; We replace the image under point with an SVG image that looks
    ;; just like that image.  That allows us to draw lines over it.
    ;; At the end, we replace that SVG with a cropped version of the
    ;; original image.
    (let* ((data (cl-getf (cdr image) :data))
           (type (cond
                  ((cl-getf (cdr image) :format)
                   (format "%s" (cl-getf (cdr image) :format)))
                  (data
                   (image-crop--content-type data))))
           (image-scaling-factor 1)
           (orig-point (point))
           (size (image-size image t))
           (svg (svg-create (car size) (cdr size)
                            :xmlns:xlink "http://www.w3.org/1999/xlink"
                            :stroke-width 5))
           ;; We want to get the original text that's covered by the
           ;; image so that we can restore it.
           (image-start
            (save-excursion
              (let ((match (text-property-search-backward 'display image)))
                (if match
                    (prop-match-end match)
                  (point-min)))))
           (image-end
            (save-excursion
              (let ((match (text-property-search-forward 'display image)))
                (if match
                    (prop-match-beginning match)
                  (point-max)))))
           (text (buffer-substring image-start image-end))
           (inhibit-read-only t)
           orig-data svg-end)
      (with-temp-buffer
        (set-buffer-multibyte nil)
        (if (null data)
            (insert-file-contents-literally (cl-getf (cdr image) :file))
          (insert data))
        (let ((image-crop-exif-rotate nil))
          (image-crop--possibly-rotate-buffer image))
        (setq orig-data (buffer-string))
        (setq type (image-crop--content-type orig-data))
        (image-crop--process image-crop-resize-command
                             `((?w . 600)
                               (?f . ,(cadr (split-string type "/")))))
        (setq data (buffer-string)))
      (svg-embed svg data type t
                 :width (car size)
                 :height (cdr size))
      (with-temp-buffer
        (svg-insert-image svg)
        (switch-to-buffer (current-buffer))
        (setq svg-end (point))
        ;; Area
        (let ((area
               (condition-case _
                   (save-excursion
                     (forward-line 1)
                     (image-crop--crop-image-1
                      svg op))
                 (quit nil))))
          (when area
            ;;  scale to original
            (let* ((image-scaling-factor 1)
                   (osize (image-size (create-image orig-data nil t) t))
                   (factor (/ (float (car osize)) (car size)))
                   ;; width x height + left + top
                   (width (abs (truncate (* factor (- (cl-getf area :right)
                                                      (cl-getf area :left))))))
                   (height (abs (truncate (* factor (- (cl-getf area :bottom)
                                                       (cl-getf area :top))))))
                   (left (truncate (* factor (min (cl-getf area :left)
                                                  (cl-getf area :right)))))
                   (top (truncate (* factor (min (cl-getf area :top)
                                                 (cl-getf area :bottom))))))
              (list :left left :top top
                    :width width :height height
                    :right (+ left width)
                    :bottom (+ top height)))))))))

Then we can use it to select part of an image, and then use ImageMagick to extract that part of the image:

(defun my-image-write-region ()
  "Copy a section of the image under point to a different file.
This command presents the image with a rectangular area superimposed
on it, and allows moving and resizing the area to define which
part of it to crop.

While moving/resizing the cropping area, the following key bindings
are available:

`q':   Exit without changing anything.
`RET': Save the image.
`m':   Make mouse movements move the rectangle instead of altering the
       rectangle shape.
`s':   Same as `m', but make the rectangle into a square first."
  (interactive)
  (when-let* ((orig-data (buffer-string))
              (area (my-image-select-rect "write"))
              (inhibit-read-only t)
              (type (image-crop--content-type orig-data))
              (left (plist-get area :left))
              (top (plist-get area :top))
              (width (plist-get area :width))
              (height (plist-get area :height)))
    (with-temp-file (read-file-name "File: ")
      (set-buffer-multibyte nil)
      (insert orig-data)
      (image-crop--process image-crop-crop-command
                           `((?l . ,left)
                             (?t . ,top)
                             (?w . ,width)
                             (?h . ,height)
                             (?f . ,(cadr (split-string type "/"))))))))

i w seems like a sensible shortcut for writing a region of an image.

(with-eval-after-load 'image
  (keymap-set image-mode-map "i w" #'my-image-write-region))
This is part of my Emacs configuration.
View org source for this post
-1:-- Emacs: Extract part of an image to another file (Post Sacha Chua)--L0--C0--November 04, 2024 07:57 PM

Irreal: Adding A Year Tag From A Capture Template

James Dyer has a good idea for organizing his org-based notes. It’s simple: add a year tag to each note. It helps to organize the notes and makes it easy to filter them by year.

When he first implemented the system, he simply hard coded the year into the capture template but then, of course, he had to remember to update it every year. We all know what a fragile process that can be. Dyer decided he needed a better way so he looked into generating the year tag programmatically. He found a couple of ways.

They both involved using the format time specifiers. You can take a look at his post for the details but it turns out to be really easy so if you’re interested in doing something similar you should definitely spend a couple of minutes reading his post. It’s another great example of the flexibility of Emacs and Org mode.

-1:-- Adding A Year Tag From A Capture Template (Post jcs)--L0--C0--November 04, 2024 04:18 PM

Sacha Chua: 2024-11-04 Emacs news

Reminder: Emacs News is moving to info-gnu-emacs instead of emacs-tangents. If you're subscribed through emacs-tangents, you may want to subscribe to info-gnu-emacs as well.

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

View org source for this post
-1:-- 2024-11-04 Emacs news (Post Sacha Chua)--L0--C0--November 04, 2024 01:21 PM

Marcin Borkowski: Persisting variables across Emacs sessions

Today, I have a short tip to all people who write Elisp and want to preserve some variable other than user customizations between Emacs sessions. (For user settings, configuring them manually in init.el is the standard way to go.) A classic example would be histories of the user’s entries.
-1:-- Persisting variables across Emacs sessions (Post)--L0--C0--November 04, 2024 07:24 AM

Emacs Notes: Enable completions for `Font Family’ field in `M-x customize-face RET’

Emacs offers NO completion aid for filling out Font Family field in M-x customize-face RET In an earlier post titled Use `org-extra-emphasis’ , when you need more Emphasis Markers in Emacs Org mode, I talked about how one can have custom emphasis in org-mode. In that post, bulk of the effort involves installing some additional … Continue reading Enable completions for `Font Family’ field in `M-x customize-face RET’
-1:-- Enable completions for `Font Family’ field in `M-x customize-face RET’ (Post Emacks)--L0--C0--November 03, 2024 01:29 PM

Ben Whitley: Denote Project Tasks

Tracking project-specific tasks is something I've changed many times over the years. I've tried apps like Taskwarrior (which I loved), using in-line TODO comments throughout my code and collecting them with something like magit-todos, to now just a strategically-named plain org file I can just spawn when I need it. And recently I got a bug to try something new. I'm writing this post in parallel of me trying to implement it so it follows my train of thought and trials.
-1:-- Denote Project Tasks (Post)--L0--C0--November 03, 2024 12:00 AM

Sacha Chua: Org Mode: Format Libby book highlights exported as JSON

The Toronto Public Library (and many other libraries) offers e-book access through Overdrive, which I can read through the Libby app on my phone. It turns out that I can select passages to highlight. It also turns out that I can use the Reading Journey view to export the highlights as JSON, even for books I've returned. This is what the JSON looks like.

{
  "version": 1,
  "readingJourney": {
    "cover": {
      "contentType": "image/jpeg",
      "url": "https://img1.od-cdn.com/ImageType-100/7635-1/{B41A3269-BC2A-4497-8C71-0A3F1FA3C694}Img100.jpg",
      "title": "How to Take Smart Notes",
      "color": "#D9D9D9",
      "format": "ebook"
    },
    "title": {
      "text": "How to Take Smart Notes",
      "url": "https://share.libbyapp.com/title/5796521",
      "titleId": "5796521"
    },
    "author": "Sönke Ahrens",
    "publisher": "Sönke Ahrens",
    "isbn": "9781393776819",
    "percent": 0.313229455252918
  },
  "highlights": [
    {
      "timestamp": 1729898852000,
      "chapter": "13       Share Your Insight",
      "percent": 0.824912451361868,
      "color": "#FFB",
      "quote": "For every document I write, I have another called “xy-rest.doc,” and every single time I cut something, I copy it into the other document, convincing myself that I will later look through it and add it back where it might fit. Of"
    },
    {
      "timestamp": 1729898760000,
      "chapter": "13       Share Your Insight",
      "percent": 0.801566108949416,
      "color": "#FFB",
      "quote": "I always work on different manuscripts at the same time. With this method, to work on different things simultaneously, I never encounter any mental blockages"
    },
    ...
 ]
}

I want to save those highlights in my books.org file for easy searching, grouping the highlights by chapter. The following code helps with that:

(defun my-org-insert-book-highlights-from-libby (url)
  (interactive "MURL: ")
  (let-alist (plz 'get url :as #'json-read)
    (insert
     "* "
     .readingJourney.title.text
     " - "
     .readingJourney.author
     "\n")
    (org-set-property "ISBN" .readingJourney.isbn)
    (org-set-property "COVER" .readingJourney.cover.url)
    (org-set-property "TITLE" .readingJourney.title.text)
    (org-set-property "AUTHOR" .readingJourney.author)
    (insert (org-link-make-string .readingJourney.title.url .readingJourney.cover.url)
            "\n")
    ;; sort the highlights by chapter
    (insert
     (mapconcat
      (lambda (row)
        (concat "** " (replace-regexp-in-string " +" " " (car row)) "\n"
                (mapconcat (lambda (quote)
                             (concat "#+begin_quote\n"
                                     (alist-get 'quote quote)
                                     "\n#+end_quote\n\n"))
                           (cdr row)
                           "")
                "\n\n"))
      (seq-group-by
       (lambda (o) (alist-get 'chapter o))
       (sort .highlights
             :key (lambda (o) (alist-get 'percent o))))))))

This is what the resulting document looks like:

* How to Take Smart Notes - Sönke Ahrens
:PROPERTIES:
:ISBN:     9781393776819
:COVER:    https://img1.od-cdn.com/ImageType-100/7635-1/{B41A3269-BC2A-4497-8C71-0A3F1FA3C694}Img100.jpg
:TITLE:    How to Take Smart Notes
:AUTHOR:   Sönke Ahrens
:END:
https://img1.od-cdn.com/ImageType-100/7635-1/{B41A3269-BC2A-4497-8C71-0A3F1FA3C694}Img100.jpg
** 1  Everything You Need to Know
#+begin_quote
 never force myself to do anything I don’t feel like. Whenever I am stuck, I do something else.”
#+end_quote

#+begin_quote
Luhmann’s only real help was a housekeeper who cooked for him and his children during the week, not that extraordinary considering he had to raise three children on his own after his wife died early.
#+end_quote

...
This is part of my Emacs configuration.
View org source for this post
-1:-- Org Mode: Format Libby book highlights exported as JSON (Post Sacha Chua)--L0--C0--November 02, 2024 09:48 PM

TAONAW - Emacs and Org Mode: Digital Notes vs. Analog notebook

The other day, I needed to copy some notes from my pocket notebook to my project file in org-mode, which is synced to my iPhone with iCloud. I was on the subway on my way downtown with a friend.

I played around with Beorg, which allows me to work with org-mode files on the go. Not only did I manage to get all the items in, but I also figured out how to display my active projects on the app so they show neatly on my weekly agenda.

It was relatively painless to transfer my handwritten notes into the file. I was also able to add a few more to-do items with the app, something that would be nearly impossible to do with my notebook on a moving and shaking train. My handwriting is terrible enough as is.

When I got home, the updated file with the tasks was already waiting on my Mac, synced.

I spent my reading time in bed reading into Beorg’s documentation. I was excited but also conflicted. Should I even bother with my pocket notebook when capturing notes with my phone (and watch, with Reminders) is so easy? Is there any sense in transcribing and deciphering my handwritten notes into dates and checklist items when those can be created semi-automatically for me?

The speed alone, not to mention the clarity and search capability, would increase my productivity to a new level—one that I definitely need at work right now.

-1:-- Digital Notes vs. Analog notebook (Post)--L0--C0--November 02, 2024 05:19 PM

Irreal: TSV To Table

Philippe Gaultier has an interesting post on making a table of project dependencies. He’s using Rust, for which there is a tool to produce a tab-delimited (TSV) file of dependencies. The problem, for Gaultier, is that the output is not very human readable.

His solution was to write an AWK script that converts the TSV file to a version of Markdown and then export that to HTML. It works well and produces nice output that he can share with his coworkers. Take a look at his post to see the results.

Not to be that guy but when I read his post I thought, “Gee, that seems like a lot of work. How would I do that in Emacs?” After a few moments thought, I realized that I was already doing exactly that. I have a TSV file that I export from my iPhone and want to turn into an Org table. I simple paste the TSV data into my file and call (org-table-create-or-convert-from-region '(16)) to reformat the data to Org-mode table format.

The '(16) parameter tells org-table-create-or-covert-from-region that the data is tab delimited. There are other possible delimiters, see the documentation for the details.

Again, not to be that guy but this is another example of how powerful and flexible Emacs is. Have some data you want to convert? Chances are Emacs already has a way of doing it. Even if it doesn’t, it’s generally pretty easy to add a bit of Elisp to do it. The worst case is you’ll have to write an external app—in AWK, or whatever—to convert the data in your Emacs buffer to the format you need. Regardless, the whole process can be handled without leaving Emacs.

-1:-- TSV To Table (Post jcs)--L0--C0--November 01, 2024 03:40 PM

James Dyer: Generate Current Year tag in an Org Capture Template

A crucial aspect of maintaining organized and up-to-date notes is the use of Org Capture templates.

I have currently always hard-coded/set the current year in my org capture templates for use when exporting/constructing my web pages and as a tag for some filtering / web index generation. Of course the main disadvantage of this is that I have to remember to update the year each year, of which I often fail miserably. ☹️

Can I get an org capture template to auto generate just the year as a tag like other capture template attributes?

Well yes, yes you can, and there a couple of ways to achieve this.

Firstly there is the org capture family of format strings which inserts a date when the capture is triggered. This is a bit much for me and instead of generating just a string for the year, each specifier will generate a full timestamp:

  • %U — Inactive Timestamp (Full Date and Time)
  • %T — Active Timestamp (Full Date and Time)
  • %t — Active Timestamp (Current Date Only)
  • %u — Inactive Timestamp (Current Date Only)

However there is another format specifier, which can just insert the year, simply use %<%Y> which is part of a pretty standard common date or time string format options, for example, here are some useful format specifiers that can be used:

  • `%Y`: Year (e.g., `2023`)
  • `%m`: Month (e.g., `10` for October)
  • `%d`: Day (e.g., `05`)
  • `%H`: Hour (24-hour clock)
  • `%M`: Minute
  • `%S`: Seconds
  • `%A`: Full weekday name (e.g., `Monday`)
  • `%B`: Full month name (e.g., `October`)

Well that was easy, so to insert a year tag I can just wrap colons around %<%Y>

Just for fun, lets try something a little more advanced to achieve the same goal but this time allowing much more flexibility.

A particularly useful functional aspect of an org template is that the dynamic generation of the current year can be achieved using some elisp. Lets use the (format-time-string) function.

Understanding (format-time-string "%Y")

Before diving into the implementation, let’s break down what (format-time-string "%Y") does:

  • format-time-string: This is an Emacs Lisp function that formats the current time and date into a string based on a specified format.

  • "%Y": This format code specifically fetches the four-digit representation of the current year. For example, in 2023, it would insert “2023”, and conforms to the date specifiers defined above for the more simple capture template format definition.

By embedding this function into my Org Capture templates, the inclusion of the current year is neatly automated, this not only reduces manual updates but also ensures consistency across my entries.

Implementing Dynamic Year in Capture Templates

Here’s an example Org Capture template that uses (format-time-string "%Y") to dynamically manage the year for Emacs-related entries:

("e" "Emacs" plain
  (file+function
    "~/DCIM/content/emacs--all.org"
    my-capture-top-level)
  "* TODO %^{title} :emacs:%(format-time-string \"%Y\"):"
:PROPERTIES:
:EXPORT_FILE_NAME: %<%Y%m%d%H%M%S>-emacs--%\\1
:EXPORT_HUGO_SECTION: emacs
:EXPORT_HUGO_LASTMOD: <%<%Y-%m-%d %H:%M>>
:EXPORT_HUGO_CUSTOM_FRONT_MATTER+: :thumbnail /emacs/%<%Y%m%d%H%M%S>-emacs--%\\1.jpg
:END:
%?
" :prepend t :jump-to-captured t)

Key Features of this Template

  • Automatic Year Insertion:
    • The directive :%(format-time-string \"%Y\"):, within the headline, ensures that the current year is automatically included as a tag whenever you create a new entry. This functionality is particularly useful for organizing tasks by year, making it easier to retrieve and filter information based on time.
  • Enhanced Organization:
    • By integrating the current year automatically, you maintain a systematic arrangement of notes and tasks, minimizing the need for manual adjustments every new year.
  • Ease of Use:
    • This template is set up for simplicity and re-usability. Once implemented, it requires no further changes for year-specific adjustments, allowing you to focus on content generation rather than template management.

Benefits of Dynamic Year Management

  • Time-Saving: No need to modify the template annually, thus saving valuable time.
  • Consistent Records: Automatic year tagging provides a consistent way of tracking entries over time.
  • Improved Searchability: Facilitates year-based searches and statistics generation, enhancing the utility of your Org files.
-1:-- Generate Current Year tag in an Org Capture Template (Post James Dyer)--L0--C0--November 01, 2024 08:30 AM

200ok: EmacsConf 2024: Join Us in Lucerne for a Celebration of Free Software!

EmacsConf Returns to Lucerne!

Emacs enthusiasts, mark your calendars! On December 7-8, 2024, the heart of Switzerland will once again beat to the rhythm of parentheses and key bindings. 200OK and Ardeo are thrilled to announce our continued partnership as hosts of the official Swiss satellite for EmacsConf 2024.

  • Immersive Experience: Dive deep into Emacs culture surrounded by like-minded individuals.
  • Networking Opportunities: Build connections that last beyond the conference.
  • Hands-on Hacking: Our dedicated hacking room is perfect for collaborative coding sessions.
  • Swiss Hospitality: Enjoy the welcoming venue of Ardeo and the charm of Lucerne.

What to Expect

  • Dates: December 7-8, 2024 (Saturday and Sunday)
  • Location: Ardeo's Coworking Hub, Hirschmattstrasse 42, 6003 Lucerne
  • Capacity: Limited to 25 attendees - secure your spot early!
  • Schedule: Doors open at 14:30 local time both days
  • Tracks:
    • General: Emacs workflows and community insights
    • Development: Technical deep-dives for the Emacs curious and experienced alike
Hacking Room

Photography

We plan to take photos during the event for online publication. If you prefer not to be photographed, please consider this before attending. Guests are also welcome to take and share their own photos.

Admission

Admission is free. On-site donations (for the venue) are welcome and appreciated.

Why We Host

At 200OK, we're passionate about Free Software and the Emacs community. Hosting EmacsConf is our way of contributing to this vibrant ecosystem. It's more than an event; it's a celebration of the values that drive innovation and collaboration in the Free/Libre and Open Source Software (FLOSS) world.

Sign up

Looking forward to EmacsConf? Here's how to secure your spot:

  1. Email info@200ok.ch with the subject "Register for EmacsConf 2024 in Lucerne"
  2. Include the following details:
    • Days attending: Dec 7 and/or Dec 8
    • Number of attendees in your group

Remember, space is limited to 25 attendees, so early registration is encouraged!

Can't Make It to Lucerne?

EmacsConf 2024 will also be streamed online, ensuring global participation.

Impressions from previous years

Here are some impressions from previous EmacsConf. It was a truly special weekend, and we are grateful to have been a part of it.

Join the Conversation

For general discussions about EmacsConf, you can join the emacsconf-discuss mailing list. If you're interested in the organizational aspects, the emacsconf-org mailing list is the place to be. Public and private emails can be sent to emacsconf-org@gnu.org and emacsconf-org-private@gnu.org, respectively.

To engage in real-time discussions, the #emacsconf channel on irc.libera.chat is the go-to place. You can join the chat using your favorite IRC client or by visiting chat.emacsconf.org in your web browser.

-1:-- EmacsConf 2024: Join Us in Lucerne for a Celebration of Free Software! (Post Phil Hofmann, Alain M. Lafon, Mario Trost (info@200ok.ch))--L0--C0--November 01, 2024 12:00 AM

Irreal: Define Alternatives

Marcin Borkowski (mbork) has an excellent post concerning a function I didn’t know about. It helps with the following problem: suppose you have a function with several implementations, want to access them with a single function name, and need to choose the implementation to use when you invoke the common function name.

That probably seems a little obscure but the example that mbork gives makes it clear. His use case is wanting to play some music using one of mplayer, vlc, or mpv using a single invocation name.

There are plenty of straightforward ways of doing this, of course, but mbork shows a very nice builtin method: define-alternatives. It’s easy to use and set up. You simply provide an alist of method/function pairs and use define-alternatives to specify a function name that will invoke the method of the user’s choice. See mborks post or the documentation for the details.

Define-alternatives is a great way of handling this situation. It’s hard to imagine a method that requires less code or effort on the developer’s part. As mbork says, the method doesn’t seem to be well known so it’s worthwhile pointing to mbork’s post as a way of getting the word out.

-1:-- Define Alternatives (Post jcs)--L0--C0--October 31, 2024 03:24 PM

Sacha Chua: Org Mode: Prompt for a heading and then refile it to point

I sometimes want the inverse of org-refile when I create a subtree and think of things that should probably go into it. This function prompts for a heading that matches org-refile-targets and then moves it to the current location.

(defun my-org-refile-to-point (refloc)
  "Prompt for a heading and refile it to point."
  (interactive (list (org-refile-get-location "Heading: ")))
  (let* ((file (nth 1 refloc))
         (pos (nth 3 refloc)))
    (save-excursion
      (with-current-buffer (find-file-noselect file 'noward)
        (save-excursion
          (save-restriction
            (widen)
            (goto-char pos)
            (org-copy-subtree 1 t))))
      (org-paste-subtree nil nil nil t))))
View org source for this post
-1:-- Org Mode: Prompt for a heading and then refile it to point (Post Sacha Chua)--L0--C0--October 31, 2024 02:42 PM

Jack Baty: Diving back into Org-roam

I’ve decided to dive back into Org-roam and see how it feels. I’ve done this before, but eventually moved back to Denote. I love Denote’s simplicity, but I have noticed that I don’t take advantage of many of its main advantages. For example, I always use Org-mode files, never Markdown or plain .txt. I almost never filter my files based solely on components of their names. I like using multiple tags, but doing so makes Denote filenames even more unweildy. And so on.

How did I end up back in Org-roam? I summed it up yesterday, so start there.

I’m getting over my internet-induced fear of “lock-in”. I mean, Org-roam uses a (GASP!) database! Who in their right mind relies on a database for managing their precious plain-text notes? 🙄🙋‍♂️. You can call it lock-in if you want, but the first requirement for my notes is that they are as useful as possible to me…today. If that means there’s a chance they end up less useful in some hypothetical scenario 20 years from now, I don’t care. Besides, they will be useful in 20 years. They’re still just plain text. The database is only a wrapper around a bunch of text files, so without that the only important thing I lose is the convenient linking and backlinks, etc. So they’ll just be a little less useful, I suppose. That’s fine, and a trade-off I’m willing to make.

One thing I’m doing to help with future-proofing is to use org-roam-dblocks from Chris Barrett. This lets me “burn” backlinks or query results directly into the files, removing the need for the database-ey bits. Here’s an example:

A dblock with links to everything tagged Emacs

A dblock with links to everything tagged Emacs

(use-package org-roam-dblocks
  :after org-roam
  :load-path "~/.config/emacs/lisp/nursery/lisp"
  :hook (org-mode . org-roam-dblocks-autoupdate-mode))

I have it configured to automatically update whenever the file is opened/saved. That helps. Without this, though, there’s always search 😀.

Speaking of search, I’ve configured the wonderful Deadgrep as the default way I search in Org-roam. It required that I write a small lisp function, but it works great. I love Deadgrep.

(defun jab/search-roam (search-term dir)
      "deadgrep in org-roam-directory"
      (interactive (let ((search-term (deadgrep--read-search-term)))
                     (list search-term org-roam-directory)))
      (deadgrep search-term dir))

Here’s what the Deadgrep search results look like:

Deadgrep results for ’emacs'

Deadgrep results for ’emacs'

That earlier post explained why I like using Org-roam, but here’s a quick list:

  • Any org heading can be a node
  • Aliases
  • Multiple tags without cluttering up the file names
  • Feature-rich Daily notes functionality
  • Org-roam-refile

I even like the Graph made possible by org-roam-ui, even though I make fun of it.

I am hedging my bets just a little, though. My default org-roam-capture-template creates new files using Denote’s default format. It also includes the #+identifer: front matter that Denote uses. While I don’t intend to use both Denote and Org-roam like I used to, it’s nice to know that I can.

-1:-- Diving back into Org-roam (Post)--L0--C0--October 30, 2024 11:15 AM

James Cherti: Essential Emacs Packages for Efficient Software Development and General Text Editing

In the pursuit of an optimized Emacs setup, I focused on enhancing defaults and minimizing the number of installed packages to maintain simplicity and efficiency:

  • The initial step involved creating minimal-emacs.d, a project that has resonated with the Emacs community, providing a foundational template for many users’ init.el and early-init.el vanilla Emacs configuration.
  • Next, I experimented with hundreds of Emacs packages, carefully selecting the most valuable ones that, ideally, leverage built-in Emacs functions. (This is why I chose corfu over company, eglot over lsp-mode, and flymake over flycheck, etc.)

In this article, I will share the Emacs packages I use daily for software development and general text editing. Please share in the comments the Emacs packages you are using!

Where can I find the third-party packages listed below?

The following Emacs packages installed whether from MELPA or ELPA.

Category: Code completion

  • corfu: A completion framework that integrates with the built-in completion system in Emacs. For example, it can complete Python code when using the eglot package and a Python language server such as Pylsp.
  • prescient: Provides smart completion suggestions based on history and context. For example, it can enable fuzzy completion with Corfu/Cape or anticipate your next input based on previous selections.
  • cape: A completion-at-point extension for various completion frameworks in Emacs, enhancing Corfu.
  • nerd-icons-corfu: Integrates Nerd Icons with the Corfu completion framework, enhancing the appearance of completion candidates.

Category: Software development (General)

  • eglot (built-in): An LSP client that provides features like code completion, diagnostics, formatting, and more, powered by language servers. For example, it can be used to add Python code completion using the language server Pylsp. There are many language servers available for many other programming languages.
  • outline-indent: Enables code folding based on indentation levels. This package is useful for editing indentation-based text files, such as YAML, Python, and other indented text files.
  • treesit (built-in): This package provides a way to work with tree-sitter, a syntax code parser that performs syntax highlighting, code navigation, and structural editing across various programming languages.
  • highlight-symbol: Highlight occurrences of symbols in your code.
    (The author is now using the built-in alternative: The
    (highlight-symbol-at-point)
    function to highlight and
    (unhighlight-regexp (regexp-quote (thing-at-point 'symbol t)))
    to unhighlight.)
  • reformatter: Define commands which run reformatters on the current Emacs buffer
  • flymake (built-in): An on-the-fly syntax checking system that works well with eglot.
  • indent-bars: Provides indentation guide-bars.
  • paren (built-in): Matching parenthesis highlighting.
  • ws-butler: Automatically trim extraneous white-space only in edited lines.
  • yasnippet: A template system for Emacs that allows for easy insertion of code snippets, improving coding efficiency. (The author is also using ultyas to share the same code snippets in Emacs and Vim)
  • dtrt-indent: Automatically adjusts indentation based on the surrounding context in code files, improving code readability.

Category: Version Control System

  • magit: A comprehensive interface for Git within Emacs, allowing for easy version control operations.
  • diff-hl: Displays git diff information in the fringe of your Emacs window.
  • git-gutter: Displays git diff information in the fringe of your Emacs window. (alternative to diff-hl.)
  • git-modes: A collection of major and minor modes for various Git-related files.

Category: Better minibuffer

  • consult: Provides intelligent search and navigation commands, powered by the Emacs completion function, completing-read.
  • consult-dir: insert paths into minibuffer prompts in Emacs. Similar to fasd.
  • vertico: minimalistic vertical completion UI. (There is also built-in alternative to vertico: fido-vertical-mode)
  • marginalia: Enhances the display of completion candidates in the minibuffer.
  • embark: Enhances minibuffer completion and interaction with various Emacs commands and actions.

Category: Session management / persist and restore

  • easysession: A lightweight Emacs session manager that can persist and restore file editing buffers, indirect buffers/clones, Dired buffers, the tab-bar, and the Emacs frames (with or without the Emacs frames size, width, and height).
  • saveplace (built-in): Persist and restore your current cursor position.
  • savehist (built-in): Persist and restore your Emacs command history.

Category: Themes

  • tomorrow-night-deepblue-theme: A blue color theme for Emacs inspired by the Tomorrow Night color scheme.
  • ef-themes: A collection of light and dark themes for GNU Emacs whose goal is to provide colorful themes.

Category: Vim emulation

  • evil: An extensible vi layer for Emacs, providing a modal editing experience similar to Vim.
  • evil-collection: A collection of Emacs packages that integrate with Evil mode to provide consistent keybindings across multiple modes.
  • evil-snipe: Provides enhanced search and jump functionality for Evil mode.
  • evil-surround: Enhances text object handling in Evil mode, allowing for easier manipulation of surrounding characters.
  • vdiff: Provides a visual interface for comparing two versions of a file that is similar to the Vim editor.
  • vim-tab-bar: Provides a tab-bar interface reminiscent of Vim.

Category: Terminal Emulators

  • eat: A terminal emulator, written in Elisp.
  • vterm: A terminal emulator for Emacs, written in C.

Category: Undo/Redo

  • undo-fu: An advanced undo/redo system that enhances the default undo behavior in Emacs.
  • undo-fu-session: Integrates with undo-fu to provide session management for undo history.

Category: Elisp

  • easy-escape: Improve readability of escape characters.
  • aggressive-indent: Automatically keeps your code indented as you type. The author mainly uses this package with Elisp.
  • paren-face: Visually enhances Elisp parentheses.
  • package-lint: Lints Emacs Lisp packages to ensure compliance with best practices and package standards.
  • helpful: An improved help system for Emacs.
  • Paredit: A minor mode that enforces balanced parentheses while editing Lisp code. (In addition to paredit, the author uses modern-evil-paredit.)

Category: File Manager

  • dired (built-in): File manager.
  • nerd-icons-dired: Enhances Dired mode with icons from Nerd Fonts, improving file browsing.
  • dired-hacks: Extends the functionality of dired. (The author primarily uses it to hide or show hidden files and Git-ignored files.)

Category: Other packages

  • expand-region: Expands the selected region in code, making it easier to select logical blocks of code or text.
  • disable-mouse: Disables mouse support within Emacs, encouraging keyboard-centric navigation and editing. This can be beneficial for some users who prefer a more traditional text editor experience. (An alternative that is simpler and more efficient for disabling the mouse: inhibit-mouse.el)
  • project.el (built-in): A package for managing and navigating projects, providing utilities for project-based operations like searching, switching, and file management within defined project directories.
  • visual-fill-column: A package that allows wrapping lines at a specified fill-column width.
  • sdcv: Bring the Stardict’s dictionary functionality directly into your Emacs workflow. This will turn Emacs into a dictionary. (EDIT: The author is now using quick-sdcv.el)
  • fasd: Offers fast access to files and directories based on your history and usage patterns, optimizing file navigation.
  • dir-config: Automatically find and evaluate .dir-config.el Elisp files to configure directory-specific settings.
  • exec-path-from-shell: Ensures Emacs uses the same environment variables as your shell.
  • wgrep: Allows for in-buffer editing of grep results, improving the usability of search results. (It can be used to modify the occurrences returned by the Embark package embark-export function.)
  • flyspell-mode (built-in): An interface for spell-checking text using external programs like ispell, aspell, or hunspell for checking and correcting spelling in buffers. (EDIT: I replaced Jinx with Flyspell because Jinx was slowing down Emacs.)
  • which-key (built-in): Displays available keybindings in a popup, helping users learn and remember key combinations in Emacs.

Category: Miscellaneous file types

  • org (built-in): A powerful mode for organizing notes, tasks, and project planning within Emacs.
  • org-appear: Improves the visibility of Org mode elements in the buffer by automatically toggling visibility based on context.
  • toc-org: Automatically generates a table of contents for Org mode documents.
  • markdown-mode: Provides major mode support for editing Markdown files.
  • markdown-toc: Automatically generates and manages a table of contents for Markdown files, making navigation easier.
  • lua-mode: Provides major mode support for editing Lua files.
  • php-mode: Provides major mode support for editing PHP files.
  • dockerfile-mode: Provides syntax highlighting and editing support for Dockerfile files.
  • yaml-mode: Provides major mode support for editing YAML files, complete with syntax highlighting and formatting commands. (Can be replaced with its tree-sitter equivalent: yaml-ts-mode.)
  • ansible-doc: Provides documentation lookup for Ansible modules.
  • flymake-ansible-lint: Provides on-the-fly syntax checking for Ansible playbooks and roles, ensuring code quality.
  • flymake-bashate: Integrates bashate for syntax checking of Bash scripts in real-time within Emacs. (Emacs also offers a built-in Flymake backend for ShellCheck.)

By focusing on these packages, the Emacs configuration was simplified while still maintaining a highly functional setup.

And you, what Emacs packages are you using?

-1:-- Essential Emacs Packages for Efficient Software Development and General Text Editing (Post James Cherti)--L0--C0--October 29, 2024 06:05 PM

Irreal: Who Created Emacs

Over at the Emacs subreddit, FirmSupermarket6933 asks who really created Emacs. He cites various sources claiming that RMS did or did not create it. Is he responsible only for GNU Emacs or was he there from the beginning? Sadly the commenters purporting to answer his question have no more idea than FirmSupermarket6933 about the editor’s origin.

All of this was long ago and far away but almost everyone who has a reasonable grasp of Emacs’ history agree on some basic facts:

  • Emacs began circa 1976 as a set of macros for the TECO editor. That’s where the macs in “Emacs” comes from. The origin of the E is more controversial. Some say it stands for “Editing” but Stallman and others say it was chosen for more pragmatic reasons.
  • Stallman was heavily involved from the beginning. Guy Steele has produced some email threads that show this definitively.
  • Many others including Steele, David Moon, and James Gosling were instrumental in moving the effort forward. The end of this process is what we now know as GNU Emacs

Even the original effort was more curation than invention. The original TECO macros were collected from the macros that people in the AI Lab were using. The idea was to have a standard set of macros that everyone could use. Even so, there was a surprising amount of work to get everything working. See Steele’s email threads for the details.

All of this began almost 50 years ago so memories are dim and, sadly, many of the principals are nearing the end of their lives so it’s important to get these facts right while we can.

-1:-- Who Created Emacs (Post jcs)--L0--C0--October 29, 2024 03:48 PM

Sacha Chua: Yay Emacs 7: Rewriting and copying custom Org Mode links

I use org-link-set-parameters to define a lot of custom links in Org Mode for things like my blog or my Emacs config. Then I can code how I want to complete, open, and export those links. These links don't make sense to other people, of course. I want to be able to quickly copy or replace my custom links with regular web links, like the ones I use when I export to HTML.

My shortcut for this is C-. u to copy the exported URL and C-. r to rewrite a link. These stand for my-embark-org-copy-exported-url and my-embark-replace-link-with-exported-url respectively.

You can watch this short on YouTube, download the video, or download the audio.

View org source for this post
-1:-- Yay Emacs 7: Rewriting and copying custom Org Mode links (Post Sacha Chua)--L0--C0--October 29, 2024 02:44 PM

TAONAW - Emacs and Org Mode: Back to digital journaling once more...

For the last week or so I’ve been journaling on my computer again instead of in my notebook. This is a cycle for me I keep going through.

The urge to write in a handwritten journal is there, and I love the feeling of sitting down at a desk with a good pen and paper pages. The problem I’m having is the amount of details I need to put in—and with it, the time I need to spend on writing—and the references I need to make while writing.

Unsurprisingly, the culprit is my work. There are so many to-do items each day that, combined with my personal tasks, Start to cause me to lose track of the big picture. While I still have my projects organized in big bullet points with all the references I need in org-mode, I am missing the “so, what does this make me feel?” aspect of it all—the reflection of looking back on what I did last week or last month.

This is where my written journal would have fit in, but a written journal cannot link to my projects directly. Meanwhile, when I want to write about a fun hangout I’ve had, I want to include a list of places and map snippets, and while I can do that in my notebook, I just don’t have the time to find the locations, write down the addresses, and print out maps snippets - all are things I do within minutes in my digital journal.

Another issue is that my hand cramps if I keep writing for a long time, especially as I start writing faster or get excited. My handwriting becomes sloppier and I can’t fix my spelling mistakes without crossing out a word. Sure, I can use write out (or Tipp-Ex, depending on where you’re from), but that introduces even more time and more friction.

I started to realize that instead of just writing, the first thought I have is if I should write, where, and when. The option of taking out a personal notebook filled with intimate details is not realistic in most cases most of the time, so I can only reflect on my day at specific times that I don’t always have or want to spend on something else. I miss the availability of “just writing” what I need.

Ironically, I use a notebook, my pocket one, to write quick ideas or summaries. Again, it comes down to speed: taking my pocket notebook out of my pocket with my pen to write something down is faster than doing it on the phone.

So I guess I came a full circle. Journaling is digital, and quick ideas I want to capture are handwritten in a notebook. 📓 🤷🏼

-1:-- Back to digital journaling once more... (Post)--L0--C0--October 29, 2024 08:29 AM

Protesilaos Stavrou: ‘Ask me anything’ live stream on 2024-10-31 at 14:00 Europe/Athens about Emacs or life in general

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

I did a live stream where I answered all questions I got about Emacs, free software, politics, philosophy, my dating life, and more. I had a good time and will go it again sometime.

Below is the old description.


I will do a live stream this Thursday. The idea is to answer any question from those who join the stream. The topics can be about anything, from Emacs to philosophy, to life in general.

If there are no questions, then I will do some maintenance of my Emacs packages (not sure which ones, but there is always something).

Depending on how things go, the event will be around two hours long. I am happy to run it for longer (four hours maximum because then the sun sets and I have to switch off the computer).

The event will be recorded. No worries if you cannot make it.

-1:-- ‘Ask me anything’ live stream on 2024-10-31 at 14:00 Europe/Athens about Emacs or life in general (Post)--L0--C0--October 29, 2024 12:00 AM

İsmail Efe: Who Do I Want to Be?

Who Do I Want to Be?

İsmail Efe Top

2024-10-29


A drawing of a rose.

For me, there is only one answer to "What do you want to be?".

I want to be content.

I want to be content with what I do for a living, I want to be content with where I reside, and more importantly, I want to be content with who I am.

While I do have specific plans for my future, in the end, nothing else matters if I am not content.

I can't find true fulfillment in material things; it has to come from the work I put in. I have to work diligently, I have to always take the long road, and build myself with blood, sweat, and tears. So that I can cherish everything I have, as I will know for sure that they were deserved.

I also have to build my surroundings. We are reflections of our friends. That means I have to look up to and be proud of people whom I call friends. A fellow blogger, Marcel, has a great blog post called "Life-Affirming Choices". In that blog post, he says

"I want to be, and surround myself with, people who are willing to put in the effort to live a life their future selves will thank them for—people who make scalable, life-affirming choices because they know these actions grow and compound over time, leading to greater, unexpected benefits."

I recommend checking out his post as he has been a great inspiration for this.


A drawing of an ivy.

While I am proud and happy with everything I've achieved up until now, I also know my potential. I know that I can do great things that can change the world for the better, and I want to live up to it.


In the end, our life is too fleeting not to do great things.

-1:-- Who Do I Want to Be? (Post İsmail Efe Top (ismailefetop@gmail.com))--L0--C0--October 28, 2024 09:00 PM

Marcin Borkowski: Command alternatives

Today I’d like to write about an Emacs feature I didn’t know about, even though it’s part of Emacs since quite some time – it appeared in version 24.4, which means it is over 10 years old! It seems I’m not the only one who didn’t know this exists – I’ve just searched my ~/.emacs.d/elpa directory (which contains almost a hundred packages now!), and none of the packages I have installed there uses it, either.
-1:-- Command alternatives (Post)--L0--C0--October 28, 2024 08:16 PM

Irreal: Casual Redux

Charles Choi has a new announcement about his Casual package. Several of his users encouraged him to offer Casual to Emacs core or Elpa. He did that and, of course, he got push back. The main complaint was that there were too many apps.

I’ve always felt that having separately installable apps was an advantage. Others disagree and so Choi has implemented a new package that includes all the casual apps and has announced that he will remove the current apps from MELPA shortly. Take a look at Chou’s post for the details.

I don’t understand why any of this is necessary. The purists insist that MELPA is an illegitimate repository because … reasons. But the truth is that almost every popular Emacs package is curated there and that for all intents and purposes, MELPA is Elpa. I would have been happier if Casual had remained on MELPA and the various apps had remained separately installable.

Regardless, if you like the Casual apps—and there’s a lot to like—you will need to take action to update your configuration. Perhaps the Casual apps will one day be absorbed into Emacs core and all this silliness will be unnecessary but until then you will have to update your init.el to keep using them.

-1:-- Casual Redux (Post jcs)--L0--C0--October 28, 2024 03:19 PM

Sacha Chua: 2024-10-28 Emacs news

UPDATE: I'm moving Emacs News to the info-gnu-emacs mailing list instead of emacs-tangents. If you're subscribed to Emacs News through emacs-tangents, you may want to switch your subscriptions. Emacs News will also continue to be available on the web and through RSS. I'll post to both info-gnu-emacs and emacs-tangents for a little while.

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

View org source for this post
-1:-- 2024-10-28 Emacs news (Post Sacha Chua)--L0--C0--October 28, 2024 12:11 PM

Aimé Bertrand: Custom Emacs functions No. 7 - Mu4e

EDIT - 2024-11-09: See the Edits section further down.

Intro

In the name of bringing the kitchen sink inside of Emacs, I manage my mails here as well. Mu4e is my choice of a mail client.

As a quite opinionated fellow when it comes to my tools, I tend to change stuff a lot. This includes extending functions and commands that are delivered with Mu4e by default. Or even creating new ones.

Barring changes in Mu4e or related updates, these functions should remain relevant. However some where created a good while ago. Which in turn might result in “obsolete” code or easier solutions.

Commands and Functions

timu-mu4e-in-new-tab

I always, I mean ALWAYS open Mu4e in a new tab. This one does it for me with a custom keybinding.

(defun timu-mu4e-in-new-tab ()
  "Open `mu4e' in a new tab with `tab-bar-new-tab'."
  (interactive)
  (progn
    (tab-bar-new-tab)
    (mu4e)))

timu-mu4e-quit

Since I always open Mu4e in a new tab, this function allows me to close the “mail-tab” upon quitting Mu4e.

(defun timu-mu4e-quit ()
  "Quit `mu4e' and close the tab with `tab-bar-close-tab'."
  (interactive)
  (progn
    (mu4e-quit)
    (tab-bar-close-tab)))

timu-mu4e-execute-no-confirm

Executing marks – moving, deleting, archiving mails and more – in Mu4e (mostly in headers view) happens many many times a day. Having to confirm all of those action would result in me throwing my Mac out of the window after a while. The following function helps execute marks without confirmation.

(defun timu-mu4e-execute-no-confirm ()
  "Execute all without confirmation.
Use the argument NO-COMFIRM in the command `mu4e-mark-execute-all'."
  (interactive)
  (mu4e-mark-execute-all 'no-confirm))

timu-mu4e-jump-to-maildir

To simplify mailbox navigation, I use completing-read with the command below, bound to J..

(defun timu-mu4e-jump-to-maildir ()
  "Use `completing-read' to jump to a maildir.
Credit: https://emacs.stackexchange.com/a/47580/30874
Credit: https://arupajhana.wordpress.com/2014/09/26/mu4e-with-helm."
  (interactive)
  (let ((maildir (completing-read "Maildir: " (mu4e-get-maildirs))))
    (mu4e-headers-search (format "maildir:\"%s\"" maildir))))

timu-mu4e-attach-file

This one helps add attachments to a compose buffer with completion in the minibuffer (read-file-name).

(defun timu-mu4e-attach-file ()
  "Attach a file to an email.
Use the built-in function `mml-attach-file'."
  (interactive)
  (let ((default-directory "~/"))
    (let ((file (read-file-name "Select a file to attach: ")))
      (mml-attach-file (expand-file-name file)))))

timu-mu4e-view-save-attachments

The default command for saving attachments, mu4e-view-save-attachments automatically chooses a – in the variable mu4e-attachment-dir – predefined directory. This is fine and dandy, but I mostly want to select the directory my self – on a case-by-case basis.

(defun timu-mu4e-view-save-attachments ()
  "Save all attachements in a selected directory.
This is `mu4e-view-save-attachments' with prefix Argument."
  (interactive)
  (let ((current-prefix-arg '(4))
        (embark-confirm-act-all nil))
    (call-interactively #'mu4e-view-save-attachments)))

timu-mu4e-get-mail

The variable mu4e-get-mail-command defines which CLI command to use to fetch emails with Mu4e. In my case – using the isync program (mbsync) – I want sometimes to only fetch mails per account or all accounts.

(defun timu-mu4e-get-mail ()
  "Select the Account before syncing.
This makes the syncing of mails more flexible."
  (interactive)
  (let ((mu4e-get-mail-command
         (concat
          "/opt/homebrew/bin/mbsync "
          (completing-read
           "Which Account: "
           '("icloud" "aimebertrand" "moclub" "--all")))))
    (mu4e-update-mail-and-index t)))

Commands and functions to deal with signatures

The following two commands are extensively covered in the previous post “Signature above the cited text in mu4e”.

(defun timu-mu4e-message-insert-signature (&optional force)
  "Insert a signature at the end of the buffer.

Original command is `message-insert-signature'.
See https://macowners.club/posts/signature-above-cited-text-mu4e/ for reasons.

See the documentation for the `message-signature' variable for
more information.

If FORCE is 0 (or when called interactively), the global values
of the signature variables will be consulted if the local ones
are null."
  (interactive (list 0) message-mode)
  (let ((timu-message-signature timu-message-signature)
        (message-signature-file message-signature-file))
    ;; If called interactively and there's no signature to insert,
    ;; consult the global values to see whether there's anything they
    ;; have to say for themselves.  This can happen when using
    ;; `gnus-posting-styles', for instance.
    (when (and (null timu-message-signature)
               (null message-signature-file)
               (eq force 0))
      (setq timu-message-signature (default-value 'timu-message-signature)
            message-signature-file (default-value 'message-signature-file)))
    (let* ((signature
            (cond
             ((and (null timu-message-signature)
                   (eq force 0))
              (save-excursion
                (goto-char (point-max))
                (not (re-search-backward message-signature-separator nil t))))
             ((and (null timu-message-signature)
                   force)
              t)
             ((functionp timu-message-signature)
              (funcall timu-message-signature))
             ((listp timu-message-signature)
              (eval timu-message-signature t))
             (t timu-message-signature)))
           signature-file)
      (setq signature
            (cond ((stringp signature)
                   signature)
                  ((and (eq t signature) message-signature-file)
                   (setq signature-file
                         (if (and message-signature-directory
                                  ;; don't actually use the signature directory
                                  ;; if message-signature-file contains a path.
                                  (not (file-name-directory
                                        message-signature-file)))
                             (expand-file-name message-signature-file
                                               message-signature-directory)
                           message-signature-file))
                   (file-exists-p signature-file))))
      (when signature
        (goto-char (point-max))
        ;; Insert the signature.
        (unless (bolp)
          (newline))
        (when message-signature-insert-empty-line
          (newline))
        (insert "...... ")
        (newline)
        (if (eq signature t)
            (insert-file-contents signature-file)
          (insert signature))
        (goto-char (point-max))
        (or (bolp) (newline))))))
(defun timu-mu4e-message-insert-signature-at-point (pmode)
  "Function to insert signature at right point according to PMODE.
Uses `timu-mu4e-message-insert-signature'.
This is a modified version of `message-insert-signature'."
  (when pmode (message-goto-body))
  (interactive)
  (require 'message)
  (message-goto-body)
  (newline)
  (message-goto-body)
  (save-restriction
    (narrow-to-region (point) (point))
    (timu-mu4e-message-insert-signature))
  (message-goto-body))

Automatically switching the context

Whenever switching to specific mailbox, I want to be in the right mu4e-context. This is in short a setting set. In my case to mostly identify the correct account.

Based on my current research, there is no built-in solution to automatically switch contexts. I use the following function as a mu4e-headers-found-hook to achieve this.

(defun timu-mu4e-switch-context ()
  "Switch context of the current maildir.
Uses `mu4e--search-last-query' and regex to get the context."
  (let ((new-context
         (timu-get-mu4e-context)))
    (if new-context
        (mu4e-context-switch t new-context)
      (mu4e-context-switch t "icloud"))))

… Which in turn uses the following function.

(defun timu-get-mu4e-context ()
  "Extract context from `mu4e--search-last-query'."
  (if (string-match "/\\(.+?\\)/.*" mu4e--search-last-query)
      (match-string 1 mu4e--search-last-query) ""))

You can find more details in the older post “AutoSwitch Mu4e context depending on mailbox”.

timu-mu4e-msmtp-select-account

When sending emails, which use the CLI program msmtp in my configuration, the ‘from’ address should be pre-populated with the correct sender address.

(defun timu-mu4e-msmtp-select-account ()
  "Select the right account/context according to the from line."
  (if (message-mail-p)
      (save-excursion
        (let*
            ((from (save-restriction
                     (message-narrow-to-headers)
                     (message-fetch-field "from")))
             (account
              (cond
               ((string-match timu-personal-icloud-email from) "icloud")
               ((string-match timu-personal-aimebertrand-email from) "aimebertrand")
               ((string-match timu-personal-moclub-email from) "moclub"))))
          (setq message-sendmail-extra-arguments (list '"-a" account))))))

Edits

2024-11-09 - Adding/Fixing a function to save all attachments

You can find this in the new post Mu4e - Update - save attachments faster.

-1:-- Custom Emacs functions No. 7 - Mu4e (Post)--L0--C0--October 27, 2024 11:00 PM

Bz01: Optional dependency loading in Emacs, a good idea?

Hey guys! I have gotten a sudden motivation to refactor my nixos dotfiles, and I have an idea, don’t know if it’s good or not so here it is:

While developing code, I feel like your system should have 0 development dependencies, all of them should be project dependencies instead. However my text editor has certain configuration files for all languages, so it has packages installed for all of the possible languages and frameworks and tools that i’ll be using.

Instead of that, would it be a wise decision so that emacs only loads code and installs packages related to the project I’m currently working on? I’d love to hear your opinions! Reach out to me at Fosstodon: @binarydigitz01@fosstodon.org, or mail me at binarydigitz01 at protonmail.com.

-1:-- Optional dependency loading in Emacs, a good idea? (Post)--L0--C0--October 27, 2024 06:42 AM

Marie K. Ekeberg: Read documentation from the comfort of Emacs - man-pages, developer documentation and more

Are you also tired of having to leave Emacs to read documentation? Whether be a simple command for your terminal (which you can run inside Emacs off course!), or information relating to the code you are working on? The good news it that you can read much of this documentation directly from inside of Emacs! No need to ever leave it again. By reading this post, I hope you will learn of a new way to get more of your information without ever leaving your favorite editor.
-1:-- Read documentation from the comfort of Emacs - man-pages, developer documentation and more (Post)--L0--C0--October 27, 2024 12:00 AM

Protesilaos Stavrou: Emacs: modus-themes version 4.6.0

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

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


4.6.0 on 2024-10-27

This is a small release that makes minor refinements to an already stable base.

Command to rotate between selected Modus themes

The command modus-themes-rotate switches from one theme to the next in the list defined in the user option modus-themes-to-rotate. The default value of the user option covers all the Modus themes, though users may prefer to set it to a small subset thereof.

Rotation works in such a way that (i) if the theme-to-be-loaded is already the current one, the next in line is loaded instead, and (ii) the next candidate is always to the right of the currently loaded theme.

The rotation is done from left to right. When at the end of the list, “right” points to the beginning.

The command modus-themes-rotate complements the existing commands modus-themes-toggle (which reads the user option modus-themes-to-toggle to switch between two themes) and modus-themes-select to select one among all the Modus themes using minibuffer completion.

More accurate faces for Org agenda dates

We now adopt a more semantically consistent approach to the use of font weights and colour intensity when styling all the permutations of scheduled date and deadline faces. Pressing tasks stand out more, while those that do not require immediate attention are rendered in a more subtle style.

Thanks to Adam Porter (aka GitHub alphapapa) for suggesting this revision and discussing the technicalities with me. This was done in issue 102: https://github.com/protesilaos/modus-themes/issues/102.

A slightly revised red-cooler palette entry

The value of this named colour now has a lower contribution from the blue channel of light, meaning that it looks less pink and more rosy red. The change is small, though it contributes to a more harmonious distribution of colour in certain major modes that have preprocessor constructs (e.g. for the C language).

red-cooler is also used in some contexts in Org and Org agenda buffers.

Completion popups are monospaced if modus-themes-mixed-fonts is non-nil

The user option modus-themes-mixed-fonts ensures that spacing-sensitive constructs are always rendered in a monospaced font (technically, they inherit the fixed-pitch face). This is especially useful when enabling variable-pitch-mode in, say, an Org buffer that has tables and code blocks.

The popup produced by the corfu and company packages will also be rendered in a monospaced font if the necessary conditions are met, ensuring proper alignment of all the elements.

Directory icon colours are in line with each theme’s palette

The directory icon presented by the all-the-icons and nerd-icons packages is now rendered in the style of a semantic palette mapping from the active theme, instead of using a hardcoded faint cyan colour. This is to ensure that styles are consistent and that users with deuteranopia or tritanopia get the desired colours while using the relevant Modus themes.

For those who define palette overrides to refashion the themes, the mapping is called accent-0: it is used in places where one or more colours are needed for variation, such as what orderless does in the minibuffer or magit in its status buffer.

Refined support for embark and forge packages

We now cover more of their faces, have updated the relevant symbols of those faces, and have made stylistic tweaks in the interest of theme-wide consistency (i.e. the kind of quality you only appreciate over time).

Support for the built-in hexl-mode

It was using some background colour values that were somewhat hard to read. Those are replaced with appropriate foreground colours.

Documentation on how to support some packages

These are:

Those are not covered by the themes for a variety of reasons, but that may change in the future.

Updated a colour value about the solaire package

This is another package whose support we only document. The manual was referring to a colour that has long been removed from the themes.

Thanks to Edgar Vincent for bringing this matter to my attention. This was done on the GitLab mirror, issue 316: https://gitlab.com/protesilaos/modus-themes/-/issues/316.

Removed some needless :set values from defcustom forms

We did this after reviewing the state of the code following a discussion with shipmints and Adam Porter about the behaviour of the setopt macro when setting user options from the Modus themes. There should be no visible change for users, though the edit is still useful for the maintainability of the code. This was done in issue 118: https://github.com/protesilaos/modus-themes/issues/118.

Switched to if-let* and its variants everywhere

Emacs 31 deprecates the forms of these macros that lack the asterisk. We can comply right away since the functionality is the same.

-1:-- Emacs: modus-themes version 4.6.0 (Post)--L0--C0--October 27, 2024 12:00 AM

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