aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2025-04-18 19:43:45 +0100
committerJoão Távora2025-04-20 23:20:33 +0100
commited1311a62a4e02817e548b0873ab21114047c076 (patch)
treef8cde8c3473983e5f1d3fae93be54a6cb5b36c0b
parent0fe05a920adc457d6f4adca71979059b8e2d0253 (diff)
downloademacs-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.texi3
-rw-r--r--lisp/progmodes/flymake.el116
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
351early aid that relieves you from moving around or reaching for the 351early aid that relieves you from moving around or reaching for the
352mouse to consult an error message. 352mouse to consult an error message.
353 353
354@item flymake-diagnostic-format-alist
355Control which parts of a diagnostic to show in various situations.
356
354@item flymake-error-eol 357@item flymake-error-eol
355A custom face for summarizing diagnostic error messages. 358A 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.
459Value is an alist where each element looks like (DESTINATION . PARTS).
460DESTINATION 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
470PARTS says which parts of the diagnostic to include. It is a list of
471symbols 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.
491PARTS says which parts of the diagnostic to include. It is a list of
492symbols as described in `flymake-diagnostic-format-alist' (which see).
493PARTS 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.
465This is useful for displaying the DIAG's text to the user in 522This is useful for displaying the DIAG's text to the user in
466confined spaces, such as the echo are. Unless NOPAINTP is t, 523confined spaces, such as the echo are. Unless NOPAINTP is t,
467propertize returned text with the `echo-face' property of DIAG's 524propertize returned text with the `echo-face' property of DIAG's
468type." 525type."
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'."
1584Intended for `eldoc-documentation-functions' (which see)." 1641Intended 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'.
1949PROJECT-ROOT indicates that each entry should be preceded by the 2020PROJECT-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