master 6223d243da3 3/4: Flymake: rework inline diagnostic text annotations

João Távora <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: master
commit 6223d243da3f45be380867c810c5cc64d17e290b
Author: João Távora <[email protected]>
Commit: João Távora <[email protected]>

    Flymake: rework inline diagnostic text annotations
    
    Replace flymake-show-diagnostics-at-end-of-line with a simpler, more
    powerful flymake-inline-diagnostics.  The new variable has an easier name
    offers the new possibilities inspired by other packages, of having only
    the current diagnostic be affected by each setting..
    
    * doc/misc/flymake.texi: Update.
    
    * etc/NEWS: Update
    
    * lisp/progmodes/flymake.el (flymake-annotation-style): New variable.
    (flymake-inline-annotation-face)
    (flymake-error-inline, flymake-warning-inline)
    (flymake-note-inline): New faces.
    (flymake--highlight-line)
    (flymake--handle-report)
    (flymake-after-change-function): Update to use new variable name.
    (flymake--update-current-eol-overlay): New helper.
    (flymake--eol-current-overlay): New variable.
    (flymake--update-all-eol-overlays): Rename from flymake--update-eol-overlays.
    (flymake-make-report-fn): Keep point stable.
    (flymake--update-eol-overlays): Tweak.
    (flymake--eol-overlay-summary): Rewrite.
    (flymake-mode): Set post-command-hook
    (flymake--update-eol-overlays): Rework.
    (flymake--update-eol-overlays-1): New helper.
    (flymake-diagnostic-format-alist): Enhance.
    (flymake--format-diagnostic): Handle old :eol value.
    (flymake-inline-annotation-face)
    (flymake-error-inline)
    (flymake-warning-inline)
    (flymake-note-inline): New faces.
    (flymake-show-diagnostics-at-end-of-line)
    (flymake-end-of-line-diagnostics-face)
    (flymake-error-echo-at-eol)
    (flymake-warning-echo-at-eol)
    (flymake-note-echo-at-eol): Deprecate
    (flymake--eol-draw-fancy): Tweak geometry slightly
---
 doc/misc/flymake.texi     |  48 +++++----
 etc/NEWS                  |  14 +++
 lisp/progmodes/flymake.el | 260 ++++++++++++++++++++++++++++++++--------------
 3 files changed, 228 insertions(+), 94 deletions(-)

diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi
index d0983bc76db..9c68aa5ef10 100644
--- a/doc/misc/flymake.texi
+++ b/doc/misc/flymake.texi
@@ -146,10 +146,9 @@ is.  Alternatively, place point on the highlighted regions and use the
 commands @code{eldoc} or @code{display-local-help}.
 
 Another easy way to get instant access to the diagnostic text is to
-set @code{flymake-show-diagnostics-at-end-of-line} to a non-@code{nil}
-value.  This makes the diagnostic messages appear at the end of the
-line where the regular annotation is located (@pxref{Customizable
-variables})
+set @code{flymake-inline-diagnostics} to a non-@code{nil} value.  This
+makes the diagnostic messages appear directly in the buffer, in the
+vicinity of the affected line (@pxref{Customizable variables})
 
 @cindex next and previous diagnostic
 If the diagnostics are outside the visible region of the buffer,
@@ -347,26 +346,39 @@ Only relevant if @code{flymake-indicator-type} is set to @code{margins}.
 If non-@code{nil}, moving to errors with @code{flymake-goto-next-error} and
 @code{flymake-goto-prev-error} wraps around buffer boundaries.
 
