Emacs,Linux和国际键盘布局

18

当你使用非英语(俄语)键盘布局时,有没有一种简单的方法来使用Emacs快捷键?

当启用国际布局时,所有按键都会被字面解释,例如M-ф而不是M-a。因此,我无法使用命令。

如果Linux可以根据国际布局解释非前缀和Shift前缀键,同时保持其余部分为英文,那将很好。


4
在使用Emacs时,一种方法是使用英文布局。如果你想在Emacs中写俄语,可以通过按下C-\ 来更改Emacs输入法。 - kindahero
5个回答

13

你可以通过输入以下内容来设置输入法(感谢kindahero):

M-x set-input-method RET cyrillic-yawerty RET
或者
M-x set-input-method RET cyrillic-jcuken RET
要永久存储它,请添加:
(setq default-input-method "cyrillic-yawerty")

为了配置 ~/.emacs文件(并使用C-\ 在不同的键盘布局之间切换)。


1
你是说使用 M-x set-input-method 命令,然后通过按下 C-\ 键在俄语和英语之间进行切换吗?至少这对我有效。 - sabof

7

这里是一种使用操作系统语言的替代方案,基于syndikat的答案。

有些关键翻译缺失,但很容易添加它们。

;; 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))

3

我不确定sabof得到了1500亿。我运行了这段代码(感谢Yuri Khan,来自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))))))

只有128种组合。不幸的是,像C-x b这样只有一个字母的组合不起作用。我仍在努力寻找更好的解决方案。


1
这意味着你没有理解我的评论。我已经添加了一个改进版本作为答案,以防有人需要它。 - sabof
似乎你可以使用类似以下的代码来创建 <kbd>C-x b</kbd> 组合键:(loop for from across "йцукенгшщзхъфывапролджэячсмитьбюЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖ\ЭЯЧСМИТЬБЮ№" for to across "qwertyuiop[]asdfghjkl;'zxcvbnm,.QWERTYUIOP{}ASDFGHJKL:\"ZXCVBNM<>#" do (global-set-key (kbd (concat "C-x " (string from))) (key-binding (kbd (concat "C-x " (string to))) t)) ) - Simon Kozlov

1

我使用以下代码片段来切换西里尔字母键盘,对我来说效果很好:

(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)

除此之外:

我知道的唯一问题是,由于俄语布局映射到C-c- *,而*更改其位置,因此OrgTable公式的重新计算在俄语布局中无法正常工作。

source


0
如果你想在Emacs中继续使用俄语布局(而不是使用Emacs自己的输入法),目前我所知道的唯一方法是添加以下形式的绑定:
(define-key function-key-map [?\M-ф] [?\M-a])

这将告诉Emacs,如果M-ф未绑定,则应尝试查找M-a。不幸的是,您需要很多这些绑定。如果有人编写了一个可以自动提供所有这些绑定的补丁/软件包,我很乐意将其包含在Emacs中。


我进行了粗略的计算,得出了1500亿种组合,假设有4个修饰键,4个长和弦和40个按键。一个即时翻译器函数可能更好。 - sabof
我写了一段代码片段来处理绑定。它还不完善 - 它可以从Mule中获取映射,为所有键盘提供绑定。它还会与覆盖self-insert命令的模式(如cua-rectangle)发生冲突。 - sabof
@sabof:虽然需要覆盖所有情况的组合数量很大,但并不像你想象的那么大,因为这种重新映射是在键序列内部应用的。因此,我展示的单个示例已经可以覆盖C-x M-фM-ф M-ф等情况。但是,40个按键加上4个修饰键会给您提供480个绑定,显然在程序上动态地完成这一点会更好。 - Stefan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接