noctuid / link-hint.el

Pentadactyl-like Link Hinting in Emacs with Avy
GNU General Public License v3.0
160 stars 22 forks source link

Getting links in *Completions* buffer no longer works on Emacs >29 #215

Open mmarshall540 opened 1 year ago

mmarshall540 commented 1 year ago

I will submit a pull request for this, but I don't know if it will be accepted, since Emacs 29 hasn't been released yet. I'm submitting this issue so that others who run into the same problem may find this potential solution.

When using Emacs compiled from git sources on either the "master" or "emacs-29" branch, calling link-hint-open-link on the default Completions buffer causes an infinite loop.

This is caused by a change in how Emacs handles movement when calling the next-completion command.

This can be recreated with the following steps:

  1. Install Emacs from the master branch.
  2. Move your Emacs configuration so you'll be able to install link-hint without any other packages in the way. Example "mv ~/.emacs.d ~/.emacs.d.backup"
  3. Open Emacs with "emacs -Q"
  4. Paste the following into your scratch buffer and evaluate it.
    (require 'package)
    (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
    (package-refresh-contents)
    (package-install 'link-hint)
    (global-set-key "\M-o" 'link-hint-open-link)
  5. Begin a completion like so, "M-x emacs" then press TAB until the Completions buffer appears.
  6. Press "M-o" to call link-hint-open-link.

After waiting for a bit, you should notice that nothing is happening, or the hourglass appears. Press "C-g" to cancel the operation.

As I alluded to above, this happens because the new version of next-completion no longer moves point to the end of the buffer when called from the last completion candidate. Instead, it leaves point in place, which means that the current version of link-hint--next-completion-list-candidate never returns nil.

Replacing its definition with the one below solves the problem.

(defun link-hint--next-completion-list-candidate (bound)
  "Find the next completion list candidate location.
Only search the range between just after the point and BOUND."
  (let ((bound (or bound (window-end)))
    (initpoint (point))
        point)
    (forward-char)
    (next-completion 1)
    (setq point (point))
    (when (and
       (not (eql initpoint point))
       (> (- point initpoint) 1)
       (< point bound))
      point)))