💾 Archived View for gem.librehacker.com › gemlog › starlog › 20240304-0.gmi captured on 2024-06-16 at 12:13:22. Gemini links have been rewritten to link to archived content
⬅️ Previous capture (2024-03-21)
-=-=-=-=-=-=-
The last few weeks I've been moving more of my work out of Gnome Console into Emacs. A lot of that Console work was just calling one-off shell commands, so I figured why not call those commands using shell-command or async-shell-command from Emacs. I take the the commonly used, longer-running commands and wrap them in async-shell-command inside of a simple interactive function with an easy to remember name.
The thing I was missing after the switch, however, is that after command completion, Gnome Console would send a notification to Gnome shell, which would pop up below the notification area and do a good job of getting my attention. This was helpful after running a command that takes an twenty minutes to complete, so I want some kind of notification when it is done. Emacs, however, just sends a message to the echo area, which is easily missed and often quickly removed by some other command.
Fortunately, Gnome Shell includes a command-line utility called "notify-send" which simply requires a string passed-in as an argument. Example usage would be "guix system reconfigure mysystem.scm && notify-send done". That basically works, but it is a bother to add that onto each call to async-shell-command, and also it doesn't pass the command name or termination signal on to the notification.
Unfortunately, Emacs doesn't currently (29.1) have a hook available to do anything after the async process terminates. I e-mailed emacs-devel suggesting such a hook. In the meantime, it is possible to get what I want by overriding the sentinel function from simple.el. Here is the original function:
(defun shell-command-sentinel (process signal) (when (memq (process-status process) '(exit signal)) (shell-command-set-point-after-cmd (process-buffer process)) (message "%s: %s." (car (cdr (cdr (process-command process)))) (substring signal 0 -1))))
And here is the override function in my init.el:
(defun shell-command-sentinel (process signal) (when (memq (process-status process) '(exit signal)) (shell-command-set-point-after-cmd (process-buffer process)) (let ((command-string (car (cdr (cdr (process-command process))))) (signal-string (substring signal 0 -1))) (message "%s: %s." command-string signal-string) (start-process "notify" nil "notify-send" (concat command-string ": " signal-string)))))
I still think it would be good to have a real hook there, with the sentinel passing the process and signal to the callback(s). But this override is sufficient for my present needs.
This work © 2024 by Christopher Howard is licensed under Attribution-ShareAlike 4.0 International.