EmacsのC-hでBackspaceするのに紆余曲折したことのメモ

key-translation-map あるいは bind-key* で解決

gnu_emacs_002.jpg

Ctrl+hC-h )でカーソルの前の文字を削除する、つまりバックスペースするというのは UNIX 系ではよくあるキーバインディングで、端末エミュレータなんかでよく使う。

右上の遠いところにある BackSpace まで指を持っていかなくっていい。するとキーボード操作が早くなって生産性は上がるはずだし、だったらそれはイライラが少しでも減る、ということでしょう。

それはなにより Emacs でもかように願いたい、となるのだけれど、どういうわけだか Emacs では C-h がヘルプ機能になっているものだから、設定で割り当て直す必要がある。

それでこれを設定するのに私はちょっとばかり紆余曲折したので、そのメモをまとめておく。

global-map

Emacs を使い始めたとき、当然のように下のような記述をして、 C-h のヘルプ機能をバックスペースに変えるよう設定した。

(global-set-key (kbd "C-h") 'delete-backward-char)

しかし、使ってみるとミニバッファで働いてくれないことに気づく。 i-search とかでちょっとイライラするよね程度と思いきや、helm (anything)なんかを使い出すとすごく便利な反面でイライラがつのるようになった。だから helm-mode で C-h をバックスペースにするよう設定を書き加えてみたりした。けれどなんだか場当たり的だし、スマートでないような気もする。

keyboard-translate

そこでいくらか調べていくうちに、 keyboard-translate で機能を交換するといいらしいことを聞きかじったのだった。

(keyboard-translate ?\C-h ?\C-?)

これだとミニバッファでも有効だし適確かと思った。それで何年もこれで過ごしたのでした。

さてそれからは GUI Emacs を中心にして、 emacsclient は GUI のウィンドウへ全部送るような使い方をしていたんだけど、故あって Emacs をデーモンモードで起動してターミナルエミュレータ上でも Emacs を使うようにした。

そしたら上記の keyboard-translate の設定が効かなくなってしまった。

これは困った。最初の方法しかないのだろうか。

key-translation-map

これは困ったと EmacsWiki を訪ねてみたところなんか書いてあった。

EmacsWiki Home Backspace Key

自分でもやったようなことも含めていくつかの事が書いてあり、以下のように記述するのが確実っぽい。

(define-key key-translation-map [?\C-h] [?\C-?])

実際にやってみるとターミナルエミュレータ上の Emacs でも C-h でバックスペースできる。よかった。

なお、ヘルプの機能は F1 キーでも使えるけれど、ファンクションキーが使い難いという時もある。

私のキーボードは A キーの左が Control キーで、その下に Shift キーがある。だから Control キーを押すその小指をピンと伸ばすことで、一緒に Shift キーを押せてしまう。そこで Control+Shift+/ にヘルプ機能をあてている。すなわち、

(global-set-key (kbd "C-?") 'help-for-help)

としている。

M-? にするという話もきく。

bind-key*

私のパッケージ管理は el-get ばかり使ってきたのだけれど、 package.el + use-package の組み合わせが良いと聞いたので使ってみたら use-package はものすごくいいものとわかった。

いつもナーバスになってしまう autoload だの eval-after-load だのに煩わされなくなるし、 el-get-bundle みたいなやつもできるし、ほかにも色々便利があって、私は精神の安定を図ることができた。ありがとうございます。

そこらへんはお題が違うからこれくらいにしたいけれど、ここで触れたいのは use-package が依存する bind-key パッケージ。

これは冒頭にもあるような、ドッティーマックス(dot_emacs擬人化)内で頻繁に書く、

(define-key global-map (kbd "C-x C-j") 'hoge-commando)

みたいな、キーバインディングを決めるあれを、

(bind-key "C-x C-j" 'hoge-commando)

みたいに短く書けてしまう。

加えて、 bind-key* / bind-keys* (ケツにアスタリスク)というのがあって、 define-key だとモードによっては上書きされてしまうようなときも、これを使うとガッチリとあてて上書きされないようにしてくれる。これは今回のお題にピッタリ。

この bind-key* でもって delete-backward-charC-h に当てれば、上述した helm のバッファなんかでもきちんとバックスペース機能が働いてくれる。コンソール版でも試してみたけれど、これも問題ない。

導入方法としては、MELPAリポジトリをパッケージアーカイブリストに追加した状態で bind-key パッケージをインストールし (bind-key* "C-h" 'delete-backward-char) を評価するようにする。

MELPA の追加から記述すると以下のように。

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(package-initialize)

(unless (require 'bind-key nil t)
  (package-refresh-contents)
  (package-install 'bind-key))
(bind-key* "C-h" 'delete-backward-char)

どの方法がいい

なんだかだらだらと書いてしまったのだけれど、私が思うのは bind-key はシンプルでイイ。けれどパッケージのインストールを必要とするから、キーバインディングという基本的な設定要素を扱ううえでは二の足を踏む向きも少なからずおいでかと思う。

だって私もパッケージの試用で最小構成のドッティーを持ち出すことがあるけれど、そこでは key-translation-mapC-h にバックスペースをバインドしている。

もっとも、将来 use-package が Emacs 標準になる可能性もある。ぜひなってほしいなぁと思った。

おまけ(蛇足)のメモ

私は use-package はすごくいいものと思うのでインストールのところをちょっとまとめた。以下は Emacs を起動すると最初だけ use-package をインストールする。ドッティーマックスの最初のほうに付け加えるとイイ。なお use-package を入れるとお題の bind-key も依存解決でインストールされるのだった。

;; add MELPA and initialize
(when (require 'package nil t)
  (add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
  (package-initialize)
  ;; install use-package if not there
  (unless (require 'use-package nil t)
    (unless package-archive-contents (package-refresh-contents))
    (package-install 'use-package)))

when だの unless だのとエラー回避が煩わしいけれど、use-package を入れた後の記述ではそういうのを少なくできる。

use-package の詳しい扱い方は以下を。

Revisions

  • [2016-02-16 Tue] bind-key を追記

スポンサードリンク