-@item flymake-show-diagnostics-at-end-of-line
-If non-@code{nil}, show summarized descriptions of diagnostics at the
-end of the line.  Depending on your preference, this can either be
-distracting and easily confused with actual code, or a significant early
-aid that relieves you from moving around or reaching for the mouse to
-consult an error message.  This value may also be set to @code{fancy},
-which will attempt to layout diagnostics below the affected line using
-unicode graphics to point to diagnostic locus.
+@item flymake-inline-diagnostics
+If non-@code{nil}, annotate lines with diagnostics directly in the
+buffer.  Depending on your preference, this can either be distracting
+and easily confused with actual code, or a significant early aid that
+relieves you from moving around or reaching for the mouse to consult an
+error message.  A number of styles can be used: the value @code{eol}
+shows all diagnostics at the end of the line, @code{short} shows only
+the most severe one, and @code{fancy} lays out the diagnostics below the
+affected line using Unicode graphics to point to the diagnostic locus.
+
+The value can also be an alist, which allows you to have the position of
+point dictate the style used for nearby annotation of nearby
+diagnostics.  The alist keys @code{current} and @code{current-line}
+designate the style affect the appearance of nearby diagnostics, while a
+value keyed by @code{t} is style used for every other diagnostic.  For
+example, to keep a discreet @code{short} annotation on most lines while
+expanding to @code{fancy} only for the diagnostic point in currently on:
+
+@lisp
+(setopt flymake-inline-diagnostics '((current . fancy) (t . short)))
+@end lisp
 
 @item flymake-diagnostic-format-alist
 Control which parts of a diagnostic to show in various situations.
 
-@item flymake-error-eol
-A custom face for summarizing diagnostic error messages.
+@item flymake-error-inline
+A custom face for inline diagnostic error messages.
 
-@item flymake-warning-eol
-A custom face for summarizing diagnostic warning messages.
+@item flymake-warning-inline
+A custom face for inline diagnostic warning messages.
 
-@item flymake-note-eol
-A custom face for summarizing diagnostic notes.
+@item flymake-note-inline
+A custom face for inline diagnostic notes.
 @end vtable
 
 @node Flymake API, The legacy Proc backend, Using Flymake, Top
diff --git a/etc/NEWS b/etc/NEWS
index a9628a32e1e..723f08cf6e7 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -136,6 +136,20 @@ check out the repository to prepare a patch for the package maintainer.
 ---
 *** Messages from Ansible are now recognized.
 
+** Flymake
+
++++
+*** Overhauled inline diagnostics
+A new variable 'flymake-inline-diagnostics' replaces
+'flymake-show-diagnostics-at-end-of-line' and controls how Flymake
+annotates diagnostic text directly in the buffer.  Besides the previous
+styles ('eol', 'short', and 'fancy'), it can be used to only display
+certain styles in certain situations, such as using a 'fancy' inline
+displays on nearby diagnostic only.  The old variable is now an obsolete
+alias.  In parallel, the variable 'flymake-diagnostic-format-alist'
+contains new options to configure exactly which parts of a diagnostic to
+show for each inline layout possibility.
+
 ** Man
 
 ---
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index 8bc3dc3e4f3..2d9ff648dce 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -454,20 +454,27 @@ diagnostics at BEG."
 
 (defcustom flymake-diagnostic-format-alist
   '((:help-echo . (origin code oneliner))
-    (:eol . (oneliner))
+    (:inline-eol . (oneliner code))
+    (:inline-short . (oneliner))
+    (:inline-fancy . (oneliner code))
     (:eldoc . (origin code message))
     (:eldoc-echo . (origin code oneliner))
     (t . (origin code oneliner)))
-  "How to format diagnostics for different output destinations.
+  "Specify which parts of diagnostics to use when formatting them.
+
 Value is an alist where each element looks like (DESTINATION . PARTS).
 DESTINATION is a symbol designating an outlet.  One of:
 
 - `:help-echo', for the native Flymake echoing of diagnostics in the
-   echo area as used my `flymake-goto-next-error' and `flymake-goto-prev-error';
-- `:eol', for use with `flymake-show-diagnostics-at-end-of-line';
+   echo area as used by `flymake-goto-next-error' and
+   `flymake-goto-prev-error';
+- `:inline-eol', `:inline-short' or `:inline-fancy', for use
+   `flymake-inline-diagnostics' in non-nil, meaning  the diagnostic text is
+   presented in the the buffer itself.  See `flymake-inline-diagnostics'
+   for the meaning of `eol', `short' and `fancy'.
 - `:eldoc', for use with Flymake's ElDoc backend;
-- `:eldoc-echo', for use with Flymake's ElDoc backend, but for ElDoc's own
-   confined outlets;
+- `:eldoc-echo', like `:eldoc' but specifically when Eldoc has little
+   space to spare in the echo area.
 - t for all other destinations.
 
 PARTS says which parts of the diagnostic to include.  It is a list of
@@ -479,7 +486,9 @@ symbols where the following values are meaningful:
 - `oneliner': include truncated diagnostic text;"
   :package-version '(Flymake . "1.4.0")
   :type '(alist :key-type (choice (const :help-echo)
-                                  (const :eol)
+                                  (const :inline-eol)
+                                  (const :inline-short)
+                                  (const :inline-fancy)
                                   (const :eldoc)
                                   (const :eldoc-echo)
                                   (const t))
@@ -515,6 +524,7 @@ order to concatenate them.  It is a list of symbols as described in
    when text concat it))
 
 (defun flymake--format-diagnostic (diag destination face-prop)
+  (when (eq destination :eol) (setq destination :inline-eol)) ;; backward compat
   (let ((txt (flymake-diagnostic-text
               diag (alist-get destination flymake-diagnostic-format-alist
                               (alist-get t flymake-diagnostic-format-alist
@@ -591,29 +601,29 @@ verify FILTER, a function, and sort them by COMPARE (using KEY)."
   "Face used for showing summarized descriptions of notes."
   :package-version '(Flymake . "1.3.4"))
 
-(defface flymake-end-of-line-diagnostics-face
+(defface flymake-inline-annotation-face
   '((t :height 0.85))
-  "Face used for end-of-line diagnostics.
-See variable `flymake-show-diagnostics-at-end-of-line'."
-  :package-version '(Flymake . "1.3.5"))
+  "Face used for inline diagnostics text.
+See variable `flymake-inline-diagnostics'."
+  :package-version '(Flymake . "1.4.5"))
 
-(defface flymake-error-echo-at-eol
-  '((t :inherit (flymake-end-of-line-diagnostics-face compilation-error)))
-  "Face like `flymake-error-echo', but for end-of-line overlays."
-  :package-version '(Flymake . "1.3.5"))
+(defface flymake-error-inline
+  '((t :inherit (flymake-inline-annotation-face compilation-error)))
+  "Face for error annotations in the buffer."
+  :package-version '(Flymake . "1.4.5"))
 
-(defface flymake-warning-echo-at-eol
-  '((t :inherit (flymake-end-of-line-diagnostics-face compilation-warning)))
-  "Face like `flymake-warning-echo', but for end-of-line overlays."
-  :package-version '(Flymake . "1.3.5"))
+(defface flymake-warning-inline
+  '((t :inherit (flymake-inline-annotation-face compilation-warning)))
+  "Face for warning annotations in the buffer."
+  :package-version '(Flymake . "1.4.5"))
 
-(defface flymake-note-echo-at-eol
-  '((t :inherit (flymake-end-of-line-diagnostics-face compilation-info)))
-  "Face like `flymake-note-echo', but for end-of-line overlays."
-  :package-version '(Flymake . "1.3.5"))
+(defface flymake-note-inline
+  '((t :inherit (flymake-inline-annotation-face compilation-info)))
+  "Face for note annotations in the buffer."
+  :package-version '(Flymake . "1.4.5"))
 
 (defface flymake-eol-information-face
-  '((t :inherit (flymake-end-of-line-diagnostics-face)
+  '((t :inherit (flymake-inline-annotation-face)
        :box nil
        :slant italic))
   "Face used for information about end-of-line diagnostics."
@@ -634,22 +644,55 @@ See variable `flymake-show-diagnostics-at-end-of-line'."
   :version "31.1"
   :package-version '(Flymake . "1.4.4"))
 
-(defcustom flymake-show-diagnostics-at-end-of-line nil
-  "If non-nil, add diagnostic summary messages at end-of-line.
-The value `short' means that only the most severe diagnostic
-shall be shown.
-The value `fancy' means to layout diagnostic summary information
-below the affected line with Unicode graphics.
-Any other non-nil value means show all diagnostic summaries at
-end-of-line."
-  :type '(choice (const :tag "Display most severe diagnostic" short)
-                 (const :tag "Display all diagnostics" t)
-                 (const :tag "Display all diagnostics using Unicode" fancy)
-                 (const :tag "Don't display diagnostics at end-of-line" nil))
-  :package-version '(Flymake . "1.3.6"))
+(define-obsolete-variable-alias 'flymake-show-diagnostics-at-end-of-line
+  'flymake-inline-diagnostics "32.1")
+
+(defcustom flymake-inline-diagnostics nil
+  "How Flymake styles diagnostic text in the buffer itself.
+
+The following values designating styles are possible:
+
+- `nil': no diagnostic info is added in the buffer;
+- `eol': diagnostic information is shown at the end of line;
+- `short': like `eol' but only the most severe diagnostic is considered;
+- `fancy': layout diagnostic information below the affected line with
+  Unicode graphics.
+- An alist ((WHERE . HOW) ...) where WHERE is `current', `current-line'
+  or t.  `current' selects the style for diagnostics that point is on;
+  `current-line' selects the style used for diagnostic on the same line
+  as point; and t selects the style used for every other diagnostic.  If
+  both `current' and `current-line' are given, `current' takes
+  precedence.  HOW is one of the symbols above.
+
+Regardless of styles, see variable `flymake-diagnostic-format-alist' for
+exactly which elements of information are included for each possibility."
+  :type
+  '(choice
+    (const :tag "No inline diagnostics" nil)
+    (const :tag "All diagnostics inlined at end of line" eol)
+    (const :tag "Most severe diagnostic inlined at end of line" short)
+    (const :tag "All diagnostics laid out with Unicode graphics" fancy)
+    (alist
+     :tag "Different inlining styles depending on situation"
+     :key-type (choice (const :tag "Diagnostics near point" current)
+                       (const :tag "Diagnostics on current line" current-line)
+                       (const :tag "Every other diagnostic" t))
+     :value-type (choice (const :tag "No inline diagnostics" nil)
+                         (const :tag "All diagnostics" eol)
+                         (const :tag "Only the most severe" short)
+                         (const :tag "Fancy Unicode graphics" fancy))))
+  :package-version '(Flymake . "1.4.5"))
 
 (define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1")
 (define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1")
+(define-obsolete-face-alias 'flymake-end-of-line-diagnostics-face
+  'flymake-inline-annotation-face "32.1")
+(define-obsolete-face-alias 'flymake-error-echo-at-eol
+  'flymake-error-inline "32.1")
+(define-obsolete-face-alias 'flymake-warning-echo-at-eol
+  'flymake-warning-inline "32.1")
+(define-obsolete-face-alias 'flymake-note-echo-at-eol
+  'flymake-note-inline "32.1")
 
 ;;;###autoload
 (defun flymake-diag-region (buffer line &optional col)
@@ -987,9 +1030,10 @@ Return nil or the overlay created."
     (overlay-put ov 'evaporate t)
     (overlay-put ov 'flymake-overlay t)
     (overlay-put ov 'flymake-diagnostic diagnostic)
-    ;; Handle `flymake-show-diagnostics-at-end-of-line'
+    ;; Handle `flymake-inline-diagnostics'.  If anything except nil,
+    ;; create an `flymake--eold
     ;;
-    (when flymake-show-diagnostics-at-end-of-line
+    (when flymake-inline-diagnostics
       (save-excursion
         (goto-char (overlay-start ov))
         (let* ((start (line-end-position))
@@ -1117,14 +1161,17 @@ report applies to that region."
                      (float-time
                       (time-since flymake-check-start-time))))))
     (setf (flymake--state-reported-p state) t)
-    ;; All of the above might have touched the eol overlays, so issue
-    ;; a call to update them.  But check running and reporting
-    ;; backends first to flickering when multiple backends touch the
-    ;; same eol overlays.
-    (when (and flymake-show-diagnostics-at-end-of-line
+    ;; All of the above might have influecned the eol overlays, so maybe
+    ;; issue a call to update them.  But to avoid flickering, wait for
+    ;; backends to finish first to avoid flickering when multiple
+    ;; backends touch the same eol overlays.  Also don't update if
+    ;; `flymake-timer' is non-nil, meaning the a scheduled
+    ;; `flymake-start' hasn't yet finished.
+    (when (and flymake-inline-diagnostics
+               (not flymake-timer)
                (not (cl-set-difference (flymake-running-backends)
                                        (flymake-reporting-backends))))
-      (flymake--update-eol-overlays))
+      (flymake--update-all-eol-overlays))
     (flymake--update-diagnostics-listings (current-buffer))))
 
 (defun flymake--clear-foreign-diags (state)
@@ -1209,10 +1256,12 @@ and other buffers."
 BACKEND is used to help Flymake distinguish different diagnostic
 sources.  If provided, TOKEN helps Flymake distinguish between
 different runs of the same backend."
-  (let ((buffer (current-buffer)))
+  (let ((buffer (current-buffer))
+        (point (point)))
     (lambda (&rest args)
       (when (buffer-live-p buffer)
         (with-current-buffer buffer
+          (goto-char point)
           (apply #'flymake--handle-report backend token args))))))
 
 (defun flymake--collect (fn &optional message-prefix)
@@ -1473,6 +1522,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     (add-hook 'after-change-functions 'flymake-after-change-function nil t)
     (add-hook 'after-save-hook 'flymake-after-save-hook nil t)
     (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t)
+    (add-hook 'post-command-hook 'flymake--update-current-eol-overlay nil t)
     (add-hook 'eldoc-documentation-functions 'flymake-eldoc-function t t)
 
     ;; Maybe auto-resize margins
@@ -1492,6 +1542,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     (remove-hook 'after-change-functions 'flymake-after-change-function t)
     (remove-hook 'after-save-hook 'flymake-after-save-hook t)
     (remove-hook 'kill-buffer-hook 'flymake-kill-buffer-hook t)
+    (remove-hook 'post-command-hook 'flymake--update-current-eol-overlay t)
     ;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t)
     (remove-hook 'eldoc-documentation-functions 'flymake-eldoc-function t)
 
@@ -1554,7 +1605,7 @@ START and STOP and LEN are as in `after-change-functions'."
     (flymake--schedule-timer-maybe))
   ;; Some special handling to prevent eol overlays from temporarily
   ;; moving to wrong line
-  (when (and flymake-show-diagnostics-at-end-of-line
+  (when (and flymake-inline-diagnostics
              (zerop pre-change-len))
     (save-excursion
       (goto-char start)
@@ -2269,44 +2320,100 @@ some of this variable's contents the diagnostic listings.")
 
 ;;; Eol overlay helpers
 ;;;
-(defun flymake--update-eol-overlays ()
-  "Update the `display' property of end-of-line overlays."
+(defvar-local flymake--eol-current-overlay nil
+  "Eol overlay, if any, currently styled for the diagnostic at point.")
+
+(cl-defun flymake--update-current-eol-overlay
+    (&aux style-entry (fid flymake-inline-diagnostics)
+          (old-o flymake--eol-current-overlay))
+  "Maybe paint nearby eol diagnostics with special `current-*' styles."
+  (when (and (consp fid)
+             (setq style-entry (or (assoc 'current fid)
+                                   (assoc 'current-line fid)))
+             ;; JT@2026-08-09: Don't consider current/current-line
+             ;; entries if a region is active or a flymake hasn't
+             ;; finished.  FIXME: An active in-buffer completion session
+             ;; should probably also have the same inhibiting effect,
+             ;; but at time of writing there is no easy way to answer
+             ;; that question.
+             (not (region-active-p))
+             (not flymake-timer))
+    (cl-loop
+     for style = (cdr style-entry)
+     for o in (overlays-at (line-end-position))
+     for src-ovs = (overlay-get o 'flymake-eol-source-overlays)
+     when (and src-ovs
+               (or (eq (car style-entry) 'current-line)
+                   (cl-some (lambda (o) (<= (overlay-start o) (point)
+                                            (overlay-end o)))
+                            src-ovs)))
+     do
+     (unless (eq o old-o)
+       (when (and old-o (overlay-buffer old-o))
+         (overlay-put old-o 'display (flymake--eol-overlay-summary old-o)))
+       (overlay-put o 'display (flymake--eol-overlay-summary o style))
+       (setq flymake--eol-current-overlay o))
+     (cl-return-from flymake--update-current-eol-overlay))
+    (when old-o
+      (overlay-put old-o 'display (flymake--eol-overlay-summary old-o))
+      (setq flymake--eol-current-overlay nil))))
+
+(defun flymake--update-all-eol-overlays ()
+  "Helper for flymake--handle-report."
   (save-restriction
     (widen)
     (dolist (o (overlays-in (point-min) (point-max)))
       (when (overlay-get o 'flymake--eol-overlay)
-        (if-let* ((src-ovs (overlay-get o 'flymake-eol-source-overlays)))
-            (overlay-put o 'display (flymake--eol-overlay-summary src-ovs))
-          (delete-overlay o))))))
-
-(defun flymake--eol-overlay-summary (src-ovs)
-  "Helper function for `flymake--update-eol-overlays'."
-  (cl-flet ((summarize (d)
-              (flymake--format-diagnostic d :eol 'eol-face)))
-    (let* ((diags
+        (if (cl-some #'overlay-buffer
+                     (overlay-get o 'flymake-eol-source-overlays))
+            (overlay-put o 'display (flymake--eol-overlay-summary o))
+          (delete-overlay o))))
+    (flymake--update-current-eol-overlay)))
+
+(defun flymake--eol-default-style ()
+  (cond ((not (consp flymake-inline-diagnostics))
+         flymake-inline-diagnostics)
+        (t
+         (alist-get t flymake-inline-diagnostics))))
+
+(cl-defun flymake--eol-overlay-summary
+    (eol-ov &optional (style (flymake--eol-default-style)))
+  "Helper function for `flymake--update-eol-overlays-1'."
+  (cl-labels ((summarize (d)
+                (flymake--format-diagnostic
+                 d
+                 (cl-case style
+                   (short :inline-short)
+                   (eol   :inline-eol)
+                   (fancy :inline-fancy)
+                   (default :inline-eol))
+                 'eol-face)))
+    (let* ((src-ovs (overlay-get eol-ov 'flymake-eol-source-overlays))
+           (diags
             (cl-sort
              (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs)
              #'>
              :key (lambda (d) (flymake--severity (flymake-diagnostic-type d)))))
            (summary
-            (concat
-             "  "
-             (cond ((eq flymake-show-diagnostics-at-end-of-line 'short)
+            (and diags
+                 (cl-case style
+                   (short
                     (concat
                      (summarize (car diags))
                      (and (cdr diags)
                           (concat
                            " "
-                           (propertize (format "and %s more"
+                           (propertize (format "(%s more)"
                                                (1- (length diags)))
                                        'face 'flymake-eol-information-face)))))
-                   ((eq flymake-show-diagnostics-at-end-of-line 'fancy)
+                   (fancy
                     (flymake--eol-draw-fancy diags #'summarize))
-                   (t
-                    (mapconcat #'summarize diags " ")))
-             "\n")))
-      (put-text-property 0 1 'cursor t summary)
-      summary)))
+                   (eol
+                    (mapconcat #'summarize diags " "))))))
+      (when summary
+        (setq summary (concat "  " summary "\n"))
+        (put-text-property 0 1 'cursor t summary)
+        summary))))
 
 (defun flymake--eol-draw-fancy-1 (text boxdraw-face line-beg-col
                                        height-to-clear
@@ -2339,13 +2446,13 @@ some of this variable's contents the diagnostic listings.")
        (insert
         (propertize
          (cond ;; ((zerop i) "┬")
-          ((memq c '(?└ ?├)) fork)
+          ((memq c '(?╰ ?├)) fork)
           (t         pipe))
          'face boxdraw-face)))
      (onward))
     (move line-beg-col)
     (delete-char -1)
-    (insert (propertize "└" 'face boxdraw-face))
+    (insert (propertize "╰" 'face boxdraw-face))
     (insert (propertize (make-string (- text-beg-col line-beg-col 1)
                                      ?─)
                         'face boxdraw-face))
@@ -2366,21 +2473,22 @@ some of this variable's contents the diagnostic listings.")
      with sorted = (cl-sort diags #'> :key #'flymake-diagnostic-beg)
      for diag in sorted
      for text = (funcall summarize-fn diag)
+     for beg = (flymake-diagnostic-beg diag)
+     for prev-line-beg-col = nil then line-beg-col
      for line-beg-col =
      (with-current-buffer (flymake-diagnostic-buffer diag)
-       (save-excursion
-         (goto-char (flymake-diagnostic-beg diag))
-         (1+ (current-column))))
+       (save-excursion (goto-char beg) (1+ (current-column))))
      for height-to-clear = 0 then ret
      for i from 0
-     for adjust = (* i 2)
+     for prev-adjust = 0 then adjust
+     for adjust = (+ prev-adjust (if (eql line-beg-col prev-line-beg-col) 0 2))
      for face = `(:foreground
                   ,(face-attribute
                     (or (get-text-property 0 'face text)
                         'flymake-error)
                     :foreground nil t))
-     for text-beg-col = (max (- (max 30 (+ line-beg-col 5)) adjust) (+ line-beg-col 1))
-     for text-end-col = (max 100 (+ text-beg-col 40))
+     for text-beg-col = (max (- (max 25 (+ line-beg-col 3)) adjust) (+ line-beg-col 1))
+     for text-end-col = (max 80 (+ text-beg-col 50))
      for ret = (flymake--eol-draw-fancy-1
                 text
                 face
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.