From 0c82d44943c72f743fa9cb24390fc582abebcc10 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Wed, 21 May 2025 14:21:57 +0200 Subject: [PATCH] update flymake --- elpa/flymake-1.3.7.signed | 1 - elpa/flymake-1.3.7/flymake-pkg.el | 2 - elpa/flymake-1.4.1.signed | 1 + .../flymake-autoloads.el | 41 +- elpa/flymake-1.4.1/flymake-pkg.el | 2 + .../flymake.el | 725 ++++++++++++------ 6 files changed, 535 insertions(+), 237 deletions(-) delete mode 100644 elpa/flymake-1.3.7.signed delete mode 100644 elpa/flymake-1.3.7/flymake-pkg.el create mode 100644 elpa/flymake-1.4.1.signed rename elpa/{flymake-1.3.7 => flymake-1.4.1}/flymake-autoloads.el (79%) create mode 100644 elpa/flymake-1.4.1/flymake-pkg.el rename elpa/{flymake-1.3.7 => flymake-1.4.1}/flymake.el (75%) diff --git a/elpa/flymake-1.3.7.signed b/elpa/flymake-1.3.7.signed deleted file mode 100644 index 2b29588e..00000000 --- a/elpa/flymake-1.3.7.signed +++ /dev/null @@ -1 +0,0 @@ -Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) (trust undefined) created at 2024-03-31T11:25:11+0200 using EDDSA \ No newline at end of file diff --git a/elpa/flymake-1.3.7/flymake-pkg.el b/elpa/flymake-1.3.7/flymake-pkg.el deleted file mode 100644 index 2d97e2a3..00000000 --- a/elpa/flymake-1.3.7/flymake-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;; Generated package description from flymake.el -*- no-byte-compile: t -*- -(define-package "flymake" "1.3.7" "A universal on-the-fly syntax checker" '((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) :commit "309823ff7796416414cee8c6f4d2650615c19f64" :url "https://elpa.gnu.org/packages/flymake.html" :authors '(("Pavel Kobyakov" . "pk_at_work@yahoo.com")) :maintainer '("João Távora" . "joaotavora@gmail.com") :keywords '("c" "languages" "tools")) diff --git a/elpa/flymake-1.4.1.signed b/elpa/flymake-1.4.1.signed new file mode 100644 index 00000000..bbcbb78c --- /dev/null +++ b/elpa/flymake-1.4.1.signed @@ -0,0 +1 @@ +Good signature from 645357D2883A0966 GNU ELPA Signing Agent (2023) (trust undefined) created at 2025-04-23T11:05:01+0200 using EDDSA \ No newline at end of file diff --git a/elpa/flymake-1.3.7/flymake-autoloads.el b/elpa/flymake-1.4.1/flymake-autoloads.el similarity index 79% rename from elpa/flymake-1.3.7/flymake-autoloads.el rename to elpa/flymake-1.4.1/flymake-autoloads.el index 6be9ff24..0b5cfea9 100644 --- a/elpa/flymake-1.3.7/flymake-autoloads.el +++ b/elpa/flymake-1.4.1/flymake-autoloads.el @@ -23,24 +23,29 @@ generated it. Make a Flymake diagnostic for LOCUS's region from BEG to END. LOCUS is a buffer object or a string designating a file name. -TYPE is a diagnostic symbol and TEXT is string describing the -problem detected in this region. DATA is any object that the -caller wishes to attach to the created diagnostic for later -retrieval with `flymake-diagnostic-data'. - -If LOCUS is a buffer BEG and END should be buffer positions -inside it. If LOCUS designates a file, BEG and END should be a -cons (LINE . COL) indicating a file position. In this second -case, END may be omitted in which case the region is computed -using `flymake-diag-region' if the diagnostic is appended to an -actual buffer. - -OVERLAY-PROPERTIES is an alist of properties attached to the -created diagnostic, overriding the default properties and any -properties listed in the `flymake-overlay-control' property of -the diagnostic's type symbol. - -(fn LOCUS BEG END TYPE TEXT &optional DATA OVERLAY-PROPERTIES)") +TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error +types') + +INFO is a description of the problem detected. It may be a string, or +list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the +diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a +number or nil. MESSAGE must be a string. + +DATA is any object that the caller wishes to attach to the created +diagnostic for later retrieval with `flymake-diagnostic-data'. + +If LOCUS is a buffer, BEG and END should be buffer positions inside it. +If LOCUS designates a file, BEG and END should be a cons (LINE . COL) +indicating a file position. In this second case, END may be omitted in +which case the region is computed using `flymake-diag-region' if the +diagnostic is appended to an actual buffer. + +OVERLAY-PROPERTIES is an alist of properties attached to the created +diagnostic, overriding the default properties and any properties listed +in the `flymake-overlay-control' property of the diagnostic's type +symbol. + +(fn LOCUS BEG END TYPE INFO &optional DATA OVERLAY-PROPERTIES)") (autoload 'flymake-diagnostics "flymake" "\ Get Flymake diagnostics in region determined by BEG and END. diff --git a/elpa/flymake-1.4.1/flymake-pkg.el b/elpa/flymake-1.4.1/flymake-pkg.el new file mode 100644 index 00000000..7f285b88 --- /dev/null +++ b/elpa/flymake-1.4.1/flymake-pkg.el @@ -0,0 +1,2 @@ +;; Generated package description from flymake.el -*- no-byte-compile: t -*- +(define-package "flymake" "1.4.1" "A universal on-the-fly syntax checker" '((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) :commit "a25fc9a518dc1c4bf1ef86bb949ed2f3c995adea" :url "https://elpa.gnu.org/packages/flymake.html" :authors '(("Pavel Kobyakov" . "pk_at_work@yahoo.com")) :maintainer '("Spencer Baugh" . "sbaugh@janestreet.com") :keywords '("c" "languages" "tools")) diff --git a/elpa/flymake-1.3.7/flymake.el b/elpa/flymake-1.4.1/flymake.el similarity index 75% rename from elpa/flymake-1.3.7/flymake.el rename to elpa/flymake-1.4.1/flymake.el index fb000517..26a7b67f 100644 --- a/elpa/flymake-1.3.7/flymake.el +++ b/elpa/flymake-1.4.1/flymake.el @@ -1,10 +1,10 @@ ;;; flymake.el --- A universal on-the-fly syntax checker -*- lexical-binding: t; -*- -;; Copyright (C) 2003-2023 Free Software Foundation, Inc. +;; Copyright (C) 2003-2025 Free Software Foundation, Inc. ;; Author: Pavel Kobyakov -;; Maintainer: João Távora -;; Version: 1.3.7 +;; Maintainer: Spencer Baugh +;; Version: 1.4.1 ;; Keywords: c languages tools ;; Package-Requires: ((emacs "26.1") (eldoc "1.14.0") (project "0.7.1")) @@ -128,6 +128,11 @@ :link '(custom-manual "(flymake) Top") :group 'tools) +(add-to-list 'customize-package-emacs-version-alist + '(Flymake ("1.3.4" . "30.1") + ("1.3.5" . "30.1") + ("1.3.6" . "30.1"))) + (defcustom flymake-error-bitmap '(flymake-double-exclamation-mark compilation-error) "Bitmap (a symbol) used in the fringe for indicating errors. @@ -180,6 +185,60 @@ See `flymake-error-bitmap' and `flymake-warning-bitmap'." (const right-fringe) (const :tag "No fringe indicators" nil))) +(defcustom flymake-indicator-type 'fringes + "Indicate which indicator type to use for display errors. + +The value can be nil (don't indicate errors but just highlight them), +the symbol `fringes' (use fringes) or the symbol `margins' (use +margins). + +Difference between fringes and margin is that fringes support displaying +bitmaps on graphical displays and margins display text in a blank area +from current buffer that works in both graphical and text displays. +Thus, even when `fringes' is selected, margins will still be used on +text displays and also when fringes are disabled. + +See Info node `Fringes' and Info node `(elisp)Display Margins'." + :version "31.1" + :type '(choice (const :tag "Use Fringes" fringes) + (const :tag "Use Margins" margins) + (const :tag "No indicators" nil))) + +(defcustom flymake-margin-indicators-string + '((error "!!" compilation-error) + (warning "!" compilation-warning) + (note "!" compilation-info)) + "Strings used for margins indicators. +The value of each list may be a list of 3 elements where specifies the +error type, the string to use and its face, +or a list of 2 elements specifying only the error type and +the corresponding string. + +The option `flymake-margin-indicator-position' controls how and where +this is used." + :version "30.1" + :type '(repeat :tag "Error types lists" + (list :tag "String and face for error types" + (symbol :tag "Error type") + (string :tag "String") + (face :tag "Face")))) + +(defcustom flymake-autoresize-margins t + "If non-nil, automatically resize margin-width calling `flymake--resize-margins'. + +Only relevant if `flymake-indicator-type' is set to margins." + :version "30.1" + :type 'boolean) + +(defcustom flymake-margin-indicator-position 'left-margin + "The position to put Flymake margin indicator. +The value can be nil (do not use indicators), `left-margin' or `right-margin'. +See `flymake-margin-indicators-string'." + :version "30.1" + :type '(choice (const left-margin) + (const right-margin) + (const :tag "No margin indicators" nil))) + (make-obsolete-variable 'flymake-start-syntax-check-on-newline "can check on newline in post-self-insert-hook" "27.1") @@ -258,6 +317,11 @@ If set to nil, don't suppress any zero counters." (defvar-local flymake-check-start-time nil "Time at which syntax check was started.") +(defvar-local flymake--original-margin-width nil + "Store original margin width. +Used by `flymake--resize-margins' for restoring original margin width +when flymake is turned off.") + (defun flymake--log-1 (level sublog msg &rest args) "Do actual work for `flymake-log'." (let (;; never popup the log buffer @@ -307,7 +371,7 @@ generated it." (cl-defstruct (flymake--diag (:constructor flymake--diag-make)) - locus beg end type text backend data overlay-properties overlay + locus beg end type origin code message backend data overlay-properties overlay ;; FIXME: See usage of these two in `flymake--highlight-line'. ;; Ideally they wouldn't be needed. orig-beg orig-end) @@ -317,32 +381,42 @@ generated it." beg end type - text + info &optional data overlay-properties) "Make a Flymake diagnostic for LOCUS's region from BEG to END. LOCUS is a buffer object or a string designating a file name. -TYPE is a diagnostic symbol and TEXT is string describing the -problem detected in this region. DATA is any object that the -caller wishes to attach to the created diagnostic for later -retrieval with `flymake-diagnostic-data'. - -If LOCUS is a buffer BEG and END should be buffer positions -inside it. If LOCUS designates a file, BEG and END should be a -cons (LINE . COL) indicating a file position. In this second -case, END may be omitted in which case the region is computed -using `flymake-diag-region' if the diagnostic is appended to an -actual buffer. - -OVERLAY-PROPERTIES is an alist of properties attached to the -created diagnostic, overriding the default properties and any -properties listed in the `flymake-overlay-control' property of -the diagnostic's type symbol." +TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error +types') + +INFO is a description of the problem detected. It may be a string, or +list (ORIGIN CODE MESSAGE) appropriately categorizing and describing the +diagnostic. ORIGIN may be a string or nil. CODE maybe be a string, a +number or nil. MESSAGE must be a string. + +DATA is any object that the caller wishes to attach to the created +diagnostic for later retrieval with `flymake-diagnostic-data'. + +If LOCUS is a buffer, BEG and END should be buffer positions inside it. +If LOCUS designates a file, BEG and END should be a cons (LINE . COL) +indicating a file position. In this second case, END may be omitted in +which case the region is computed using `flymake-diag-region' if the +diagnostic is appended to an actual buffer. + +OVERLAY-PROPERTIES is an alist of properties attached to the created +diagnostic, overriding the default properties and any properties listed +in the `flymake-overlay-control' property of the diagnostic's type +symbol." (when (stringp locus) (setq locus (expand-file-name locus))) + (cond ((stringp info) + (setq info (list nil nil info))) + ((numberp (cadr info)) + (setf (cadr info) (number-to-string (cadr info))))) (flymake--diag-make :locus locus :beg beg :end end - :type type :text text :data data + :type type :origin (car info) :code (cadr info) + :message (caddr info) :data data :overlay-properties overlay-properties :orig-beg beg :orig-end end)) @@ -368,27 +442,98 @@ diagnostics at BEG." ,(format "Get Flymake diagnostic DIAG's %s." (symbol-name thing)) (,internal diag))) -(flymake--diag-accessor flymake-diagnostic-text flymake--diag-text text) (flymake--diag-accessor flymake-diagnostic-type flymake--diag-type type) (flymake--diag-accessor flymake-diagnostic-backend flymake--diag-backend backend) +(flymake--diag-accessor flymake-diagnostic-origin flymake--diag-origin backend) +(flymake--diag-accessor flymake-diagnostic-code flymake--diag-code backend) +(flymake--diag-accessor flymake-diagnostic-message flymake--diag-message backend) (flymake--diag-accessor flymake-diagnostic-data flymake--diag-data data) (flymake--diag-accessor flymake-diagnostic-beg flymake--diag-beg beg) (flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) (flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) +(defcustom flymake-diagnostic-format-alist + '((:help-echo . (origin code oneliner)) + (:eol . (oneliner)) + (:eldoc . (origin code message)) + (:eldoc-echo . (origin code oneliner)) + (t . (origin code oneliner))) + "How to format diagnostics for different output destinations. +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'; +- `:eldoc', for use with Flymake's ElDoc backend; +- `:eldoc-echo', for use with Flymake's ElDoc backend, but for ElDoc's own + confined outlets; +- t for all other destinations. + +PARTS says which parts of the diagnostic to include. It is a list of +symbols where the following values are meaningful: + +- `origin': include diagnostic origin if it exists; +- `code': include diagnostics code if it exists; +- `message': include the full diagnostic's message text; +- `oneliner': include truncated diagnostic text;" + :package-version '(Flymake . "1.4.0") + :type '(alist :key-type (choice (const :help-echo) + (const :eol) + (const :eldoc) + (const :eldoc-echo) + (const t)) + :value-type (set (const origin) + (const code) + (const message) + (const oneliner)))) + +(cl-defun flymake-diagnostic-text (diag + &optional (parts '(origin code message))) + "Describe diagnostic DIAG's as a string. +PARTS says which parts of the diagnostic to include. It is a list of +symbols as described in `flymake-diagnostic-format-alist' (which see). +PARTS defaults to `(origin code message)'." + (let* ((w parts) + (a (and (memq 'origin w) (flymake--diag-origin diag))) + (b (and (memq 'code w) (flymake--diag-code diag))) + (c (cond ((memq 'message w) (flymake--diag-message diag)) + ((memq 'oneliner w) + (let* ((msg (flymake--diag-message diag))) + (substring msg 0 (cl-loop for i from 0 for a across msg + when (eq a ?\n) return i))))))) + (concat a + (when (and a b) " ") + (when b (concat "[" b "]")) + (when (and c (or a b)) ": ") + c))) + +(defun flymake--format-diagnostic (diag destination face-prop) + (let ((txt (flymake-diagnostic-text + diag (alist-get destination flymake-diagnostic-format-alist + (alist-get t flymake-diagnostic-format-alist + '(origin code message)))))) + (if face-prop + (propertize txt 'face + (flymake--lookup-type-property + (flymake-diagnostic-type diag) face-prop + 'flymake-error)) + txt))) + (defun flymake-diagnostic-oneliner (diag &optional nopaintp) "Get truncated one-line text string for diagnostic DIAG. This is useful for displaying the DIAG's text to the user in confined spaces, such as the echo are. Unless NOPAINTP is t, propertize returned text with the `echo-face' property of DIAG's type." - (let* ((txt (flymake-diagnostic-text diag)) - (txt (substring txt 0 (cl-loop for i from 0 for a across txt - when (eq a ?\n) return i)))) + (let* ((txt (flymake-diagnostic-text diag '(origin code oneliner)))) (if nopaintp txt (propertize txt 'face (flymake--lookup-type-property (flymake-diagnostic-type diag) 'echo-face 'flymake-error))))) +(make-obsolete 'flymake-diagnostic-oneliner + "use `flymake-diagnostic-text' instead." + "Flymake package version 1.4.0") (cl-defun flymake--really-all-overlays () "Get flymake-related overlays. @@ -630,6 +775,7 @@ Node `(Flymake)Flymake error types'" (put 'flymake-error 'face 'flymake-error) (put 'flymake-error 'flymake-bitmap 'flymake-error-bitmap) +(put 'flymake-error 'flymake-margin-string (alist-get 'error flymake-margin-indicators-string)) (put 'flymake-error 'severity (warning-numeric-level :error)) (put 'flymake-error 'mode-line-face 'flymake-error-echo) (put 'flymake-error 'echo-face 'flymake-error-echo) @@ -638,6 +784,7 @@ Node `(Flymake)Flymake error types'" (put 'flymake-warning 'face 'flymake-warning) (put 'flymake-warning 'flymake-bitmap 'flymake-warning-bitmap) +(put 'flymake-warning 'flymake-margin-string (alist-get 'warning flymake-margin-indicators-string)) (put 'flymake-warning 'severity (warning-numeric-level :warning)) (put 'flymake-warning 'mode-line-face 'flymake-warning-echo) (put 'flymake-warning 'echo-face 'flymake-warning-echo) @@ -646,6 +793,7 @@ Node `(Flymake)Flymake error types'" (put 'flymake-note 'face 'flymake-note) (put 'flymake-note 'flymake-bitmap 'flymake-note-bitmap) +(put 'flymake-note 'flymake-margin-string (alist-get 'note flymake-margin-indicators-string)) (put 'flymake-note 'severity (warning-numeric-level :debug)) (put 'flymake-note 'mode-line-face 'flymake-note-echo) (put 'flymake-note 'echo-face 'flymake-note-echo) @@ -682,19 +830,64 @@ associated `flymake-category' return DEFAULT." (flymake--lookup-type-property type 'severity (warning-numeric-level :error))) -(defun flymake--fringe-overlay-spec (bitmap &optional recursed) - (if (and (symbolp bitmap) - (boundp bitmap) - (not recursed)) - (flymake--fringe-overlay-spec - (symbol-value bitmap) t) - (and flymake-fringe-indicator-position - bitmap - (propertize "!" 'display - (cons flymake-fringe-indicator-position - (if (listp bitmap) - bitmap - (list bitmap))))))) +(defun flymake--indicator-overlay-spec (type) + "Return INDICATOR as propertized string to use in error indicators." + (let* ((indicator (flymake--lookup-type-property + type + (cond ((eq flymake-indicator-type 'fringes) + 'flymake-bitmap) + ((eq flymake-indicator-type 'margins) + 'flymake-margin-string)) + (alist-get 'bitmap (alist-get type ; backward compat + flymake-diagnostic-types-alist)))) + (value (if (symbolp indicator) + (symbol-value indicator) + indicator)) + (valuelist (if (listp value) + value + (list value))) + (indicator-car (car valuelist))) + + (cond + ((and (symbolp indicator-car) + flymake-fringe-indicator-position) + (propertize "!" 'display + (cons flymake-fringe-indicator-position valuelist))) + ((and (stringp indicator-car) + flymake-margin-indicator-position) + (propertize "!" + 'display + `((margin ,flymake-margin-indicator-position) + ,(propertize indicator-car + 'face `(:inherit (,(cdr valuelist) default)) + 'mouse-face 'highlight + 'help-echo "Open Flymake diagnostics" + 'keymap (let ((map (make-sparse-keymap))) + (define-key + map `[,flymake-margin-indicator-position mouse-1] + #'flymake-show-buffer-diagnostics) + map)))))))) + +(defun flymake--resize-margins (&optional orig-width) + "Resize current window margins according to `flymake-margin-indicator-position'. +Return to original margin width if ORIG-WIDTH is non-nil." + (when (and (eq flymake-indicator-type 'margins) + flymake-autoresize-margins) + (cond + ((and orig-width flymake--original-margin-width) + (if (eq flymake-margin-indicator-position 'left-margin) + (setq left-margin-width flymake--original-margin-width) + (setq right-margin-width flymake--original-margin-width))) + (t + (if (eq flymake-margin-indicator-position 'left-margin) + (setq flymake--original-margin-width left-margin-width + left-margin-width 2) + (setq flymake--original-margin-width right-margin-width + right-margin-width 2)))) + ;; Apply margin to all windows available. + (mapc (lambda (x) + (set-window-buffer x (window-buffer x))) + (get-buffer-window-list nil nil 'visible)))) (defun flymake--equal-diagnostic-p (a b) "Tell if A and B are equivalent `flymake--diag' objects." @@ -703,7 +896,9 @@ associated `flymake-category' return DEFAULT." flymake--diag-beg flymake-diagnostic-type flymake-diagnostic-backend - flymake-diagnostic-text) + flymake-diagnostic-origin + flymake-diagnostic-code + flymake-diagnostic-message) always (equal (funcall comp a) (funcall comp b))))) (defun flymake--delete-overlay (ov) @@ -715,11 +910,9 @@ associated `flymake-category' return DEFAULT." (delete-overlay ov))) (defun flymake--eol-overlay-summary (src-ovs) - "Helper function for `flymake--eol-overlay-update'." + "Helper function for `flymake--update-eol-overlays'." (cl-flet ((summarize (d) - (propertize (flymake-diagnostic-oneliner d t) 'face - (flymake--lookup-type-property (flymake--diag-type d) - 'eol-face)))) + (flymake--format-diagnostic d :eol 'eol-face))) (let* ((diags (cl-sort (mapcar (lambda (o) (overlay-get o 'flymake-diagnostic)) src-ovs) @@ -744,11 +937,11 @@ associated `flymake-category' return DEFAULT." (defun flymake--update-eol-overlays () "Update the `before-string' property of end-of-line overlays." - (save-excursion + (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))) + (if-let* ((src-ovs (overlay-get o 'flymake-eol-source-overlays))) (overlay-put o 'before-string (flymake--eol-overlay-summary src-ovs)) (delete-overlay o)))))) @@ -839,20 +1032,15 @@ Return nil or the overlay created." (overlay-put ov prop (flymake--lookup-type-property type prop value))))) (default-maybe 'face 'flymake-error) - (default-maybe 'before-string - (flymake--fringe-overlay-spec - (flymake--lookup-type-property - type - 'flymake-bitmap - (alist-get 'bitmap (alist-get type ; backward compat - flymake-diagnostic-types-alist))))) + (default-maybe 'before-string (flymake--indicator-overlay-spec type)) ;; (default-maybe 'after-string ;; (flymake--diag-text diagnostic)) (default-maybe 'help-echo (lambda (window _ov pos) (with-selected-window window (mapconcat - #'flymake-diagnostic-oneliner + (lambda (d) + (flymake--format-diagnostic d :help-echo 'echo-face)) (flymake-diagnostics pos) "\n")))) (default-maybe 'severity (warning-numeric-level :error)) @@ -1131,7 +1319,7 @@ If MESSAGE-PREFIX, echo a message using that prefix." (defun flymake--disable-backend (backend &optional explanation) "Disable BACKEND because EXPLANATION. If it is running also stop it." - (flymake-log :warning "Disabling backend %s because %s" backend explanation) + (flymake-log :warning "Disabling backend %s because %S" backend explanation) (flymake--with-backend-state backend state (setf (flymake--state-running state) nil (flymake--state-disabled state) explanation @@ -1142,7 +1330,7 @@ If it is running also stop it." ARGS is a keyword-value plist passed to the backend along with a report function." (flymake-log :debug "Running backend %s" backend) - (let ((run-token (cl-gensym "backend-token"))) + (let ((run-token (gensym "backend-token"))) (flymake--with-backend-state backend state (setf (flymake--state-running state) run-token (flymake--state-disabled state) nil @@ -1157,6 +1345,37 @@ with a report function." "Recent changes collected by `flymake-after-change-function'.") (defvar flymake-mode) +(defun flymake--import-foreign-diagnostics () + ;; Other diagnostic sources may already target this buffer's file + ;; before we turned on: these sources may be of two types... + (let ((source (current-buffer)) + (bfn buffer-file-name)) + ;; 1. For `flymake-list-only-diagnostics': here, we do nothing. + ;; FIXME: We could remove the corresponding entry from that + ;; variable, as we assume that new diagnostics will come in soon + ;; via the brand new `flymake-mode' setup. For simplicity's + ;; sake, we have opted to leave the backend for now. + nil + ;; 2. other buffers where a backend has created "foreign + ;; diagnostics" and pointed them here. We must highlight them in + ;; this buffer, i.e. create overlays for them. Those other + ;; buffers and backends are still responsible for them, i.e. the + ;; current buffer does not "own" these foreign diags. + (dolist (buffer (buffer-list)) + (with-current-buffer buffer + (when flymake-mode + (maphash (lambda (_backend state) + (maphash (lambda (file diags) + (when (or (eq file source) + (string= bfn (expand-file-name file))) + (with-current-buffer source + (mapc (lambda (diag) + (flymake--highlight-line diag + 'foreign)) + diags)))) + (flymake--state-foreign-diags state))) + flymake--state)))))) + (defun flymake-start (&optional deferred force) "Start a syntax check for the current buffer. DEFERRED is a list of symbols designating conditions to wait for @@ -1230,11 +1449,16 @@ Interactively, with a prefix arg, FORCE is t." backend)) (t (flymake--run-backend backend backend-args))) - nil)))))))) + nil))) + (flymake--import-foreign-diagnostics)))))) (defvar flymake-mode-map - (let ((map (make-sparse-keymap))) map) - "Keymap for `flymake-mode'.") + (let ((map (make-sparse-keymap))) + (define-key map + `[,flymake-fringe-indicator-position mouse-1] + #'flymake-show-buffer-diagnostics) + map) + "Keymap for `flymake-mode'") ;;;###autoload (define-minor-mode flymake-mode @@ -1285,45 +1509,23 @@ special *Flymake log* buffer." :group 'flymake :lighter (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t) (add-hook 'eldoc-documentation-functions 'flymake-eldoc-function t t) - ;; If Flymake happened to be already ON, we must cleanup - ;; 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 #'flymake--delete-overlay (flymake--really-all-overlays)) - (setq flymake--state (make-hash-table)) + (when (and (eq flymake-indicator-type 'fringes) + (not (cl-case flymake-fringe-indicator-position + (left-fringe (< 0 (nth 0 (window-fringes)))) + (right-fringe (< 0 (nth 1 (window-fringes))))))) + ;; There are no fringes in the buffer, fallback to margins. + (setq-local flymake-indicator-type 'margins)) + + ;; AutoResize margins. + (flymake--resize-margins) + + ;; We can't just `clrhash' `flymake--state': there may be in + ;; in-transit requests from other backends if `flymake-mode' was + ;; already active. I.e. `flymake-mode' function should be as + ;; idempotent as possible. See bug#69809. + (unless flymake--state (setq flymake--state (make-hash-table))) (setq flymake--recent-changes nil) - - (when flymake-start-on-flymake-mode (flymake-start t)) - - ;; Other diagnostic sources may already target this buffer's file - ;; before we turned on: these sources may be of two types... - (let ((source (current-buffer)) - (bfn buffer-file-name)) - ;; 1. For `flymake-list-only-diagnostics': here, we do nothing. - ;; FIXME: We could remove the corresponding entry from that - ;; variable, as we assume that new diagnostics will come in soon - ;; via the brand new `flymake-mode' setup. For simplicity's - ;; sake, we have opted to leave the backend for now. - nil - ;; 2. other buffers where a backend has created "foreign" - ;; diagnostics and pointed them here. We must highlight them in - ;; this buffer, i.e. create overlays for them. Those other - ;; buffers and backends are still responsible for them, i.e. the - ;; current buffer does not "own" these foreign diags. - (dolist (buffer (buffer-list)) - (with-current-buffer buffer - (when (and flymake-mode flymake--state) - (maphash (lambda (_backend state) - (maphash (lambda (file diags) - (when (or (eq file source) - (string= bfn (expand-file-name file))) - (with-current-buffer source - (mapc (lambda (diag) - (flymake--highlight-line diag - 'foreign)) - diags)))) - (flymake--state-foreign-diags state))) - flymake--state)))))) + (when flymake-start-on-flymake-mode (flymake-start t))) ;; Turning the mode OFF. (t @@ -1333,6 +1535,9 @@ special *Flymake log* buffer." :group 'flymake :lighter ;;+(remove-hook 'find-file-hook (function flymake-find-file-hook) t) (remove-hook 'eldoc-documentation-functions 'flymake-eldoc-function t) + ;; return margin to original size + (flymake--resize-margins t) + (when flymake-timer (cancel-timer flymake-timer) (setq flymake-timer nil)) @@ -1424,11 +1629,15 @@ START and STOP and LEN are as in `after-change-functions'." (defun flymake-eldoc-function (report-doc &rest _) "Document diagnostics at point. Intended for `eldoc-documentation-functions' (which see)." - (when-let ((diags (flymake-diagnostics (point)))) + (when-let* ((diags (flymake-diagnostics (point)))) (funcall report-doc - (mapconcat #'flymake-diagnostic-text diags "\n") - :echo (mapconcat #'flymake-diagnostic-oneliner - diags "\n")))) + (mapconcat (lambda (d) + (flymake--format-diagnostic d :eldoc 'echo-face)) + diags "\n") + :echo (mapconcat + (lambda (d) + (flymake--format-diagnostic d :eldoc-echo 'echo-face)) + diags "\n")))) (defun flymake-goto-next-error (&optional n filter interactive) "Go to Nth next Flymake diagnostic that matches FILTER. @@ -1569,13 +1778,19 @@ correctly.") ,flymake-mode-line-lighter mouse-face mode-line-highlight help-echo - ,(lambda (&rest _) - (concat - (format "%s known backends\n" (hash-table-count flymake--state)) - (format "%s running\n" (length (flymake-running-backends))) - (format "%s disabled\n" (length (flymake-disabled-backends))) - "mouse-1: Display minor mode menu\n" - "mouse-2: Show help for minor mode")) + ,(lambda (w &rest _) + (with-current-buffer (window-buffer w) + ;; Mouse can activate tool-tip without window being active. + ;; `flymake--state' is buffer local and is null when line + ;; lighter appears in *Help* `describe-mode'. + (concat + (unless (null flymake--state) + (concat + (format "%s known backends\n" (hash-table-count flymake--state)) + (format "%s running\n" (length (flymake-running-backends))) + (format "%s disabled\n" (length (flymake-disabled-backends))))) + "mouse-1: Display minor mode menu\n" + "mouse-2: Show help for minor mode"))) keymap ,(let ((map (make-sparse-keymap))) (define-key map [mode-line down-mouse-1] @@ -1637,14 +1852,17 @@ correctly.") (defvar flymake--mode-line-counter-map (let ((map (make-sparse-keymap))) - (define-key map (vector 'mode-line mouse-wheel-down-event) - #'flymake--mode-line-counter-scroll-prev) - (define-key map [mode-line wheel-down] - #'flymake--mode-line-counter-scroll-prev) - (define-key map (vector 'mode-line mouse-wheel-up-event) - #'flymake--mode-line-counter-scroll-next) - (define-key map [mode-line wheel-up] - #'flymake--mode-line-counter-scroll-next) + ;; BEWARE: `mouse-wheel-UP-event' corresponds to `wheel-DOWN' events + ;; and vice versa!! + (with-no-warnings + (define-key map (vector 'mode-line mouse-wheel-down-event) + #'flymake--mode-line-counter-scroll-prev) + (define-key map [mode-line wheel-down] + #'flymake--mode-line-counter-scroll-next) + (define-key map (vector 'mode-line mouse-wheel-up-event) + #'flymake--mode-line-counter-scroll-next) + (define-key map [mode-line wheel-up] + #'flymake--mode-line-counter-scroll-prev)) map)) (defun flymake--mode-line-counter-1 (type) @@ -1688,8 +1906,9 @@ TYPE is usually keyword `:error', `:warning' or `:note'." (flymake--mode-line-counter-1 type)) probe))) -;;; Per-buffer diagnostic listing - + +;;; Per-buffer diagnostic listings +;;; (defvar-local flymake--diagnostics-buffer-source nil) (defvar flymake-diagnostics-buffer-mode-map @@ -1699,7 +1918,7 @@ TYPE is usually keyword `:error', `:warning' or `:note'." map)) (defun flymake-show-diagnostic (pos &optional other-window) - "Show location of diagnostic at POS." + "From Flymake diagnostics buffer, show source of diagnostic at POS." (interactive (list (point) t)) (let* ((id (or (tabulated-list-get-id pos) (user-error "Nothing at point"))) @@ -1709,9 +1928,8 @@ TYPE is usually keyword `:error', `:warning' or `:note'." (end (flymake--diag-end diag)) (visit (lambda (b e) (goto-char b) - (pulse-momentary-highlight-region (point) - (or e (line-end-position)) - 'highlight)))) + (pulse-momentary-highlight-region + b (or e (line-end-position)))))) (with-current-buffer (cond ((bufferp locus) locus) (t (find-file-noselect locus))) (with-selected-window @@ -1730,17 +1948,33 @@ TYPE is usually keyword `:error', `:warning' or `:note'." (current-buffer)))) (defun flymake-goto-diagnostic (pos) - "Show location of diagnostic at POS. + "From Flymake diagnostics buffer, goto source of diagnostic at POS. POS can be a buffer position or a button" (interactive "d") (pop-to-buffer (flymake-show-diagnostic (if (button-type pos) (button-start pos) pos)))) -(defun flymake--tabulated-entries-1 (diags project-root) - "Helper for `flymake--diagnostics-buffer-entries'. -PROJECT-ROOT indicates that each entry should be preceded by the -filename of the diagnostic relative to that directory." +(defvar flymake--tabulated-list-format-base + `[("File" 15) + ("Line" 5 ,(lambda (l1 l2) + (< (plist-get (car l1) :line) + (plist-get (car l2) :line))) + :right-align t) + ("Col" 3 nil :right-align t) + ("Type" 8 ,(lambda (l1 l2) + (< (plist-get (car l1) :severity) + (plist-get (car l2) :severity)))) + ("Origin" 8 t) + ("Code" 8 t) + ("Message" 0 t)]) + +(defun flymake--tabulated-setup-1 (diags project-root) + "Helper for `flymake--tabulated-setup'. +Sets `tabulated-list-format' and `tabulated-list-entries', dinamically +resizing columns and ommiting redudant columns." (cl-loop + with fields = (copy-tree flymake--tabulated-list-format-base t) + initially (cl-loop for y across fields do (setf (cadr y) nil)) for diag in diags for locus = (flymake-diagnostic-buffer diag) for file = (if (bufferp locus) @@ -1765,79 +1999,99 @@ filename of the diagnostic relative to that directory." (;; somehow dead annotated diagnostic, ignore/give up t nil)) for type = (flymake-diagnostic-type diag) - for backend = (flymake-diagnostic-backend diag) - for bname = (or (ignore-errors (symbol-name backend)) - "(anonymous function)") - for data-vec = `[,(format "%s" line) - ,(format "%s" col) - ,(propertize (format "%s" - (flymake--lookup-type-property - type 'flymake-type-name type)) - 'face (flymake--lookup-type-property - type 'mode-line-face 'flymake-error)) - ,(propertize - (if bname - (replace-regexp-in-string "\\(.\\)[^-]+\\(-\\|$\\)" - "\\1\\2" bname) - "(anon)") - 'help-echo (format "From `%s' backend" backend)) - (,(flymake-diagnostic-oneliner diag t) - mouse-face highlight - help-echo "mouse-2: visit this diagnostic" - face nil - action flymake-goto-diagnostic - mouse-action flymake-goto-diagnostic)] - when (and line col) collect - (list (list :diagnostic diag - :line line - :severity (flymake--lookup-type-property - type - 'severity (warning-numeric-level :error))) - (if project-root - (vconcat `[(,(file-name-nondirectory file) - help-echo ,(file-relative-name file project-root) - face nil - mouse-face highlight - action flymake-goto-diagnostic - mouse-action flymake-goto-diagnostic )] - data-vec) - data-vec)))) - -(defun flymake--diagnostics-buffer-entries () - "Get tabulated list entries for current tabulated list buffer. -Expects `flymake--diagnostics-buffer-entries' to be bound to a -buffer." - ;; Do nothing if 'flymake--diagnostics-buffer-source' has not yet - ;; been set to a valid buffer. This could happen when this function - ;; is called too early. For example 'global-display-line-numbers-mode' - ;; calls us from its mode hook, when the diagnostic buffer has just - ;; been created by 'flymake-show-buffer-diagnostics', but is not yet - ;; set up properly (Bug#40529). - (when (bufferp flymake--diagnostics-buffer-source) - (with-current-buffer flymake--diagnostics-buffer-source - (when flymake-mode - (flymake--tabulated-entries-1 (flymake-diagnostics) nil))))) - -(defvar flymake--diagnostics-base-tabulated-list-format - `[("Line" 5 ,(lambda (l1 l2) - (< (plist-get (car l1) :line) - (plist-get (car l2) :line))) - :right-align t) - ("Col" 3 nil :right-align t) - ("Type" 8 ,(lambda (l1 l2) - (< (plist-get (car l1) :severity) - (plist-get (car l2) :severity)))) - ("Backend" 8 t) - ("Message" 0 t)]) + for data-line = `[,(and project-root + `(,(file-name-nondirectory file) + help-echo ,(file-relative-name file project-root) + face nil + mouse-face highlight + action flymake-goto-diagnostic + mouse-action flymake-goto-diagnostic )) + ,(format "%s" line) + ,(format "%s" col) + ,(propertize (format "%s" + (flymake--lookup-type-property + type 'flymake-type-name type)) + 'face (flymake--lookup-type-property + type 'mode-line-face 'flymake-error)) + ,(flymake-diagnostic-origin diag) + ,(flymake-diagnostic-code diag) + (,(flymake-diagnostic-text diag '(oneliner)) + mouse-face highlight + help-echo "mouse-2: visit this diagnostic" + face nil + action flymake-goto-diagnostic + mouse-action flymake-goto-diagnostic)] + for meta = (and line col + (list :diagnostic diag + :line line + :severity (flymake--lookup-type-property + type + 'severity (warning-numeric-level :error)))) + when meta + do (cl-loop for x across data-line + for y across fields + for z across flymake--tabulated-list-format-base + for xlen = (cond ((stringp x) (length x)) + (t (length (car x)))) + when (cl-plusp xlen) + do (setf (cadr y) + (max xlen + (or (cadr y) (cadr z))))) + collect (list meta data-line) into data + finally + ;; `data' and `fields' now hold more or less suitable values for + ;; `tabulated-list-entries' and `tabulated-list-format' respectively, + ;; but we need to trim them, first removing the columns of data where + ;; the corresponding field is known to be nil for every line, and + ;; then removing the field description itself. + (cl-loop + for entry in data + do (setf (cadr entry) (cl-loop for x across (cadr entry) + for y across fields + when (cadr y) + vconcat (vector (or x "-"))))) + (setq tabulated-list-entries data + tabulated-list-format + (cl-loop for y across fields + when (cadr y) vconcat (vector y))))) + +(defun flymake--tabulated-setup (use-project) + "Helper for `flymake-diagnostics-buffer-mode'. +And also `flymake-project-diagnostics-mode'." + (let ((saved-r-b-f revert-buffer-function) + (refresh + (lambda () + (cond + (use-project + (let ((p (project-current))) + (flymake--tabulated-setup-1 + (flymake--project-diagnostics p) + (project-root p)))) + (t + ;; Do nothing if 'flymake--diagnostics-buffer-source' has + ;; not yet been set to a valid buffer. This could happen + ;; when this function is called too early. For example + ;; 'global-display-line-numbers-mode' calls us from its + ;; mode hook, when the diagnostic buffer has just been + ;; created by 'flymake-show-buffer-diagnostics', but is not + ;; yet set up properly (Bug#40529). + (flymake--tabulated-setup-1 + (and (bufferp flymake--diagnostics-buffer-source) + (with-current-buffer flymake--diagnostics-buffer-source + (and flymake-mode + (flymake-diagnostics)))) + nil))) + (tabulated-list-init-header)))) + (setq revert-buffer-function + (lambda (&rest args) + (funcall refresh) + (apply saved-r-b-f args))))) (define-derived-mode flymake-diagnostics-buffer-mode tabulated-list-mode "Flymake diagnostics" "A mode for listing Flymake diagnostics." :interactive nil - (setq tabulated-list-format flymake--diagnostics-base-tabulated-list-format) - (setq tabulated-list-entries - 'flymake--diagnostics-buffer-entries) - (tabulated-list-init-header)) + (flymake--tabulated-setup nil)) (defun flymake--diagnostics-buffer-name () (format "*Flymake diagnostics for `%s'*" (current-buffer))) @@ -1845,9 +2099,39 @@ buffer." (define-obsolete-function-alias 'flymake-show-diagnostics-buffer 'flymake-show-buffer-diagnostics "1.2.1") -(defun flymake-show-buffer-diagnostics () - "Show a list of Flymake diagnostics for current buffer." - (interactive) +(defun flymake--fit-diagnostics-window (window) + (fit-window-to-buffer window 15 8)) + +(defun flymake-show-buffer-diagnostics (&optional diagnostic) + "Show listing of Flymake diagnostics for current buffer. +With optional DIAGNOSTIC, find and highlight this diagnostic in the +listing. + +Interactively, grab DIAGNOSTIC from context. For mouse events in +margins and fringes, use the first diagnostic in the corresponding line, +else look in the click position. For non-mouse events, look for +diagnostics at point. + +This function doesn't move point" + (interactive + (if (mouse-event-p last-command-event) + (with-selected-window (posn-window (event-end last-command-event)) + (with-current-buffer (window-buffer) + (let* ((event-point (posn-point (event-end last-command-event))) + (diags + (or + (flymake-diagnostics event-point) + (let (event-lbp event-lep) + (save-excursion + (goto-char event-point) + (setq event-lbp (line-beginning-position) + event-lep (line-end-position))) + (flymake-diagnostics event-lbp event-lep)))) + (diag (car diags))) + (unless diag + (error "No diagnostics here")) + (list diag)))) + (flymake-diagnostics (point)))) (unless flymake-mode (user-error "Flymake mode is not enabled in the current buffer")) (let* ((name (flymake--diagnostics-buffer-name)) @@ -1855,11 +2139,27 @@ buffer." (target (or (get-buffer name) (with-current-buffer (get-buffer-create name) (flymake-diagnostics-buffer-mode) - (current-buffer))))) + (current-buffer)))) + window) (with-current-buffer target (setq flymake--diagnostics-buffer-source source) - (display-buffer (current-buffer)) - (revert-buffer)))) + (revert-buffer) + (setq window + (display-buffer (current-buffer) + `((display-buffer-reuse-window + display-buffer-below-selected) + (window-height . flymake--fit-diagnostics-window)))) + (when (and window diagnostic) + (with-selected-window window + (cl-loop initially (goto-char (point-min)) + until (eobp) + until (eq (plist-get (tabulated-list-get-id) :diagnostic) + diagnostic) + do (forward-line) + finally + (recenter) + (pulse-momentary-highlight-one-line + (point) 'highlight))))))) ;;; Per-project diagnostic listing @@ -1890,14 +2190,9 @@ some of this variable's contents the diagnostic listings.") (define-derived-mode flymake-project-diagnostics-mode tabulated-list-mode "Flymake diagnostics" - "A mode for listing Flymake diagnostics." + "A mode for listing Flymake diagnostics in a project." :interactive nil - (setq tabulated-list-format - (vconcat [("File" 25 t)] - flymake--diagnostics-base-tabulated-list-format)) - (setq tabulated-list-entries - 'flymake--project-diagnostics-entries) - (tabulated-list-init-header)) + (flymake--tabulated-setup t)) (cl-defun flymake--project-diagnostics (&optional (project (project-current))) "Get all known relevant diagnostics for PROJECT." @@ -1917,7 +2212,7 @@ some of this variable's contents the diagnostic listings.") (cl-loop for buf in visited-buffers do (with-current-buffer buf - (when (and flymake-mode flymake--state) + (when flymake-mode (maphash (lambda (_backend state) (maphash @@ -1942,11 +2237,6 @@ some of this variable's contents the diagnostic listings.") append diags)) (append buffer-annotated-diags relevant-foreign-diags list-only-diags))) -(defun flymake--project-diagnostics-entries () - (let ((p (project-current))) - (flymake--tabulated-entries-1 (flymake--project-diagnostics p) - (project-root p)))) - (defun flymake--project-diagnostics-buffer (root) (get-buffer-create (format "*Flymake diagnostics for `%s'*" root))) @@ -1959,8 +2249,11 @@ some of this variable's contents the diagnostic listings.") (with-current-buffer buffer (flymake-project-diagnostics-mode) (setq-local flymake--project-diagnostic-list-project prj) - (display-buffer (current-buffer)) - (revert-buffer)))) + (revert-buffer) + (display-buffer (current-buffer) + `((display-buffer-reuse-window + display-buffer-at-bottom) + (window-height . flymake--fit-diagnostics-window)))))) (defun flymake--update-diagnostics-listings (buffer) "Update diagnostics listings somehow relevant to BUFFER." -- 2.47.3