2

私はマイナーモードを定義しようとしていますが、それを模倣していますisearch-mode(これは一種のインタラクティブな検索と置換ツールであるため、良い出発点になると思いました)。私のコマンドは(グローバルキーバインディングでテストされて)うまく機能しますが、ローカルで(マイナーモードマップで)いくつかのキー、つまり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))

(もちろん、キーマップをマイナーモードマップアリストに入れました。

スペースバウンドコマンドは正常に機能しますが、TABとRETはどういうわけか機能しません。たとえば、「\t」を「[f11]」に変更すると、正常に機能します。「ベクトル表記」([?\ t])を使用してみたところ、同じ結果が得られました(Ch Cvを実行した後、キーマップを作成しても驚くことではありませんでした)。何が起こっているのでしょうか?

編集:問題を明確にするために、私はそれを分離しようとしました、そして私は次のコードを思いつきました。tabbangTabキーで感嘆符を挿入する、人工的な、かなり最小限のマイナーモードが必要だとします。私はこれをやっています:

(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はモードを終了します(正しい)が、改行を挿入します(間違っています)。そして、他のコードが介入しないように(site-fileと.emacsをロードせずに)「新鮮な」emacsを試してみました(yasnippetがTABなどをキャプチャするのを恐れていました)。

4

3 に答える 3

5

それぞれ「\t」と「\r」の代わりに変更できると思います(kbd "<tab>")(kbd "<return>")


あなたの編集に応えて、はい、以下は私にとって完璧に機能します:

...
(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)
...
于 2012-02-04T04:31:24.340 に答える
3

問題は次のとおりです。一部のキーはfunction-key-mapを介して変換されます。これは、キーがバインドされていない場合にのみ変換を実行します。たとえば、Tabキーを押したときにGUIで生成された[tab]イベントは、[tab]にバインドされていない場合、[?\t]に変換されます。[?\r]にマップされる[return]についても同じです。ここで問題となるのは、キャッチオール[t]バインディングは、任意のキーシーケンスにバインディングがあることを意味するため、[tab]が[?\t]に再マップされなくなることです。isearchにも同じ問題があります。isearch-other-meta-charで行うゆがみを参照してください。

この問題への正しいアプローチは、[t]バインディングを回避し、代わりに別の方法で「他のキーの終了モード」を実装することだと思います(最近の私の親指のルールは次のとおりです。 -コマンドイベント、あなたはおそらくそれを間違っています」)。これを行う1つの方法は、 `this-command'が自分のものであるかどうか、または(this-command-keys-vector)がキーマップにバインドされているかどうかをチェックするpre-command-hookを使用することです。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)))
于 2012-02-08T21:29:29.333 に答える
0

文字列 "tab" (つまり、 で得られるもの"\t") は、有効なキー名に対応していません。"\C-i"タブと"\C-j"改行のようなものが必要です。

于 2012-02-04T10:48:19.193 に答える