Subject: bug#78264: closed (Re: bug#78264: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode)

From: [email-masked] (GNU bug Tracking System)
Date: Mon, 12 May 2025 16:42:02 +0000

Your bug report

#78264: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
78264: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=78264
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#78264: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode
From: Stefan Monnier <[email-masked]>
To: [email-masked]
Date: Mon, 12 May 2025 12:41:39 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

Pushed to `master`, closing,

        Stefan

Subject: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode
From: Stefan Monnier <[email-masked]>
To: [email-masked]
Date: Mon, 05 May 2025 12:01:22 -0400
List-Id: <debbugs-submit.debbugs.gnu.org>

Tags: patch

While

    (add-hook 'before-save-hook #'delete-trailing-whitespace nil t)

is simple enough to put into one's init file, it's a bit rough around
the edges (e.g. for read-only buffers, or interaction with
editorconfig).  So I suggest we add a simple
`delete-trailing-whitespace-mode` minor mode.

Comments?  Objections?

        Stefan

 In GNU Emacs 31.0.50 (build 1, i686-pc-linux-gnu, GTK+ Version 3.24.49,
 cairo version 1.18.4) of 2025-05-01 built on alfajor
Repository revision: 3555aa795435c6c150e9291386cb776acd35e564
Repository branch: work
Windowing system distributor 'The X.Org Foundation', version 11.0.12101016
System Description: Debian GNU/Linux trixie/sid

Configured using:
 'configure -C --enable-checking --enable-check-lisp-object-type --with-modules --with-cairo --with-tiff=ifavailable
 'CFLAGS=-Wall -g3 -Og -Wno-pointer-sign'
 PKG_CONFIG_PATH=/home/monnier/lib/pkgconfig'

>From 5740c9b27883de86888df8d201e5daed97d7dd0b Mon Sep 17 00:00:00 2001
From: Stefan Monnier <[email-masked]>
Date: Mon, 5 May 2025 11:55:29 -0400
Subject: [PATCH] simple.el (delete-trailing-whitespace-mode): New minor mode

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.
---
 etc/NEWS             |  4 ++++
 lisp/editorconfig.el | 38 +++++++++++---------------------------
 lisp/simple.el       | 15 +++++++++++++++
 3 files changed, 30 insertions(+), 27 deletions(-)

diff --git a/etc/NEWS b/etc/NEWS
index 146cdedaa43..8efb6e6ae07 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -2034,6 +2034,10 @@ the file name, using the minibuffer's "future history".
 
 * New Modes and Packages in Emacs 31.1
 
+** New minor mode 'delete-trailing-whitespace-mode'.
+A simple buffer-local mode that runs 'delete-trailing-whitespace'
+before saving the buffer.
+
 ** New major mode 'conf-npmrc-mode'.
 A major mode based on 'conf-mode' for editing ".npmrc" files.
 
diff --git a/lisp/editorconfig.el b/lisp/editorconfig.el
index 7cdd79fa3b0..bfc8ef46ed3 100644
--- a/lisp/editorconfig.el
+++ b/lisp/editorconfig.el
@@ -277,13 +277,13 @@ editorconfig-indentation-alist
   :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.
@@ -542,33 +542,17 @@ editorconfig--delete-trailing-whitespace
   "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 486092de2c8..f686907ad68 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -888,6 +888,21 @@ delete-trailing-whitespace
   ;; 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.47.2