Q: how to find out if buffer has history?

Is there a cheap way to find out if a buffer has (non-empty) forward or backwards history from lisp? Extra marks for detecting if forward history has multiple branches.

I confess that I am finding the history mechanism a bit opaque!

Reason for asking: I would like cleverer history buttons on the status line…

Yes, there is a way! Example functions:

(defun forward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path (buffer source)))
    (htree:children (htree:current-owner-node history))))

(defun backward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path (buffer source)))
    (htree:all-parents history)))

But, as you can see, it’s just a call to htree:all-parents to know whether there’s backwards history, and htree:children plus htree:current-owner-node for forward history.

You can look at the code in web-mode.lisp and at the htree – the library we use for history storage.

Many thanks. That is super-helpful.

Here is working code that corrects two issues:

  1. (buffer source) should be buffer. A cut/paste issue, I think.
  2. I call these when constructing the status buffer and htree:children, htree:all-parents can error out in that situation (they get passed nill) if I am making a new buffer or window.
(defun forward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path buffer))
    ;; the following errors out on a new buffer or window
    (ignore-errors (htree:children (htree:current-owner-node history)))))

(defun backward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path buffer))
    ;; the following errors out on a new buffer or window
    (ignore-errors (htree:all-parents history))))
1 Like

Time passes and nyxt evolves. Changes in the history library mean that the above code no longer works and should be replaced by:

(defun forward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path buffer))
    ;; ignore-errors for new buffer or window:
    (ignore-errors (htree:children (htree:current (htree:owner history (id buffer)))))))

(defun backward-history-p (&optional (buffer (current-buffer)))
  (with-data-unsafe (history (history-path buffer))
    ;; ignore-errors for new buffer or window:
    (ignore-errors (htree:all-parents history :owner (id buffer)))))