Emacs in the terminal

terminal emacs

Unfortunately, the Emacs community seems to don’t like very much the idea of using Emacs inside a terminal. I can relate to that afterall we have Tramp Mode and all the nicities that Emacs executes behind the scenes to make other commands work flawlessly like Magit, and some REPL interactions.

However, life is harder than that and often full of requirements. I have a slow connection and I need to work in a project that cannot leave a remote machine. I code in Clojure and the delay to access code completion, eldoc hints, magit commands, saving files and running scripts, navigating around folder structures in dired, etc, is too much for my taste and for my internet connection pinging ~150ms.

Therefore, this post will be my collection of tips I’ve been using to make my Emacs in terminal life more pleasant.

Choose a good terminal emulator

Yeah, I have been using Xfce Terminal for a while and most of my work was done inside Eshell. I tried several emulators and settled with RXVT which is a bless and a curse at the same time.

I’m using Arch linux and you can install by:

pacman -S rxvt-unicode

Making RXVT looks good

The relevant portions of my ~/.Xresources file:

Xft.dpi:                    96
Xft.antialias:              true
Xft.rgba:                   rgb
Xft.hinting:                1
Xft.hintstyle:              hintslight
URxvt*buffered: false

URxvt*font: xft:Fira Code:style=Retina:pixelsize=14:antialias=true:hinting=true

URxvt.geometry:             90x30
URxvt.transparent:          false
URxvt.visualBell:           false
URxvt.inheritPixmap:        false
URxvt.loginShell:           true
URxvt.saveLines:            50
URxvt.scrollBar:            false
URxvt.internalBorder:       0
URxvt.lineSpace:            0

! fix cursor size
Xcursor.size: 16

! Fix font space
URxvt*letterSpace: -1

I don’t want to engage in color scheme fights, I often use the simple black on white default from Emacs.

Leveraging remappings in RXVT

For an Emacs user, the most frustrated moment is to type that powercord that is wired in your brain for ages and the result be the unexpected.

For me C-backspace was very very important. I rely on that to kill words all the time. Fortunately, RXVT can help me out here. Let’s look at it.

! remapping some command 
URxvt.keysym.C-BackSpace: \033[33~
URxvt.keysym.C-equal: \033[34~

What is happening? RXVT is remapping C-Backspace and C-equal to <f9> and <f10>. So you already know what to do, right?

(global-set-key (kbd "<f9>") 'backward-kill-word)
(global-set-key (kbd "<f10>") 'er/expand-region)

And life can go on!

I haven’t tested if the rxvt remap is consistent across different machines, I recommend remapping and using C-h k inside emacs to figure out which was the target key.

For some reason I could not find a list with all the available keysyms to be remapped in rxvt, but let me list those I have used:

C-equal, C-apostrophe, C-0, C-minus, C-plus, C-S-Down, C-slash, C-S-Up, C-M-v, Escape.

Copy, paste and resize

Crazy, hein? In 2020 we have issues with copy and paste in a reliable form. I installed a package with Perl extensions to improve this a bit.

pacman -S urxvt-perls

And the relevant portions for configuration:

URxvt.perl-ext-common:      default,clipboard,resize-font
URxvt.keysym.Shift-Control-V: perl:clipboard:paste

! scale fonts
URxvt.resize-font.reset: C-0

However, the resize-font plugin was extracted from somewhere else. You have to create a folder (if not exist yet) at ~/.urxvt/ext/, paste the script from here in there and update RXVT using xrdb ~/.Xresources

You can follow more detailed steps in this great post

You can now use C-+ and C-- to resize the font and also C-0 to reset it. I change the default because I wanted C-= to be used by expand-region.

Ok, these are the configurations from the RXVT side, let’s go inside Emacs and see what we need to change.

;;; fix kill rings
(setq save-interprogram-paste-before-kill t
      x-select-enable-clipboard t
      select-enable-clipboard t)

(use-package xclip
  :ensure t
  :config
  (xclip-mode +1))

I am assuming you have use-package or know how to install packages otherwise.

Now you can simply copy something from Firefox and paste inside Emacs using the regular C-y. And the opposite is also true, just copy something with M-w and paste inside your external program.

Run emacs in daemon mode

At the terminal, you might be using tmux or screen to handle different workspaces and you might want to open Emacs in there to some quick editing.

Therefore, I find easier to run emacs as a daemon to quickly jump to a running server when I need.

I run the following code in the remote machine.

emacs --daemon

And I have this function inside my ~/.init.el:

(defun server-shutdown ()
  "Save buffers, quit, and shutdown server"
  (interactive)
  (save-some-buffers)
  (kill-emacs))

Also, the following alias at the ~/.bashrc remote machine:

alias ee="emacsclient -t"

But now, you will notice something bad… when you type ee my_f and hit TAB you would expect a completion. I had to use the complete_alias project to make it work.

It was simple, just follow their README, but in essence you need to install bash-completion, copy their complete_alias script inside your ~/.bash_completion file and setup your alias as:

alias ee="emacsclient -t"
complete -F _complete_alias ee

Fine!

Multiplexers

If you are using tmux you will notice that the default keybind to manipulate it is C-b :/. I often do not use it inside Emacs, but I would like to have something to not conflict with basic keys.

This is my ~/.tmux.conf using C-] as the leader key for tmux.

set-window-option -g mode-keys emacs

unbind-key C-b
set-option -g prefix C-']'

bind-key r source-file ~/.tmux.conf \; display-message "~/.tmux.conf reloaded"

A new friendier binding

I just wanted to point out that I have never used C-z (suspend-frame) before. And this is killer right now, C-z and fg reminds me of my darker background as a vim user a long time ago.

Conclusion

I was expecting to be a lot easier to have a more similar experience in the terminal as we have in GUI, but I was even more astonished by the lack of informations to help a newcomer (me) to setup a workable environment.

Hope to continue releasing more about Emacs inside the Terminal as I move along. Please, if you have any tips, share them around! Reddit or hackernews are great platforms to achieve visibility.

All this post was made in Emacs, inside a rxvt terminal. No complaints.