TABとは異なるCiをバインドする方法は?


15

Control-i実行したいindent-region(基本的にはXcodeがそのマッスルメモリを既に構築しているため)。

私はそれを実現Control-iし、tabアスキーの意味では区別できないが、彼らはキーコードの意味です。

私は明白なことを試しました:

(global-unset-key (kbd "C-i"))
(global-set-key (kbd "C-i") 'indent-region)

役に立たない-を押すとControl-itabキーが現在のコンテキストで行うことは何でも実行されます。Emacsがタブボタンを別の方法で扱うのを助けるためにできることはありますControl-iか?

更新:リージョンが選択されたときにtab/ Control-iプレスが何をするかを再マッピングできることで、同等の結果が達成されると思います。


1
これはGUIフレームからですか、それとも端末フレームからですか?ターミナルでオーバーライドできるかどうかはわかりません。
14

良いQ、通常はGUIフレームですが、私はサーバーにリモート接続し、時々ターミナルでemacsを使用します(もちろんgit-shared emacs.dで:)
Mark Aufflick 14

回答:


14

これは端末から実現できるとは思いませんが、GUIモードではこれを試すことができます。

(define-key input-decode-map [?\C-i] [C-i])
(global-set-key (kbd "<C-i>") 'indent-region)

と同じことをするC-mので、RET

編集:

GUIモードでもTTYモードでも、次のように機能します。

;; Unbind <C-i> from the TAB key and bind it to indent-region.
;; Since TAB and <C-i> cannot be differentiated in TTY emacs,
;; the workaround is to conditionally bind TAB to indent-region
;; when there is an active region selected.
(if (window-system)
  ; IF we are not in a TTY, unbind C-i from TAB
    (progn
      (define-key input-decode-map [?\C-i] [C-i])
      ; ... and remap it to indent-region
      (global-set-key (kbd "<C-i>") 'indent-region))
  ; ELSE IF we are in a TTY, create a replacement for TAB
  (defun my/tab-replacement (&optional START END)
    (interactive "r")
    (if (use-region-p)
      ; IF active region, use indent-region
        (indent-region START END)
      ; ELSE IF no active region, use default tab command
      (indent-for-tab-command)))
  ; Bind our quick-and-dirty TAB replacement to the TAB key
  (global-set-key (kbd "TAB") 'my/tab-replacement))

それはきれいではありませんが、仕事をしているようです。必要に応じて、このコードの改良または編集を歓迎します。


1
完全に動作します!++はemacs stackexchangeを再度購入します:)
Mark Aufflick

私が考えた小さな問題は、ウィンドウシステムで起動したEmacsに対して端末emacsclientを起動できることです(これは時々行います)。遅延が表示されない場合は、すべての場合にタブ置換機能を使用します。
マークAufflick 14

1
私はちょうどことを追加したい<C-i>[C-i]同様に、任意の識別子だったかもしれない<foobar>[foobar]、それはまだ動作しますが、tabまたはそれを呼び出さないでくださいbackspace
xdavidliu

13

GUIフレーム

GUIフレーム(X11、Windows、OSXなど)では、EmacsはTabキーをtabファンクションキーとして読み取ります。ただし、Tab端末のキーは伝統的に^IControl + I)文字を送信するため、EmacsはtabファンクションキーをControl + I文字(文字9)に変換しますTAB。この変換はを介して行われfunction-key-mapます。

他のいくつかのファンクションキーでも同様の変換が行われます。(BackspaceそしてDelete、私はここで詳細に議論しない厄介なケースです。)

Function key    Translated to character         Notes
                Number  Name  Decomposition
backspace       127     DEL   Ctrl+?            May be translated to C-h instead
tab               9     TAB   Ctrl+I
linefeed         10     LFD   Ctrl+J            Few keyboards have this key
return           13     RET   Ctrl+M
escape           27     ESC   Ctrl+[

+ から完全に分離Tabしたい場合は、次からバインディングを削除します。CtrlIfunction-key-map

(define-key function-key-map [tab] nil)

ただし、のエントリfunction-key-mapはモード固有のキーマップまたはグローバルマップのバインディングによってオーバーライドされるため、これはあまり役に立ちません。あなたは異なるが、バインディング定義したいのであればtab、ちょうどそれを行う(elispのではなく、対話形式で、プロンプト読んキーが適用されるためfunction-key-map、あなたが再バインド終わると思いますので、翻訳をTABしていませんtab)。

(global-set-key [tab] '…)
(define-key some-mode-map [tab] '…)

Tabキーのアクションを変更するすべての標準モードは、キーを変更することで実行しTABます。これはC-i、キーの組み合わせCtrl+ によって生成される文字のニックネームですI。にtabではなく標準のバインディングを適用する場合はC-i、キーfunction-key-mapマップをそのままにしてモードを解除し、代わりにCtrl+ Iを別のキーにリダイレクトします。

(define-key input-decode-map [(control ?i)] [control-i])
(define-key input-decode-map [(control ?I)] [(shift control-i)])
(define-key some-mode-map [control-i] '…)

これで、EmacsはCtrl+ Iを「<control-i>(から翻訳TAB)」として報告します。これはきれいではありませんが、避けられませんTAB。Emacsソースコードに組み込まれている文字9のきれいな印刷です。

端子台

ターミナルフレームでは、問題はより難しく、多くの場合不可能です。端末はキーを送信せず、文字を送信します(実際には、バイトを送信します)。Tabコントロール+ Iで、キーの組み合わせ何と同じ-キーはタブ文字として送信されてCtrl+がI生成されます。対応する文字を持たないファンクションキー(カーソルキーなど)は、エスケープシーケンスとして送信されます。つまり、ESC= Control + [で始まる文字のシーケンスです(これが、Emacs escapeがプレフィックスキーとして定義する理由—プレフィックスであるESC必要があります)。キーボード入力とテキスト出力の仕組みをご覧くださいより多くの背景。

ファンクションキーに異なるキーシーケンスを送信するように構成できる端末はいくつかありますが、多くはありません。LeoNerdのlibtermkey / libtickitThomas Dickeyのxterm(バージョン216以降)の両方がこれをサポートしています。Xtermでは、この機能はオプションであり、modifyOtherKeysリソースを介してアクティブ化されます。ただし、これをサポートするxterm以外の一般的な端末エミュレーター、特にlibvteで構築された多くのエミュレーターは知りません。一部のターミナルエミュレータでは、キーコードからエスケープシーケンスへのユーザー定義の対応を通じて、これを手動で行うことができます。

このメカニズムにより、タブ/ Ci、return / Cm、およびescape / C- [だけでなく、多くのキーの組み合わせを区別できます。より詳細な説明については、ターミナル使用時のキーバインディングの問題を参照してください。

Emacs 24.4以降、基本的なxterm機能がサポートされています。しかし、ファンダメンタルズ(特にはTabReturnEscapeBackspaceそれはアプリケーションが期待するものだから)まだ、従来の制御文字を送信します。Ctrl+ letterが制御文字の代わりにエスケープシーケンスを送信するモードがあります。そのため、ファンクションキーCtrlとEmacs 24.4 の組み合わせを区別するにはmodifyOtherKeys、リソースを1ではなく2に設定して、このモードを使用するためのサポートを変更します。

;; xterm with the resource ?.VT100.modifyOtherKeys: 2
;; GNU Emacs >=24.4 sets xterm in this mode and define
;; some of the escape sequences but not all of them.
(defun character-apply-modifiers (c &rest modifiers)
  "Apply modifiers to the character C.
MODIFIERS must be a list of symbols amongst (meta control shift).
Return an event vector."
  (if (memq 'control modifiers) (setq c (if (or (and (<= ?@ c) (<= c ?_))
                                                (and (<= ?a c) (<= c ?z)))
                                            (logand c ?\x1f)
                                          (logior (lsh 1 26) c))))
  (if (memq 'meta modifiers) (setq c (logior (lsh 1 27) c)))
  (if (memq 'shift modifiers) (setq c (logior (lsh 1 25) c)))
  (vector c))
(defun my-eval-after-load-xterm ()
  (when (and (boundp 'xterm-extra-capabilities) (boundp 'xterm-function-map))
    ;; Override the standard definition to set modifyOtherKeys to 2 instead of 1
    (defun xterm-turn-on-modify-other-keys ()
      "Turn the modifyOtherKeys feature of xterm back on."
      (let ((terminal (frame-terminal)))
        (when (and (terminal-live-p terminal)
                   (memq terminal xterm-modify-other-keys-terminal-list))
          (send-string-to-terminal "\e[>4;2m" terminal))))
    (let ((c 32))
      (while (<= c 126)
        (mapc (lambda (x)
                (define-key xterm-function-map (format (car x) c)
                  (apply 'character-apply-modifiers c (cdr x))))
              '(;; with ?.VT100.formatOtherKeys: 0
                ("\e\[27;3;%d~" meta)
                ("\e\[27;5;%d~" control)
                ("\e\[27;6;%d~" control shift)
                ("\e\[27;7;%d~" control meta)
                ("\e\[27;8;%d~" control meta shift)
                ;; with ?.VT100.formatOtherKeys: 1
                ("\e\[%d;3~" meta)
                ("\e\[%d;5~" control)
                ("\e\[%d;6~" control shift)
                ("\e\[%d;7~" control meta)
                ("\e\[%d;8~" control meta shift)))
        (setq c (1+ c)))))
  (define-key xterm-function-map "")
  t)
(eval-after-load "xterm" '(my-eval-after-load-xterm))

「Emacs 24.24」と言うとき、「Emacs 24.4」という意味ですか?
-tarsius

1
@tarsius initファイルからコピーされたコードのコメントは「24.4」と言っているので、それは正しいと思います。この回答のために書いたテキストの「24.24」は「24.4」の誤字でした。
ジル 'SO-悪であるのをやめる'
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.