feat(emacs-lisp): add back/forward commands for helpful

Adapted from Janfel's snippet in Wilfred/helpful#250.

And bound to C-{o,i} and {<,>} for evil users, and C-c C-{b,f} and {l,r}
for vanilla users (mirroring the back/forward keybinds for help.el).

Ref: Wilfred/helpful#250
This commit is contained in:
Henrik Lissner
2025-04-16 23:40:17 -04:00
parent 8f97949975
commit 20381dea16
3 changed files with 75 additions and 2 deletions

View File

@ -1,4 +1,4 @@
;;; lang/emacs-lisp/autoload.el -*- lexical-binding: t; -*-
;;; lang/emacs-lisp/autoload/emacs-lisp.el -*- lexical-binding: t; -*-
;;
;;; Library

View File

@ -0,0 +1,62 @@
;;; lang/emacs-lisp/autoload/helpful.el -*- lexical-binding: t; -*-
(defvar +emacs-lisp--helpful-buffer-ring-size 5
"How many buffers are stored for use with `*helpful-next'.")
(defvar +emacs-lisp--helpful-buffer-ring (make-ring +emacs-lisp--helpful-buffer-ring-size)
"Ring that stores the current Helpful buffer history.")
(defun +emacs-lisp--helpful-buffer-index (&optional buffer)
"If BUFFER is a Helpful buffer, return its index in the buffer ring."
(let ((buf (or buffer (current-buffer))))
(and (eq (buffer-local-value 'major-mode buf) 'helpful-mode)
(seq-position (ring-elements +emacs-lisp--helpful-buffer-ring) buf #'eq))))
;;;###autoload
(defun +emacs-lisp-record-new-buffers-a (buf)
"Update the buffer ring according to the current buffer and HELP-BUF."
(let ((buf-ring +emacs-lisp--helpful-buffer-ring))
(let ((newer-buffers (or (+emacs-lisp--helpful-buffer-index) 0)))
(dotimes (_ newer-buffers) (ring-remove buf-ring 0)))
(when (/= (ring-size buf-ring) +emacs-lisp--helpful-buffer-ring-size)
(ring-resize buf-ring +emacs-lisp--helpful-buffer-ring-size))
(ring-insert buf-ring buf)))
(defun +emacs-lisp--helpful-next (&optional buffer)
"Return the next live Helpful buffer relative to BUFFER."
(let ((buf-ring +emacs-lisp--helpful-buffer-ring)
(index (or (+emacs-lisp--helpful-buffer-index buffer) -1)))
(cl-block nil
(while (> index 0)
(cl-decf index)
(let ((buf (ring-ref buf-ring index)))
(if (buffer-live-p buf) (cl-return buf)))
(ring-remove buf-ring index)))))
(defun +emacs-lisp--helpful-previous (&optional buffer)
"Return the previous live Helpful buffer relative to BUFFER."
(let ((buf-ring +emacs-lisp--helpful-buffer-ring)
(index (1+ (or (+emacs-lisp--helpful-buffer-index buffer) -1))))
(cl-block nil
(while (< index (ring-length buf-ring))
(let ((buf (ring-ref buf-ring index)))
(if (buffer-live-p buf) (cl-return buf)))
(ring-remove buf-ring index)))))
;;;###autoload
(defun +emacs-lisp/helpful-next ()
"Go to the next Helpful buffer."
(interactive)
(if-let* ((buf (+emacs-lisp--helpful-next)))
(funcall helpful-switch-buffer-function buf)
(user-error "No helpful buffer to switch to")))
;;;###autoload
(defun +emacs-lisp/helpful-previous ()
"Go to the previous Helpful buffer."
(interactive)
(if-let* ((buf (+emacs-lisp--helpful-previous)))
(funcall helpful-switch-buffer-function buf)
(user-error "No helpful buffer to switch to")))
;;; helpful.el ends here

View File

@ -318,9 +318,20 @@ current buffer."
;; Open help:* links with helpful-* instead of describe-*
(advice-add #'org-link--open-help :around #'doom-use-helpful-a)
;; Keep a record of buffers so our next/previous commands work.
(advice-add #'helpful--buffer :filter-return #'+emacs-lisp-record-new-buffers-a)
(map! :map helpful-mode-map
:ng "o" #'link-hint-open-link
:n "gr" #'helpful-update))
:n "gr" #'helpful-update
:n "C-o" #'+emacs-lisp/helpful-previous
:n [C-i] #'+emacs-lisp/helpful-next
:n "<" #'+emacs-lisp/helpful-previous
:n ">" #'+emacs-lisp/helpful-next
"C-c C-b" #'+emacs-lisp/helpful-previous
"C-c C-f" #'+emacs-lisp/helpful-next
"l" #'+emacs-lisp/helpful-previous
"r" #'+emacs-lisp/helpful-next))
;;