helpful.el 应该不少人用,比自带的help功能强很多。唯一的痛点是,helpful不像help那样,永远只用一个window,并且还有back/forward按钮;而是每次都创建一个新buffer并占用一个新window,back/forward也没有。
我搞了一下,现在helpful只占用一个window并且顶端有back/forward按钮:
(use-package helpful
:commands (helpful-callable
helpful-variable
helpful-key
helpful-at-point)
:config
(setq helpful-max-buffers 5)
;; don't pop new window
(setq helpful-switch-buffer-function
(lambda (buf) (if-let ((window (display-buffer-reuse-mode-window buf '((mode . helpful-mode)))))
;; ensure the helpful window is selected for `helpful-update'.
(select-window window)
;; line above returns nil if no available window is found
(pop-to-buffer buf))))
(defvar moon-helpful-history () "History of helpful, a list of buffers.")
(advice-add #'helpful-update :around #'moon-helpful@helpful-update)
(advice-add #'helpful--buffer :around (lambda (oldfunc &rest _)
(let ((buf (apply oldfunc _)))
(push buf moon-helpful-history)
buf))))
(defun moon-helpful@helpful-update (oldfunc)
"Insert back/forward buttons."
(funcall oldfunc)
(let ((inhibit-read-only t))
(goto-char (point-min))
(insert-text-button "Back"
'action (lambda (&rest _)
(interactive)
(moon-helpful-switch-to-buffer (current-buffer) 1)))
(insert " / ")
(insert-text-button "Forward"
'action (lambda (&rest _)
(interactive)
(moon-helpful-switch-to-buffer (current-buffer) -1)))
(insert "\n\n")))
(defun moon-helpful-switch-to-buffer (buffer &optional offset)
"Jump to last SYMBOL in helpful history, offset by OFFSET."
(interactive)
(require 'seq)
(require 'cl-lib)
(setq moon-helpful-history (seq-remove (lambda (buf) (not (buffer-live-p buf))) moon-helpful-history))
(cl-labels ((find-index (elt lst)
(let ((idx 0)
(len (length lst)))
(while (and (not (eq elt (nth idx lst)))
(not (eq idx len)))
(setq idx (1+ idx)))
(if (eq idx len)
nil
idx))))
(let ((idx (+ (or offset 0) (find-index buffer moon-helpful-history))))
(if (or (>= idx (length moon-helpful-history))
(< idx 0))
(message "No further history.")
(switch-to-buffer (nth idx moon-helpful-history))))))