I have this advice in place that executes the called function over the whole buffer if a region is not selected. But I would also like to print a message that tells the user that the function they just called acted on the whole buffer.
(defun modi/whole-buffer-if-not-region (orig-fn &rest args)
(save-excursion
(if (region-active-p) ; do the default thing if a region is selected
(apply orig-fn args)
(let (fn-name) ; indent the whole buffer otherwise
(apply orig-fn (list (point-min) (point-max)))
(setq fn-name (cl-case (type-of orig-fn)
('subr (subr-name orig-fn))
;; ('compiled-function (symbol-name orig-fn)) ; doesn't work
(t orig-fn)))
(message "Executed %s on the whole buffer" fn-name)))))
(advice-add #'indent-region :around #'modi/whole-buffer-if-not-region)
(advice-add #'eval-region :around #'modi/whole-buffer-if-not-region)
Using the above code,
- If I do
M-x eval-region
without selecting a region, I see the messageExecuted eval-region on the whole buffer
. - I would like to get a similar message when I do
M-x indent-region
without selecting a region.symbol-name
does not work here as I learned that theindent-region
function is of the type'compiled-function
With the above code I get the below when I do M-x indent-region
without region selection:
Executed #[770 \211\203A \303!\262\212b\210\304 \262b\210n\204 \305y\210`W\2038 `\306\307w\210`|\210l\2042 \310\311"\210\305y\210\202 \307\211\223\210)\202\324 \203u \212b\210\304 \262b\210\312!`W\203p \313!\204j n\203g l\204j c\210\305y\210\202S \210)\202\324 \203\201 "\210\202\324 \212\314!\262b\210\315 ?\205\225 \316\317`#`W\203\305 n\203\243 l\204\246 \320 \210\305y\210\211\203\225 \211`\211\247\203\273 \211@Y\203\300 \321"\210\266\202\225 \211\203\315 \322!\210\307\211\223\266)\323\211\207 [fill-prefix indent-region-function deactivate-mark prefix-numeric-value point-marker 1 nil indent-to 0 regexp-quote looking-at copy-marker minibufferp make-progress-reporter Indenting region... indent-according-to-mode progress-reporter-do-update progress-reporter-done t] 9 2037903 r
P] on the whole buffer
How do I extract the compiled-function
name (indent-region
in this case)?
Solution
Thanks to @abo-abo's solution below, I got this working as I wanted using the below:
(defmacro modi/add-whole-buffer-if-not-region-advice (symbol)
"Advice SYMBOL function (that originally acts on a region) to act on the
whole buffer if a region is not selected."
`(advice-add ,symbol :around (lambda (orig-fn &rest args)
(save-excursion
;; Execute the original SYMBOL function if
;; it is called indirectly. Example: we do
;; not want to trigger this advice if
;; `eval-region' is called via `eval-defun'.
(if (or (not (eq ,symbol this-command))
(use-region-p))
(apply orig-fn args)
(apply orig-fn (list (point-min) (point-max)))
(message "Executed %s on the whole buffer"
(propertize
(symbol-name ,symbol)
'face
'font-lock-function-name-face)))))))
(modi/add-whole-buffer-if-not-region-advice #'indent-region)
(modi/add-whole-buffer-if-not-region-advice #'eval-region)