2012-02-04 85 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

相關問題