anchor.diff:        (setf (ps:@ element text-content) hint)
         element))
   
  -  (defun hint-add (element hint)
  -    "Adds a hint on a single element. Additionally sets a unique
  -identifier for every hinted element."
  -    (ps:chain element (set-attribute "nyxt-identifier" hint))
  -    (ps:let ((hint-element (hint-create-element element hint)))
  -      (ps:chain document body (append-child hint-element))))
  -
  -  (defun object-create (element hint)
  -    (cond ((equal "A" (ps:@ element tag-name))
  -           (ps:create "type" "link" "hint" hint "href" (ps:@ element href) "body" (ps:@ element |innerHTML|)))
  -          ((equal "BUTTON" (ps:@ element tag-name))
  -           (ps:create "type" "button" "hint" hint "identifier" hint "body" (ps:@ element |innerHTML|)))
  -          ((equal "INPUT" (ps:@ element tag-name))
  -           (ps:create "type" "input" "hint" hint "identifier" hint "placeholder" (ps:@ element placeholder)))
  -          ((equal "TEXTAREA" (ps:@ element tag-name))
  -           (ps:create "type" "textarea" "hint" hint "identifier" hint "placeholder" (ps:@ element placeholder)))
  -          ((equal "IMG" (ps:@ element tag-name))
  -           (ps:create "type" "img" "hint" hint "identifier" hint "src" (ps:@ element src) "alt" (ps:@ element alt)))
  -          ((ps:@ element onclick)
  -           (ps:create "type" "clickable" "hint" hint "identifier" hint "body" (ps:@ element |innerHTML|)))
  -          ((ps:@ element onfocus)
  -           (ps:create "type" "focusable" "hint" hint "identifier" hint))))
  -
  -  (defun hints-add (elements)
  -    "Adds hints on elements"
  -    (ps:let* ((elements-length (length elements))
  -              (hints (hints-generate elements-length)))
  -      (ps:chain |json|
  -                (stringify
  -                 (loop for i from 0 to (- elements-length 1)
  -                       when (and (nyxt/ps:element-drawable-p (elt elements i))
  -                                 (nyxt/ps:element-in-view-port-p (elt elements i)))
  -                       do (hint-add (elt elements i) (elt hints i))
  -                       when (or (and (nyxt/ps:element-drawable-p (elt elements i))
  -                                     (not (ps:lisp annotate-visible-only-p)))
  -                                (and (nyxt/ps:element-drawable-p (elt elements i))
  -                                     (nyxt/ps:element-in-view-port-p (elt elements i))))
  -                       collect (object-create (elt elements i) (elt hints i)))))))
  -
  -  (defun hints-determine-chars-length (length alphabet)
  -    "Finds out how many chars long the hints must be"
  -    (floor (+ 1 (/ (log length) (log (ps:@ alphabet length))))))
  -
  -  (defun hints-generate (length)
  -    "Generates hints that will appear on the elements"
  -    (ps:let ((alphabet (ps:lisp (hints-alphabet (current-mode 'web)))))
  -      (strings-generate length alphabet)))
  -
  -  (defun strings-generate (length alphabet)
  -    "Generates strings of specified length"
  -    (ps:let ((chars-length (hints-determine-chars-length length alphabet)))
  -      (ps:let ((minimum (1+ (ps:chain -math (pow (ps:@ alphabet length)
  -                                                 (- chars-length 1))))))
  -        (loop for i from minimum to (+ minimum length)
  -              collect (string-generate i alphabet)))))
  -
  -  (defun string-generate (n alphabet)
  -    "Generates a string from a number"
  -    (ps:let ((alphabet-length (ps:@ alphabet length)))
  -      (if (>= n 0)
  -          (+ (string-generate (floor (- (/ n alphabet-length) 1)) alphabet)
  -             (aref alphabet (rem n alphabet-length))) "")))
  -
  -  (add-stylesheet)
  -  (hints-add (nyxt/ps:qsa document (list "a" "button" "input" "textarea" "img"))))
  +  (let ((element (nyxt/ps:qs document (ps:lisp (format nil "[nyxt-identifier=\"~a\"]" nyxt-identifier)))))
  +    (ps:chain element (set-attribute "nyxt-identifier" (ps:lisp hint)))
  +    (ps:let ((hint-element (hint-create-element element (ps:lisp hint))))
  +      (ps:chain document body (append-child hint-element)))))
  +
  +(defun add-element-hints (&key (selectors '("a" "button" "input" "textarea")))
  +  ;; TODO: Use hint generator from https://github.com/atlas-engineer/nyxt/issues/1290 maybe?
  +  (labels ((select-from-alphabet (code char-length alphabet)
  +             (let* ((exponents (nreverse (loop for pow below char-length
  +                                               collect (expt (length alphabet) pow)))))
  +               (coerce (loop for exp in exponents
  +                             for quotinent = (floor (/ code exp))
  +                             collect (aref alphabet quotinent)
  +                             do (decf code (* quotinent exp)))
  +                       'string)))
  +           (generate-hints (length)
  +             (let* ((alphabet (hints-alphabet (current-mode 'web)))
  +                    (char-length (ceiling (log length (length alphabet)))))
  +               (loop for i below length collect (select-from-alphabet i char-length alphabet)))))
  +    (let* ((dom (update-document-model))
  +           (hintable-elements (alex:mappend #'(lambda (selector)
  +                                                (coerce (clss:select selector dom) 'list))
  +                                            selectors))
  +           (hints (generate-hints (length hintable-elements))))
  +      (add-stylesheet)
  +      (mapcar #'(lambda (elem hint)
  +                  (hint-element (get-nyxt-id elem) hint)
  +                  (plump:set-attribute elem "nyxt-hint" hint)
  +                  elem)
  +              hintable-elements hints))))
   
   (define-parenscript remove-element-hints ()
     (defun hints-remove-all ()
  
positive.code:                    (make-instance
                      'hint-source
                      :multi-selection-p multi-selection-p
                      :constructor
                      (elements-from-json (add-element-hints
                                           :annotate-visible-only-p annotate-visible-only-p)))
                     :after-destructor
                     (lambda ()
                       (with-current-buffer buffer
                         (remove-element-hints))))))
        (funcall function result))))
  
  (defun elements-from-json (elements-json)
    (loop for element in (cl-json:decode-json-from-string elements-json)
          collect (str:string-case (alex:assoc-value element :type)
                    ("link"
                     (make-instance 'link-hint
                                    :hint (alex:assoc-value element :hint)
                                    :identifier (alex:assoc-value element :hint)
                                    :url (quri:uri (alex:assoc-value element :href))
                                    :body (plump:text (plump:parse (alex:assoc-value element :body)))))
                    ("button"
                     (make-instance 'button-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :hint (alex:assoc-value element :hint)
                                    :body (plump:text (plump:parse (alex:assoc-value element :body)))))
                    ("input"
                     (make-instance 'input-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :hint (alex:assoc-value element :hint)
                                    :placeholder-text (alex:assoc-value element :placeholder)))
                    ("textarea"
                     (make-instance 'textarea-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :hint (alex:assoc-value element :hint)
                                    :placeholder-text (alex:assoc-value element :placeholder)))
                    ("img"
                     (make-instance 'image-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :url (quri:uri (alex:assoc-value element :src))
                                    :alt (alex:assoc-value element :alt)
                                    :hint (alex:assoc-value element :hint)))
                    ("clickable"
                     (make-instance 'clickable-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :hint (alex:assoc-value element :hint)
                                    :body (plump:text (plump:parse (alex:assoc-value element :body)))))
                    ("focusable"
                     (make-instance 'focusable-hint
                                    :identifier (alex:assoc-value element :identifier)
                                    :hint (alex:assoc-value element :hint))))))
  
  (define-class hint ()
    ((hint "")
     (identifier "")
     (body ""
           :documentation "The body of the anchor tag."))
    (:accessor-name-transformer (hu.dwim.defclass-star:make-name-transformer name)))
  
  (defmethod prompter:object-attributes ((hint hint))
    `(("Hint" ,(hint hint))
      ("Body" ,(body hint))
      ("URL" ,(if (slot-exists-p hint 'url) (render-url (url hint)) ""))))
  
  (define-class clickable-hint (hint) ())
  
  (define-class focusable-hint (hint) ())
  
  (define-class button-hint (clickable-hint) ())
  
  (define-class link-hint (hint)
    ((url (quri:uri "")))
    (:accessor-name-transformer (hu.dwim.defclass-star:make-name-transformer name)))
  
  (define-class input-hint (focusable-hint)
    ((placeholder-text "" :documentation "The placeholder text of the input element.
  I.e. the grey text initially seen in it.")
     (body "Input Area"))
    (:accessor-name-transformer (hu.dwim.defclass-star:make-name-transformer name)))
  
  (define-class textarea-hint (focusable-hint)
    ((placeholder-text "" :documentation "The placeholder text of the textarea.
  I.e. the grey text initially seen in it.")
     (body "Text Area"))
    (:accessor-name-transformer (hu.dwim.defclass-star:make-name-transformer name)))
  
  (define-class image-hint (link-hint)
    ((alt "" :documentation "Alternative text for the image.")
     (body "Image"))
    (:accessor-name-transformer (hu.dwim.defclass-star:make-name-transformer name)))
  
  (defmethod %follow-hint ((link-hint link-hint))
    (buffer-load (url link-hint)))
  
  (defmethod %follow-hint ((clickable-hint clickable-hint))
    (click-element :nyxt-identifier (identifier clickable-hint)))
  
  (defmethod %follow-hint ((focusable-hint focusable-hint))
    (focus-element ()
      (nyxt/ps:qs document (ps:lisp (format nil "[nyxt-identifier=\"~a\"]" (identifier focusable-hint))))))
  
  (defmethod %follow-hint-new-buffer-focus ((link-hint link-hint) &optional parent-buffer)
    (make-buffer-focus :url (url link-hint)
                       :parent-buffer parent-buffer
                       :nosave-buffer-p (nosave-buffer-p parent-buffer)))
  
  (defmethod %follow-hint-new-buffer-focus ((hint hint) &optional parent-buffer)
    (declare (ignore parent-buffer))
    (echo "Unsupported operation for hint: can't open in new buffer."))
  
  (defmethod %follow-hint-new-buffer ((link-hint link-hint) &optional parent-buffer)
    (make-buffer :url (url link-hint) :parent-buffer parent-buffer))
  
  (defmethod %follow-hint-new-buffer ((hint hint) &optional parent-buffer)
    (declare (ignore parent-buffer))
    (echo "Unsupported operation for hint: can't open in new buffer."))
  
  (defmethod %follow-hint-nosave-buffer-focus ((link-hint link-hint))
    (make-buffer-focus :url (url link-hint) :nosave-buffer-p t))
  
  (defmethod %follow-hint-nosave-buffer-focus ((hint hint))
    (echo "Unsupported operation for hint: can't open in new buffer."))
  
  (defmethod %follow-hint-nosave-buffer ((link-hint link-hint))
    (make-nosave-buffer :url (url link-hint)))
  
  (defmethod %follow-hint-nosave-buffer ((hint hint))
    (echo "Unsupported operation for hint: can't open in new buffer."))
  
  (defmethod %copy-hint-url ((link-hint link-hint))
    (trivial-clipboard:text (render-url (url link-hint))))
  
  (defmethod %copy-hint-url ((hint hint))
    (echo "Unsupported operation for hint: can't copy URL."))
  
  (defun prompt-buffer-selection-highlight-hint (&key suggestions scroll follow
                                                   (prompt-buffer (current-prompt-buffer))
                                                   (buffer (current-buffer)))
    (let ((hint (flet ((hintp (hint-suggestion)
                         (if (typep hint-suggestion '(or link-hint button-hint search-match))
                             hint-suggestion
                             nil)))
                  (if suggestions
  
negative.code:            (and (slot-exists-p hint 'buffer)
                  (equal (buffer hint) buffer)))
            (with-current-buffer buffer
              (highlight-selected-hint :element hint
                                       :scroll scroll))
            (remove-focus)))))
  
  (define-command follow-hint ()
    "Show a set of element hints, and go to the user inputted one in the current
  buffer."
    (query-hints "Go to element" (lambda (results) (%follow-hint (first results)))))
  
  (define-command follow-hint-new-buffer ()
    "Show a set of element hints, and open the user inputted one in a new
  buffer (not set to visible active buffer)."
    (let ((buffer (current-buffer)))
      (query-hints "Open element in new buffer"
                   (lambda (result) (mapcar (alex:rcurry #'%follow-hint-new-buffer buffer)
                                            result))
                   :multi-selection-p t)))
  
  (define-command follow-hint-new-buffer-focus ()
    "Show a set of element hints, and open the user inputted one in a new
  visible active buffer."
    (let ((buffer (current-buffer)))
  