Emacs, Linux and international keyboard layouts

后端 未结 5 1318
太阳男子
太阳男子 2020-12-25 14:32

Is there an easy way to use Emacs key-bindings when you are using a not-English (Russian) keyboard layout?

Whenever an international layout is on, all keystrokes are

相关标签:
5条回答
  • 2020-12-25 14:43

    If you want to keep using the Russian layout in Emacs (rather than use Emacs's own input methods), the only way I know of for now is to add bindings of the form:

    (define-key function-key-map [?\M-ф] [?\M-a])
    

    This will tell Emacs that in case M-ф is not bound, it should try to lookup M-a instead. Sadly, you'll need a lot of these bindings. If someone writes up a patch/package that can automatically provide all these bindings, I'd be happy to include it in Emacs.

    0 讨论(0)
  • 2020-12-25 14:44

    Not sure, where did sabof got 150 billion. I ran this code (thanks to Yuri Khan, taken from EmacsWiki):

    (loop
     for from across "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
     for to   across "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"
     do
     (eval `(define-key key-translation-map (kbd ,(concat "C-" (string from))) (kbd ,(concat     "C-" (string to)))))
     (eval `(define-key key-translation-map (kbd ,(concat "M-" (string from))) (kbd ,(concat     "M-" (string to))))))
    

    It's only 128 combinations. Unfortunately, combinations with single letters like C-x b don't work. I'm still trying to find a better solution.

    0 讨论(0)
  • 2020-12-25 14:46

    You can set input method (kudos go to kindahero) by typing

    M-x set-input-method RET cyrillic-yawerty RET
    

    or

    M-x set-input-method RET cyrillic-jcuken RET
    

    To store it permanently, add

    (setq default-input-method "cyrillic-yawerty")
    

    to ~/.emacs config (and use C-\ to switch between keyboard layouts).

    0 讨论(0)
  • 2020-12-25 14:56

    Here is an alternative solution that uses the OS language, based on syndikat's answer.

    Some key translations are missing, but it should be easy to add them.

    ;; USAGE:
    ;; Put in your .emacs:
    ;; 
    ;; (translate-keystrokes-ru->en)
    ;; (add-hook 'text-mode-hook
    ;;           (lambda () (literal-insert-mode 1)))
    ;; 
    ;; Only buffers with literal-insert-mode active will be sensitive to the
    ;; environment language. Prefixed keybindings will still be usable.
    
    (defun translate-keystrokes-ru->en ()
      "Make emacs output english characters, regardless whether
    the OS keyboard is english or russian"
      (flet ((make-key-stroke (prefix char)
               (eval `(kbd ,(if (and (string-match "^C-" prefix)
                                     (string-match "[A-Z]" (string char)))
                                (concat "S-" prefix (string (downcase char)))
                                (concat prefix (string char)))))))
        (let ((case-fold-search nil)
              (keys-pairs (mapcar* 'cons
                                   "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№"
                                   "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
              (prefixes '(""    "s-"    "M-"    "M-s-"
                          "C-"  "C-s-"  "C-M-"  "C-M-s-")))
          (mapc (lambda (prefix)
                  (mapc (lambda (pair)
                          (define-key key-translation-map
                              (make-key-stroke prefix (car pair))
                            (make-key-stroke prefix (cdr pair))))
                        keys-pairs))
                prefixes))))
    
    (defun literal-insert ()
      (interactive)
      (insert-char last-input-event 1))
    
    (define-minor-mode literal-insert-mode
        "Make emacs output characters corresponging to the OS keyboard,
     ignoring the key-translation-map"
      :keymap (let ((new-map (make-sparse-keymap))
                    (english-chars "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#"))
                (mapc (lambda (char)
                        (define-key new-map (string char)
                          'literal-insert))
                      english-chars)
                new-map))
    
    0 讨论(0)
  • 2020-12-25 15:05

    I use following snippet for Cyrillic keyboard and it works fine for me:

    (defun reverse-input-method (input-method)
      "Build the reverse mapping of single letters from INPUT-METHOD."
      (interactive
       (list (read-input-method-name "Use input method (default current): ")))
      (if (and input-method (symbolp input-method))
          (setq input-method (symbol-name input-method)))
      (let ((current current-input-method)
            (modifiers '(nil (control) (meta) (control meta))))
        (when input-method
          (activate-input-method input-method))
        (when (and current-input-method quail-keyboard-layout)
          (dolist (map (cdr (quail-map)))
            (let* ((to (car map))
                   (from (quail-get-translation
                          (cadr map) (char-to-string to) 1)))
              (when (and (characterp from) (characterp to))
                (dolist (mod modifiers)
                  (define-key local-function-key-map
                    (vector (append mod (list from)))
                    (vector (append mod (list to)))))))))
        (when input-method
          (activate-input-method current))))
    
    (reverse-input-method 'russian-computer)
    

    Except:

    The only issue I know is that recalculation of OrgTable formulas isn't working in Russian layout because it is mapped to C-c-* and * change its location.

    source

    0 讨论(0)
提交回复
热议问题