Raw Syntax

The stuff programs are made of

Learn Emacs: Zsh and Multi-Term


I've been experimenting with running multi-term in emacs instead of using an external program like iTerm2. While multi-term is good, it can have some show-stopping problems out of the box. As usual, EmacsWiki has some good tips, but there isn't a comprehensive setup all on one page.

View a short demo of this integration on youtube.

Why Multi-Term

I found eshell to be lacking terminal functionality. It didn't work well for me when trying to use a pager or using screen / tmux. I chose multi-term because it runs a real terminal and has convenience functions for running multiple terminals, which matches my old workflow in iTerm2.

Setup Problems

The first problem I noticed was that multi-term would not display certain colors. Inspecting $TERM in multi-term revealed that it was set to eterm-color, but my system lacked terminfo for that terminal. The following command resolves this problem:

tic -o ~/.terminfo /Applications/Emacs.app/Contents/Resources/etc/e/eterm-color.ti

If your Emacs.app doesn't contain that file, you can try searching your system emacs install for eterm-color.ti. That file has been included in emacs for many years.

Secondly, it's important to verify which sh multi-term is running against. I prefer zsh.

I also noticed that my default zsh theme includes UTF-8 characters, which aren't displayed correctly by my emacs. While I haven't found a fix for this, I have added a conditional to my .zshrc to use a more compatible theme inside emacs.

Another annoyance is that the default history limit is quite low (only 2048 lines). If you are feeling lucky, you can set that value to 0, to have an unlimited terminal buffer. However, you can bring your emacs to a crawl if you have a runaway process in your terminal. I set mine to 10000 now and plan to increase it if performance is not a problem.

Term Mode Customizations

I have a couple minor-modes I'd like to turn off in term-mode. A hook is provided for this purpose.

I run a couple different terminals with multi-term. I tried the usual way of binding keys to cycle through terminals with M-[ and M-], but local-set-key and others didn't work. After reading the multi-term.el source code, I found that multi-term handles key bindings using two lists: term-unbind-key-list and term-bind-key-alist.

I customize these with:

A note about buffer naming: multi-term-next and multi-term-prev require the terminal buffers to be named in a sequential way. I tried renaming my terminal buffers and found that the bindings stop working. Those commands simply implement or decrement the trailing number of the buffer name (e.g. *terminal<1>*).

I also found that yanking / pasting text into a terminal buffer didn't work. This is frustrating but easily fixed.


For ideas on how to integrate terminal actions into your emacs workflow see my previous post.