bootless.dev

using shell-pop to toggle between eshell and ansi-term

I use shell-pop to work with the terminal in emacs. Binding the shell-pop function to a key (I use SPC ') creates a shell buffer on the bottom portion of the screen. shell-pop supports eshell, term/ansi-term, and shell out of the box, but it can only be configured to use one per invocation.

I recently got the urge to learn eshell, so I changed the shell-pop config accordingly ... and was annoyed. There were still times I wanted to use ansi-term, and I was forced to resort to M-x ansi-term which of course lacks the functionality of shell-pop. In the grand scheme of things, this isn't a big deal, but I was willing to spend a silly amount of time writing a function to extend shell-pop to be able to use both:


(defun choose-shell ()
  (interactive)
  (require 'helm)

  (helm :sources
	(helm-build-sync-source "Select Shell"
	  :candidates '("eshell" "ansi-term"))
	:buffer "*Select Shell"))

(defun configure-shell-pop ()
  (interactive)
  (require 'shell-pop)

   (let ((shell-choice (choose-shell)))

   (cond
   ((equal shell-choice "ansi-term")
    (setq shell-pop-shell-type
	  (quote ("ansi-term" "*ansi-term*"
	     (lambda () (ansi-term shell-pop-term-shell))))))
   ((equal shell-choice "eshell")
    (setq shell-pop-shell-type
	  (quote ("eshell" "*eshell*"
	     (lambda () (eshell))))))))
   (shell-pop--set-shell-type 'shell-pop-shell-type shell-pop-shell-type))
	    

choose-shell opens a helm buffer allowing the user to choose ansi-term or eshell, and that choice is stored in the shell-choice variable in the configure-shell-pop function. Depending on the choice, we set the shell-pop-shell-type variable to the appropriate shell. Following this function (which I bind to SPC ") any subsequent invocations of shell-pop will use the chosen shell.

This setup does not delete the previous shell buffer if you switch while having one open, so you can keep both in your buffer ring. Hopefully this can be of use to fellow shell-pop users!