helpful icon indicating copy to clipboard operation
helpful copied to clipboard

[Feature request] helpful-go-back, helpful-go-forward functions

Open sebmiq opened this issue 4 years ago • 3 comments

Hi, I've recently been trying this package out.

help-mode provides help-go-back and help-go-forward functions that I find helpful to navigate the help.

I couldn't find any similar feature for helpful.

Regards,

sebmiq avatar Oct 03 '20 09:10 sebmiq

I would love to see those, too.

srnnkls avatar Oct 16 '20 15:10 srnnkls

I am currently experimenting with something like that in my own config. This is what I have so far, feel free to use it until the devs get around to implementing this feature.

;; Only needed when using Doom Emacs with (featurep! :ui popup).
(set-popup-rule! "^\\*helpful " :size 0.35 :ttl nil :select t)

(defvar *helpful-buffer-ring-size 5
  "How many buffers are stored for use with `*helpful-next'.")

(defvar *helpful--buffer-ring (make-ring *helpful-buffer-ring-size)
  "Ring that stores the current Helpful buffer history.")

(defun *helpful--buffer-index (&optional buffer)
  "If BUFFER is a Helpful buffer, return it’s 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 *helpful--buffer-ring) buf #'eq))))

;; This macro is basically just `defun' + `advice-add'.
(defadvice! *helpful--new-buffer-a (help-buf)
  "Update the buffer ring according to the current buffer and HELP-BUF."
  :filter-return #'helpful--buffer
  (let ((buf-ring *helpful--buffer-ring))
    (let ((newer-buffers (or (*helpful--buffer-index) 0)))
      (dotimes (_ newer-buffers) (ring-remove buf-ring 0)))
    (when (/= (ring-size buf-ring) *helpful-buffer-ring-size)
      (ring-resize buf-ring *helpful-buffer-ring-size))
    (ring-insert buf-ring help-buf)))

(defun *helpful--next (&optional buffer)
  "Return the next live Helpful buffer relative to BUFFER."
  (let ((buf-ring *helpful--buffer-ring)
        (index (or (*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 *helpful--previous (&optional buffer)
  "Return the previous live Helpful buffer relative to BUFFER."
  (let ((buf-ring *helpful--buffer-ring)
        (index (1+ (or (*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)))))

(defun *helpful-next ()
  "Go to the next Helpful buffer."
  (interactive)
  (when-let (buf (*helpful--next))
    (funcall helpful-switch-buffer-function buf)))

(defun *helpful-previous ()
  "Go to the previous Helpful buffer."
  (interactive)
  (when-let (buf (*helpful--previous))
    (funcall helpful-switch-buffer-function buf)))

Janfel avatar Oct 28 '21 22:10 Janfel