diff options
| author | João Távora | 2025-04-18 19:43:45 +0100 |
|---|---|---|
| committer | João Távora | 2025-04-20 23:20:33 +0100 |
| commit | ed1311a62a4e02817e548b0873ab21114047c076 (patch) | |
| tree | f8cde8c3473983e5f1d3fae93be54a6cb5b36c0b | |
| parent | 0fe05a920adc457d6f4adca71979059b8e2d0253 (diff) | |
| download | emacs-ed1311a62a4e02817e548b0873ab21114047c076.tar.gz emacs-ed1311a62a4e02817e548b0873ab21114047c076.zip | |
Flymake: new flymake-diagnostic-format-alist (bug#77439, bug#77480)
* lisp/progmodes/flymake.el (flymake-diagnostic-text): Overhaul.
(flymake-diagnostic-format-alist): New defcustom.
(flymake--diagnostic-format): New util.
(flymake--eol-overlay-summary)
(flymake--highlight-line)
(flymake-eldoc-function): Use flymake--diagnostic-format.
(flymake--tabulated-diagnostic-origin): New helper.
(flymake--tabulated-entries-1): Use flymake--tabulated-diagnostic-origin.
(flymake--diagnostics-base-tabulated-list-format): "Backend" -> "Origin"
* doc/misc/flymake.texi (Customizable variable): Mention new variable.
| -rw-r--r-- | doc/misc/flymake.texi | 3 | ||||
| -rw-r--r-- | lisp/progmodes/flymake.el | 116 |
2 files changed, 93 insertions, 26 deletions
diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi index 0e43df17aa2..dd60e0a1bca 100644 --- a/doc/misc/flymake.texi +++ b/doc/misc/flymake.texi | |||
| @@ -351,6 +351,9 @@ distracting and easily confused with actual code, or a significant | |||
| 351 | early aid that relieves you from moving around or reaching for the | 351 | early aid that relieves you from moving around or reaching for the |
| 352 | mouse to consult an error message. | 352 | mouse to consult an error message. |
| 353 | 353 | ||
| 354 | @item flymake-diagnostic-format-alist | ||
| 355 | Control which parts of a diagnostic to show in various situations. | ||
| 356 | |||
| 354 | @item flymake-error-eol | 357 | @item flymake-error-eol |
| 355 | A custom face for summarizing diagnostic error messages. | 358 | A custom face for summarizing diagnostic error messages. |
| 356 | 359 | ||
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index e63b7ed1675..f2f59f05131 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el | |||
| @@ -449,30 +449,88 @@ diagnostics at BEG." | |||
| 449 | (flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) | 449 | (flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) |
| 450 | (flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) | 450 | (flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) |
| 451 | 451 | ||
| 452 | (defun flymake-diagnostic-text (diag) | 452 | (defcustom flymake-diagnostic-format-alist |
| 453 | "Get Flymake diagnostic DIAG's text." | 453 | '((:help-echo . (origin code oneliner)) |
| 454 | (let ((a (flymake--diag-origin diag)) | 454 | (:eol . (oneliner)) |
| 455 | (b (flymake--diag-code diag)) | 455 | (:eldoc . (origin code message)) |
| 456 | (c (flymake--diag-message diag))) | 456 | (:eldoc-echo . (origin code oneliner)) |
| 457 | (t . (origin code oneliner))) | ||
| 458 | "How to format diagnostics for different output destinations. | ||
| 459 | Value is an alist where each element looks like (DESTINATION . PARTS). | ||
| 460 | DESTINATION is a symbol designating an outlet. One of: | ||
| 461 | |||
| 462 | - `:help-echo', for the native Flymake echoing of diagnostics in the | ||
| 463 | echo area as used my `flymake-goto-next-error' and `flymake-goto-prev-error'; | ||
| 464 | - `:eol', for use with `flymake-show-diagnostics-at-end-of-line'; | ||
| 465 | - `:eldoc', for use with Flymake's ElDoc backend; | ||
| 466 | - `:eldoc-echo', for use with Flymake's ElDoc backend, but for ElDoc's own | ||
| 467 | confined outlets; | ||
| 468 | - t for all other destinations. | ||
| 469 | |||
| 470 | PARTS says which parts of the diagnostic to include. It is a list of | ||
| 471 | symbols where the following values are meaningful: | ||
| 472 | |||
| 473 | - `origin': include diagnostic origin if it exists; | ||
| 474 | - `code': include diagnostics code if it exists; | ||
| 475 | - `message': include the full diagnostic's message text; | ||
| 476 | - `oneliner': include truncated diagnostic text;" | ||
| 477 | :package-version '(Flymake . "1.4.0") | ||
| 478 | :type '(alist :key-type (choice (const :help-echo) | ||
| 479 | (const :eol) | ||
| 480 | (const :eldoc) | ||
| 481 | (const :eldoc-echo) | ||
| 482 | (const t)) | ||
| 483 | :value-type (set (const origin) | ||
| 484 | (const code) | ||
| 485 | (const message) | ||
| 486 | (const oneliner)))) | ||
| 487 | |||
| 488 | (cl-defun flymake-diagnostic-text (diag | ||
| 489 | &optional (parts '(origin code message))) | ||
| 490 | "Describe diagnostic DIAG's as a string. | ||
| 491 | PARTS says which parts of the diagnostic to include. It is a list of | ||
| 492 | symbols as described in `flymake-diagnostic-format-alist' (which see). | ||
| 493 | PARTS defaults to `(origin code message)'." | ||
| 494 | (let* ((w parts) | ||
| 495 | (a (and (memq 'origin w) (flymake--diag-origin diag))) | ||
| 496 | (b (and (memq 'code w) (flymake--diag-code diag))) | ||
| 497 | (c (cond ((memq 'message w) (flymake--diag-message diag)) | ||
| 498 | ((memq 'oneliner w) | ||
| 499 | (let* ((msg (flymake--diag-message diag))) | ||
| 500 | (substring msg 0 (cl-loop for i from 0 for a across msg | ||
| 501 | when (eq a ?\n) return i))))))) | ||
| 457 | (concat a | 502 | (concat a |
| 458 | (when (and a b) " ") | 503 | (when (and a b) " ") |
| 459 | (when b (concat "[" b "]")) | 504 | (when b (concat "[" b "]")) |
| 460 | (when (and c (or a b)) ": ") | 505 | (when (and c (or a b)) ": ") |
| 461 | c))) | 506 | c))) |
| 462 | 507 | ||
| 508 | (defun flymake--format-diagnostic (diag destination face-prop) | ||
| 509 | (let ((txt (flymake-diagnostic-text | ||
| 510 | diag (alist-get destination flymake-diagnostic-format-alist | ||
| 511 | (alist-get t flymake-diagnostic-format-alist | ||
| 512 | '(origin code message)))))) | ||
| 513 | (if face-prop | ||
| 514 | (propertize txt 'face | ||
| 515 | (flymake--lookup-type-property | ||
| 516 | (flymake-diagnostic-type diag) face-prop | ||
| 517 | 'flymake-error)) | ||
| 518 | txt))) | ||
| 519 | |||
| 463 | (defun flymake-diagnostic-oneliner (diag &optional nopaintp) | 520 | (defun flymake-diagnostic-oneliner (diag &optional nopaintp) |
| 464 | "Get truncated one-line text string for diagnostic DIAG. | 521 | "Get truncated one-line text string for diagnostic DIAG. |
| 465 | This is useful for displaying the DIAG's text to the user in | 522 | This is useful for displaying the DIAG's text to the user in |
| 466 | confined spaces, such as the echo are. Unless NOPAINTP is t, | 523 | confined spaces, such as the echo are. Unless NOPAINTP is t, |
| 467 | propertize returned text with the `echo-face' property of DIAG's | 524 | propertize returned text with the `echo-face' property of DIAG's |
| 468 | type." | 525 | type." |
| 469 | (let* ((txt (flymake-diagnostic-text diag)) | 526 | (let* ((txt (flymake-diagnostic-text diag '(origin code oneliner)))) |
| 470 | (txt (substring txt 0 (cl-loop for i from 0 for a across txt | ||
| 471 | when (eq a ?\n) return i)))) | ||
| 472 | (if nopaintp txt | 527 | (if nopaintp txt |
| 473 | (propertize txt 'face | 528 | (propertize txt 'face |
| 474 | (flymake--lookup-type-property | 529 | (flymake--lookup-type-property |
| 475 | (flymake-diagnostic-type diag) 'echo-face 'flymake-error))))) | 530 | (flymake-diagnostic-type diag) 'echo-face 'flymake-error))))) |
| 531 | (make-obsolete 'flymake-diagnostic-oneliner | ||
| 532 | "use `flymake-diagnostic-text' instead." | ||
| 533 | "Flymake package version 1.4.0") | ||
| 476 | 534 | ||
| 477 | (cl-defun flymake--really-all-overlays () | 535 | (cl-defun flymake--really-all-overlays () |
| 478 | "Get flymake-related overlays. | 536 | "Get flymake-related overlays. |
| @@ -849,9 +907,7 @@ Return to original margin width if ORIG-WIDTH is non-nil." | |||
| 849 | (defun flymake--eol-overlay-summary (src-ovs) | 907 | (defun flymake--eol-overlay-summary (src-ovs) |
| 850 | "Helper function for `flymake--update-eol-overlays'." | 908 | "Helper function for `flymake--update-eol-overlays'." |
| 851 | (cl-flet ((summarize (d) | 909 | (cl-flet ((summarize (d) |
| 852 | (propertize (flymake-diagnostic-oneliner d t) 'face | 910 | (flymake--format-diagnostic d :eol 'eol-face))) |
| 853 | (flymake--lookup-type-property (flymake--diag-type d) | ||
| 854 | 'eol-face)))) | ||
| 855 | (let* ((diags | 911 | (let* ((diags |
| 856 | (cl-sort | 912 | (cl-sort |
| 857 | (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs) | 913 | (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs) |
| @@ -978,7 +1034,8 @@ Return nil or the overlay created." | |||
| 978 | (lambda (window _ov pos) | 1034 | (lambda (window _ov pos) |
| 979 | (with-selected-window window | 1035 | (with-selected-window window |
| 980 | (mapconcat | 1036 | (mapconcat |
| 981 | #'flymake-diagnostic-oneliner | 1037 | (lambda (d) |
| 1038 | (flymake--format-diagnostic d :help-echo 'echo-face)) | ||
| 982 | (flymake-diagnostics pos) | 1039 | (flymake-diagnostics pos) |
| 983 | "\n")))) | 1040 | "\n")))) |
| 984 | (default-maybe 'severity (warning-numeric-level :error)) | 1041 | (default-maybe 'severity (warning-numeric-level :error)) |
| @@ -1584,9 +1641,13 @@ START and STOP and LEN are as in `after-change-functions'." | |||
| 1584 | Intended for `eldoc-documentation-functions' (which see)." | 1641 | Intended for `eldoc-documentation-functions' (which see)." |
| 1585 | (when-let* ((diags (flymake-diagnostics (point)))) | 1642 | (when-let* ((diags (flymake-diagnostics (point)))) |
| 1586 | (funcall report-doc | 1643 | (funcall report-doc |
| 1587 | (mapconcat #'flymake-diagnostic-text diags "\n") | 1644 | (mapconcat (lambda (d) |
| 1588 | :echo (mapconcat #'flymake-diagnostic-oneliner | 1645 | (flymake--format-diagnostic d :eldoc 'echo-face)) |
| 1589 | diags "\n")))) | 1646 | diags "\n") |
| 1647 | :echo (mapconcat | ||
| 1648 | (lambda (d) | ||
| 1649 | (flymake--format-diagnostic d :eldoc-echo 'echo-face)) | ||
| 1650 | diags "\n")))) | ||
| 1590 | 1651 | ||
| 1591 | (defun flymake-goto-next-error (&optional n filter interactive) | 1652 | (defun flymake-goto-next-error (&optional n filter interactive) |
| 1592 | "Go to Nth next Flymake diagnostic that matches FILTER. | 1653 | "Go to Nth next Flymake diagnostic that matches FILTER. |
| @@ -1944,6 +2005,16 @@ POS can be a buffer position or a button" | |||
| 1944 | (pop-to-buffer | 2005 | (pop-to-buffer |
| 1945 | (flymake-show-diagnostic (if (button-type pos) (button-start pos) pos)))) | 2006 | (flymake-show-diagnostic (if (button-type pos) (button-start pos) pos)))) |
| 1946 | 2007 | ||
| 2008 | (defun flymake--tabulated-diagnostic-origin (diag) | ||
| 2009 | (or (flymake-diagnostic-origin diag) | ||
| 2010 | (let* ((backend (flymake-diagnostic-backend diag)) | ||
| 2011 | (bname (or (ignore-errors (symbol-name backend)) | ||
| 2012 | "(anonymous function)"))) | ||
| 2013 | (propertize | ||
| 2014 | (replace-regexp-in-string "\\(.\\)[^-]+\\(-\\|$\\)" | ||
| 2015 | "\\1\\2" bname) | ||
| 2016 | 'help-echo (format "From `%s' backend" backend))))) | ||
| 2017 | |||
| 1947 | (defun flymake--tabulated-entries-1 (diags project-root) | 2018 | (defun flymake--tabulated-entries-1 (diags project-root) |
| 1948 | "Helper for `flymake--diagnostics-buffer-entries'. | 2019 | "Helper for `flymake--diagnostics-buffer-entries'. |
| 1949 | PROJECT-ROOT indicates that each entry should be preceded by the | 2020 | PROJECT-ROOT indicates that each entry should be preceded by the |
| @@ -1973,9 +2044,7 @@ filename of the diagnostic relative to that directory." | |||
| 1973 | (;; somehow dead annotated diagnostic, ignore/give up | 2044 | (;; somehow dead annotated diagnostic, ignore/give up |
| 1974 | t nil)) | 2045 | t nil)) |
| 1975 | for type = (flymake-diagnostic-type diag) | 2046 | for type = (flymake-diagnostic-type diag) |
| 1976 | for backend = (flymake-diagnostic-backend diag) | 2047 | for origin = (flymake--tabulated-diagnostic-origin diag) |
| 1977 | for bname = (or (ignore-errors (symbol-name backend)) | ||
| 1978 | "(anonymous function)") | ||
| 1979 | for data-vec = `[,(format "%s" line) | 2048 | for data-vec = `[,(format "%s" line) |
| 1980 | ,(format "%s" col) | 2049 | ,(format "%s" col) |
| 1981 | ,(propertize (format "%s" | 2050 | ,(propertize (format "%s" |
| @@ -1983,13 +2052,8 @@ filename of the diagnostic relative to that directory." | |||
| 1983 | type 'flymake-type-name type)) | 2052 | type 'flymake-type-name type)) |
| 1984 | 'face (flymake--lookup-type-property | 2053 | 'face (flymake--lookup-type-property |
| 1985 | type 'mode-line-face 'flymake-error)) | 2054 | type 'mode-line-face 'flymake-error)) |
| 1986 | ,(propertize | 2055 | ,origin |
| 1987 | (if bname | 2056 | (,(flymake-diagnostic-text diag '(oneliner)) |
| 1988 | (replace-regexp-in-string "\\(.\\)[^-]+\\(-\\|$\\)" | ||
| 1989 | "\\1\\2" bname) | ||
| 1990 | "(anon)") | ||
| 1991 | 'help-echo (format "From `%s' backend" backend)) | ||
| 1992 | (,(flymake-diagnostic-oneliner diag t) | ||
| 1993 | mouse-face highlight | 2057 | mouse-face highlight |
| 1994 | help-echo "mouse-2: visit this diagnostic" | 2058 | help-echo "mouse-2: visit this diagnostic" |
| 1995 | face nil | 2059 | face nil |
| @@ -2035,7 +2099,7 @@ buffer." | |||
| 2035 | ("Type" 8 ,(lambda (l1 l2) | 2099 | ("Type" 8 ,(lambda (l1 l2) |
| 2036 | (< (plist-get (car l1) :severity) | 2100 | (< (plist-get (car l1) :severity) |
| 2037 | (plist-get (car l2) :severity)))) | 2101 | (plist-get (car l2) :severity)))) |
| 2038 | ("Backend" 8 t) | 2102 | ("Origin" 8 t) |
| 2039 | ("Message" 0 t)]) | 2103 | ("Message" 0 t)]) |
| 2040 | 2104 | ||
| 2041 | (define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode | 2105 | (define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode |