Endless Parentheses

Concise ramblings on Emacs productivity.

Flycheck a directory and report the results

This weekend I found myself doing some heavy-weight refactoring in CIDER. This is the kind of situation where Flycheck helps a lot, but I still needed it to do a bit more. Every time I made a significant change to a file, I had to visit 3 or 5 other files and trigger Flycheck on each one of them. It wasn’t long before I decide there had to be a way to just Flycheck a whole directory.

Enter endless/flycheck-dir. This command runs Flycheck on all files in the current directory and reports the result to the *Compile-Log* buffer. You can then navigate through all issues for the entire directory by TAB-ing through the buffer or using next-error.

(define-key flycheck-command-map "d"
  #'endless/flycheck-dir)
(defun endless/flycheck-dir (dir)
  "Run flycheck for each file in current directory.
Results are reported in a compilation buffer."
  (interactive "DDirectory: ")
  (displaying-byte-compile-warnings
   (let ((p nil))
     (with-current-buffer (get-buffer-create
                           byte-compile-log-buffer)
       (setq default-directory dir)
       (unless (eq major-mode 'compilation-mode)
         (compilation-mode))
       (goto-char (point-max))
       (let ((inhibit-read-only t))
         (insert "\n\xc\n\n"))
       (setq p (point)))
     (dolist (file (directory-files "./" nil
                                    "\\`[^\\.].*\\'"))
       (endless/-flycheck-file file))
     (with-selected-window (display-buffer
                            byte-compile-log-buffer)
       (goto-char p)
       (recenter 1)))))

(defun endless/-report-error (fmt &rest args)
  "Print an error on `byte-compile-log-buffer'."
  (let ((inhibit-read-only t)
        (fill-prefix "    "))
    (with-current-buffer byte-compile-log-buffer
      (let ((l (point)))
        (insert "\n" (apply #'format fmt args))
        (fill-region (1+ l) (point))))))

(defun endless/-flycheck-file (file)
  "Check FILE and report to `byte-compile-log-buffer'."
  (let ((was-visited (find-buffer-visiting file)))
    (with-current-buffer (or was-visited
                             (progn (find-file file)
                                    (current-buffer)))
      (when (ignore-errors (flycheck-buffer))
        (while (flycheck-running-p)
          (accept-process-output nil 0.1))
        (pcase flycheck-last-status-change
          ((or `errored `suspicious)
           (endless/-report-error
            "%s: Something wrong here!"
            (file-name-nondirectory (buffer-file-name))))
          (`finished
           (dolist (e flycheck-current-errors)
             (endless/-report-error
              "%s:%s:%s:%s: %s"
              (file-name-nondirectory (buffer-file-name))
              (flycheck-error-line e)
              (flycheck-error-column e)
              (flycheck-error-level e)
              (flycheck-error-message e))))))
      (if was-visited
          (bury-buffer was-visited)
        (kill-buffer (current-buffer))))))

Tags: programming, flycheck, init.el, emacs

Say thanks on Gratipay
comments powered by Disqus