]> git.eshelyaron.com Git - emacs.git/commitdiff
Flymake: add new flymake-show-diagnostics-at-end-of-line option
authorJoão Távora <joaotavora@gmail.com>
Thu, 2 Mar 2023 22:55:31 +0000 (22:55 +0000)
committerJoão Távora <joaotavora@gmail.com>
Thu, 13 Apr 2023 16:42:37 +0000 (17:42 +0100)
Some editors have this.  Depending on your preference, this can either
be wildly 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.  To be safe, hide this
behind a customization variable and keep it disabled.

Personally, I find it less obstrusive and more helpful than expected.

* lisp/progmodes/flymake.el (flymake--delete-overlay): New helper.
(flymake--highlight-line): Handle flymake-show-diagnostics-at-end-of-line.
(flymake--clear-foreign-diags): Use flymake--delete-overlay.
(flymake--publish-diagnostics): Use flymake--delete-overlay.
(flymake-mode): Use flymake--delete-overlay.
(flymake-error-echo)
(flymake-warning-echo, flymake-note-echo): New faces.
(flymake-show-diagnostics-at-end-of-line): New option.
(Version): Bump to 1.3.4

* doc/misc/flymake.texi:
(Finding diagnostics): Mention flymake-show-diagnostics-at-end-of-line.
(Customizable variables): Mention
flymake-show-diagnostics-at-end-of-line and a few more relevant faces.

* etc/NEWS (Flymake): Mention flymake-show-diagnostics-at-end-of-line.

doc/misc/flymake.texi
etc/NEWS
lisp/progmodes/flymake.el

index 13616f39f16c8d8c188597874957eee54ebfd72b..304a7d29ecea797462d5a5ae7ee49e590c17e44c 100644 (file)
@@ -1,7 +1,7 @@
 \input texinfo   @c -*- mode: texinfo; coding: utf-8 -*-
 @comment %**start of header
 @setfilename ../../info/flymake.info
-@set VERSION 1.3.3
+@set VERSION 1.3.4
 @set UPDATED April 2023
 @settitle GNU Flymake @value{VERSION}
 @include docstyle.texi
@@ -142,6 +142,12 @@ highlighted regions to learn what the specific problem
 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})
+
 @cindex next and previous diagnostic
 If the diagnostics are outside the visible region of the buffer,
 @code{flymake-goto-next-error} and @code{flymake-goto-prev-error} are
@@ -316,6 +322,23 @@ If non-@code{nil}, moving to errors with @code{flymake-goto-next-error} and
 @code{flymake-goto-prev-error} wraps around buffer boundaries.
 @end vtable
 
+@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.
+
+@item flymake-error-eol
+A custom face for summarizing diagnostic error messages.
+
+@item flymake-warning-eol
+A custom face for summarizing diagnostic warning messages.
+
+@item flymake-note-eol
+A custom face for summarizing diagnostic notes.
+@end vtable
+
 @node Extending Flymake
 @chapter Extending Flymake
 @cindex extending flymake
index 5e1fd76e99e2eb7ca7c9a23ca9a55629fe01290b..611dcf3dc7d4d943d5cc7675691b4af374b7d97e 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -259,13 +259,21 @@ following to your init file:
               #'shortdoc-help-fns-examples-function)
 
 ** Package
-
 ---
 *** New user option 'package-vc-register-as-project'.
 When non-nil, it will automatically register every package as a
 project, that you can quickly select using 'project-switch-project'
 ('C-x p p').
 
+** Flymake
++++
+*** New user option 'flymake-show-diagnostics-at-end-of-line'.
+When non-nil, Flymake shows 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 the buffer or reaching for the
+mouse to consult an error message.
+
 \f
 * New Modes and Packages in Emacs 30.1
 
index c751e5bd432dd4f3925e46a7d9deb3b01f1ba696..f2fe97cb7736c3fe34c61493c64bf1993a3c3a02 100644 (file)
@@ -4,7 +4,7 @@
 
 ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
 ;; Maintainer: João Távora <joaotavora@gmail.com>
-;; Version: 1.3.3
+;; Version: 1.3.4
 ;; Keywords: c languages tools
 ;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1"))
 
@@ -431,6 +431,26 @@ verify FILTER, a function, and sort them by COMPARE (using KEY)."
   "Face used for marking note regions."
   :version "26.1")
 
