emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A solution to display completion candidates after point in a minibuf


From: Gregory Heytings
Subject: Re: A solution to display completion candidates after point in a minibuffer
Date: Fri, 02 Oct 2020 17:17:03 +0000
User-agent: Alpine 2.22 (NEB 394 2020-01-19)


Hi Stefan,

Thank you for your feedback!


I think you should better define the problem you're trying to solve.


This problem is known to those who have been working on workarounds to circumvent it: displaying completion candidates in the minibuffer after prompt, without hiding the prompt.


AFAIK the main issue ("when there are too many completion candidates, the minibuffer prompt is hidden") has been solved by Eli


No it has not. It has been solved in a partial way, which means that it will still be necessary to use workarounds to solve it in a clean, user-friendly way. I sent a simple recipe on bug#43572, which demonstrates why Eli's solution is incomplete:

emacs -Q
(let (w bd)
  (setq w 60)
  (setq bd (concat (temporary-file-directory) (make-string w ?a) "/"))
  (dolist (d '("a" "b" "c" "d" "e")) (make-directory (concat bd d) t))
  (setq default-directory bd)
  (set-frame-height nil 20)
  (set-frame-width nil (+ (length bd) 10))
  (icomplete-mode)
  (setq icomplete-separator "\n")
  (call-interactively 'insert-file))

This recipe works with Emacs 24, 25, 26, 27 and 28, except that "(temporary-file-directory)" should be "temporary-file-directory" (without parentheses) in Emacs 24 and 25.


[ I sightly tweaked your code ]


Thanks, your modified version works fine.


Also this has some problematic aspects:

- it focuses all its energy on showing the text before point, which is often the right choice, but not always.


Indeed, that's not always the right choice, which is why this solution does this if, and only if, the buffer-local variable start-display-at-beginning-of-minibuffer has been set, in minibuffer-setup-hook.


- There's of course a risk of inf-loop if (set-window-start nil (1- end)) leads to (pos-visible-in-window-p end nil t) returning nil. How/when could this happen, I'm not completely sure, but it doesn't seem impossible.


In practice it's not possible, unless the width of the Emacs frame is so small that setting window-start near point (at point-1) would still leave point invisible.


- `window-scroll-functions` says explicitly:

Warning: Do not use this feature to alter the way the window is scrolled. It is not designed for that, and such use probably won’t work.


Yes, I know ;-)


Now, I know experience shows that it does work at least in some cases, but if so I think the code should come with a clear comment explaining why that warning doesn't apply here (and maybe the corresponding C code should also get a comment explaining the properties/invariants/berhaviors that it preserves and that make such uses work, so we don't break it by accident).


This I cannot do, alas, I'm not an expert. I tried this solution extensively, on different Emacs versions. Perhaps there are cases where it does not work, but I doubt it.

2. The only drawback of the above solution is that is is not possible to display an ellipsis ("...") at the end of the completion candidates list, to indicate that some completion candidates are not displayed. It seems to me that this is a minor limitation.

Actually, it seems like your code would allow to do that by running some icomplete code at the end of your `set-window-start-at-begin` to truncate the overlay's text according to where the text is truncated.


That's possible, thanks for the idea, I'll try to see if this can be done. But I'm not sure, because modifying the contents of the buffer would mean that redisplay would be called again, which would again set window-start to another value.

7. (add-hook 'post-command-hook 'start-display-at-beginning-of-minibuffer) is necessary only with variable width faces, but it is does not harm to use it with fixed width faces.

I don't understand why the kind of face in use would make a difference w.r.t needing to use `post-command-hook`.


I don't understand it either, alas. An example, which does not work without start-display-at-beginning-of-minibuffer in post-command-hook with Emacs 26.3 (but works without it with Emacs 27.1):

emacs -Q
(let (w bd)
  (setq w 60)
  (setq bd (concat temporary-file-directory (make-string w ?a) "/"))
  (dolist (d '("a" "b" "c" "d" "e")) (make-directory (concat bd d) t))
  (setq default-directory bd)
  (set-frame-width nil 80)
  (set-frame-height nil 30)
  (icomplete-mode 1)
  (setq icomplete-separator "\n")
  (add-hook 'minibuffer-setup-hook (lambda () (buffer-face-mode t)))
  (set-face-attribute 'variable-pitch nil :height 1.2)
  (call-interactively 'insert-file)))

reply via email to

[Prev in Thread] Current Thread [Next in Thread]