diff options
| author | João Távora | 2023-03-02 22:55:31 +0000 |
|---|---|---|
| committer | João Távora | 2023-04-13 17:42:37 +0100 |
| commit | d45f450cff757ed520a7ee36c632ab62387c7bc9 (patch) | |
| tree | 7ce124c795aa77a80780c741de48ce36855ffbe5 | |
| parent | d590af749f18ea3b82e46bb498568c77a2640d29 (diff) | |
| download | emacs-d45f450cff757ed520a7ee36c632ab62387c7bc9.tar.gz emacs-d45f450cff757ed520a7ee36c632ab62387c7bc9.zip | |
Flymake: add new flymake-show-diagnostics-at-end-of-line option
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.
| -rw-r--r-- | doc/misc/flymake.texi | 25 | ||||
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/progmodes/flymake.el | 89 |
3 files changed, 109 insertions, 15 deletions
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi index 13616f39f16..304a7d29ece 100644 --- a/doc/misc/flymake.texi +++ b/doc/misc/flymake.texi | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | \input texinfo @c -*- mode: texinfo; coding: utf-8 -*- | 1 | \input texinfo @c -*- mode: texinfo; coding: utf-8 -*- |
| 2 | @comment %**start of header | 2 | @comment %**start of header |
| 3 | @setfilename ../../info/flymake.info | 3 | @setfilename ../../info/flymake.info |
| 4 | @set VERSION 1.3.3 | 4 | @set VERSION 1.3.4 |
| 5 | @set UPDATED April 2023 | 5 | @set UPDATED April 2023 |
| 6 | @settitle GNU Flymake @value{VERSION} | 6 | @settitle GNU Flymake @value{VERSION} |
| 7 | @include docstyle.texi | 7 | @include docstyle.texi |
| @@ -142,6 +142,12 @@ highlighted regions to learn what the specific problem | |||
| 142 | is. Alternatively, place point on the highlighted regions and use the | 142 | is. Alternatively, place point on the highlighted regions and use the |
| 143 | commands @code{eldoc} or @code{display-local-help}. | 143 | commands @code{eldoc} or @code{display-local-help}. |
| 144 | 144 | ||
| 145 | Another easy way to get instant access to the diagnostic text is to | ||
| 146 | set @code{flymake-show-diagnostics-at-end-of-line} to a non-@code{nil} | ||
| 147 | value. This makes the diagnostic messages appear at the end of the | ||
| 148 | line where the regular annotation is located (@pxref{Customizable | ||
| 149 | variables}) | ||
| 150 | |||
| 145 | @cindex next and previous diagnostic | 151 | @cindex next and previous diagnostic |
| 146 | If the diagnostics are outside the visible region of the buffer, | 152 | If the diagnostics are outside the visible region of the buffer, |
| 147 | @code{flymake-goto-next-error} and @code{flymake-goto-prev-error} are | 153 | @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 | |||
| 316 | @code{flymake-goto-prev-error} wraps around buffer boundaries. | 322 | @code{flymake-goto-prev-error} wraps around buffer boundaries. |
| 317 | @end vtable | 323 | @end vtable |
| 318 | 324 | ||
| 325 | @item flymake-show-diagnostics-at-end-of-line | ||
| 326 | If non-@code{nil}, show summarized descriptions of diagnostics at the | ||
| 327 | end of the line. Depending on your preference, this can either be | ||
| 328 | distracting and easily confused with actual code, or a significant | ||
| 329 | early aid that relieves you from moving around or reaching for the | ||
| 330 | mouse to consult an error message. | ||
| 331 | |||
| 332 | @item flymake-error-eol | ||
| 333 | A custom face for summarizing diagnostic error messages. | ||
| 334 | |||
| 335 | @item flymake-warning-eol | ||
| 336 | A custom face for summarizing diagnostic warning messages. | ||
| 337 | |||
| 338 | @item flymake-note-eol | ||
| 339 | A custom face for summarizing diagnostic notes. | ||
| 340 | @end vtable | ||
| 341 | |||
| 319 | @node Extending Flymake | 342 | @node Extending Flymake |
| 320 | @chapter Extending Flymake | 343 | @chapter Extending Flymake |
| 321 | @cindex extending flymake | 344 | @cindex extending flymake |
| @@ -259,13 +259,21 @@ following to your init file: | |||
| 259 | #'shortdoc-help-fns-examples-function) | 259 | #'shortdoc-help-fns-examples-function) |
| 260 | 260 | ||
| 261 | ** Package | 261 | ** Package |
| 262 | |||
| 263 | --- | 262 | --- |
| 264 | *** New user option 'package-vc-register-as-project'. | 263 | *** New user option 'package-vc-register-as-project'. |
| 265 | When non-nil, it will automatically register every package as a | 264 | When non-nil, it will automatically register every package as a |
| 266 | project, that you can quickly select using 'project-switch-project' | 265 | project, that you can quickly select using 'project-switch-project' |
| 267 | ('C-x p p'). | 266 | ('C-x p p'). |
| 268 | 267 | ||
| 268 | ** Flymake | ||
| 269 | +++ | ||
| 270 | *** New user option 'flymake-show-diagnostics-at-end-of-line'. | ||
| 271 | When non-nil, Flymake shows summarized descriptions of diagnostics at | ||
| 272 | the end of the line. Depending on your preference, this can either be | ||
| 273 | distracting and easily confused with actual code, or a significant | ||
| 274 | early aid that relieves you from moving the buffer or reaching for the | ||
| 275 | mouse to consult an error message. | ||
| 276 | |||
| 269 | 277 | ||
| 270 | * New Modes and Packages in Emacs 30.1 | 278 | * New Modes and Packages in Emacs 30.1 |
| 271 | 279 | ||
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index c751e5bd432..f2fe97cb773 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com> | 5 | ;; Author: Pavel Kobyakov <pk_at_work@yahoo.com> |
| 6 | ;; Maintainer: João Távora <joaotavora@gmail.com> | 6 | ;; Maintainer: João Távora <joaotavora@gmail.com> |
| 7 | ;; Version: 1.3.3 | 7 | ;; Version: 1.3.4 |
| 8 | ;; Keywords: c languages tools | 8 | ;; Keywords: c languages tools |
| 9 | ;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) | 9 | ;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) |
| 10 | 10 | ||
| @@ -431,6 +431,26 @@ verify FILTER, a function, and sort them by COMPARE (using KEY)." | |||
| 431 | "Face used for marking note regions." | 431 | "Face used for marking note regions." |
| 432 | :version "26.1") | 432 | :version "26.1") |
| 433 | 433 | ||
| 434 | (defface flymake-error-echo | ||
| 435 | '((t :inherit compilation-error)) | ||
| 436 | "Face used for showing summarized descriptions of errors." | ||
| 437 | :package-version '("Flymake" . "1.3.4")) | ||
| 438 | |||
| 439 | (defface flymake-warning-echo | ||
| 440 | '((t :inherit compilation-warning)) | ||
| 441 | "Face used for showing summarized descriptions of warnings." | ||
| 442 | :package-version '("Flymake" . "1.3.4")) | ||
| 443 | |||
| 444 | (defface flymake-note-echo | ||
| 445 | '((t :inherit flymake-note)) | ||
| 446 | "Face used for showing summarized descriptions of notes." | ||
| 447 | :package-version '("Flymake" . "1.3.4")) | ||
| 448 | |||
| 449 | (defcustom flymake-show-diagnostics-at-end-of-line nil | ||
| 450 | "If non-nil, add diagnostic summary messages at end-of-line." | ||
| 451 | :type 'boolean | ||
| 452 | :package-version '("Flymake" . "1.3.4")) | ||
| 453 | |||
| 434 | (define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1") | 454 | (define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1") |
| 435 | (define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1") | 455 | (define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1") |
| 436 | 456 | ||
| @@ -584,22 +604,25 @@ Node `(Flymake)Flymake error types'" | |||
| 584 | (put 'flymake-error 'face 'flymake-error) | 604 | (put 'flymake-error 'face 'flymake-error) |
| 585 | (put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap) | 605 | (put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap) |
| 586 | (put 'flymake-error 'severity (warning-numeric-level :error)) | 606 | (put 'flymake-error 'severity (warning-numeric-level :error)) |
| 587 | (put 'flymake-error 'mode-line-face 'compilation-error) | 607 | (put 'flymake-error 'mode-line-face 'flymake-error-echo) |
| 588 | (put 'flymake-error 'echo-face 'error) | 608 | (put 'flymake-error 'echo-face 'flymake-error-echo) |
| 609 | (put 'flymake-error 'eol-face 'flymake-error-echo) | ||
| 589 | (put 'flymake-error 'flymake-type-name "error") | 610 | (put 'flymake-error 'flymake-type-name "error") |
| 590 | 611 | ||
| 591 | (put 'flymake-warning 'face 'flymake-warning) | 612 | (put 'flymake-warning 'face 'flymake-warning) |
| 592 | (put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap) | 613 | (put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap) |
| 593 | (put 'flymake-warning 'severity (warning-numeric-level :warning)) | 614 | (put 'flymake-warning 'severity (warning-numeric-level :warning)) |
| 594 | (put 'flymake-warning 'mode-line-face 'compilation-warning) | 615 | (put 'flymake-warning 'mode-line-face 'flymake-warning-echo) |
| 595 | (put 'flymake-warning 'echo-face 'warning) | 616 | (put 'flymake-warning 'echo-face 'flymake-warning-echo) |
| 617 | (put 'flymake-warning 'eol-face 'flymake-warning-echo) | ||
| 596 | (put 'flymake-warning 'flymake-type-name "warning") | 618 | (put 'flymake-warning 'flymake-type-name "warning") |
| 597 | 619 | ||
| 598 | (put 'flymake-note 'face 'flymake-note) | 620 | (put 'flymake-note 'face 'flymake-note) |
| 599 | (put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap) | 621 | (put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap) |
| 600 | (put 'flymake-note 'severity (warning-numeric-level :debug)) | 622 | (put 'flymake-note 'severity (warning-numeric-level :debug)) |
| 601 | (put 'flymake-note 'mode-line-face 'compilation-info) | 623 | (put 'flymake-note 'mode-line-face 'flymake-note-echo) |
| 602 | (put 'flymake-note 'echo-face 'compilation-info) | 624 | (put 'flymake-note 'echo-face 'flymake-note-echo) |
| 625 | (put 'flymake-note 'eol-face 'flymake-note-echo) | ||
| 603 | (put 'flymake-note 'flymake-type-name "note") | 626 | (put 'flymake-note 'flymake-type-name "note") |
| 604 | 627 | ||
| 605 | (defun flymake--lookup-type-property (type prop &optional default) | 628 | (defun flymake--lookup-type-property (type prop &optional default) |
| @@ -656,6 +679,12 @@ associated `flymake-category' return DEFAULT." | |||
| 656 | flymake-diagnostic-text) | 679 | flymake-diagnostic-text) |
| 657 | always (equal (funcall comp a) (funcall comp b))))) | 680 | always (equal (funcall comp a) (funcall comp b))))) |
| 658 | 681 | ||
| 682 | (defun flymake--delete-overlay (ov) | ||
| 683 | "Like `delete-overlay', delete OV, but do some more stuff." | ||
| 684 | (let ((eolov (overlay-get ov 'eol-ov))) | ||
| 685 | (when eolov (delete-overlay eolov)) | ||
| 686 | (delete-overlay ov))) | ||
| 687 | |||
| 659 | (cl-defun flymake--highlight-line (diagnostic &optional foreign) | 688 | (cl-defun flymake--highlight-line (diagnostic &optional foreign) |
| 660 | "Attempt to overlay DIAGNOSTIC in current buffer. | 689 | "Attempt to overlay DIAGNOSTIC in current buffer. |
| 661 | 690 | ||
| @@ -695,6 +724,7 @@ Return nil or the overlay created." | |||
| 695 | ;; diagnostic is already registered in the same place, which only | 724 | ;; diagnostic is already registered in the same place, which only |
| 696 | ;; happens for clashes between domestic and foreign diagnostics | 725 | ;; happens for clashes between domestic and foreign diagnostics |
| 697 | (cl-loop for e in (flymake-diagnostics beg end) | 726 | (cl-loop for e in (flymake-diagnostics beg end) |
| 727 | for eov = (flymake--diag-overlay e) | ||
| 698 | when (flymake--equal-diagnostic-p e diagnostic) | 728 | when (flymake--equal-diagnostic-p e diagnostic) |
| 699 | ;; FIXME. This is an imperfect heuristic. Ideally, we'd | 729 | ;; FIXME. This is an imperfect heuristic. Ideally, we'd |
| 700 | ;; want to delete no overlays and keep annotating the | 730 | ;; want to delete no overlays and keep annotating the |
| @@ -710,7 +740,7 @@ Return nil or the overlay created." | |||
| 710 | (flymake--diag-orig-beg e) | 740 | (flymake--diag-orig-beg e) |
| 711 | (flymake--diag-end e) | 741 | (flymake--diag-end e) |
| 712 | (flymake--diag-orig-end e)) | 742 | (flymake--diag-orig-end e)) |
| 713 | (delete-overlay (flymake--diag-overlay e)))) | 743 | (flymake--delete-overlay eov))) |
| 714 | (setq ov (make-overlay end beg)) | 744 | (setq ov (make-overlay end beg)) |
| 715 | (setf (flymake--diag-beg diagnostic) (overlay-start ov) | 745 | (setf (flymake--diag-beg diagnostic) (overlay-start ov) |
| 716 | (flymake--diag-end diagnostic) (overlay-end ov)) | 746 | (flymake--diag-end diagnostic) (overlay-end ov)) |
| @@ -728,6 +758,37 @@ Return nil or the overlay created." | |||
| 728 | (flymake--lookup-type-property type 'flymake-overlay-control)) | 758 | (flymake--lookup-type-property type 'flymake-overlay-control)) |
| 729 | (alist-get type flymake-diagnostic-types-alist)) | 759 | (alist-get type flymake-diagnostic-types-alist)) |
| 730 | do (overlay-put ov ov-prop value)) | 760 | do (overlay-put ov ov-prop value)) |
| 761 | ;; Handle `flymake-show-diagnostics-at-end-of-line' | ||
| 762 | ;; | ||
| 763 | (when-let ((eol-face (and flymake-show-diagnostics-at-end-of-line | ||
| 764 | (flymake--lookup-type-property type 'eol-face)))) | ||
| 765 | (save-excursion | ||
| 766 | (goto-char (overlay-start ov)) | ||
| 767 | (let* ((start (line-end-position)) | ||
| 768 | (end (min (1+ start) (point-max))) | ||
| 769 | (eolov (car | ||
| 770 | (cl-remove-if-not | ||
| 771 | (lambda (o) (overlay-get o 'flymake-source-ovs)) | ||
| 772 | (overlays-at start)))) | ||
| 773 | (bs (flymake-diagnostic-oneliner diagnostic t))) | ||
| 774 | (setq bs (propertize bs 'face eol-face)) | ||
| 775 | ;; FIXME: 1. no checking if there are unexpectedly more than | ||
| 776 | ;; one eolov at point. 2. The first regular source ov to | ||
| 777 | ;; die also kills the eolov (very rare this matters, but | ||
| 778 | ;; could be improved). | ||
| 779 | (cond (eolov | ||
| 780 | (overlay-put eolov 'before-string | ||
| 781 | (concat (overlay-get eolov 'before-string) " " bs)) | ||
| 782 | (overlay-put eolov 'flymake-source-ovs | ||
| 783 | (cons ov (overlay-get eolov 'flymake-source-ovs)))) | ||
| 784 | (t | ||
| 785 | (setq eolov (make-overlay start end nil t nil)) | ||
| 786 | (setq bs (concat " " bs)) | ||
| 787 | (put-text-property 0 1 'cursor t bs) | ||
| 788 | (overlay-put eolov 'before-string bs) | ||
| 789 | (overlay-put eolov 'evaporate (not (= start end))) | ||
| 790 | (overlay-put eolov 'flymake-source-ovs (list ov)) | ||
| 791 | (overlay-put ov 'eol-ov eolov)))))) | ||
| 731 | ;; Now ensure some essential defaults are set | 792 | ;; Now ensure some essential defaults are set |
| 732 | ;; | 793 | ;; |
| 733 | (cl-flet ((default-maybe | 794 | (cl-flet ((default-maybe |
| @@ -743,6 +804,8 @@ Return nil or the overlay created." | |||
| 743 | 'flymake-bitmap | 804 | 'flymake-bitmap |
| 744 | (alist-get 'bitmap (alist-get type ; backward compat | 805 | (alist-get 'bitmap (alist-get type ; backward compat |
| 745 | flymake-diagnostic-types-alist))))) | 806 | flymake-diagnostic-types-alist))))) |
| 807 | ;; (default-maybe 'after-string | ||
| 808 | ;; (flymake--diag-text diagnostic)) | ||
| 746 | (default-maybe 'help-echo | 809 | (default-maybe 'help-echo |
| 747 | (lambda (window _ov pos) | 810 | (lambda (window _ov pos) |
| 748 | (with-selected-window window | 811 | (with-selected-window window |
| @@ -873,7 +936,7 @@ report applies to that region." | |||
| 873 | (maphash (lambda (_buffer diags) | 936 | (maphash (lambda (_buffer diags) |
| 874 | (cl-loop for d in diags | 937 | (cl-loop for d in diags |
| 875 | when (flymake--diag-overlay d) | 938 | when (flymake--diag-overlay d) |
| 876 | do (delete-overlay it))) | 939 | do (flymake--delete-overlay it))) |
| 877 | (flymake--state-foreign-diags state)) | 940 | (flymake--state-foreign-diags state)) |
| 878 | (clrhash (flymake--state-foreign-diags state))) | 941 | (clrhash (flymake--state-foreign-diags state))) |
| 879 | 942 | ||
| @@ -900,7 +963,7 @@ and other buffers." | |||
| 900 | (flymake--intersects-p | 963 | (flymake--intersects-p |
| 901 | (overlay-start ov) (overlay-end ov) | 964 | (overlay-start ov) (overlay-end ov) |
| 902 | (car region) (cdr region))) | 965 | (car region) (cdr region))) |
| 903 | do (delete-overlay ov) | 966 | do (flymake--delete-overlay ov) |
| 904 | else collect diag into surviving | 967 | else collect diag into surviving |
| 905 | finally (setf (flymake--state-diags state) | 968 | finally (setf (flymake--state-diags state) |
| 906 | surviving))) | 969 | surviving))) |
| @@ -909,7 +972,7 @@ and other buffers." | |||
| 909 | (not (flymake--state-reported-p state)) | 972 | (not (flymake--state-reported-p state)) |
| 910 | (cl-loop for diag in (flymake--state-diags state) | 973 | (cl-loop for diag in (flymake--state-diags state) |
| 911 | for ov = (flymake--diag-overlay diag) | 974 | for ov = (flymake--diag-overlay diag) |
| 912 | when ov do (delete-overlay ov)) | 975 | when ov do (flymake--delete-overlay ov)) |
| 913 | (setf (flymake--state-diags state) nil) | 976 | (setf (flymake--state-diags state) nil) |
| 914 | ;; Also clear all overlays for `foreign-diags' in all other | 977 | ;; Also clear all overlays for `foreign-diags' in all other |
| 915 | ;; buffers. | 978 | ;; buffers. |
| @@ -1153,7 +1216,7 @@ special *Flymake log* buffer." :group 'flymake :lighter | |||
| 1153 | ;; existing diagnostic overlays, lest we forget them by blindly | 1216 | ;; existing diagnostic overlays, lest we forget them by blindly |
| 1154 | ;; reinitializing `flymake--state' in the next line. | 1217 | ;; reinitializing `flymake--state' in the next line. |
| 1155 | ;; See https://github.com/joaotavora/eglot/issues/223. | 1218 | ;; See https://github.com/joaotavora/eglot/issues/223. |
| 1156 | (mapc #'delete-overlay (flymake--overlays)) | 1219 | (mapc #'flymake--delete-overlay (flymake--overlays)) |
| 1157 | (setq flymake--state (make-hash-table)) | 1220 | (setq flymake--state (make-hash-table)) |
| 1158 | (setq flymake--recent-changes nil) | 1221 | (setq flymake--recent-changes nil) |
| 1159 | 1222 | ||
| @@ -1200,7 +1263,7 @@ special *Flymake log* buffer." :group 'flymake :lighter | |||
| 1200 | (when flymake-timer | 1263 | (when flymake-timer |
| 1201 | (cancel-timer flymake-timer) | 1264 | (cancel-timer flymake-timer) |
| 1202 | (setq flymake-timer nil)) | 1265 | (setq flymake-timer nil)) |
| 1203 | (mapc #'delete-overlay (flymake--overlays)) | 1266 | (mapc #'flymake--delete-overlay (flymake--overlays)) |
| 1204 | (when flymake--state | 1267 | (when flymake--state |
| 1205 | (maphash (lambda (_backend state) | 1268 | (maphash (lambda (_backend state) |
| 1206 | (flymake--clear-foreign-diags state)) | 1269 | (flymake--clear-foreign-diags state)) |