dotfiles

๐ŸŽœ Clone'em, tweak'em, stick'em in your $HOME ๐ŸŽ
git clone https://git.kevinlegouguec.net/dotfiles
Log | Files | Refs | README

commit 7e9e8be2ee5f6ce0097b2779d5a2a61c69410d70
parent de53c1eade0b53579dda80a91a7c59a849bf6b4b
Author: Kรฉvin Le Gouguec <kevin.legouguec@gmail.com>
Date:   Sun, 24 Mar 2024 13:10:29 +0100

Beef up program-running helpers

* .emacs (my/run-strip-newline): New escape hatch, to let my/run DTRT
most of the time and spare most callers the cognitive load.
(my/run): Heed it.  Document.
(my/kill-command): New helper; meant for programmatic use where
arglists are manipulated as lists, and and no shell escaping is
required.
(my/kill-date, my/describe-revision): Use it.
(my/kill-shell): Document, to disambiguate with my/kill-command.

Diffstat:
M.emacs | 41++++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)

diff --git a/.emacs b/.emacs @@ -189,13 +189,25 @@ (defun my/read (prompt default) (read-string (format-prompt prompt default) nil nil default)) +(defvar my/run-strip-newline t + "Whether `my/run' will remove a trailing newline from a command's output.") + (defun my/run (program &rest args) - (let ((handler (lambda (status) - (unless (eq status 0) - (user-error - "%s returned %d:\n%s" - program status (buffer-string)))))) - (apply 'process-lines-handling-status program handler args))) + "Return output from 'PROGRAM [ARGSโ€ฆ]'. +Raise a user error if the command fails. Heed `my/run-strip-newline'." + (with-temp-buffer + (let* ((status (apply 'call-process program nil t nil args)) + (output (buffer-string))) + (if (eq status 0) + (if my/run-strip-newline + (string-remove-suffix "\n" output) + output) + (user-error "%s returned %d:\n%s" program status output))))) + +(defun my/kill-command (program &rest args) + "Send output from PROGRAM to kill-ring. +See `my/run' for details, e.g. status handling and output massaging." + (my/kill (apply 'my/run program args))) (defun my/kill-date (date format) (interactive @@ -203,8 +215,7 @@ (list (my/read "Date spec?" "today") (my/read "Format?" "%F")) (list "today" "%F"))) - (my/kill - (car (my/run "date" (concat "-d" date) (concat "+" format))))) + (my/kill-command "date" (concat "-d" date) (concat "+" format))) (defun my/kill-filename () (interactive) @@ -220,6 +231,10 @@ (my/kill (buffer-string))))) (defun my/kill-shell (command) + "Send output from COMMAND to kill-ring. +Meant for interactive prompting for full commands passed to a shell. +For Lisp use, prefer `my/kill-command', where arguments are passed via a +list and require no escaping." (interactive (list (read-shell-command "Shell command: "))) (with-temp-buffer (call-process-shell-command command nil t) @@ -436,13 +451,9 @@ (defun my/describe-revision (rev) "Format a Git revision in a format suitable for changelogs." (interactive - (list (let ((rev (my/revision-at-point))) - (read-string (format-prompt "Revision" rev) - nil nil rev)))) - (my/kill (string-trim - (shell-command-to-string - (format "git show --no-patch --date=short --format='%s' %s" - "%cd \"%s\" (%h)" rev))))) + (list (my/read "Revision" (my/revision-at-point)))) + (my/kill-command + "git" "show" "--no-patch" "--date=short" "--format=%cd \"%s\" (%h)" rev)) ;;; Major modes configuration.