Make flymake only check for errors on save including Eglot

If you're anything like me, having syntax errors pop up as you're writing code and you're not even finished with what you were trying to do is incredibly annoying. You may already know flycheck has a setting like this to only check on save:


(setq flycheck-check-syntax-automatically '(mode-enabled save))

But what if you use flymake? The equivalent is this which disables flymake's automatic idle checking:


(setq flymake-no-changes-timeout nil)

However now this is not compatible with Eglot and the flymake reporting is delayed and always seems one step behind. As a developer of Eglot explains:

joaotavora commented on Sep 20, 2023:

ACK. There's not much to do here, except recommending you don't do this customization for Eglot.

When the buffer is saved, Flymake asks for diagnostics, and at that time, the server hasn't yet published the notification that says there are no diagnostics at all. According to the LSP spec, it can take all the time in the world for that.

There is now a "pull diagnostics" specification in LSP that would presumably fix this, but Eglot does not yet support this feature.

Maybe this 100% untested hack will work for you:


(cl-defmethod eglot-handle-notification :after
  (_server (_method (eql textDocument/publishDiagnostics)) &key uri
           &allow-other-keys)
  (when-let ((buffer (find-buffer-visiting (eglot-uri-to-path uri))))
    (with-current-buffer buffer
      (if (and (eq nil flymake-no-changes-timeout)
               (not (buffer-modified-p)))
          (flymake-start t)))))

View the original comment

The hack works OK for me but you have to make sure to have the latest GNU ELPA version of eglot and not the one that is built-in to Emacs. It takes a moment to register the changes after the save but that's better than never at all or reporting errors that you already fixed.