解いた問題

3/18/2012

tabbar.elのグループ化機能をせっかくだから使ってみる

ググッて調べてみても、グループ化しているブログの記事をあまり見ない。もちろん、自分でも使っていない。
でも、せっかくだから使ってみる。

デフォだとメジャーモードでタブをグループ化する様になっている。
私感ではこれが使いやすいとは思えないので、自分でグループ化する機能を描いてみる。
まだ使い込んだわけではないので、バグの1つもあると思うけど、そこはご愛嬌。

もう tabbar をいじるのに飽きてきた。

アイデアは"新たなバッファは直近で使用していたバッファと同じグループに属する"という簡単なモノ。


コマンド

  • M-x tabbar-change-group
    • そのバッファの属しているグループを変更する。既存のグループを指定しなかった場合は、新たなグループを作成する。
  • M-x tabbar-switch-to-group
    • 別のタブグループを表示させる。
  • M-x tabbar-kill-group
    • あるグループに属しているバッファを全て閉じる。
  • M-x tabbar-init-groups-name
    • 全てのタブのグループ分けをデフォルトのグループに変更する。たぶん使わない。
  • M-x tabbar-sort-tab
    • そのタブの属しているグループのタブの表示をバッファ名の昇順にソートする。とくに関係ないけど、思いつきで描いた。


キーバインド

  • C-x <up>
    • 表示グループの変更。
  • C-x <down>
    • 表示グループの変更


私の設定では、ボタンを全て非表示にしているので、現在表示しているタブグループの名前が分からない。
場当たり的な対処ではあるけど、とりあえずモードラインにグループ名を表示させておく。
気に入らなければ、変更しましょう。


以下ソース

;; tabbar-buffer-group-function
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(setq tabbar-cycle-scope 'tabs)
;; (define-key global-map (kbd "\C-x <up>") 'tabbar-forward-group)
;; (define-key global-map (kbd "\C-x <down>") 'tabbar-backward-group)
(global-set-key [(C-tab)] 'tabbar-forward-group)
(global-set-key [(C-S-tab)] 'tabbar-backward-group)
;; Switching Between Two Recently Used Buffers
;; http://www.emacswiki.org/emacs/SwitchingBuffers
(defun resently-used-buffer ()
(other-buffer (current-buffer) 1))
;; key : #<buffer>
;; value : group-name
(setq tabbar-groups-hash (make-hash-table :test 'equal))
(defun tabbar-init-groups-name ()
(interactive)
(setq tabbar-groups-hash (make-hash-table :test 'equal)))
(defun tabbar-set-group-name (buff group)
(if (not (equal (buffer-name buff) "*tmp*"))
(puthash buff group tabbar-groups-hash)))
(defun tabbar-get-group-name (buff)
(gethash buff tabbar-groups-hash))
(defun my-tabbar-buffer-groups-function ()
(let ((g (tabbar-get-group-name (current-buffer))))
(if (not g)
(progn
(setq g (or (tabbar-get-group-name (resently-used-buffer)) "Default"))
(tabbar-set-group-name (current-buffer) g)))
(list g)))
;; tabbar.el ってグループの一覧くらい保持してないの? してそうじゃない?
(defun tabbar-get-all-group-name ()
(let (gs unique)
(setq gs (loop for v being the hash-values
in tabbar-groups-hash
collect v))
(setq unique '())
(while gs
(setq unique (cons (car gs) unique))
(setq gs (delq (car gs) gs)))
(sort unique 'string-lessp)))
(defun tabbar-change-group (name)
(interactive
(list (completing-read "group name : "
(tabbar-get-all-group-name))))
(tabbar-set-group-name (current-buffer) name)
(tabbar-display-update))
(defun tabbar-switch-to-group (name)
(interactive
(list (completing-read "group name : "
(tabbar-get-all-group-name))))
(switch-to-buffer (find-if (lambda (buff)
(equal name (tabbar-get-group-name buff)))
(buffer-list))))
(defun tabbar-kill-group (name)
(interactive
(list (completing-read "group name : "
(tabbar-get-all-group-name))))
(mapcar (lambda (buff)
(if (equal name (tabbar-get-group-name buff))
(kill-buffer buff)))
(buffer-list)))
;; ゴミ掃除
(defun tabbar-remove-killed-buffers ()
(let ((entry (loop for k being the hash-keys
in tabbar-groups-hash
using (hash-values v)
collect (cons k v))))
(tabbar-init-groups-name)
(mapcar (lambda (e)
(if (buffer-live-p (car e))
(tabbar-set-group-name (car e) (cdr e))))
entry)))
(setq tabbar-buffer-groups-function 'my-tabbar-buffer-groups-function)
;; こんなに頻繁にやる必要があるのかどうか
(add-hook 'kill-buffer-hook 'tabbar-remove-killed-buffers)
;; とりあえず、モードラインに表示しておく。
(add-to-list 'default-mode-line-format
'(:eval
(concat " [" (format "%s" (tabbar-current-tabset t)) "] ")))
;; tabbar-buffer-group-function ここまで
(defun tabbar-sort-tab ()
(interactive)
(let* ((ctabset (tabbar-current-tabset 't))
(ctabs (tabbar-tabs ctabset)))
(if (and ctabset ctabs)
(progn
(set ctabset (sort ctabs (lambda (b1 b2)
(string-lessp (buffer-name (car b1))
(buffer-name (car b2))))))
(put ctabset 'template nil)
(tabbar-display-update)))))