From 92bd2d865f217bf40ceb0ff8f03f2326b08e5ba2 Mon Sep 17 00:00:00 2001 From: Stefan Monnier Date: Mon, 5 May 2025 11:55:29 -0400 Subject: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode (bug#78264) Partly motivated by bug#78097. * lisp/simple.el (delete-trailing-whitespace-if-possible): New function. (delete-trailing-whitespace-mode): New minor mode. * lisp/editorconfig.el (editorconfig-trim-whitespaces-mode): Change default to `delete-trailing-whitespace-mode`. (editorconfig--get-trailing-ws): Simplify accordingly. (editorconfig--add-hook-safe-p): Delete function. Don't touch `safe-local-eval-function` any more. (cherry picked from commit 8a19c249f813e9f3830308e40f0205d7665f78a3) --- lisp/editorconfig.el | 38 +++++++++++--------------------------- lisp/simple.el | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/lisp/editorconfig.el b/lisp/editorconfig.el index 28b1cc9a3d1..0c219e13e4e 100644 --- a/lisp/editorconfig.el +++ b/lisp/editorconfig.el @@ -271,13 +271,13 @@ a list of settings in the form (VARIABLE . VALUE)." :version "30.1" :risky t) -(defcustom editorconfig-trim-whitespaces-mode nil +(defcustom editorconfig-trim-whitespaces-mode #'delete-trailing-whitespace-mode "Buffer local minor-mode to use to trim trailing whitespaces. If set, enable that mode when `trim_trailing_whitespace` is set to true. Otherwise, use `delete-trailing-whitespace'." :version "30.1" - :type 'symbol) + :type 'function) (defvar-local editorconfig-properties-hash nil "Hash object of EditorConfig properties that was enabled for current buffer. @@ -536,33 +536,17 @@ This function will revert buffer when the coding-system has been changed." "Call `delete-trailing-whitespace' unless the buffer is read-only." (unless buffer-read-only (delete-trailing-whitespace))) -;; Arrange for our (eval . (add-hook ...)) "local var" to be considered safe. -(defun editorconfig--add-hook-safe-p (exp) - (equal exp '(add-hook 'before-save-hook - #'editorconfig--delete-trailing-whitespace nil t))) -(let ((predicates (get 'add-hook 'safe-local-eval-function))) - (when (functionp predicates) - (setq predicates (list predicates))) - (unless (memq #'editorconfig--add-hook-safe-p predicates) - (put 'add-hook 'safe-local-eval-function #'editorconfig--add-hook-safe-p))) - (defun editorconfig--get-trailing-ws (props) "Get vars to trim of trailing whitespace according to PROPS." - (pcase (gethash 'trim_trailing_whitespace props) - ("true" - `((eval - . ,(if editorconfig-trim-whitespaces-mode - `(,editorconfig-trim-whitespaces-mode 1) - '(add-hook 'before-save-hook - #'editorconfig--delete-trailing-whitespace nil t))))) - ("false" - ;; Just do it right away rather than return a (VAR . VAL), which - ;; would be probably more trouble than it's worth. - (when editorconfig-trim-whitespaces-mode - (funcall editorconfig-trim-whitespaces-mode 0)) - (remove-hook 'before-save-hook - #'editorconfig--delete-trailing-whitespace t) - nil))) + (let ((fun (or editorconfig-trim-whitespaces-mode + #'delete-trailing-whitespace-mode))) + (pcase (gethash 'trim_trailing_whitespace props) + ("true" `((eval . (,fun 1)))) + ("false" + ;; Just do it right away rather than return a (VAR . VAL), which + ;; would be probably more trouble than it's worth. + (funcall fun 0) + nil)))) (defun editorconfig--get-line-length (props) "Get the max line length (`fill-column') to PROPS." diff --git a/lisp/simple.el b/lisp/simple.el index fcc91910a6e..aaf64fb6adc 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -900,6 +900,21 @@ buffer if the variable `delete-trailing-lines' is non-nil." ;; Return nil for the benefit of `write-file-functions'. nil) +(defun delete-trailing-whitespace-if-possible () + "Call `delete-trailing-whitespace' unless the buffer is read-only." + (unless buffer-read-only (delete-trailing-whitespace))) + +(define-minor-mode delete-trailing-whitespace-mode + "Delete trailing whitespace before saving the current buffer." + :global nil + (cond + (delete-trailing-whitespace-mode + (add-hook 'before-save-hook + #'delete-trailing-whitespace-if-possible nil t)) + (t + (remove-hook 'before-save-hook + #'delete-trailing-whitespace-if-possible t)))) + (defun newline-and-indent (&optional arg) "Insert a newline, then indent according to major mode. Indentation is done using the value of `indent-line-function'. -- 2.39.5