aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoão Távora2017-09-27 02:31:58 +0100
committerJoão Távora2017-10-03 14:18:54 +0100
commite0df7b9699539a6831dd7d72d6845d2995fb619e (patch)
treef94fa89ece1463c79b0e015fa95f4d2fc12b9b9b
parent73601787b45d08cdd5026ea36ff680bd49076950 (diff)
downloademacs-e0df7b9699539a6831dd7d72d6845d2995fb619e.tar.gz
emacs-e0df7b9699539a6831dd7d72d6845d2995fb619e.zip
Fancy Flymake mode-line construct displays status
Imitates compilation-mode's mode-line a bit, and uses its faces. * lisp/progmodes/flymake.el (flymake-error, flymake-warning, flymake-note): Add mode-line-face to these flymake error types. (flymake-note): Notes don't need a noisy fringe bitmap. (flymake-lighter): Delete. (flymake--update-lighter): Delete. (flymake--mode-line-format): New function and variable. (flymake--diagnostics-table): New buffer-local variable. (flymake--handle-report): Don't update "lighters". Affect flymake--diagnostics-table. (flymake--run-backend): Init flymake--diagnostics-table for backend. (flymake-mode): Use flymake--mode-line-format. (flymake-mode): Don't update lighter. (flymake--highlight-line): Be more careful when overriding a nil default overlay property.
-rw-r--r--lisp/progmodes/flymake.el134
1 files changed, 112 insertions, 22 deletions
diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el
index f136e14ec19..03b319f8715 100644
--- a/lisp/progmodes/flymake.el
+++ b/lisp/progmodes/flymake.el
@@ -35,7 +35,8 @@
35(require 'cl-lib) 35(require 'cl-lib)
36(require 'thingatpt) ; end-of-thing 36(require 'thingatpt) ; end-of-thing
37(require 'warnings) ; warning-numeric-level, display-warning 37(require 'warnings) ; warning-numeric-level, display-warning
38(eval-when-compile (require 'subr-x)) ; when-let*, if-let* 38(require 'compile) ; for some faces
39(eval-when-compile (require 'subr-x)) ; when-let*, if-let*, hash-table-keys
39 40
40(defgroup flymake nil 41(defgroup flymake nil
41 "Universal on-the-fly syntax checker." 42 "Universal on-the-fly syntax checker."
@@ -362,20 +363,23 @@ the diagnostics of each type. The recognized properties are:
362(put 'flymake-error 'face 'flymake-error) 363(put 'flymake-error 'face 'flymake-error)
363(put 'flymake-error 'bitmap flymake-error-bitmap) 364(put 'flymake-error 'bitmap flymake-error-bitmap)
364(put 'flymake-error 'severity (warning-numeric-level :error)) 365(put 'flymake-error 'severity (warning-numeric-level :error))
366(put 'flymake-error 'mode-line-face 'compilation-error)
365 367
366(put 'flymake-warning 'face 'flymake-warning) 368(put 'flymake-warning 'face 'flymake-warning)
367(put 'flymake-warning 'bitmap flymake-warning-bitmap) 369(put 'flymake-warning 'bitmap flymake-warning-bitmap)
368(put 'flymake-warning 'severity (warning-numeric-level :warning)) 370(put 'flymake-warning 'severity (warning-numeric-level :warning))
371(put 'flymake-warning 'mode-line-face 'compilation-warning)
369 372
370(put 'flymake-note 'face 'flymake-note) 373(put 'flymake-note 'face 'flymake-note)
371(put 'flymake-note 'bitmap flymake-warning-bitmap) 374(put 'flymake-note 'bitmap nil)
372(put 'flymake-note 'severity (warning-numeric-level :debug)) 375(put 'flymake-note 'severity (warning-numeric-level :debug))
376(put 'flymake-note 'mode-line-face 'compilation-info)
373 377
374(defun flymake--lookup-type-property (type prop &optional default) 378(defun flymake--lookup-type-property (type prop &optional default)
375 "Look up PROP for TYPE in `flymake-diagnostic-types-alist'. 379 "Look up PROP for TYPE in `flymake-diagnostic-types-alist'.
376If TYPE doesn't declare PROP in either 380If TYPE doesn't declare PROP in either
377`flymake-diagnostic-types-alist' or its associated 381`flymake-diagnostic-types-alist' or in the symbol of its
378`flymake-category', return DEFAULT." 382associated `flymake-category' return DEFAULT."
379 (let ((alist-probe (assoc type flymake-diagnostic-types-alist))) 383 (let ((alist-probe (assoc type flymake-diagnostic-types-alist)))
380 (cond (alist-probe 384 (cond (alist-probe
381 (let* ((alist (cdr alist-probe)) 385 (let* ((alist (cdr alist-probe))
@@ -496,16 +500,6 @@ If TYPE doesn't declare PROP in either
496 ;; 500 ;;
497 (when choice (goto-char (overlay-start choice))))) 501 (when choice (goto-char (overlay-start choice)))))
498 502
499;; flymake minor mode declarations
500(defvar-local flymake-lighter nil)
501
502(defun flymake--update-lighter (info &optional extended)
503 "Update Flymake’s \"lighter\" with INFO and EXTENDED."
504 (setq flymake-lighter (format " Flymake(%s%s)"
505 info
506 (if extended
507 (format ",%s" extended)
508 ""))))
509 503
510;; Nothing in flymake uses this at all any more, so this is just for 504;; Nothing in flymake uses this at all any more, so this is just for
511;; third-party compatibility. 505;; third-party compatibility.
@@ -520,6 +514,9 @@ that has been invoked but hasn't reported any final status yet.")
520 "List of currently disabled flymake backends. 514 "List of currently disabled flymake backends.
521A backend is disabled if it reported `:panic'.") 515A backend is disabled if it reported `:panic'.")
522 516
517(defvar-local flymake--diagnostics-table nil
518 "Hash table of all diagnostics indexed by backend.")
519
523(defun flymake-is-running () 520(defun flymake-is-running ()
524 "Tell if flymake has running backends in this buffer" 521 "Tell if flymake has running backends in this buffer"
525 flymake--running-backends) 522 flymake--running-backends)
@@ -547,6 +544,7 @@ A backend is disabled if it reported `:panic'.")
547 (eq backend 544 (eq backend
548 (flymake--diag-backend 545 (flymake--diag-backend
549 (overlay-get ov 'flymake--diagnostic))))) 546 (overlay-get ov 'flymake--diagnostic)))))
547 (puthash backend diagnostics flymake--diagnostics-table)
550 (mapc (lambda (diag) 548 (mapc (lambda (diag)
551 (flymake--highlight-line diag) 549 (flymake--highlight-line diag)
552 (setf (flymake--diag-backend diag) backend)) 550 (setf (flymake--diag-backend diag) backend))
@@ -557,11 +555,7 @@ A backend is disabled if it reported `:panic'.")
557 (when flymake-check-start-time 555 (when flymake-check-start-time
558 (flymake-log 2 "%d error(s), %d other(s) in %.2f second(s)" 556 (flymake-log 2 "%d error(s), %d other(s) in %.2f second(s)"
559 err-count warn-count 557 err-count warn-count
560 (- (float-time) flymake-check-start-time))) 558 (- (float-time) flymake-check-start-time)))))))
561 (if (null diagnostics)
562 (flymake--update-lighter "[ok]")
563 (flymake--update-lighter
564 (format "%d/%d" err-count warn-count)))))))
565 (t 559 (t
566 (flymake--disable-backend "?" 560 (flymake--disable-backend "?"
567 :strange 561 :strange
@@ -584,6 +578,7 @@ sources."
584(defun flymake--run-backend (backend) 578(defun flymake--run-backend (backend)
585 "Run the backend BACKEND." 579 "Run the backend BACKEND."
586 (push backend flymake--running-backends) 580 (push backend flymake--running-backends)
581 (remhash backend flymake--diagnostics-table)
587 ;; FIXME: Should use `condition-case-unless-debug' 582 ;; FIXME: Should use `condition-case-unless-debug'
588 ;; here, but that won't let me catch errors during 583 ;; here, but that won't let me catch errors during
589 ;; testing where `debug-on-error' is always t 584 ;; testing where `debug-on-error' is always t
@@ -621,7 +616,7 @@ non-nil."
621 616
622;;;###autoload 617;;;###autoload
623(define-minor-mode flymake-mode nil 618(define-minor-mode flymake-mode nil
624 :group 'flymake :lighter flymake-lighter 619 :group 'flymake :lighter flymake--mode-line-format
625 (setq flymake--running-backends nil 620 (setq flymake--running-backends nil
626 flymake--disabled-backends nil) 621 flymake--disabled-backends nil)
627 (cond 622 (cond
@@ -635,10 +630,9 @@ non-nil."
635 (add-hook 'after-save-hook 'flymake-after-save-hook nil t) 630 (add-hook 'after-save-hook 'flymake-after-save-hook nil t)
636 (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t) 631 (add-hook 'kill-buffer-hook 'flymake-kill-buffer-hook nil t)
637 632
638 (flymake--update-lighter "*" "*")
639
640 (setq flymake-timer 633 (setq flymake-timer
641 (run-at-time nil 1 'flymake-on-timer-event (current-buffer))) 634 (run-at-time nil 1 'flymake-on-timer-event (current-buffer)))
635 (setq flymake--diagnostics-table (make-hash-table))
642 636
643 (when flymake-start-syntax-check-on-find-file 637 (when flymake-start-syntax-check-on-find-file
644 (flymake--start-syntax-check))))) 638 (flymake--start-syntax-check)))))
@@ -757,6 +751,102 @@ diagnostics of type `:error' and `:warning'."
757 t)) 751 t))
758 (flymake-goto-next-error (- (or n 1)) filter interactive)) 752 (flymake-goto-next-error (- (or n 1)) filter interactive))
759 753
754
755;;; Mode-line fanciness
756;;;
757(defvar flymake--mode-line-format `(:eval (flymake--mode-line-format)))
758
759(put 'flymake--mode-line-format 'risky-local-variable t)
760
761(defun flymake--mode-line-format ()
762 "Produce a pretty minor mode indicator."
763 (let ((running flymake--running-backends)
764 (reported (hash-table-keys flymake--diagnostics-table)))
765 `((:propertize " Flymake"
766 mouse-face mode-line-highlight
767 ,@(when (not reported)
768 `(face compilation-mode-line-fail))
769 help-echo
770 ,(concat (format "%s registered backends\n"
771 (length flymake-diagnostic-functions))
772 (format "%s running\n"
773 (length running))
774 (format "%s disabled\n"
775 (length flymake--disabled-backends))
776 "mouse-1: go to log buffer ")
777 keymap
778 ,(let ((map (make-sparse-keymap)))
779 (define-key map [mode-line mouse-1]
780 (lambda (_event)
781 (interactive "e")
782 (switch-to-buffer "*Flymake log*")))
783 map))
784 ,@(when running
785 `(":" (:propertize "Run"
786 face compilation-mode-line-run
787 help-echo
788 ,(format "%s running backends"
789 (length running)))))
790 ,@(when reported
791 (let ((by-type (make-hash-table)))
792 (maphash (lambda (_backend diags)
793 (mapc (lambda (diag)
794 (push diag
795 (gethash (flymake--diag-type diag)
796 by-type)))
797 diags))
798 flymake--diagnostics-table)
799 (cl-loop
800 for (type . severity)
801 in (cl-sort (mapcar (lambda (type)
802 (cons type (flymake--lookup-type-property
803 type
804 'severity
805 (warning-numeric-level :error))))
806 (cl-union (hash-table-keys by-type)
807 '(:error :warning)))
808 #'>
809 :key #'cdr)
810 for diags = (gethash type by-type)
811 for face = (flymake--lookup-type-property type
812 'mode-line-face
813 'compilation-error)
814 when (or diags
815 (>= severity (warning-numeric-level :warning)))
816 collect `(:propertize
817 ,(format "%d" (length diags))
818 face ,face
819 mouse-face mode-line-highlight
820 keymap
821 ,(let ((map (make-sparse-keymap))
822 (type type))
823 (define-key map [mode-line mouse-4]
824 (lambda (_event)
825 (interactive "e")
826 (flymake-goto-prev-error 1 (list type) t)))
827 (define-key map [mode-line mouse-5]
828 (lambda (_event)
829 (interactive "e")
830 (flymake-goto-next-error 1 (list type) t)))
831 map)
832 help-echo
833 ,(concat (format "%s diagnostics of type %s\n"
834 (propertize (format "%d"
835 (length diags))
836 'face face)
837 (propertize (format "%s" type)
838 'face face))
839 "mouse-4/mouse-5: previous/next of this type\n"))
840 into forms
841 finally return
842 `((:propertize "[")
843 ,@(cl-loop for (a . rest) on forms by #'cdr
844 collect a when rest collect
845 '(:propertize " "))
846 (:propertize "]"))))))))
847
848
849
760 850
761(provide 'flymake) 851(provide 'flymake)
762 852