+(defface flymake-error-echo
+  '((t :inherit compilation-error))
+  "Face used for showing summarized descriptions of errors."
+  :package-version '("Flymake" . "1.3.4"))
+
+(defface flymake-warning-echo
+  '((t :inherit compilation-warning))
+  "Face used for showing summarized descriptions of warnings."
+  :package-version '("Flymake" . "1.3.4"))
+
+(defface flymake-note-echo
+  '((t :inherit flymake-note))
+  "Face used for showing summarized descriptions of notes."
+  :package-version '("Flymake" . "1.3.4"))
+
+(defcustom flymake-show-diagnostics-at-end-of-line nil
+  "If non-nil, add diagnostic summary messages at end-of-line."
+  :type 'boolean
+  :package-version '("Flymake" . "1.3.4"))
+
 (define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1")
 (define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1")
 
@@ -584,22 +604,25 @@ Node `(Flymake)Flymake error types'"
 (put 'flymake-error 'face 'flymake-error)
 (put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap)
 (put 'flymake-error 'severity (warning-numeric-level :error))
-(put 'flymake-error 'mode-line-face 'compilation-error)
-(put 'flymake-error 'echo-face 'error)
+(put 'flymake-error 'mode-line-face 'flymake-error-echo)
+(put 'flymake-error 'echo-face 'flymake-error-echo)
+(put 'flymake-error 'eol-face 'flymake-error-echo)
 (put 'flymake-error 'flymake-type-name "error")
 
 (put 'flymake-warning 'face 'flymake-warning)
 (put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap)
 (put 'flymake-warning 'severity (warning-numeric-level :warning))
-(put 'flymake-warning 'mode-line-face 'compilation-warning)
-(put 'flymake-warning 'echo-face 'warning)
+(put 'flymake-warning 'mode-line-face 'flymake-warning-echo)
+(put 'flymake-warning 'echo-face 'flymake-warning-echo)
+(put 'flymake-warning 'eol-face 'flymake-warning-echo)
 (put 'flymake-warning 'flymake-type-name "warning")
 
 (put 'flymake-note 'face 'flymake-note)
 (put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap)
 (put 'flymake-note 'severity (warning-numeric-level :debug))
-(put 'flymake-note 'mode-line-face 'compilation-info)
-(put 'flymake-note 'echo-face 'compilation-info)
+(put 'flymake-note 'mode-line-face 'flymake-note-echo)
+(put 'flymake-note 'echo-face 'flymake-note-echo)
+(put 'flymake-note 'eol-face 'flymake-note-echo)
 (put 'flymake-note 'flymake-type-name "note")
 
 (defun flymake--lookup-type-property (type prop &optional default)
@@ -656,6 +679,12 @@ associated `flymake-category' return DEFAULT."
                              flymake-diagnostic-text)
                always (equal (funcall comp a) (funcall comp b)))))
 
+(defun flymake--delete-overlay (ov)
+  "Like `delete-overlay', delete OV, but do some more stuff."
+  (let ((eolov (overlay-get ov 'eol-ov)))
+    (when eolov (delete-overlay eolov))
+    (delete-overlay ov)))
+
 (cl-defun flymake--highlight-line (diagnostic &optional foreign)
   "Attempt to overlay DIAGNOSTIC in current buffer.
 
@@ -695,6 +724,7 @@ Return nil or the overlay created."
     ;; diagnostic is already registered in the same place, which only
     ;; happens for clashes between domestic and foreign diagnostics
     (cl-loop for e in (flymake-diagnostics beg end)
+             for eov = (flymake--diag-overlay e)
              when (flymake--equal-diagnostic-p e diagnostic)
              ;; FIXME.  This is an imperfect heuristic.  Ideally, we'd
              ;; want to delete no overlays and keep annotating the
@@ -710,7 +740,7 @@ Return nil or the overlay created."
                         (flymake--diag-orig-beg e)
                         (flymake--diag-end e)
                         (flymake--diag-orig-end e))
-                  (delete-overlay (flymake--diag-overlay e))))
+                  (flymake--delete-overlay eov)))
     (setq ov (make-overlay end beg))
     (setf (flymake--diag-beg diagnostic) (overlay-start ov)
           (flymake--diag-end diagnostic) (overlay-end ov))
@@ -728,6 +758,37 @@ Return nil or the overlay created."
               (flymake--lookup-type-property type 'flymake-overlay-control))
              (alist-get type flymake-diagnostic-types-alist))
      do (overlay-put ov ov-prop value))
+    ;; Handle `flymake-show-diagnostics-at-end-of-line'
+    ;;
+    (when-let ((eol-face (and flymake-show-diagnostics-at-end-of-line
+                              (flymake--lookup-type-property type 'eol-face))))
+      (save-excursion
+        (goto-char (overlay-start ov))
+        (let* ((start (line-end-position))
+               (end (min (1+ start) (point-max)))
+               (eolov (car
+                       (cl-remove-if-not
+                        (lambda (o) (overlay-get o 'flymake-source-ovs))
+                        (overlays-at start))))
+               (bs (flymake-diagnostic-oneliner diagnostic t)))
+          (setq bs (propertize bs 'face eol-face))
+          ;; FIXME: 1. no checking if there are unexpectedly more than
+          ;; one eolov at point.  2. The first regular source ov to
+          ;; die also kills the eolov (very rare this matters, but
+          ;; could be improved).
+          (cond (eolov
+                 (overlay-put eolov 'before-string
+                              (concat (overlay-get eolov 'before-string) " " bs))
+                 (overlay-put eolov 'flymake-source-ovs
+                              (cons ov (overlay-get eolov 'flymake-source-ovs))))
+                (t
+                 (setq eolov (make-overlay start end nil t nil))
+                 (setq bs (concat "   " bs))
+                 (put-text-property 0 1 'cursor t bs)
+                 (overlay-put eolov 'before-string bs)
+                 (overlay-put eolov 'evaporate (not (= start end)))
+                 (overlay-put eolov 'flymake-source-ovs (list ov))
+                 (overlay-put ov 'eol-ov eolov))))))
     ;; Now ensure some essential defaults are set
     ;;
     (cl-flet ((default-maybe
@@ -743,6 +804,8 @@ Return nil or the overlay created."
           'flymake-bitmap
           (alist-get 'bitmap (alist-get type ; backward compat
                                         flymake-diagnostic-types-alist)))))
+      ;; (default-maybe 'after-string
+      ;;                (flymake--diag-text diagnostic))
       (default-maybe 'help-echo
         (lambda (window _ov pos)
           (with-selected-window window
@@ -873,7 +936,7 @@ report applies to that region."
   (maphash (lambda (_buffer diags)
              (cl-loop for d in diags
                       when (flymake--diag-overlay d)
-                      do (delete-overlay it)))
+                      do (flymake--delete-overlay it)))
            (flymake--state-foreign-diags state))
   (clrhash (flymake--state-foreign-diags state)))
 
@@ -900,7 +963,7 @@ and other buffers."
                       (flymake--intersects-p
                        (overlay-start ov) (overlay-end ov)
                        (car region) (cdr region)))
-               do (delete-overlay ov)
+               do (flymake--delete-overlay ov)
                else collect diag into surviving
                finally (setf (flymake--state-diags state)
                              surviving)))
@@ -909,7 +972,7 @@ and other buffers."
       (not (flymake--state-reported-p state))
       (cl-loop for diag in (flymake--state-diags state)
                for ov = (flymake--diag-overlay diag)
-               when ov do (delete-overlay ov))
+               when ov do (flymake--delete-overlay ov))
       (setf (flymake--state-diags state) nil)
       ;; Also clear all overlays for `foreign-diags' in all other
       ;; buffers.
@@ -1153,7 +1216,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     ;; existing diagnostic overlays, lest we forget them by blindly
     ;; reinitializing `flymake--state' in the next line.
     ;; See https://github.com/joaotavora/eglot/issues/223.
-    (mapc #'delete-overlay (flymake--overlays))
+    (mapc #'flymake--delete-overlay (flymake--overlays))
     (setq flymake--state (make-hash-table))
     (setq flymake--recent-changes nil)
 
@@ -1200,7 +1263,7 @@ special *Flymake log* buffer."  :group 'flymake :lighter
     (when flymake-timer
       (cancel-timer flymake-timer)
       (setq flymake-timer nil))
-    (mapc #'delete-overlay (flymake--overlays))
+    (mapc #'flymake--delete-overlay (flymake--overlays))
     (when flymake--state
       (maphash (lambda (_backend state)
                  (flymake--clear-foreign-diags state))