I have a test for fsharp-mode to exercise the jump to definition functionality. Communicating with the background process involves sending a command and then letting the filter function handle the response, which may involve switching to a different buffer. This works fine "for real", but no in the test. Strangely, the buffer switch seems to have worked in the filter function, but has no effect on what the main test function considers to be the current buffer.
I have created a minimal repro, which is included below. It simply runs ls, and has a filter function that uses find-file to switch buffer. The output from message indicates that the buffer switch has succeeded, but the test function which polls the current buffer at 1s intervals always outputs the same result for the current buffer.
The test can be run with emacs -Q --batch -l repro.el -l ert -f ert-run-tests-batch-and-exit if the below text is saved to repro.el.
(require 'ert)
(defun start-proc ()
(let ((proc (let (process-connection-type)
(start-process "background" "*background*" "/bin/ls"))))
(when (process-live-p proc)
(progn
(set-process-coding-system proc 'utf-8-auto)
(set-process-filter proc 'bg-filter-output)
(set-process-query-on-exit-flag proc nil)))))
(defun bg-filter-output (proc str)
(message "In filter")
(find-file "2.txt")
(message "Buffer name now: %s" (file-name-nondirectory buffer-file-name)))
(defun wait-for-condition (fun)
(with-timeout (3)
(while (not (funcall fun))
(sleep-for 1))))
(ert-deftest change-file-bg ()
"Check it changes file even in filter output"
(find-file "1.txt")
(start-proc)
(wait-for-condition
(lambda () (progn
(message "buffer: %s" (file-name-nondirectory buffer-file-name))
(not (equal "1.txt" (file-name-nondirectory buffer-file-name))))))
(should (equal (file-name-nondirectory buffer-file-name) "2.txt")))
What have I done wrong?
find-file
callsswitch-to-buffer
which "Display buffer BUFFER-OR-NAME in the selected window." Once the normal eval loop ends, it makes the buffer in the selected window the current. However, in your case, this never happens since you're still running the ert code. I guess that you can get around this by doing something like(set-buffer (window-buffer (selected-window)))
.(set-buffer (window-buffer (selected-window)))
after(find-file "2.txt")
, and this doesn't seem to make any difference. Is that what you meant? How did you find this information about the eval loop?follow-mode
back in 1995 since it has to deal with things like that... Anyway, I did a search and found the following in the elisp manual: "When an editing command returns to the editor command loop, Emacs automatically calls set-buffer on the buffer shown in the selected window" (gnu.org/software/emacs/manual/html_node/elisp/…)set-buffer
works if I use it in the ERT function in thewait-for-condition
code, which is probably what you meant the first time. If you post as an answer I will accept that. Thanks!