Andrew Pimlott's Xmodmap Solution

This page is adapted from an e-mail message sent by Andrew Pimlott. Andrew had several other excellent suggestions that I have incorporated into my XWindows page.

Andrew has developed a perl script that automgically generates the appropriate xmodmap keysym file for the system it is running on. Andrew recommends the following steps for Dvorak lovers:

  1. Extract the attached script and put it in your bin directory (which we'll assume is in your path).

  2. Grab a keysym file or two. Andrew submitted keysym files called .dvorak and .qwerty. Both these files obey the rules given in the second paragraph of the perl script's introductory comments. Also, this site did not previously have a keysym file for going from Dvorak to QWERTY.

  3. Create the following aliases in one of your login files (thanks to Don Reed who submitted this idea):
       alias aoeu xmodmap_kludge ~/.qwerty \| xmodmap -
       alias asdf xmodmap_kludge ~/.dvorak \| xmodmap -

    (These aliases work in csh and tcsh; something similar should work in your shell.)

Now, switching's a breeze, and it should work correctly on every X.


Andrew's Xmodmap Perl Script

Note: The "<" and ">" signs in the following text are encoded for html. They should come across OK if you copy and paste from this document, but be sure to check before running the script.

#!/usr/bin/perl

# xmodmap_kludge

# Filter for xmodmap input that converts keysym expressions to keycode
# expressions, using somewhat more friendly rules than xmodmap does.  In
# particular, the keysym on the left is translated only into the keycodes for
# which it is the first keysym.  This prevents unexpected results when a keysym
# is bound to a keycode with an obscure modifier.  As an example, part of
# keymap table (as output by xmodmap -pke) on my machine is:
#   keycode  17 = 8 asterisk bracketleft trademark
# (This means the 8 key can produce a trademark when various other keys are
# held down.  Don't ask me why.)  If I feed xmodmap the expression:
#   keysym bracketleft = slash question
# it will assign 'slash question' to keycode 17, my 8 key!  If you use this
# script to filter the expression, it will assign 'slash question' only to the
# _real_ bracketleft key.

# You should be sure that the "assigned to" keysym in your expressions is the
# same as what xmodmap -pke spits out (for that key).  For example, (my)
# xmodmap accepts both apostrophe and the deprecated quoteright for the '
# character, but will always output the keysym as apostrophe.  Therefore, input
# to this script must use apostrophe on the left side of assignments.  You can
# make sure this script understands all the keysyms you're assigning to (as
# well as perform a couple other sanity checks) by running this script as:
#   xmodmap_kludge .xmodmaprc > /dev/null
# and watching for warnings.  Normally, use as:
#   xmodmap_kludge .xmodmaprc | xmodmap -

# Andrew Pimlott <pimlott_AT_math.harvard.edu>

open (MAP, 'xmodmap -pke |') || die "Can't run xmodmap -pke!\n";
while (<MAP>) {
        next unless (($code, $firstsym) = /^keycode\s+(\d+)\s*=\s*(\w+)/);
        push @{$keycode{$firstsym}}, $code;
}

while (<>) {
        print, next unless (($from, $to) = /^keysym\s+(\w+)\s*=([\w\s]*)$/);
        @to = split " ", $to;
        @{$keycode{$from}} || warn "$from was not bound to begin!\n";
        foreach (@{$keycode{$from}}) {
                print "keycode $_ = @to\n";
        }
}

Andrew's Dvorak Keysym File

! keysym 1 = 1 exclam
! keysym 2 = 2 at
! keysym 3 = 3 numbersign
! keysym 4 = 4 dollar
! keysym 5 = 5 percent
! keysym 6 = 6 asciicircum
! keysym 7 = 7 ampersand
! keysym 8 = 8 asterisk
! keysym 9 = 9 parenleft
! keysym 0 = 0 parenright
keysym minus = bracketleft braceleft
keysym equal = bracketright braceright
keysym q = apostrophe quotedbl
keysym w = comma less
keysym e = period greater
keysym r = p P
keysym t = y Y
keysym y = f F
keysym u = g G
keysym i = c C
keysym o = r R
keysym p = l L
keysym bracketleft = slash question
keysym bracketright = equal plus
! keysym a = a A
keysym s = o O
keysym d = e E
keysym f = u U
keysym g = i I
keysym h = d D
keysym j = h H
keysym k = t T
keysym l = n N
keysym semicolon = s S
keysym apostrophe = minus underscore
keysym z = semicolon colon
keysym x = q Q
keysym c = j J
keysym v = k K
keysym b = x X
keysym n = b B
! keysym m = m M
keysym comma = w W
keysym period = v V
keysym slash = z Z

Andrew's QWERTY Keysym File

! keysym 1 = 1 exclam
! keysym 2 = 2 at
! keysym 3 = 3 numbersign
! keysym 4 = 4 dollar
! keysym 5 = 5 percent
! keysym 6 = 6 asciicircum
! keysym 7 = 7 ampersand
! keysym 8 = 8 asterisk
! keysym 9 = 9 parenleft
! keysym 0 = 0 parenright
keysym bracketleft = minus underscore
keysym bracketright = equal plus
keysym apostrophe = q Q
keysym comma = w W
keysym period = e E
keysym p = r R
keysym y = t T
keysym f = y Y
keysym g = u U
keysym c = i I
keysym r = o O
keysym l = p P
keysym slash = bracketleft braceleft
keysym equal = bracketright braceright
! keysym a = a A
keysym o = s S
keysym e = d D
keysym u = f F
keysym i = g G
keysym d = h H
keysym h = j J
keysym t = k K
keysym n = l L
keysym s = semicolon colon
keysym minus = apostrophe quotedbl
keysym semicolon = z Z
keysym q = x X
keysym j = c C
keysym k = v V
keysym x = b B
keysym b = n N
! keysym m = m M
keysym w = comma less
keysym v = period greater
keysym z = slash question

Visits to this page since 9 February 2002:
Original page established: 26 December 1998

Back to Introducing the Dvorak Keyboard.

(With thanks to Andrew Pimlott)
Marcus Brooks -- 25 March 1999

Back to Introducing the Dvorak Keyboard.


Last update: 8 December 1996
Original page established: 25 February 1996
Marcus Brooks:  HTML Home  Weblog