Toggle hidden files in Dired buffers

emacs

The more time I spend in Emacs' Dired mode, the more I want to tweak things. I wrote about a few of these last year.

One other thing I wanted was to hide any hidden (.dot) files in Dired listings. The simplest way to do this would be to set dired-listing-switches from -al to -l instead. But that would always hide them. I wanted to toggle them on and off, like I can in Finder on macOS using CMD-Shift-..

I poked around the Emacs documentation and a handful of Reddit posts and cobbled together something that worked. I figured I might as well share it. I assume there are smarter ways to do this, but here are the relevant bits from my config.

(use-package dired
  :init
   (require 'dired-x) ;; I think this is required for dired-omit-mode

  :bind
  (:map dired-mode-map
	("s->" . dired-omit-mode)) ;; toggle using Command-Shift-.  same as macOS Finder

  :hook
  (dired-mode . (lambda () (dired-omit-mode))) ;; hide .dot files by default

  :config
  (setq dired-omit-files   ;; hide .dot files when in dired-omit-mode
      (concat dired-omit-files "\\|^\\..+$")))

This configuration means that every time I create a dired buffer, the .dot files are hidden. What I haven't figured out is how to toggle it globally. Sometimes I want to show hidden files by default instead, for a while. It's not hard to toggle them, but it would be nice to "turn them on" until I want to "turn them off" again. This works well enough for now, though.

Permalink #

Denote and Howm, sitting in a tree

Long story, short: I'm using both Howm and Denote for notes in Emacs. But why? Below are some quick notes about why (with some "how" thrown in).

Denote is such a pleasure to work with. It's simple, powerful, and sensible. There are no dependencies or gotchas.

Howm is clever and interesting and fun. It offers a useful new take on both writing and reading notes. As a long-time fan of the Noguchi filing method, Howm resonated with me immediately.

For a couple of months, I was using both packages independently. My thought was that I'd use Howm for quick, "fleeting" notes and Denote for my personal notes, projects, and "topic journals". This worked well enough, but it meant that every new note required a decision. Plus, looking for notes meant searching 2 places. My dream has always been "Everything in one place" so keeping them separate wasn't ideal.

The trick for me was learning a way to make my Howm notes look just like Denote notes, and then manage them all using Denote. Here's a summary of what that involved.

Both Howm and Denote can be configured to use any kind of note format (e.g. Org mode, Markdown, etc.).

Recent versions of Howm have some built-in configuration for using Org mode files. This sets some basic configuration. Here's how to do that:

(require 'howm-org) ;; Write notes in Org-mode.

And here's a subset of what that does for you:

;; From howm-denote-el
(setq howm-file-name-format "%Y-%m-%d-%H%M%S.org")
(setq howm-view-title-header "*")
(setq howm-dtime-format "[%Y-%m-%d %a %H:%M]")
(setq howm-menu-file-extension ".org")

That's not Denote's file name format, so after requiring howm-org, I added the following:

(setopt howm-file-name-format "%Y%m%dT%H%M%S.org")

That's not exactly Denote's format, but the proper date string means that Denote will at least recognize it as a Denote file.

The next change was to modify the default header format to use a real #+title: because by default it uses a top-level heading ("*"):

(setopt howm-view-title-header "#+title:")

Doing that really messes with the Howm-menu and other howm lists. Buried in the comments in issue #33, I found functions (by @mmarshall540) that work around this nicely.

;; Advise `howm-view-item-basename' so that if its return value
;; includes "--", only the text before is returned.
(defun my/howm-basename-chop (str)
  "Advice for `howm-view-item-basename'.
Takes a file's basename, STR, and returns only the portion before
\"--\"."
  (let ((dashes-pos (string-match "--" str)))
    (cond (dashes-pos (substring str 0 dashes-pos))
          (t str))))

(advice-add 'howm-view-item-basename :filter-return
            'my/howm-basename-chop)


;; Advise `howm-view-item-summary' so that it removes the "#+title: "
;; portion of note titles.
(defvar howm-view-title-regexp)
(defun my/howm-cut-title (str)
  "Remove `howm-view-title-header' plus whitespace from STR."
  (let ((begin (when (string-match howm-view-title-regexp str)
                 (match-beginning 2))))
    (if begin (substring str begin) str)))

(advice-add 'howm-view-item-summary :filter-return 'my/howm-cut-title)

With that, note listings in Howm look perfect. Note that the best fix for all this is to simply always use Denote for creating files, but I'd already configured things before I decided to combine both sets of notes. Besides, now I can create notes using either method. For any files created using Howm, I do need to rename them, but that's easy enough in a Dired buffer using denote-dired-rename-marked-files-using-front-matter once in a while (or from within the buffer while taking the note, if I think of it).

Also in that thread is a function (also from mmarshall540) for converting existing Howm notes to use #+title: instead of "*" or "=". This worked great for me. here's the comment.

The final change was to make howm-directory and denote-directory the same directory.

That seems like a lot, but it's easier than it looks.

Now my Howm Menu and note lists look like they're supposed to, even though they're actually full Denote-style files and have #+title: in the first line.

Howm Recent Files

Why am I doing this again? Well, because I get the best of both worlds this way. I create notes using Denote as normal, but then I can review them easily using Howm. And I also get all the same Howm tricks with >>> and <<< links.

I haven't worked out when or if to use the Howm TODO features. They're cool, but I'm pretty invested in my Org agenda. I'm testing the idea of using Howm TODOs for "someday/maybe" tasks, using the "~" notation in Howm. This surfaces the someday stuff without distracting from my gotta-do stuff.

Still noodlin' on all this. It would be cool if someone better at this stuff than me would create a howm-denote.el package or something that encapsulated all this in an easy, consistent way.

Permalink #

I printed a mousepad

Photo of keyboard with a red mousepad next to it. My hand rests on the pad.

I like having a felt pad on my desk, but I don't like how it sometimes causes mouse movements to become choppy.

My favorite mouse is the Logitech MX Master. Maybe other mouses work better on felt, but I want to use this one, so I decided to buy a mouse pad. Then I remembered I have a 3D printer.

I downloaded this model and an hour later I had a custom-sized simple mouse pad and it works great.

Permalink #

Ladybird (web browser)

Ladybird:

Ladybird is a brand-new browser & web engine. Driven by a web standards first approach, Ladybird aims to render the modern web with good performance, stability and security.

From its humble beginnings as an HTML viewer for the SerenityOS hobby operating system project, Ladybird has since grown into a cross-platform browser supporting Linux, macOS, and other Unix-like systems.

Ladybird is currently in heavy development. We are targeting a first Alpha release for early adopters in 2026.

Something to keep an eye on.

(via Michael Tsai)

Permalink #

Friday, March 07, 2025

Alice says, 'whatever'

My eyes were bored so I changed themes again. Back to PaperMod for now.


Thursday, March 06, 2025

I'd like to not create these daily journal posts, and instead create several individial posts. The problem is that so much of what I write here in journal posts is not Postworthy. So, I'll keep doing this, I guess.


Using Gnus for email

A week ago, I toyed with the idea of using Gnus for reading Email in Emacs.

As expected, I hated it at first. But then...


Gnus is a newsreader that can be coerced into pretending it's an email client. There's no getting around this masquerade and it feels awkward. On the other hand, it's a powerful news reader pretending to be an email client.

I don't manage a ton of email, so experiments with how I deal with it aren't high risk. Still, my recent email fiasco made me nervous. It also what got me looking into using Gnus.

Most of the time, I read email on my desktop Mac. I've been using Notmuch for this. The problem is that the Notmuch database is then tied to that computer. I was eventually able to configure muchsync so that I could read everything on my laptop (MBP) as well. It was working, but felt fragile and the process would often fail for various reasons.

The other place I manage email is of course on my phone. Notmuch isn't an option there, so I use Apple Mail. As I wrote in I think I have to go back to Mu4e, Notmuch wasn't fitting my workflow as well as I'd have liked. As I was looking at returning to Mu4e, I figured I'd play with Gnus.

Gnus solves the sync problem because it feeds directly off the IMAP server (Fastmail, in my case). Using Gnus, not only do I not worry about syncing between Macs, I don't even need to sync to my desktop Mac, at all[1].

Long story short, I've stuck with Gnus for the past week and I'm kind of digging it. Once one gets past the weird terminology (Groups, Articles, Dormant, Ticked, etc.) it's actually very powerful.

I cobbled together my configuration from a half-dozen Stack Exchange answers and blog posts[2], with some tweaks from me. It ain't pretty, but it's working. I'm not even sure what some of it is doing, but here's most of it:

(use-package gnus
  :bind
  (("C-c o g" . gnus)
  (:map gnus-group-mode-map
    ;; I like seeing all mailboxes, not just those with unread messages
	("o" . my/gnus-group-list-subscribed-groups))
  (:map gnus-summary-mode-map
    ;; Move message to "Archive" folder
	("C-c a" . my/gnus-summary-archive)))
 
  :custom
  ;; Archive outgoing email in Sent Items folder, mark it as read
  ;; UPDATE: Do I need this? Fastmail saves Sent items automatically
  ;;   (gnus-message-archive-method '(nnimap "personal"))
  ;;   (gnus-message-archive-group "Sent Items")
   (gnus-message-archive-group (format-time-string "sent.%Y")) ;; keep local copy
   (gnus-gcc-mark-as-read t)
   (gnus-search-use-parsed-queries t)  ;; standardize searches
   (gnus-auto-select-next nil)
   (gnus-paging-select-next nil)
   (gnus-summary-stop-at-end-of-message t)
   (gnus-mime-display-multipart-related-as-mixed t)
   (gnus-auto-select-first nil)
   (gnus-summary-display-arrow nil)
   (gnus-thread-sort-functions
      '(gnus-thread-sort-by-most-recent-date
        (not gnus-thread-sort-by-number)))
   (gnus-show-threads t)
   (gnus-sum-thread-tree-false-root nil) ;; use subject
   (gnus-sum-thread-tree-root nil)
   (gnus-sum-thread-tree-indent " ")
   (gnus-sum-thread-tree-vertical        "│")
   (gnus-sum-thread-tree-leaf-with-other "├─► ")   ;; fancy
   (gnus-sum-thread-tree-single-leaf     "╰─► ")
   ;; |2025-03-06 (Thu)| Sender Name | Subject |
   (gnus-summary-line-format (concat
                             "%0{%U%R%z%}"
                             "%3{│%}%1{%&user-date;%}%3{│%}" ;; date
                             "%ub:"          ;; indicate (+) if known (bbdb)
                             "%4{%-20,20f%}" ;; name
                             " "
                             "%3{│%}"
                             " "
                             "%1{%B%}"
                             "%s\n"))
   
   (gnus-user-date-format-alist '((t . "%Y-%m-%d (%a)")
                                 gnus-thread-sort-functions '(gnus-thread-sort-by-date)))
   :config
    (setq gnus-select-method '(nnnil ""))
    (setq gnus-secondary-select-methods  '((nnimap "personal"
	                                       (nnimap-address "imap.fastmail.com")
                                           (nnimap-server-port 993)
                                           (nnimap-stream ssl)
			                   (nnmail-expiry-target "nnimap+personal:Trash")))))


;; Send email via Fastmail's SMTP:
(use-package smtpmail
  :custom
  (send-mail-function 'smtpmail-send-it)
  (smtpmail-default-smtp-server "smtp.fastmail.com")
  (smtpmail-stream-type 'ssl)
  (smtpmail-smtp-service 465))

I've configured BBDB (Insidious Big Brother Database) for contact management.

(use-package bbdb :ensure t
  :config
  ;; initialization for both Gnus and Notmuch
  (bbdb-initialize 'gnus 'message 'notmuch)
  (bbdb-mua-auto-update-init 'gnus 'message 'notmuch)

  ;; When invoking bbdb interactively
  (setq bbdb-mua-update-interactive-p '(query . create))

  ;; Check every address in a message and not only the first
  (setq bbdb-message-all-addresses t)

  ;; use ; on a message to invoke bbdb
  (add-hook 'gnus-summary-mode-hook
	    (lambda ()
	      (define-key gnus-summary-mode-map (kbd ";") 'bbdb-mua-edit-field)))

  (add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
  (add-hook 'gnus-startup-hook 'bbdb-insinuate-notmuch)
  (setq bbdb-complete-name-allow-cycling t))

Using BBDB is neat because when I'm viewing a message, a small window pops up at the bottom with that person's info. One nice feature is that, in the list of messages (Summary view), a "+" symbol is displayed before the name of people who are already in BBDB. (This is via %ub in the format string). Plus, Notmuch and Gnus can share the contact database. BBDB was initially developed by Jamie Zawinski.

In 1991, I wrote this program, "The Insidious Big Brother Database", which was an address-book and note-taking system that was tightly integrated with the Emacs mail and news readers. It was pretty popular until 1997 or so when even the last hold-outs stopped reading their mail in Emacs.

Well, not everyone stopped :).

I'm still very clumsy using Gnus, but it's been a blast to learn and play with. Part of the attraction is that it's built into Emacs and needs nothing else to work. It's nice not having to deal with sync or external dependencies. I admit that I also like that it's really really old and feels almost rebellious to use.


  1. That said, I am still syncing and keeping the Notmuch database up to date, because I like having a local copy of all my email. Also, who knows how long I'll be using Gnus? ↩︎

  2. This one was especially helpful: A Practical Guide to Gnus ↩︎

Permalink #

I went a little nuts with Remember mode in Emacs

I went down a rabbit hole with the built-in Remember mode in Emacs today.

Persistent Scratch with remember-note

The Emacs *scratch* buffer is handy. It's always available and easy to get to. However, by default it doesn't persist between runs of Emacs. So, when I quit Emacs, anything in the scratch buffer is lost. Sometimes I get burned by this, so I thought I'd fix it using the persistent-scratch package.

While looking for details about the package, I spotted a couple comments about using the built-in remember-notes function instead.

Return the notes buffer, creating it if needed, and maybe switch to it. This buffer is for notes that you want to preserve across Emacs sessions. The notes are saved in ‘remember-data-file’.

OK, I tried it and it works great.

My remember-notes file/buffer

I now have a persistent Org mode file as my scratchpad, and I can easily capture new notes as org headings to it using remember.

New frame defaults

Now that I had a nice, persistent scratchpad, I wanted it to be the default buffer for new frames and at startup. Easy enough:

;; Persistent notes (like persistent-scratch, but built-in)
(setq initial-buffer-choice 'remember-notes
   remember-data-file "~/Documents/Notes/remember-notes"
   remember-notes-initial-major-mode 'org-mode
   remember-notes-auto-save-visited-file-name t
   remember-in-new-frame t))

(defun my/switch-to-scratch-buffer (f)
  (with-selected-frame f
    (remember-notes t)))
 
(add-hook 'after-make-frame-functions #'my/switch-to-scratch-buffer)

I'm not sure all of that is necessary now that I've learned about remember-in-new-frame but it works as-is, so I'll leave it.

Remember mode via Raycast for system-wide capture

I'd created a keymap (C-c o n) for bringing up the remember-notes buffer while in Emacs, but thought it would be nice having a system-wide option. I've never understood how to configure =org-protocol= so I cheated and created a Raycast script:

#!/bin/bash

# Required parameters:
# @raycast.schemaVersion 1
# @raycast.title Remember
# @raycast.mode silent

# Optional parameters:
# @raycast.icon images/emacs.png

# Documentation:
# @raycast.description Open Emacs remember in new frame
# @raycast.author Jack Baty
# @raycast.authorURL https://baty.net

emacsclient -e "(remember-other-frame)"

Now I can trigger Raycast, type part of "Remember" (usually just "R" is enough) and it brings up a new Emacs frame containing the remember buffer. I type or paste whatever, and hit C-c C-c which adds the note to the remember file and kills the frame. Handy!

Creating emails via Remember mode

While reading the Remember manual, I spotted the option to save Remember notes as emails. WUT?!

(add-to-list 'remember-handler-functions 'remember-store-in-mailbox)

By default, this uses an mbox file, ~/Mail/remember, which I can use Mutt to view.

neomutt -f ~/Mail/remember

My remember notes as emails in Neomutt

Crazy, right? Yeah, I'm not going to view my captured notes in Mutt, but it's cool that I could. But it got me thinking about my urge to put everything into Notmuch. Notmuch indexes Maildir-formatted emails, not mboxes. What if I converted the mbox to Maildir and used Emacs to read the notes where I'm already reading my emails? Plus super fast search and tagging, etc.?!

I've not gotten to that yet, but it's something to think about.

Now what?

This whole thing started because I wanted to make my scratch buffer persistent. Instead, I've ended up with a whole new capture setup for quick notes.

Why not use Org-capture or Howm-remember or a million possible other things for this? Fair question. The answer is that I didn't know anything about Remember mode when I woke up this morning, and now I do. It remains to be seen whether I should have used Org-capture for this, but it was fun learning how to do it this way.

It's possible we've, er, forgotten about Remember mode too soon.

Permalink #

Denote-search, a simple search utility for Denote

lmq-10/denote-search

This package provides a search utility for Denote, the simple-to-use, focused-in-scope, and effective note-taking tool for Emacs.

The command denote-search is the main point of entry. It accepts a query, which should be a regular expression, and then searches the contents of all the notes stored in denote-directory for it. The results are put in a buffer which allows folding and further filtering; all standard commands offered by Xref are available as well.

This package has the same code principles as Denote: to be simple-to-use, focused-in-scope, and effective. We build upon Xref to be good Emacs citizens, and don't use any dependencies other than Denote and built-in libraries.

This works pretty well. It returns a nice, foldable list of results. One can also refine the results by filtering by file names, etc. I'll probably continue using Deadgrep, but denote-search is nice to have in the quiver.

Permalink #

Sunday, March 02, 2025

Avatarium is new to me. I love her soulful (clean) vocals and the doom/sludgy sound. It's like Joni Mitchell and Black Sabbath teamed up.

{{< youtube VFKfPIV_aZc >}}


Too many journals. Not enough to say.


Keeping the Leica SL2, for now

We look good together, no?

When I bought the Nikon Z f recently, the way I intended to offset the cost was to sell the Leica SL2. The mistake I made was to buy the Nikon before selling the Leica.

Yesterday, I gathered up the SL2 with accessories and took some photos of it for the listing. Picking up the camera reminded me that, as nice as the Z f is, it's not in the same league as the SL2. Everything about the Leica feels nicer. Controls, covering, grip, doors, battery, all of it.

I've been lost in the Nikon's menu system for a week. I still don't know where anything is. There's more "stuff" available on the Nikon, but the Leica's menus are simple, clear, and easy to understand. Sometimes less is more, you know?

I started to reconsider the move to Nikon for my digital photography.

On the other hand, the Z f is significantly smaller and lighter. Accessories are less expensive. The RAW files look good, and are much smaller (due to being 24MP vs 47MP, sure, but still). It's better at everything in low light. And auto-focus with the Nikon is miles ahead of the Leica. Eye detection with continuous auto-focus is a thing to behold.

I'm keeping both cameras.

The Nikon is for everyday stuff. It's perfect for the dog and my grandson and out-and-about photography. The Leica will remain for more "serious" things like studio portraits, which I want to do more of.

That's settled then. 😉.

Permalink #

Saturday, March 01, 2025

I would love to be a person who goes out to photograph because I have something to say, rather than someone looking for an excuse to play with cameras and because I'm bored.


I find YouTube to be 95% useless, but the other 5% is helpful and can be absolutely amazing and wonderful.


If I cancel my subscriptions to every newspaper that publishes something stupid, I'll have nowhere left to get any news. Mastodon, you say? Hardly.


I bet you a million dollars that the Mozilla terms-of-use kerfluffle ends up being a tempest in a teapot. Again. We're so quick to jump on things that have even the slightest whiff of "wrongdoing". That's fine, but know what you're pouncing on, first.


Thursday, February 27, 2025

New t-shirt is funny.

I've been shopping for desktop computers to run Linux. Something easy and nice, like a low-mid range Thelios, maybe. This is a terrible idea and I should stop doing it at once.


When do you think I'll finally find something that I'm good at?


There are too many people in my head.


I like Matt Birchler's Quick Reviews app, but I wish it would look up the year/director for me. The new iOS app might do something like that, but I won't use the app on iOS.


Some days I find myself in a foul mood because "Emacs is being stupid and annoying and I don't feel like dealing with it!"

Today, though, Emacs has been making me absolutely giddy. It can be wonderful, and I wish more people could put in the time to get to know (and love) it. 😍.


Wednesday, February 26, 2025

Well, I'm in that place again. You know the one. The one where I write the same thing in more than one, and sometimes more than two, places because I can't decide where stuff goes.


I've backed up and made all of my Kindle books readable on any device. I also just borrowed a book from the library, directly from my Kobo. This feels very good.


Tuesday, February 25, 2025

I'd like to get kaorahi (Howm) and Prot (Denote) together and maybe lock them in a room for a few hours. At the end, there would either be plans for building the greatest Emacs package ever...or fisticuffs.


Monday, February 24, 2025

What's New in Emacs 30.1? - Mastering Emacs

Full support for Emacs on Android, and a whole host of touch screen-related improvements to Emacs as a result.

Sooo, do I need an Android phone, now?


Most of today was spent farting around in Emacs. Again. I don't mind. It was fun. I tweaked Howm. Played with Gnus. Upgraded to Emacs 30.1, and cleaned up some config. A good time was had by all.


Org mode capture template for creating Howm TODOs

My use of Howm has continued to grow organically. In other words, I don't set out to use Howm, it just happens :).

One of Howm's unique features is its TODO implementation:

Format of schedule and todo:
[2002-10-21]@1  schedule -- (shown in schedule part. @3 = "3 days schedule to 10-23")
[2002-10-21]+7  todo -- float up slowly from the date in 7 days
[2002-10-21]!7  deadline -- float up fast from 7 days before the date
[2002-10-21]-1  reminder -- float at the date and sink slowly one unit per 1 day
[2002-10-21]~30 defer -- float at the date and repeat sinking and floating with 30 days period
[2002-10-21].   done -- sink forever
(Numbers after marks are default values.)

How to remember:
- Schedule at(@) the date
- Reminder sinks down(-).
- Todo floats up(+).
- Deadline needs attention!
- Defer waves(~) up and down.
- Done is the end(.).

These TODOs can be placed anywhere in any Howm file, but sometimes I just want to capture a task and have it added to an existing list of TODOs. I created a simple org-capture template for this:

  ("h" "Todo to Howm" plain
           (file+headline , "~/Documents/Notes/Denote/Howm/20250224T081548--todo.org" "Inbox")
           "- [%<%F>]+ %?")

Running the capture template puts a new, dated TODO into a dedicated Howm TODO file. After a few uses for testing, it looks like this:

* Inbox
- [2025-02-24]. [2025-02-24]:+ Create capture template for Howm dates
- [2025-02-24]. [2025-02-24]:+ Move TODO file to root of Howm tree
- [2025-02-24]+ Fix categories on Baty.net
- [2025-02-24]~ Buy replacement hinges for laundry room
- [2025-02-24]+ Something to do
- [2025-02-28]@ Meeting with tax guys

They show up when needed on the Howm menu, like so:

Howm Menu

At some point I should add a prompt for the date to use as well as the type of TODO, but for now, it's a small, useful quality-of-life improvement.

Permalink #

Sunday, February 23, 2025

I'm starting to worry that Severance is just being weird for the sake of being weird. Some of this stuff had better resolve itself or I'm going to be very disappointed.