(defvar apl-keyboard '( ;; number row "`◊ 1¨ 2¯ 3< 4≤ 5= 6≥ 7> 8≠ 9∨ 0∧ -× =÷ \⍝ |⍀" ;; number row SHIFTed "~⍨ !¡ @€ #£ $⍧ % ^ & *⍂ (⍱ )⍲ _≡ +⌹" ;; qwert row "q? w⍵ e∈ t∼ y↑ r⍴ u↓ i⍳ o○ p⋆" ;; qwert row shifted "Q¿ W⌽ E⋸ T⍉ Y¥ I⍸ O⍥ P⍟ [← ]→" ;; asdf row "a⍺ s⌈ d⌊ f_ g∇ h∆ j∘ k' l⎕ ;⊢ '⊣" ;; asdf row shifted "A⊖ S D F⍫ G⍒ H⍋ J⍤ K⌻ L⍞" ;; zxcv row "z⊂ x⊃ c∩ v∪ b⊥ n⊤ m∣ ,⌷ .⍎ /⍕" ;; zxcv row shifted "Z X C⍝ V B⍎ N⍕ M⌶ <⍪ >⍙ ?⌿" ) "APL keyboard is a list of keyboard rows For structure see \\[kb-block-defrules] " ) (defun kb-block-defrules (kb) "kb is a list of keyboard rows Each row is a space delimited string The elements of the rows apart from spaces are a pair of characters the first is a keyboard and the second is a translation (which could be absent) See apl-keyboard above for example. This function converts that list of strings into a lisp list of (key .translation) pairs " (let ((kbl nil)) (dolist (row kb (reverse kbl)) (let ((key-trans-list (split-string row "[ \t]+" t)) (key) (trans)) (dolist (key-trans key-trans-list) (when (= (length key-trans) 2) (setq key (aref key-trans 0) trans (aref key-trans 1) kbl (cons (cons key trans) kbl) ))))))) (defvar apl-input-mode nil) ;; obviously this will not be global when the rest of apl mode ;; are in shape. Just a hack for now (global-set-key (kbd "") 'toggle-apl-input-mode) (defvar mode-name-aplized "απλ") (defvar mode-name-ascii "APL") (defvar apl-translation-table (make-translation-table (kb-block-defrules apl-keyboard))) (defun toggle-apl-input-mode () (interactive) (setq apl-input-mode (not apl-input-mode)) (if apl-input-mode (setq keyboard-translate-table apl-translation-table mode-name mode-name-aplized) (setq keyboard-translate-table nil mode-name mode-name-ascii)) (force-mode-line-update))