qwerty 轉換到 dvorak 筆記

作者: Yong-Siang Shih / Fri 12 July 2013 / 分類: Notes

dvorak, linux, qwerty, windows, 自由行列, 行列, 輸入法

翻譯: EN

Keyboard

Windows

Windows 是透過新增輸入法的方式增加 dvoark 鍵盤,如果是新的版本,登入畫面也可以選擇不同的鍵盤使用,如果一開始安裝就選擇 dvorak 的話,就會成為預設值。如果是 XP 或者想要把像是注音輸入法的符號對應也改成 dvorak 的話,可以參考我以前寫的文章:〈Dvorak: 另一種鍵盤排列〉

Linux

最近的 Linux distributions 只要在安裝時就選擇 dvorak 鍵盤的話,大致上就會設定完成,通常 GUI 頁面也會有鍵盤設定。Linux 上輸入法和鍵盤設定通常是分開的兩個東西。如果你使用像是自由行列輸入法等等原本就有支援 dvorak 的輸入法,則符號對應只要設定一下就可以了。

如果因為某些原因無法更動設定檔,使用以下指令可以在鍵盤間切換:

setxkbmap dvorak # 更動成 dvorak
setxkbmap us     # 還原成 us 標準鍵盤

Xrdp

如果使用 rdp 的方式遠端連上 linux 的話,他的鍵盤對應是由自己的設定檔所控制,檔案位置在 /etc/xrdp/km-\*\*\*\*.ini,其中 \*\*\*\* 為不同語言設定的檔案,其編號可參考 rfc1766。通常我們需要修改的是 km-0409.ini (en-US) 這個檔案。

在正常登入的情況下,使用以下指令可以在當前目錄產生目前鍵盤對應的 xrdp 設定檔:

xrdp-genkeymap km-now.ini

接著我們把它搬移取代 xrdp 參照的檔案:

sudo mv km-now.ini /etc/xrdp/km-0409.ini

或許我們會想在覆蓋之前先備份原本的設定檔:

sudo mv /etc/xrdp/km-0409.ini /etc/xrdp/km-0409.ini.old

最後重新啟動 xrdp 伺服器就可以了:

sudo /etc/init.d/xrdp restart

但如果因為某些原因只能用 rdp 連上主機,而無法接觸正常的桌面的話,則根本無法得到 dvorak 的鍵盤對應,因此也無法產生設定檔,在這種情況下,只好直接修改原本的 km-0409.ini。而也有人說用 xrdp-genkeymap 產生的檔案有時會有問題,這時也只能直接修改了。我寫了一個程式用來做這個轉換:

#!/usr/bin/env python3
# xrdpkeymap_qwerty_to_dvorak.py
"""
Usage: python xrdpkeymap_qwerty_to_dvorak.py km-input.ini > km-output.ini
"""
import fileinput
import re

# keycodes
# $ xmodmap -pk for current mapping
# ref: http://forums.fedoraforum.org/showthread.php?t=265100
QWERTY = (20, 21, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 38, 39, 40,
          41, 42, 43, 44, 45, 46, 47, 48, 52, 53, 54, 55, 56, 57, 58, 59, 60,
          61)

DVORAK = (34, 35, 48, 59, 60, 33, 29, 41, 42, 54, 27, 46, 61, 21, 38, 32, 26,
          30, 31, 40, 43, 28, 57, 39, 20, 47, 24, 44, 45, 53, 56, 58, 25, 55,
          52)

TRANS_DICT = dict(list(zip(QWERTY, DVORAK)))


def main():
    re_title = re.compile(r'\[.*\]\n')
    re_keydef = re.compile(r'Key(\d+)=(.*)\n')
    buf = []
    buf_dict = {}

    def output_keydefs():
        for k in buf:
            if k in TRANS_DICT:
                print('Key%d=%s' % (k, buf_dict[TRANS_DICT[k]]))
            else:
                print('Key%d=%s' % (k, buf_dict[k]))
        return [], {}

    for line in fileinput.input():
        if re_title.match(line) is not None:
            buf, buf_dict = output_keydefs()
            print(line, end='')
        elif re_keydef.match(line) is not None:
            m = re_keydef.match(line)
            buf.append(int(m.group(1)))
            buf_dict[int(m.group(1))] = m.group(2)
        else:
            print(line, end='')

    # output remaining keys
    output_keydefs()


