2012-02-04 83 views
2

我想要定义我的次要模式,在isearch-mode之后模仿它(因为它是一种交互式搜索和替换工具,我认为它可能是一个很好的起点)。我的命令工作得很好(在全局键盘绑定上测试过),但是我在本地(在次要模式映射中)将某些键绑定到某些键,即TAB和RET时存在严重问题。我在做这样的事情:如何在Emacs次要模式下重新绑定TAB和RET?

(defvar my-mode-map 
    (let ((map (make-sparse-keymap))) 
    (define-key map "\s" 'my-command) 
    (define-key map "\t" 'another-one) 
    (define-key map "\r" 'yet-another) 
    map)) 

(当然,我把我的键盘映射到较小的模式,地图ALIST)

虽然空间限制的命令工作正常,TAB和RET不知何故。如果我将“\ t”更改为“[f11]”,则它工作正常。我尝试了使用“向量表示法”([?\ t])获得相同结果(在C-h C-v-ing键盘映射之后,这并不令人意外)。可能发生了什么?

编辑:澄清问题,我试图隔离它,我想出了以下代码。假设我想要一个人为的,而非最小的次要模式tabbang,其中TAB键插入一个感叹号。我这样做:

(defvar tabbang-mode) 
(add-to-list 'minor-mode-alist '(tabbang-mode tabbang-mode) t) 

(defvar tabbang-mode-map 
    (let ((map (make-sparse-keymap))) 
    (define-key map [?\t] 'tabbang-insert-bang) 
    (define-key map [?\C-\t] 'tabbang-insert-bang) 
    (define-key map [f11] 'tabbang-insert-bang) 
    (define-key map [?\r] 'tabbang-done) 
    (define-key map [t] 'tabbang-other-char) 
    map)) 
(add-to-list 'minor-mode-map-alist `(tabbang-mode . ,tabbang-mode-map) t) 

(defun tabbang-insert-bang() 
    (interactive) 
    (insert "!")) 

(defun tabbang-mode() 
    (interactive) 
    (setq tabbang-mode " tabbang")) 

(defun tabbang-other-char() 
    (interactive) 
    (tabbang-done) 
    (setq unread-command-events 
    (append (listify-key-sequence (this-command-keys)) 
     unread-command-events))) 

(defun tabbang-done() 
    (interactive) 
    (setq tabbang-mode nil)) 

虽然我tabbang-mode,“其他”项正确退出模式,并插入自己,F11插入一个感叹号(正确),TAB不退出模式(正确的),但刀片没有(错误),C-TAB产生“未定义键”错误(肯定错误),RET退出模式(正确),但插入换行符(错误)。我尝试了一个“新鲜”的emacs(没有加载站点文件和我的.emacs),所以没有其他代码应该介入(我害怕yasnippet以某种方式捕获TAB等)发生了什么?

回答

5

我相信你可以用(kbd "<tab>")(kbd "<return>")分别代替“\ t”和“\ r”来改变它们。


在回答您的编辑,是的,以下的作品完美的我:

... 
(defvar tabbang-mode-map 
    (let ((map (make-sparse-keymap))) 
    (define-key map (kbd "<tab>") 'tabbang-insert-bang) 
    (define-key map (kbd "<C-tab>") 'tabbang-insert-bang) 
    (define-key map (kbd "<f11>") 'tabbang-insert-bang) 
    (define-key map (kbd "<return>") 'tabbang-done) 
    (define-key map (kbd "t") 'tabbang-other-char) 
    map)) 
(add-to-list 'minor-mode-map-alist `(tabbang-mode . ,tabbang-mode-map) t) 
... 
+0

这是不正确的;我认为你的意思是'(kbd“)'和'(kbd”)''。 – tripleee 2012-02-04 10:44:32

+0

没错。除此之外 - 我不想绑定C-TAB,我想要TAB! (我也有C-TAB的问题,一分钟后我要编辑这个问题来反映这一点。) – mbork 2012-02-04 11:23:12

+0

哎呀。是的,我不小心加了'C's。固定。 – Inaimathi 2012-02-04 14:26:53

0

“选项卡”(也就是你所得到的与"\t")不对应于有效的字符串密钥名称。你需要"\C-i"为标签,"\C-j"为新行。

+0

我不确定。我也尝试过使用'[?\ t]',并且这两种语法在键盘映射中都产生了类似'(9. my-command)'的东西,所以我想我正确地完成了这部分。无论如何,使用'“\ C-i”'在键映射中给出了相同的条目(并且它不起作用)。 – mbork 2012-02-04 11:26:42

3

问题是:有些键通过功能键映射进行翻译,只有当键被解除绑定时键才执行翻译。例如。当你点击TAB键时,在GUI下生成的[tab]事件在没有[tab]绑定的情况下被转换为[?\ t]。 [return]也是一样,它被映射到[?\ r]。现在问题在于你的catchall [t]绑定意味着任何键序列都有一个绑定,所以[tab]不会再被重映射到[?\ t]。 isearch遭受同样的问题,请参阅我们在isearch-other-meta-char中做的扭曲。

我认为这个问题的正确方法是避免[t]绑定,而是以不同的方式实现“退出任何其他键的模式”(我现在的经验法则是:“如果你需要把事情回到未读命令事件上,你可能做错了“)。一种方法是使用一个预命令钩子来检查“this-command”是否是你的一个,或者(this-command-keys-vector)是否绑定在你的键盘映射中。在Emacs-24中,我们可能会有类似下面的代码用于这些类型的用途:

(defun set-temporary-overlay-map (map &optional keep-pred) 
    (let* ((clearfunsym (make-symbol "clear-temporary-overlay-map")) 
     (overlaysym (make-symbol "t")) 
     (alist (list (cons overlaysym map))) 
     (clearfun 
      `(lambda() 
      (unless ,(cond ((null keep-pred) nil) 
          ((eq t keep-pred) 
          `(eq this-command 
            (lookup-key ',map 
               (this-command-keys-vector)))) 
          (t `(funcall ',keep-pred))) 
       (remove-hook 'pre-command-hook ',clearfunsym) 
       (setq emulation-mode-map-alists 
        (delq ',alist emulation-mode-map-alists)))))) 
    (set overlaysym overlaysym) 
    (fset clearfunsym clearfun) 
    (add-hook 'pre-command-hook clearfunsym) 
    (push alist emulation-mode-map-alists))) 
+0

为什么你将overlaysym设置为overlaysym? – nymo 2013-08-31 14:50:48

+0

刚刚得知该符号的值需要设置为使临时地图处于活动状态。 – nymo 2013-09-29 21:27:15

相关问题