3

I have a personal elisp function that performs an multi-directory grep. It uses compilation-start, which creates a compilation-mode buffer with the results, in which I can press RET (bound to compile-goto-error) to jump to the corresponding location.

However, compile-goto-error always visits the location in another window, leaving the compilation buffer up. Half the time I am just searching for one particular location, so what I would like to do is bind some other key (say C-RET) to also visit the corresponding location in a buffer, but stay in the current window, replacing the compilation buffer with the location's buffer.

I've traced the relevant execution from compile-goto-error to next-error-internal to next-error-function to compilation-next-error-function to compilation-find-file, but can't find a nice place to hook in my differing behavior. Is there a simple way (or, failing that, a complicated one) to create a compile-goto-error variant that switches to the new buffer in-place in the window that held the compilation buffer?

dfan
  • 5,714
  • 1
  • 31
  • 27

2 Answers2

3

I suggest just advising the compile-goto-error function to do the right thing, rather than creating a custom function and keybinding. The following does the right thing for me (following Stefan's suggestion):

(defadvice compile-goto-error (around my-compile-goto-error activate)
  (let ((display-buffer-overriding-action '(display-buffer-reuse-window (inhibit-same-window . nil))))
    ad-do-it))
gcv
  • 468
  • 4
  • 10
  • Well, I want to keep the regular `compile-goto-error` around as well, since I sometimes do want to bring it up in a separate window. I ended up with a solution similar to Stefan's. – dfan Dec 12 '13 at 16:35
1

I think you should be able to get what you want by let-binding display-buffer-overriding-action, something like:

(defun my-next-error ()
  (interactive)
  (let ((display-buffer-overriding-action '(display-buffer-same-window)))
    (next-error)))
Stefan
  • 27,908
  • 4
  • 53
  • 82
  • That doesn't seem to be changing the behavior for me. I added some `(message)` statements to `display-buffer` and I can see that it is being called when I execute `my-next-error`, and that it sees `display-buffer-overriding-action` as being `'(display-buffer-same-window))`, but the buffer still shows up in a different window. Perhaps it has already chosen the new window by the time it decides to display the buffer? – dfan Apr 04 '13 at 17:27
  • The hypothesis at the end of my last question was incorrect. I used `message` to show the `(window-edges)` of the selected window inside `display-buffer`, and that identifies it as the compilation window. – dfan Apr 04 '13 at 17:42
  • The problem was that `compilation-goto-locus` explicitly calls `pop-to-buffer` with the action `other-window`, and as a result `display-buffer` passes `inhibit-same-window` to `display-buffer-same-window`, preventing it from running. I created a new function `display-buffer-same-window-override` that is like `display-buffer-same-window` but which does not respect `inhibit-same-window`, and use that for my `display-buffer-overriding-action` in this case, which achieves the desired behavior. – dfan Apr 04 '13 at 17:54
  • Then I think that `(let ((display-buffer-overriding-action '(display-buffer-same-window (inhibit-same-window . nil)))) (next-error)))` might also work for you. – Stefan Apr 05 '13 at 18:39