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: Stefan Monnier
Subject: Re: A solution to display completion candidates after point in a minibuffer
Date: Fri, 02 Oct 2020 15:24:00 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux)

>> 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.

This description is not helpful because it is too vague.
E.g. it's not clear what you mean by "prompt".
is it really just the `minibuffer-prompt`?
If so, why do you specifically care about the prompt?
I usually find it more important to see the candidates than the prompt
(the prompt is important at the beginning, before you start writing
your answer, but after that it loses a lot of its importance).

Also, what do you mean by "without hiding the prompt".  There are cases
where there's no other option than to hide the prompt, so which cases
are you specifically interested in?  Also, what if some of the prompt is
visible but not all, is that a problem you're concerned with, or not?

> (let (w bd)
>   (setq w 60)
>   (setq bd (concat (temporary-file-directory) (make-string w ?a) "/"))

AKA

    (let ((w 60)
          (bd (expand-file-name (make-string w ?a) (temporary-file-directory))))

>   (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))

[ FWIW, I just tried it in my local Emacs where I replaced the ad-hoc
  `resize_mini_window` scrolling with the use of `scroll-conservatively`,
  and I get the behavior that you seem to prefer.  ]
[ Side note: I had sent a better recipe for that using a repetition of
  `foo/..` so as to avoid having to create any new files or
  directories.  ]

Thanks.  Indeed, this recipe shows a problem where the prompt is not
displayed at all right at the beginning of the interaction, so the
unwary user won't get to see what the prompt says without extra effort.
At the same time, the text that is displayed (i.e. without the prompt
but with one more line of candidates) is arguably a better choice when
the user knows what the prompt says (as would be the case for me
when I call `insert-file`).

So while I would tend to agree that showing the first line would
probably be better it's debatable.  At least, I don't think this
minor difference warrants the kind of code you're proposing.

>> 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.

But it depends on other factors than "displaying the minibuffer".
It can vary over the lifetime of the very same minibuffer.

>> - 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.

It doesn't seem impossible even with a wide window.  I think risky
situations would include cases where point is right after a newline,
and/or where tall glyphs are involved (either via face settings, or
images, ...).

>> 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.

I'd be uneasy using such code without some vague understanding about
*why* it works.

>> 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.

Which is the kind of reason where we'd benefit from knowing *why* it works.

>>> 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):

Thanks for the example.  I think this highlights the need to better
understand how/why this works.


        Stefan




reply via email to

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