9

I'd like M-g n and M-g p to cycle, at least when I'm using them with flycheck. This feature requires writing a custom function as it's not supported (as mentioned on https://github.com/flycheck/flycheck/issues/64 and confirmed in chat), but I am an Elisp noob.

For other reasons (working around https://github.com/commercialhaskell/intero/issues/268), in flycheck-mode I bypass next-error and invoke flycheck-next-error directly. I can live with normal compilation mode not cycling since I use it seldom (though probably this will get annoying if I do start using compilation mode).

1 Answer 1

4

Here's what I came up with (as a noob) after learning about condition-case, advices, universal-argument and some internals of flycheck. I usually don't write code with so little clue of what I'm doing, so I welcome better answers.

Commented out logging is left in since I don't regard this as finished, and for those who'd like to trace execution of this code.

Finally, this does nothing for raw next-error, it is only invoked when flycheck is.

;; Optional: ensure flycheck cycles, both when going backward and forward.
;; Tries to handle arguments correctly.
;; Since flycheck-previous-error is written in terms of flycheck-next-error,
;; advising the latter is enough.
(defun flycheck-next-error-loop-advice (orig-fun &optional n reset)
  ; (message "flycheck-next-error called with args %S %S" n reset)
  (condition-case err
      (apply orig-fun (list n reset))
    ((user-error)
     (let ((error-count (length flycheck-current-errors)))
       (if (and
            (> error-count 0)                   ; There are errors so we can cycle.
            (equal (error-message-string err) "No more Flycheck errors"))
           ;; We need to cycle.
           (let* ((req-n (if (numberp n) n 1)) ; Requested displacement.
                  ; An universal argument is taken as reset, so shouldn't fail.
                  (curr-pos (if (> req-n 0) (- error-count 1) 0)) ; 0-indexed.
                  (next-pos (mod (+ curr-pos req-n) error-count))) ; next-pos must be 1-indexed
             ; (message "error-count %S; req-n %S; curr-pos %S; next-pos %S" error-count req-n curr-pos next-pos)
             ; orig-fun is flycheck-next-error (but without advise)
             ; Argument to flycheck-next-error must be 1-based.
             (apply orig-fun (list (+ 1 next-pos) 'reset)))
         (signal (car err) (cdr err)))))))

(advice-add 'flycheck-next-error :around #'flycheck-next-error-loop-advice)

This is a snapshot of https://gist.github.com/Blaisorblade/c7349438b06e7b1e034db775408ac4cb, where I'll place any updated version.

1
  • Works like a magic!
    – alper
    Commented Jun 30, 2020 at 1:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.