I am wondering if one could adjust the above so that the ansi-term behaves like M-x shell
in the sense of opening in a new window (in the current frame -- at the bottom, just like M-x shell
does).
The canonical and most flexible way to customise such rules is via display-buffer-alist
(see (emacs) Displaying Buffers
and its subnodes, as well as the nodes referenced from the Elisp manual).
The problem in this case is that term
and ansi-term
use switch-to-buffer
instead of pop-to-buffer
or similar. I consider this a bug and intend to propose an upstream fix soon.
So, whereas you can easily configure shell
buffers to be displayed in, say, the same window:
(add-to-list 'display-buffer-alist '("\\`\\*shell" display-buffer-same-window))
The same approach will not work for M-xterm
or M-xansi-term
.
FWIW, in Emacs 27 you can already work around this limitation using the new user option switch-to-buffer-obey-display-actions
:
switch-to-buffer-obey-display-actions is a variable defined in ‘window.el’.
Its value is nil
Documentation:
If non-nil, ‘switch-to-buffer’ runs ‘pop-to-buffer-same-window’ instead.
This means that when switching the buffer it respects display actions
specified by ‘display-buffer-overriding-action’, ‘display-buffer-alist’
and other display related variables. So ‘switch-to-buffer’ will display
the buffer in the window specified by the rules from these variables.
You can customize this variable.
This variable was introduced, or its default value was changed, in
version 27.1 of Emacs.
Here's how you could use it:
(defun my-term-p (name _action)
"Determine whether NAME names a `term-mode' buffer."
(with-current-buffer name
(derived-mode-p #'term-mode)))
(defun my-ansi-term ()
"Start Bash in a terminal emulator.
Like `ansi-term', but respect buffer display actions."
(interactive)
(let ((switch-to-buffer-obey-display-actions t))
(ansi-term "/bin/bash")))
(add-to-list 'display-buffer-alist '(my-term-p () (inhibit-same-window . t)))
Of course, you can then bind it to a key of your liking:
(global-set-key (kbd "C-c a") #'my-ansi-term)