[emacs] powerline.el + windows.el だと mode line が残念なことになったので修正した.
前々から気にはなっていましたが, それほど急いで導入するほどでもないかなーと思っていた powerline を, こちらのサイト を参考にして導入してみました.
とりあえず入れた直後は「おー, こりゃ cool だ! 」といった感じでしたが, 私の環境ではいくつか不都合がありました. (しかも致命的)
- windows.el を使っていると, そもそも mode-line が消える orz
- git とかの管理下にあるファイルを開くと mode-line が消える orz
1 点目はとてつもなく致命的で, 基本的に一回でも windows.el でウィンドウ構成を切り替えると, 何もしなければ未来永劫 mode-line は復活しません.
2 点目もかなり致命的で, 私は最近ソースを弄る時には SCM を必ず利用するようにしているため, それらのソースを開くとこれまた mode-line が見えなくなります. ただし, この場合は 1 点目よりはまだましで, SCM の管理下ではないバッファを開けばとりあえず問題はありません.
まだ windows.el を利用している人がどれくらいいるのかは甚だ疑問ではありますが, 自分の環境では上が直らないとせっかくのいけてる powerline.el が使えませんので, 修正してみました.
以下がその diff になります.
*** /home/derui/.emacs.d/auto-install/powerline.el 2012-05-03 09:22:47.390059651 +0900 --- /home/derui/.emacs.d/auto-install/powerline.el.mod 2012-05-03 09:10:22.249108844 +0900 *************** *** 346,356 **** diff -c /home/derui/.emacs.d/auto-install/powerline.el /home/derui/.emacs.d/auto-install/powerline.el.mod *** /home/derui/.emacs.d/auto-install/powerline.el 2012-05-03 10:31:52.939418976 +0900 --- /home/derui/.emacs.d/auto-install/powerline.el.mod 2012-05-03 10:29:52.926426900 +0900 *************** *** 345,356 **** (propertize string 'face plface 'mouse-face plface 'local-map localmap) (propertize string 'face plface)) ""))) (defun powerline-make (side string color1 &optional color2 localmap) ! (cond ((and (eq side 'right) color2) (powerline-make-right string color1 color2 localmap)) ! ((and (eq side 'left) color2) (powerline-make-left string color1 color2 localmap)) ! ((eq side 'left) (powerline-make-left string color1 color1 localmap)) ! ((eq side 'right) (powerline-make-right string color1 color1 localmap)) ! (t (powerline-make-text string color1 localmap)))) (defmacro defpowerline (name string) `(defun ,(intern (concat "powerline-" (symbol-name name))) (side color1 &optional color2) --- 345,369 ---- (propertize string 'face plface 'mouse-face plface 'local-map localmap) (propertize string 'face plface)) ""))) + (defun powerline-print-func (ls) + (cond ((stringp ls) ls) + ((symbolp ls) + (cond ((and (not (eq ls nil)) (not (eq ls t))) + (powerline-print-func (symbol-value ls))) + (t ""))) + ((listp ls) + (let ((tmp "")) + (dolist (i ls) + (setq tmp (concat tmp (powerline-print-func i)))) + tmp)) + (t ""))) (defun powerline-make (side string color1 &optional color2 localmap) ! (let ((real-string (powerline-print-func string))) ! (cond ((and (eq side 'right) color2) (powerline-make-right real-string color1 color2 localmap)) ! ((and (eq side 'left) color2) (powerline-make-left real-string color1 color2 localmap)) ! ((eq side 'left) (powerline-make-left real-string color1 color1 localmap)) ! ((eq side 'right) (powerline-make-right real-string color1 color1 localmap)) ! (t (powerline-make-text real-string color1 localmap))))) (defmacro defpowerline (name string) `(defun ,(intern (concat "powerline-" (symbol-name name))) (side color1 &optional color2) *************** *** 434,440 **** (defpowerline emacsclient mode-line-client) (defpowerline vc (when (and (buffer-file-name (current-buffer)) vc-mode) ! vc-mode-line)) (defpowerline percent-xpm (propertize " " 'display (let (pmax --- 447,453 ---- (defpowerline emacsclient mode-line-client) (defpowerline vc (when (and (buffer-file-name (current-buffer)) vc-mode) ! vc-mode)) (defpowerline percent-xpm (propertize " " 'display (let (pmax
修正点とか
結局何が問題だったのかは, diff を見ていただければわかると思いますが, windows.el の場合はちょっとわかりづらいし, 自分の備忘録も兼ねて書いておきます.
windows.el を利用している時に mode-line に表示される [a] とかは, windows.el で定義されている win:mode-string という変数に格納されています.
で, これが global-mode-string というグローバル変数に入れられ, それが mode-line に表示されているのですが, windows.el の作法が悪いのか powerline.el の処理が足らなかったのか, その辺はよくわかりませんが, windows.el では以下のような形で global-mode-string に win:mode-string を格納していました.
(or global-mode-string (setq global-mode-string '(""))) (or (memq 'win:mode-string global-mode-string) (setq global-mode-string (append global-mode-string '(win:mode-string))))
global-mode-string が nil だったら初期値として空文字列だけを要素とするリストを代入しています. つまりはこの時点で, global-mode-string はリストになっている, ということなのですが.
ここで, powerline.el での肝 (たぶん) となる関数を見てみると・・・.
(defun powerline-make (side string color1 &optional color2 localmap) (cond ((and (eq side 'right) color2) (powerline-make-right string color1 color2 localmap)) ((and (eq side 'left) color2) (powerline-make-left string color1 color2 localmap)) ((eq side 'left) (powerline-make-left string color1 color1 localmap)) ((eq side 'right) (powerline-make-right string color1 color1 localmap)) (t (powerline-make-text string color1 localmap))))
上の関数は, defpowerline マクロで呼ばれている関数ですが, この第二引数に global-mode-string が渡されています. ちなみに, さらに渡されている powerline-make-* では, propertize に利用されているだけなので, つまりはただの文字列でないとなりません.
・・・というわけで、ここに渡ってきたリストやらなんやらの中身について、シンボルとかリストとかなら展開して、文字列ならそのまま、それ以外は空文字列として扱うことにしました。mewとかもこれで一先ずは動いているようです。
vc-mode の方は多分 typo だとは思いますが, 元の vc-mode-line は関数なので, 評価したところで void-variable となってしまいます. vc-mode というのが, mode-line に出力されている文字列のようでしたので, vc-mode-line を vc-mode に変えただけです.