elscreenの挙動をカスタマイズ

風邪をひいてからここ4日間ぐらい、家に閉じこもっております。そこで、以前から興味のあったEmacs lisp, つまり ELisp について調べてみました。なにはともあれ、とりあえずカスタマイズしながら覚えよう、ということで、手元のelファイルの動作の気に入らない点を直していく感じで進めることに。。
最近Emacsを他のテキストエディタIDEのように、タブで表示できないかということに凝っていて、自分に一番合うのはelscreen.elだったようです。いや、ホントこれ作った人は偉大だと思いました。ありがとうございます。
ところがこのelscreen、通常はスクリーンを指定するのに”C-z 番号”と、2ストロークいるではありませんか。個人的には”Alt-番号”でgnome-terminalのように飛んでほしい。
あと、スクリーンをkillした時点で、例えば[0,1,2,3]からスクリーン[2]をkillすると[0,1,3]となるのも、個人的には詰めてほしい。


以下その自分なりの解決。
前者は.emacs内にキーマップする。

(global-set-key "\M-0" '(lambda () (interactive) (elscreen-goto 9)))
(global-set-key "\M-1" '(lambda () (interactive) (elscreen-goto 0)))
(global-set-key "\M-2" '(lambda () (interactive) (elscreen-goto 1)))
(以下同様)

デフォルトのジャンプ関数 elscreen-jump は、どうやらそれが呼ばれたとき、最後に押されたキーから数字を得て elscreen-goto を読んでいるようなので、1ストロークではこの関数は事実上使えません。また、微妙に割り当ての数字が対応してないのは、スクリーン番号を1から始めたかったからです。というのも、キーボード上では1〜9、0の順番なので…。また、それに応じてタブに表示する際の番号は+1しておきました(直書き)。


後者は、以下を追加。

(defun elscreen-insert-internal (screen)
  (elscreen-clone screen)
  (elscreen-kill-internal screen))

(defun elscreen-get-gap-next ()
  (let ((screen-list (sort (elscreen-get-screen-list) '<))
	(screen 0))
    (while (eq (nth screen screen-list) screen)
      (setq screen (+ screen 1)))
    (nth screen screen-list)))

(defun elscreen-get-packed-num ()
  (let ((screen-list (sort (elscreen-get-screen-list) '<))
	(current-screen (elscreen-get-current-screen))
	(screen 0))
    (while (not (eq (nth screen screen-list) current-screen))
      (setq screen (+ screen 1)))
    screen))

(defun elscreen-pack-list ()
  (interactive)
  (let ((next (elscreen-get-gap-next))
	(pack (elscreen-get-packed-num)))
    (while next
      (elscreen-insert-internal next)
      (setq next (elscreen-get-gap-next)))
    (elscreen-goto pack)
    (elscreen-notify-screen-modification 'force)))

こんな感じの elscreen-pack-list という関数を定義して、kill時に自動的に詰めたければ、elscreen-killの最後で実行されるように、elscreen-kill-hookに追加してやる。あと、ついでに elscreen-swap したあと、さっきまで見ていたバッファを追いたいので、それを調整するアドバイスも追加。

;killしたらpackする
(add-hook 'elscreen-kill-hook 'elscreen-pack-list)

;swap前後で同じバッファを表示
(defadvice elscreen-swap
  (after elscreen-swap-jump activate)
  (elscreen-goto (elscreen-get-previous-screen)))

他には、elscreen-swap関数の発展形としてカレントスクリーンを先頭や後尾に挿入する関数や、C-gでキャンセルするまでスクリーン番号を受け取って挿入や削除やらする関数も作ったけど、まぁたいしたものじゃないのでもし需要があればということで。
今回はちょっと始めてということもあってがむしゃらに作ったんですが、Elispもやってみると意外とイケるかもしれません。なによりEmacsをかなり細かくカスタマイズできることが嬉しい! 以前は先人の作ったコードを探してコピペするしか能が無かったので…
しかしこうして日記としてまとめるだけでより粗が削れていい感じがしますね。というのも、add-hookやdefadviceのとことかはこの日記を書いてて気づいたことだし、それ以前はelscreen.elのコードを縦横無尽に直いじりしまっていたので…
まぁ、今回は独自関数部が多くなってしまったのと、表示スクリーン番号の値を直に編集してしまっている(多分アドバイスでは全書き換え以外では実現できないと思う)ので、主要関数定義は.emacsではなくelscreen.elの方にしてやりました。もちろん、全部.emacsの中に放り込んでやっても大丈夫な様です。

しかし…

はてなにはスーパーPRE記法とかあったのね。最初PREタグ使ってるのにソースコードがおかしくなってげんなりしたけど、色もつけれる表示機能があったとは。
まぁでもLispの色はイマイチかも…