Using a shell in Emacs

Emacs Pumpkin

Emacs rocks.

It’s true, it does.

Recently, though, I’ve been trying to streamline my use of the shell in Emacs. Here’s my Halloween Emacs tips.

Added support for multiple shells

The first, glaring problem with shells in Emacs is that you can only have one.

I added a function that creates a shell based on the remote host of a buffer. It also names the shell after that host, so if I’m working on /example.com:/some/file, I’ll get a shell called *shell:example.com* (instead of just *shell*). This allows you to have multiple shells open simultaneously, one per host. [Credit: EmacsWiki]

(defun my/shell (&optional buffer)
   (interactive)
   (let* ((tramp-path (when (tramp-tramp-file-p default-directory)
                        (tramp-dissect-file-name default-directory)))
          (host (tramp-file-name-real-host tramp-path))
          (user (if (tramp-file-name-user tramp-path)
                  (format "%s@" (tramp-file-name-user tramp-path)) ""))
          (new-buffer-name (format "*shell:%s%s*" user host)))
     (shell (if host new-buffer-name buffer))))

Added F9 shell toggle

Then I added the F9 global key binding to toggle between the current buffer and the related shell for the current buffer’s host, creating that shell as necessary.

(defun my/shell-toggle (&optional buffer)
  (interactive)
  (if (string-match "^\\*shell[\\*:]" (buffer-name) )
      (previous-buffer)
      (my/shell buffer)))
(global-set-key [f9] 'my/shell-toggle)

Handle shell termination

There are several ways you could handle terminating the shell. You could, just for shell buffers, turn off the prompt that asks you if you’re sure you want to kill a buffer with an active subprocess running in it, and then use C-x k. But this would kill bash rudely, and bash would not save your command history. You could tell bash to save command history after every command. But this leaves executed commands between different shells all intermixed in the history file and shells would no longer have their own individual session history. That doesn’t appeal to me.

So I opted for another method: detect when the shell terminates and close the emacs buffer. This way, you can hit Ctrl-D (same as you would in a terminal window), bash saves its history, and everyone’s happy.

(add-hook 'comint-exec-hook
          (lambda ()
            (set-process-sentinel (get-buffer-process (current-buffer))
                                  'my/shell-process-sentinel)))
(defun my/shell-process-sentinel (process state)
  ;; show shell status and kill the buffer automatically
  (message "shell: %s" state)
  (if (or
       (string-match "exited abnormally with code.*" state)
       (string-match "finished" state))
      (kill-buffer (current-buffer))))

Nice.

Email this to someoneShare on RedditShare on FacebookTweet about this on TwitterShare on Google+

9th October, 2015 — computing,emacs — no comments

comments feed trackback url

Comments

No comments

Leave a Reply




XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*/?>

Cancel Reply

    • Home
    • About Me
    • Photography
    • Software
      • Android
        • Export Contacts
        • Import Contacts
        • How to install an APK
      • GTK-based
        • Manage Raws
        • Prep. Images
      • Makefiles
        • Arduino
        • General-purpose
      • sqlite3cc
  • Page Content

  • Categories
  • Archives
  • Meta
    • log in
    • site feed
  • Thanks!
    • Send me bitcoins
    • Flattr this

powered by WordPress and Gallery2   |   hosted at waxworlds.org   |   site design by edam