if __name__ == '__main__':
    main()

Vim

有的時候我們甚至無法重新啟動 xrdp server,或者根本沒有管理員權限,這時只好有限度的在 Vim 裡頭使用 dvoark。

set keymap=dvorak
set langmap=-=qwertyuiop[]sdfghjkl\\;'zxcvbn\\,./_+QWERTYUIOP{}SDFGHJKL:\"ZXCVBN<>?;[]'\\,.pyfgcrl/=oeuidhtns-\\;qjkxbwvz{}\"<>PYFGCRL?+OEUIDHTNS_:QJKXBWVZ

keymap 可以修改輸入模式的對應,langmap 則是一般及 visual 模式等指令的按鍵,後面那串其格式可參考 :help ‘langmap’,基本上是先打 qwerty 的按鍵,加個分號,再打上轉換成的 dvorak 按鍵,不過 , 和 ; 需要在前面補上 \,” 則是要補上 \。這設定唯一無法轉換的部份是 “:” 開頭的指令模式。此外,如果 set keymap 沒有作用的話,或許是系統缺少 dvorak 的 keymap,此時建立 ~/.vim/keymap/dvorak.vim 檔案,插入 dvorak.vim 的內容即可。

GCIN

有的輸入法沒有直接支援 dvoark,不只是符號對應沒有支援,連正常輸入都整個亂掉了。這時可能要搜尋一下看有沒有現成的修改版檔案,例如我曾經修改過 GCIN 的行列輸入法表格。如果沒有的話,可能就得自行轉換了。

我寫了一個轉換 GCIN .cin 檔的程式:

#!/usr/bin/env python3
# gcin_qwerty_to_dvorak.py
"""
Usage: python gcin_qwerty_to_dvorak.py input.cin > output.cin
"""
import fileinput
import re

QWERTY = '''-=qwertyuiop[]sdfghjkl;'zxcvbn,./_+QWERTYUIOP{}SDFGHJKL:"ZXCVBN<>?'''
DVORAK = '''[]',.pyfgcrl/=oeuidhtns-;qjkxbwvz{}"<>PYFGCRL?+OEUIDHTNS_:QJKXBWVZ'''
TRANS = str.maketrans(QWERTY, DVORAK)


def main():
    re_option = re.compile(r'%(selkey|endkey)\s+(\S+)')
    re_begin = re.compile(r'%\S+\s+begin')
    re_keydef = re.compile(r'^([^#]\S*)(\s+\S+)')
    re_end = re.compile(r'%\S+\s+end')

    begin = False
    for line in fileinput.input():
        # process key definitions
        if begin:
            if re_end.match(line):
                begin = False
            else:
                new_def = re_keydef.subn(
                    lambda x: x.group(1).translate(TRANS) + x.group(2), line)
                # print transformed line
                if new_def[1] != 0:
                    print(new_def[0], end='')
                    continue
            # print comment/end lines
            print(line, end='')
            continue

        m = re_option.match(line)
        if m is not None:
            print('%%%s %s' % (m.group(1), m.group(2).translate(TRANS)))
            continue
        elif re_begin.match(line):
            begin = True
        print(line, end='')


if __name__ == '__main__':
    main()

轉換完後再用 gcin2tab 產生 GCIN 能用的 .gtab 檔。

使用此程式轉換檔案的話,可能還是會需要手動調整,因為有些像是「,」 ->「,」的符號對應應該還是保留會比較好。

下載

相關程式可在 shaform/dvorak-tools 下載。

Yong-Siang Shih

作者

Yong-Siang Shih

軟體工程師,機器學習科學家,開放原始碼愛好者。曾在 Appier 從事機器學習系統開發,也曾在 Google, IBM, Microsoft 擔任軟體實習生。喜好探索學習新科技。
* 在 GitHub 上追蹤我

載入 Disqus 評論