From 7e9e8be2ee5f6ce0097b2779d5a2a61c69410d70 Mon Sep 17 00:00:00 2001 From: Kévin Le Gouguec Date: Sun, 24 Mar 2024 13:10:29 +0100 Subject: 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. --- .emacs | 41 ++++++++++++++++++++++++++--------------- 1 file changed, 26 insertions(+), 15 deletions(-) diff --git a/.emacs b/.emacs index b3866da..ff0dce1 100644 --- 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. -- cgit v1.2.3