Subject: Re: bug#77313: 30.1.50; Regression: flymake indicators are erroneously using margins

From: Spencer Baugh <[email-masked]>
Date: Thu, 27 Mar 2025 16:34:16 -0400

Juri Linkov <[email-masked]> writes:

>>>> Keep in mind I was the one who, while reviewing the flymake patch adding
>>>> margins, suggested that TTY frames automatically default to using
>>>> margins.  This code exists because I requested it.  I sadly did not
>>>> realize that the behavior was implemented with a buggy default value for
>>>> flymake-indicator-type, nor was it caught before release; I only just
>>>> now have received direct user complaints about the regression.
>>>
>>> That's fine.  We all make mistakes.  But the way to correct those
>>> mistakes is not to go back, it's to go forward.
>>>
>>> So I urge you to work on a fix which doesn't disable the indicators in
>>> "emacs -nw", but instead attempts to detect the situations you
>>> describe above and adapt the indicator style to them.
>>
>> If you insist, I will develop such a fix.  It will be more complex.  But
>> can we please nevertheless backport it to Emacs 30?  I really want this
>> regression to be fixed in Emacs 30.2; I've gotten multiple user
>> complaints about it.
>
> There are many improvements developed in Emacs 31 for flymake margins
> in bug#75841 and bug#76254.  But maybe better indeed to change
> the default in Emacs 30.2 (with no merge to master).

Yes, that's what I was suggesting, not merging to master.

Anyway, how about this patch, which changes the default so that the
fringe vs margin decision is made in a per-frame way?

(Opinions welcome on what to name the new default for
flymake-indicator-type)

>From b64253c0f56e3f15f2807654baad462379d1a052 Mon Sep 17 00:00:00 2001
From: Spencer Baugh <[email-masked]>
Date: Thu, 27 Mar 2025 16:32:59 -0400
Subject: [PATCH] flymake: default to deciding indicator type per-buffer

Previously, flymake-indicator-type defaults to either fringes or
margins.  But fringes should be used on graphical frames, and
margins on TTY frames, so a single global default is incorrect.
Instead, it should be decided on a per-frame basis.

Now flymake-indicator-type defaults to 'fringes-per-frame, which
uses fringes on (buffers in) graphical frames, margins on
(buffers in) terminal frames.

* lisp/progmodes/flymake.el (flymake-indicator-type): Set to
fringes-per-frame.  (bug#77313)
(flymake--use-fringes-p, flymake--use-margins-p): Add.
(flymake--resize-margins): Check flymake--use-margins-p.
(flymake--highlight-line): Check flymake--use-fringes-p and
flymake--use-margins.
---
 lisp/progmodes/flymake.el | 26 ++++++++++++++++++--------
 1 file changed, 18 insertions(+), 8 deletions(-)

diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 75ba3efeb65..06001abe156 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -185,9 +185,7 @@ flymake-fringe-indicator-position
 		 (const right-fringe)
 		 (const :tag "No fringe indicators" nil)))
 
-(defcustom flymake-indicator-type (if (display-graphic-p)
-                                      'fringes
-                                    'margins)
+(defcustom flymake-indicator-type 'fringes-per-frame
   "Indicate which indicator type to use for display errors.
 
 The value can be nil (don't indicate errors but just highlight them),
@@ -199,8 +197,10 @@ flymake-indicator-type
 
 See Info node `Fringes' and Info node `(elisp)Display Margins'."
   :version "30.1"
-  :type '(choice (const :tag "Use Fringes" fringes)
-                 (const :tag "Use Margins "margins)
+  :type '(choice (const :tag "Use fringes on graphical, margins on TTY frames"
+                        fringes-per-frame)
+                 (const :tag "Use Fringes" fringes)
+                 (const :tag "Use Margins" margins)
                  (const :tag "No indicators" nil)))
 
 (defcustom flymake-margin-indicators-string
@@ -777,10 +777,20 @@ flymake--indicator-overlay-spec
                       `(:inherit (,indicator-cdr
                                   default)))))))))
 
+(defun flymake--use-fringes-p ()
+  (cl-case flymake-indicator-type
+    (fringes t)
+    ((nil margins) nil)
+    (fringes-per-frame (display-graphic-p))
+    (t t)))
+
+(defun flymake--use-margins-p ()
+  (not (flymake--use-fringes-p)))
+
 (defun flymake--resize-margins (&optional orig-width)
   "Resize current window margins according to `flymake-margin-indicator-position'.
 Return to original margin width if ORIG-WIDTH is non-nil."
-  (when (and (eq flymake-indicator-type 'margins)
+  (when (and (flymake--use-margins-p)
              flymake-autoresize-margins)
     (cond
      ((and orig-width flymake--original-margin-width)
@@ -945,9 +955,9 @@ flymake--highlight-line
         (flymake--indicator-overlay-spec
          (flymake--lookup-type-property
           type
-          (cond ((eq flymake-indicator-type 'fringes)
+          (cond ((flymake--use-fringes-p)
                  'flymake-bitmap)
-                ((eq flymake-indicator-type 'margins)
+                ((flymake--use-margins-p)
                  'flymake-margin-string))
           (alist-get 'bitmap (alist-get type ; backward compat
                                         flymake-diagnostic-types-alist)))))
-- 
2.39.3