Doing Dvorak in Emacs

Home Page > Fun Stuff > 2004 > Dvorak Keyboard in Emacs

Dvorak Keyboard in Emacs

If you don't know what both Dvorak and Emacs are, then this page probably isn't for you. It describes how to set up your Emacs bindings to use the Dvorak keyboard.  There is a small percentage of the population that uses the Emacs editor, and an even smaller percentage of people who use the Dvorak keyboard (although everyone should).  So when you multiply these two small percentages together, there is a tiny percentage of us who would be interested in this page (in fact, I've never physically met anyone else who uses both Emacs & Dvorak). (Learn more about  and the Dvorak keyboard)

Update June 2009: Good news! This page may be obsolete. Charles at M.I.T. informs me that more recent versions of Emacs have a Dvorak input mode built-in. (I just now did M-x version and discovered I'm using Emacs 20.7.1 from June 2000 at home. My web host uses 21.4.1 from Oct 2006) If you have a newer version try this:

Recent versions of Emacs actually come with built-in Dvorak support. C-\ english-dvorak RET remaps the keys for typing without changing any of the chords, and C-\ will thereafter toggle Dvorak for that buffer.

Thanks, Charles! I'll leave this page here for historical reasons (and Jakob Nielson says "Pages must live forever"), as it may still be useful for some of you who are using older versions of Emacs.

I learned the Dvorak keyboard in Junior High because I had some editor on my Commodore 64 which had a Dvorak mode in it, and I thought it was cool.  I learned Emacs during college, then used it extensively at a job after that.  After I had learned Emacs, I decided to try to write some LISP functions that would implement the keyboard in Emacs.  Not knowing much about Lisp or keyboard-translate-table, I wrote the code that appears below.  At first, I was disappointed that I didn't know how to translate the Control characters, also, but now I like it that way.

Here's what I like about my system:

  • Allows you to turn on Dvorak mode in just one buffer

  • Keeps the Control keys the same as they were before (So C-e is still Control then the e key, not Control then the d key), so your fingers don't have to learn new Emacs commands.

  • Works well for keyboard that are physically QWERY

Learn more about
Emacs & Dvorak

Emacs is a programmable editor that has a following among programmers and universities. See Emacs.

The Dvorak Keyboard arranges the keys better than the intentionally-inefficient standard QWERTY layout. Everyone should learn it.  But hardly anyone will. See Marcus Brooks' Page about Dvorak

If your keyboard actually has the Dvorak physical layout, and/or you would rather have the Control keys switched also, then you should look at a 1993 post from Neil Jarram, archived at: http://www.mwbrooks.com/dvorak/qwerty.el (or at my local archived copy).

I use the Dvorak keyboard mainly when I'm typing long sections of text. I don't use it in a shell buffer, or when writing code. Since I found this program useful, a friend at work convinced me to publish it online.  If you have any comments or improvements (like making a toggle function, if you do M-2, M-2, you can't get back to qwerty mode), please email me, or use the form at the bottom of this page.

Link to downloadable copy: dvorak-mode.el (right-click, Save As...)
; dvorak-mode.el
;
; by Matthew Weathers, circa 1996, published 2004
;
; http://www.matthewweathers.com/ 
; email address: (my two initials)@matthewweathers.com
;

; This is probably not the best way to do it, but it works, and it is
; what I have been using for 8 years. See also
; http://www.mwbrooks.com/dvorak/qwerty.el for another version, by
; Neil Jerram. My version translates the keys in just the current
; buffer. Neil's version translates the keys in all buffers, and can
; translate the CTRL keys, too. I prefer to use Dvorak just when
; typing text, not in a shell, or with the control sequences.

; Define M-2 (Escape then "2") to turn on Dvorak mode
; Define M-1 to turn it off
; (you may want to set your own keys)
(global-set-key "\e1" 'dvorak-off)
(global-set-key "\e2" 'dvorak-on)

(defvar dvorak-mode-map ()
"Dvorak Keymap.")
(defvar previous-map ()
"Pre-Dvorak Local Keymap.")

(defun dvorak-on ()
"Turn Dvorak keyboard on."
(interactive)
(message "Dvorak keyboard ON, ESC-1 to turn off")
(progn
(if (current-local-map)
(progn 
(setq dvorak-mode-map (copy-keymap (current-local-map)))
(setq previous-map (copy-keymap (current-local-map))))
(progn
(setq dvorak-mode-map (make-sparse-keymap))
(setq previous-map nil)))
(define-key dvorak-mode-map "q" 'dvorak-insert)
(define-key dvorak-mode-map "w" 'dvorak-insert)
(define-key dvorak-mode-map "e" 'dvorak-insert)
(define-key dvorak-mode-map "r" 'dvorak-insert)
(define-key dvorak-mode-map "t" 'dvorak-insert)
(define-key dvorak-mode-map "y" 'dvorak-insert)
(define-key dvorak-mode-map "u" 'dvorak-insert)
(define-key dvorak-mode-map "i" 'dvorak-insert)
(define-key dvorak-mode-map "o" 'dvorak-insert)
(define-key dvorak-mode-map "p" 'dvorak-insert)
(define-key dvorak-mode-map "Q" 'dvorak-insert)
(define-key dvorak-mode-map "W" 'dvorak-insert)
(define-key dvorak-mode-map "E" 'dvorak-insert)
(define-key dvorak-mode-map "R" 'dvorak-insert)
(define-key dvorak-mode-map "T" 'dvorak-insert)
(define-key dvorak-mode-map "Y" 'dvorak-insert)
(define-key dvorak-mode-map "U" 'dvorak-insert)
(define-key dvorak-mode-map "I" 'dvorak-insert)
(define-key dvorak-mode-map "O" 'dvorak-insert)
(define-key dvorak-mode-map "P" 'dvorak-insert)
(define-key dvorak-mode-map "s" 'dvorak-insert)
(define-key dvorak-mode-map "d" 'dvorak-insert)
(define-key dvorak-mode-map "f" 'dvorak-insert)
(define-key dvorak-mode-map "g" 'dvorak-insert)
(define-key dvorak-mode-map "h" 'dvorak-insert)
(define-key dvorak-mode-map "j" 'dvorak-insert)
(define-key dvorak-mode-map "k" 'dvorak-insert)
(define-key dvorak-mode-map "l" 'dvorak-insert)
(define-key dvorak-mode-map ";" 'dvorak-insert)
(define-key dvorak-mode-map "S" 'dvorak-insert)
(define-key dvorak-mode-map "D" 'dvorak-insert)
(define-key dvorak-mode-map "F" 'dvorak-insert)
(define-key dvorak-mode-map "G" 'dvorak-insert)
(define-key dvorak-mode-map "H" 'dvorak-insert)
(define-key dvorak-mode-map "J" 'dvorak-insert)
(define-key dvorak-mode-map "K" 'dvorak-insert)
(define-key dvorak-mode-map "L" 'dvorak-insert)
(define-key dvorak-mode-map ":" 'dvorak-insert)
(define-key dvorak-mode-map "z" 'dvorak-insert)
(define-key dvorak-mode-map "x" 'dvorak-insert)
(define-key dvorak-mode-map "c" 'dvorak-insert)
(define-key dvorak-mode-map "v" 'dvorak-insert)
(define-key dvorak-mode-map "b" 'dvorak-insert)
(define-key dvorak-mode-map "n" 'dvorak-insert)
(define-key dvorak-mode-map "," 'dvorak-insert)
(define-key dvorak-mode-map "." 'dvorak-insert)
(define-key dvorak-mode-map "/" 'dvorak-insert)
(define-key dvorak-mode-map "Z" 'dvorak-insert)
(define-key dvorak-mode-map "X" 'dvorak-insert)
(define-key dvorak-mode-map "C" 'dvorak-insert)
(define-key dvorak-mode-map "V" 'dvorak-insert)
(define-key dvorak-mode-map "B" 'dvorak-insert)
(define-key dvorak-mode-map "N" 'dvorak-insert)
(define-key dvorak-mode-map "<" 'dvorak-insert)
(define-key dvorak-mode-map ">" 'dvorak-insert)
(define-key dvorak-mode-map "?" 'dvorak-insert)
(define-key dvorak-mode-map "\'" 'dvorak-insert)
(define-key dvorak-mode-map "\"" 'dvorak-insert)
(define-key dvorak-mode-map "[" 'dvorak-insert)
(define-key dvorak-mode-map "{" 'dvorak-insert)
(define-key dvorak-mode-map "-" 'dvorak-insert)
(define-key dvorak-mode-map "_" 'dvorak-insert)
(use-local-map dvorak-mode-map))) 

(defun dvorak-off ()
"Turn Dvorak keyboard off."
(interactive)
(message "Dvorak keyboard OFF, ESC-2 to turn on")
(use-local-map previous-map))

(defun dvorak-insert ()
(interactive)
"Translate typed key into Dvorak keyboard."
(progn
(cond
((= last-command-char ?m) (insert "a"))
((= last-command-char ?q) (insert "'"))
((= last-command-char ?w) (insert ","))
((= last-command-char ?e) (insert "."))
((= last-command-char ?r) (insert "p"))
((= last-command-char ?t) (insert "y"))
((= last-command-char ?y) (insert "f"))
((= last-command-char ?u) (insert "g"))
((= last-command-char ?i) (insert "c"))
((= last-command-char ?o) (insert "r"))
((= last-command-char ?p) (insert "l"))
((= last-command-char ?Q) (insert "\""))
((= last-command-char ?W) (insert "<"))
((= last-command-char ?E) (insert ">"))
((= last-command-char ?R) (insert "P"))
((= last-command-char ?T) (insert "Y"))
((= last-command-char ?Y) (insert "F"))
((= last-command-char ?U) (insert "G"))
((= last-command-char ?I) (insert "C"))
((= last-command-char ?O) (insert "R"))
((= last-command-char ?P) (insert "L"))
((= last-command-char ?s) (insert "o"))
((= last-command-char ?d) (insert "e"))
((= last-command-char ?f) (insert "u"))
((= last-command-char ?g) (insert "i"))
((= last-command-char ?h) (insert "d"))
((= last-command-char ?j) (insert "h"))
((= last-command-char ?k) (insert "t"))
((= last-command-char ?l) (insert "n"))
((= last-command-char ?\;) (insert "s"))
((= last-command-char ?S) (insert "O"))
((= last-command-char ?D) (insert "E"))
((= last-command-char ?F) (insert "U"))
((= last-command-char ?G) (insert "I"))
((= last-command-char ?H) (insert "D"))
((= last-command-char ?J) (insert "H"))
((= last-command-char ?K) (insert "T"))
((= last-command-char ?L) (insert "N"))
((= last-command-char ?:) (insert "S"))
((= last-command-char ?z) (insert ";"))
((= last-command-char ?x) (insert "q"))
((= last-command-char ?c) (insert "j"))
((= last-command-char ?v) (insert "k"))
((= last-command-char ?b) (insert "x"))
((= last-command-char ?n) (insert "b"))
((= last-command-char ?\,) (insert "w"))
((= last-command-char ?\.) (insert "v"))
((= last-command-char ?/) (insert "z"))
((= last-command-char ?Z) (insert ":"))
((= last-command-char ?X) (insert "Q"))
((= last-command-char ?C) (insert "J"))
((= last-command-char ?V) (insert "K"))
((= last-command-char ?B) (insert "X"))
((= last-command-char ?N) (insert "B"))
((= last-command-char ?<) (insert "W"))
((= last-command-char ?>) (insert "V"))
((= last-command-char ??) (insert "Z"))
((= last-command-char ?\') (insert "-"))
((= last-command-char ?\") (insert "_"))
((= last-command-char ?[) (insert "/"))
((= last-command-char ?{) (insert "?"))
((= last-command-char ?-) (insert "["))
((= last-command-char ?_) (insert "{"))
)
))

Update, May 2005: Jim Pivarski wrote me and suggested a better way to do this, using a minor mode.  However, I'm still using version 20.7.1, which doesn't have define-minor-mode.  So, I present his suggestions as-is, below.  At some point, I will incorporate his suggestion in the above.

I have a recommendation: this should be a minor mode. That way the
user can see if it is on, it still only affects one buffer at a time,
and you don't need to introduce variables to keep track of the
buffer's previous keymap. (That might be a problem if you dvorakize
more than one buffer--- does previous-map get overwritten?)

Here's how to do it:

(define-minor-mode dvorak-mode
"Toggle Dvorak mode."
nil
" Dvorak"
'(("q" . dvorak-insert)
("w" . dvorak-insert)
("e" . dvorak-insert)
("r" . dvorak-insert)
...
))

And dvorak-insert is unchanged (except that I think you need to escape
a '[' character:

((= last-command-char ?[) (insert "/"))

becomes

((= last-command-char ?\[) (insert "/"))

(Otherwise, I couldn't compile it.) dvorak-mode-map and previous-map
are no longer necessary.

Update, August 2006: I received a message from Russell about his use of Emacs and Dvorak. I'm presenting it here with his permission.  It includes some interesting history, plus his story of how he has used a Dvorak keyboard over they years.

I have been quite happy with the combination of Dvorak, Debian, XEmacs, and LaTeX for the past five years; and now with these changes to facilitate cursor movement, I am overjoyed. I wish to share this knowledge with anyone who is interested.

Here is a bit of background which you may find of interest. I learned to touch type on a QWERTY layout about 1962. I discovered the Dvorak layout shortly after acquiring an IBM-PC about 1983, and thus have used Dvorak with DOS and with Window$ from the very beginning of my PC experience. I made the transition from QWERTY to Dvorak abruptly and without looking back; it took me two or three weeks to become comfortable with Dvorak.

Thankfully, I began my Dvorak experience with a Keytronics Dvorak keyboard, which provided the "classic" Dvorak layout. The ANSI committee back in 1982 was not wise in standardizing a modification of the original Dvorak layout.

I used Micro$oft Word from version 1.0 until version 5.0, running under DOS. With version 5.5, M$ made Word dependent upon a mouse, so I refused to upgrade beyond 5.0, and I refused to use an editor which required a mouse. I used M$ Word in DOS for editing, and Adobe Aldus PageMaker in Window$ for typesetting.

However, I was forced to find a new text editor when, at the stroke of midnight on the 31st of December A.D. 1999, a genuine Y2K bug caused M$ Word 5.0 to begin writing garbage to the data files. My search led me to Emacs, LaTeX, and Debian.

I had many hundreds of text files, all of them in the proprietary M$ Word format. At great expense in time and tedium, I recovered the most important of the files, but I could not afford to recover them all. Of course, all formatting was lost and had to be restored manually. I searched extensively and tried every conversion program I could find, but I discovered that all of the programs concern themselves only with document-level formatting -- margins, columns, headings, etc. -- which, of course, is of very little consequence. None of the programs which claimed to be able to preserve formatting when converting M$ Word files paid attention to details of character-level formatting such as italic, boldface, and underline -- the things which take forever to convert manually.

Thus it was that I learned the hard way that one never should use a text editor which stores its data in a proprietary format.

The greatest challenge I have faced as Debian has progressed over the past five years has been implementing the "classic" Dvorak layout both for the terminal and X-window environments. Accordingly, I am very pleased that the classic Dvorak layout finally has become a standard part of both environments, so that it may be selected from a menu; no longer is there no need to engage the services of a Linux guru to hack the system.

Regards,
RLH

I have used the Dvorak layout since 1983, and Debian GNU/Linux with XEmacs and LaTeX since 2000. Here are two developments in which you may be interested.

(1) The original keyboard layout (or keymap) which August Dvorak devised in 1936 differs significantly from the "modified" Dvorak layout which was adopted by ANSI in 1983. The differences are confined to the numeric row and the first alphabetic row.

The original or "classic" Dvorak layout has the numeric row in the following sequence:

[{ 7& 5% 3# 1! 9( 0) 2@ 4$ 6^ 8* ]}

Also, on the first alphabetic row of the original Dvorak layout, the

/?

key is on the left, while the

'"

key on in the right.

GNU/Linux distributions including Debian currently provide for console users both the ANSI Dvorak layout

dvorak.kmap.gz

and the the original or "classic" Dvorak layout

dvorak-classic.kmap.gz

But at the current time, the Xorg package provides only the ANSI Dvorak layout. Thankfully, the xkb group has agreed to add the "classic" Dvorak layout to the Xorg distribution; see the following link:

https://bugs.freedesktop.org/show_bug.cgi?id=7503

(2) With Dvorak mapping, cursor movement in Emacs has been a matter of rote learning rather than logic, and is somewhat unnatural. After much thought and a number of hours of experimentation, I have adopted the following scheme, which is based upon physical symmetry and natural tendency, rather than upon acronyms:

---
C-g beginning-of-line
C-c end-of-line

M-g backward-paragraph
M-c forward-paragraph
---
C-f previous-line
C-b next-line

M-f backward-sentence
M-b forward-sentence
---
C-h backward-char-command
C-t forward-char-command

M-h backward-word
M-t forward-word
---
C-d delete-char
C-n backward-delete-char
---

Of course, the help key had to be relocated; C-g was available. And I moved the awkward 'C-c C-e' combination for closing a LaTeX structure to 'C-v', for I never use 'scroll-up-command'. 'C-z' was a natural binding for 'keyboard-quit', particularly in view of the fact that many people make a point of disabling the binding which suspends Emacs. Finally, I discovered that my only need for the 'command prefix' binding to 'C-c' was in order to invoke 'tex-close-latex-block', and in the Dvorak layout 'C-c' is too valuable a mapping to squander upon that function. > By experimentation (rather than accurate understanding), I have implemented these keybindings with the following lines in '~/.xemacs/custom.el':

(require 'tex-mode)

(global-unset-key (kbd "\C-c"))
(global-unset-key (kbd "\C-i"))

(global-set-key (kbd "\C-g") 'beginning-of-line)
(define-key tex-mode-map (kbd "\C-c") 'end-of-line)
(global-set-key (kbd "\C-c") 'end-of-line)

(global-set-key (kbd "\M-g") 'backward-paragraph)
(global-set-key (kbd "\M-c") 'forward-paragraph)

(global-set-key (kbd "\C-f") 'previous-line)
(global-set-key (kbd "\C-b") 'next-line)

(global-set-key (kbd "\M-f") 'backward-sentence)
(global-set-key (kbd "\M-b") 'forward-sentence)

(global-set-key (kbd "\C-h") 'backward-char-command)
(global-set-key (kbd "\C-t") 'forward-char-command)

(global-set-key (kbd "\M-h") 'backward-word)
(global-set-key (kbd "\M-t") 'forward-word)

(global-set-key (kbd "\C-n") 'backward-delete-char)

(define-key tex-mode-map (kbd "\C-v") 'tex-close-latex-block)

(global-set-key (kbd "\C-z") 'keyboard-quit)

(global-set-key (kbd "\C-i") 'help-command)

 


Comment?
From: (your name or email address, or anonymous)

Your message to Matthew:


Created and maintained by Matthew Weathers. Last updated Jun 4, 2009.