为了避免 flymake 频繁检查导致 emacs 卡顿,我将 flymake 设置为了“保存时检查”((setq flymake-no-changes-timeout nil)
),但是每次需要保存两次(即重复按两次 C-x C-s
)才能正确检查。
第一次按下 C-x C-s
时 flymake 会提示错误的检查结果,然后我只能稍微修改文件(比如加个空格)触发第二次保存,flymake 才能正确对文件进行检查。
这个问题困扰了我很久,请问大家遇到过吗?
为了避免 flymake 频繁检查导致 emacs 卡顿,我将 flymake 设置为了“保存时检查”((setq flymake-no-changes-timeout nil)
),但是每次需要保存两次(即重复按两次 C-x C-s
)才能正确检查。
第一次按下 C-x C-s
时 flymake 会提示错误的检查结果,然后我只能稍微修改文件(比如加个空格)触发第二次保存,flymake 才能正确对文件进行检查。
这个问题困扰了我很久,请问大家遇到过吗?
我试了一下, (setq flymake-no-changes-timeout nil)
没什么问题, 不能重现问题.
也许可以advicing一下flymake-after-save-hook
, 原代码,
(defun flymake-after-save-hook ()
(when flymake-start-on-save-buffer
(flymake-log :debug "starting syntax check as buffer was saved")
(flymake-start t)))
把 (flymake-start t)
改成 (flymake-start)
.
我发现问题了,似乎是和 eglot
一起使用的时候才会出现这个问题,要么将 eglot-send-changed-idle-time
设置为 0
,要么不将 flymake-no-changes-timeout
设置为 nil
。
这里 flymake
可能是让 eglot
作为后端的。假设我让 eglot-send-changed-idle-time = 1
,flymake-no-changes-timeout = nil
,那么我打了一大段字然后马上按 C-x C-s
,此时eglot
一直没有访问 LSP server,所以拿到的都是旧数据。因此报的错也都是旧的错误。
实际上最好是当我按下 C-x C-s
的时候,eglot
先和 LSP server 通信更新错误列表,然后再让 flymake 显示。
将eglot-send-changed-idle-time
设为零或较小的数值。类似设置在我自己的插件(如wucuo)也有。目的就是减小启动后台重量级进程的频率。所以保存并不一定触发后台进程。算是一个性能优化特性,不能算bug.
eglot 作者在新的 issue 给了一个解决方案(我这边试了下没问题)
(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)))))
感谢!虽然在这半年里我差不多习惯了不开 diagnostics