Emacsでhelp-fns+の代わりとしてhelpfulを使ってみたら代わり以上に良かった
help-fns+の消失
Emacsに help-fns+.el というパッケージがあります.
これはまあ色々とコマンドを提供しているのですが,
私が主に使っていたのはdescribe-keymap
でした.
Emacsの普通のdescribe-variable
で例えばhelpful-mode-map
のようなキーマップを参照すると,
のようにキーコードが数字で表示されてしまいます. これでは一部の変人以外は何がなんだかわかりませんね.
describe-keymap
で呼び出すとキーコードではなくEmacsのkbd関数引数風の文字列で表示してくれるため,
私にも読める画面になりました.
しかしこのパッケージはmelpaから削除されてしまっています.
Update on MELPA removing EmacsWiki packages: They are no longer available on MELPA as of 2018-01-24. Help-fns+ and dired+ (among others) are no longer available on MELPA. : emacs によると, melpaがEmacsWikiからのホスティングを拒否して, help-fns+の作者がEmacsWikiからの移動を拒否したから削除されたようですね.
これはもう2年ぐらい前の話なのですけれど, 私はelpaをgit commitするという狂った管理方法を使っていたため, この影響を受けませんでした.
しかし最近leaf管理に移行しました. 私の.emacs.dをelpaをgit管理下に入れる気の狂った管理方法からleafに移行させました - ncaq
なのでmelpaにないパッケージを使うのが今更面倒になったわけです.
helpful
代替を探して見つけたのが Wilfred/helpful: A better Emacs help buffer でした.
READMEにも
This project has been heavily influenced by:
help+.el, help-fns+.el, help-mode+.el Dave Williams' demo of Lucid's Energize
と書いてありますね.
私はこれを
(leaf helpful
:ensure t
:require t
:bind
([remap describe-function] . helpful-callable)
([remap describe-key] . helpful-key)
([remap describe-variable] . helpful-variable)
:defvar helpful-mode-map
:config (ncaq-set-key helpful-mode-map))
として既存のdescribe系関数を置き換えるように設定しています.
また
(leaf elisp-slime-nav
:ensure t
:bind (:elisp-slime-nav-mode-map ("C-c C-d" . helpful-at-point))
:hook emacs-lisp-mode-hook help-mode-hook)
とelisp-slime-nav-describe-elisp-thing-at-point
の代わりに使うように設定しました.
これで
のように読める表記で表示してくれます.
しかしDvorakを使ってる都合上define-key
でnilを設定しまくっているのでnilだらけで汚いですね…
nilにするのではなく取り除く関数は何処かにあるのでしょうか…
ところでこのhelpful, 単にキーコードを読める化してくれるだけではなく, 色々と便利な機能が付いていました.
その変数や関数の定義元やソースコード(C言語でもOK)の抜粋を見せてくれたり, ボタンを押すことでサクッと代入が出来たり, 逆にキーコードに戻してくれたりなど.
こんな便利なものがあるとは知りませんでした. これまで使ってなくて損していましたね.
フォーカスを移さないで欲しかったのが解決しました
このhelpful-at-point
, elisp-slime-nav-describe-elisp-thing-at-point
と違ってフォーカスをヘルプを開いたウィンドウに移してしまいます.
Emacs Lispを書いていてサクッと定義を知りたくて呼び出したら後はコーディングに戻りたいため, フォーカスを移すのは余計な動作に感じます.
解決策を探して,
helpful-switch-buffer-function
に関数を設定してあげれば挙動が変わることがわかりました.
そう言えば似たような問題を解決した経験があると思ってinit.el
を見てみたら以下の関数が見つかりました.
(defun pop-to-buffer-without-switch (buffer-or-name &optional action norecord)
"本当にwithout switchしているわけではなく前のウィンドウにフォーカスを戻すだけ"
(pop-to-buffer buffer-or-name action norecord)
(other-window -1))
強引すぎる…
しかしこの関数を設定してあげてもエラーで動かないんですよね.
cl--assertion-failed: Assertion failed: (not (null helpful--sym))
というエラーが出てきます.
バッファを切り替えてしまっているので
(cl-assert (not (null helpful--sym)))
に失敗するようです.
ウィンドウ作ってからupdateしているからですね.
かと言ってアップデート後にadviceをかけても…
いやhelpful-at-point
にadviceをかければ良いのか.
:advice (:after helpful-at-point other-window-backward)
を付け加えてみましょう.
解決しました.
でも流石に強引すぎる方法だからあまり嬉しくはないですね…
最終的にはこう.
(leaf helpful
:ensure t
:require t
:bind
([remap describe-function] . helpful-callable)
([remap describe-key] . helpful-key)
([remap describe-variable] . helpful-variable)
:defvar helpful-mode-map
:advice (:after helpful-at-point other-window-backward)
:config (ncaq-set-key helpful-mode-map))