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
(emacs) Displaying Buffers and its subnodes, as well as the nodes referenced from the Elisp manual).
The problem in this case is that
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-x
term or M-x
FWIW, in Emacs 27 you can already work around this limitation using the new user option
switch-to-buffer-obey-display-actions is a variable defined in ‘window.el’.
Its value is nil
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."
(defun my-ansi-term ()
"Start Bash in a terminal emulator.
Like `ansi-term', but respect buffer display actions."
(let ((switch-to-buffer-obey-display-actions t))
(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)