1

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?

  • (Guessing in progress, so I post this as a comment and not an answer). find-file calls switch-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))). – Lindydancer Apr 25 '15 at 18:35
  • Thanks for the suggestion. I tried inserting (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? – rneatherway Apr 27 '15 at 13:58
  • I really don't know, I think I picked it up somewhere along the way. I probably learned about it when I wrote 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/…) – Lindydancer Apr 27 '15 at 14:44
  • Well, it makes sense, and it seems it isn't specific to ERT as I see the same behaviour with a plain function. Your suggestion of set-buffer works if I use it in the ERT function in the wait-for-condition code, which is probably what you meant the first time. If you post as an answer I will accept that. Thanks! – rneatherway Apr 27 '15 at 22:02
  • Great! Answer posted! – Lindydancer Apr 28 '15 at 6:21
2

find-file calls switch-to-buffer which "Display buffer BUFFER-OR-NAME in the selected window." Once control returns to the command loop, 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. You can get around this by doing something like (set-buffer (window-buffer (selected-window))).

The command loop is documented in the elisp manual.

  • Just a small clarification, I had to make sure to call (set-buffer (window-buffer (selected-window))) in the ERT test not in the filter function. – rneatherway Apr 28 '15 at 10:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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