(or emacs irrelevant)

Semimap - .Xmodmap with semicolon as an additional modifier

Today, I'll share my keyboard layout, based on QWERTY, that facilitates all tech-related activities, especially Emacs. I've been using a version of this for about three years now, and only a single key has been changed in the last two years. Without further ado, here it is:


The most visible change

I've made ; stop inserting ; and instead act as Mode_switch: a modifier similar to control or meta.

  • I'm pressing ;-j to enter ;
  • I'm pressing ;-d to enter :

So I'm giving up the ability to press ; with a single key, and remapping : from one two-key combination to another two-key combination.

In return, I'm getting a QWERTY with all these wonderful shortcuts.

The RSI-savers

The general ones are:

  • RET on ;-v (symmetric with C-m)
  • DEL on ;-o

If you're writing a bunch of C++, _ on ;-s is very good.

Likewise, - on ;-a is great for LISP.

For LaTeX, \ on ;-w is good since I switched from a keyboard that had it near z to a keyboard that has it near RET.

I'm guessing ~ on ;-t isn't bad for shell, but I don't use it that much.

The basic remaps

These are just char-for-char remaps. They are composable, for instance I have dired-jump on C-:, which means that I'm pressing C-;-d.

Some math symbols are mnemonic: e-equal, l-lesser, g-greater. If you're using lispy, it might become more clear for you why I've put lispy-slurp on > and lispy-barf on <. Although pressing these keys with a shift isn't the worst thing, having them on the home row is pretty cool.

The pairs

Here are the translations meant for pairs: q - θ, f - φ, r - ρ, c - σ. These are meant for Emacs and .inputrc. In both cases, e.g. φ should insert () and go backward one char. Here's my .inputrc:

set input-meta on
set output-meta on
set convert-meta off
"\e\C-l":"\C-e | less\C-m"

set completion-ignore-case on

With this .inputrc, it's like I have some kind of electric mode in my bash. In Emacs, the pairs are bound in a straightforward way:

(defun ins-brackets ()
  (cond ((eq major-mode 'term-mode)
         (term-send-raw-string "[]")
         (term-send-raw-string "^B"))
         (lispy--surround-region "[" "]"))
         (insert "[]")
(global-set-key "ρ" 'ins-brackets)

For LISP, I use lispy-specific bindings:

(define-key lispy-mode-map (kbd "φ") 'lispy-parens)
(define-key lispy-mode-map (kbd "σ") 'lispy-braces)
(define-key lispy-mode-map (kbd "ρ") 'lispy-brackets)
(define-key lispy-mode-map (kbd "θ") 'lispy-quotes)
(define-key lispy-mode-map (kbd "χ") 'lispy-right)

The rest of the Greek chars

These are bound to various Emacs functions. In fact, I initially started with all Greek chars, and bound e.g.:

(global-set-key (kbd "ε") "=")

When these remap-type bindings became mature, I've put them directly into .Xmodmap, which gave the advantage of being able to compose the keys.

These bindings are as good and usable as the control plus lower case chars. Use them wisely and you can get a very ergonomic setup. Some ideas:

  • switching buffers on ;-h
  • switching windows on ;-n
  • jumping to bookmarks on ;-m

The shifted digits

I find it much easier to press e.g. ;-4 to insert $, rather than S-4. I also restored the justice of 0 coming before 1 by mapping ;-` to 0.


I hope that you'll find some use and enjoyment in these ramappings, if you're not afraid to experiment a little. The cost of losing the semicolon is pretty minor, the bigger issue is in finding the unmodified QWERTY extremely sluggish after using this approach.