How can I make display-buffer-alist
work properly without touching global settings?
The fault here lies not with display-buffer
, but with the ESS package, specifically the code in lisp/ess-inf.el
. You should report this as a bug on their issue tracker, quoting the information below.
Firstly, "*R"
is not a valid regexp, as the asterisk is a special character. In order to match it literally, it should be quoted with a literal backslash. So the correct regexp would be:
(rx "*R") ; => "\\*R"
or better yet, to avoid false positives:
(rx bos "*R*") ; => "\\`\\*R\\*"
So the correct overall incantation would be:
(setq display-buffer-alist
`((,(rx bos "*R*")
(display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . 0))))
or:
(setq display-buffer-alist
'(("\\`\\*R\\*"
(display-buffer-reuse-window display-buffer-pop-up-frame)
(reusable-frames . 0))))
Secondly, the erroneous behaviour you describe happens only the first time one types C-cC-z (ess-switch-to-inferior-or-script-buffer
) in an ess-r-mode
buffer, i.e. before the corresponding inferior *R*
process buffer has been created.
This is because ess-force-buffer-current
calls ess-request-a-process
with a non-nil
noswitch
argument when an inferior process does not already exist.
ess-request-a-process
, in turn, does the following as its last step:
(if noswitch
(pop-to-buffer (current-buffer)) ;; VS: this is weird, but is necessary
(pop-to-buffer (buffer-name (process-buffer (get-process proc)))))
This call to (pop-to-buffer (current-buffer))
is wrong and is what causes your ess-r-mode
buffer to appear a second time in the new frame. It was added in the following commit from 2012: https://github.com/emacs-ess/ESS/commit/b29ea8f934f7c08a512c73f14e914bca7229b3c1
I boldly say it is wrong because popping to the current buffer is quite an intrusive operation (as indicated by the bug in question), and the original intention of the author can almost definitely be written in a better way. I don't know what issue the author originally faced, but perhaps the ESS devs can figure it out.