As a emacs user i don’t really use a shell inside emacs that often. If i do my need for shell is satisfied with one shell that i re-use whenever necessary. To understand how emacs offers terminal emulation and shell support there is already a nice article over at masteringemacs.org ( http://www.masteringemacs.org/article/running-shells-in-emacs-overview ). I found that for my personal usage this works well:

  1. If i am in a frame with one window only, i split the window into two – one for ansi-term one for other buffer
  2. If i current window is showing an ansi-term buffer and i press my „shell-trigger-key“ i want to close it
  3. If current frame hosts more than one window i open ansi-term in a new frame

I burn this into emacs lisp and bind it to a single key to make it dwim.

;; [ ansi-term

(defconst ansi-term-window-height -15 "Height of ansi term window")
(defconst ansi-term-buffer-name "*ansi-term*")
(defconst ansi-term-shell-command "/bin/bash")

(defun start-bash-or-select-existing ()
  "If a buffer named *ansi-term* exist make it current.
Otherwise just call (ansi-term \"/bin/bash\")"
  (interactive)
  (let ((termbuffer (get-buffer ansi-term-buffer-name)))
    (if (bufferp termbuffer)
	(set-window-buffer nil termbuffer)
      (ansi-term ansi-term-shell-command))))

(defun start-bash-in-ansi-term ()
  "Context sensitive run bash from emacs ansi-term.
If the current windows buffer is called *ansi-term* delete the window.
If it's the only window in the frame, also close the frame.
If the current windows buffer is not called *ansi-term* and the current 
window shows exactly one window then split the window and either show
existing *ansi-term* buffer or execute a new shell in ansi-term. If the
current frame shows more then one window open a new frame and open an
existing *ansi-term* there (or execute a new shell in ansi-term)."
  (interactive)
  (let ((numWindows (length (window-list))))
    (if (string= (buffer-name) ansi-term-buffer-name)
	(if (eq 1 numWindows)
	    (delete-frame)
	  (delete-window))
      (if (eq 1 numWindows)
	  (let ((newwindow (split-window nil ansi-term-window-height)))
	    (select-window newwindow)
	    (start-bash-or-select-existing)	
	    )
	(progn
	  (select-frame (make-frame))
	  (start-bash-or-select-existing))))))

(global-set-key (kbd "") 'start-bash-in-ansi-term)
  
;; ]