Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

In eshell's completion-at-point, consult-completion-in-region places the minibuffer point in the middle of the completion string #48

Closed
tomfitzhenry opened this issue Dec 10, 2020 · 19 comments
Labels
bug Something isn't working

Comments

@tomfitzhenry
Copy link
Contributor

tomfitzhenry commented Dec 10, 2020

Steps to reproduce

GNU Emacs 27.1
consult: b5cbc61

$ emacs -q
(require 'consult)
(setq completion-in-region-function 'consult-completion-in-region)

In eshell, run:

touch foobar
touch football
cat foo<TAB>

Expected

I'm prompted "Completion: foo|" where | indicates where I expect point to be.

Actual

I'm prompted "Completion: |foo".

This is a problem because I then type "b" (to try to complete "foob" to "foobar"), the minibuffer actually shows "bfoo" which fails to complete.

@tomfitzhenry
Copy link
Contributor Author

tomfitzhenry commented Dec 10, 2020

Workaround: Remove this clause:

consult/consult.el

Lines 627 to 632 in b5cbc61

(if (eq category 'file)
(read-file-name "Completion: "
(file-name-directory initial)
initial t
(file-name-nondirectory initial)
predicate)

More practical workaround:

(add-hook 'eshell-mode-hook
          (lambda ()
            (setq-local completion-in-region-function 'completion--in-region)))

@minad
Copy link
Owner

minad commented Dec 10, 2020

@oantolin ideas?

@oantolin
Copy link
Contributor

Huh. Like @tomfitzhenry pointed out, it's read-file-name that's doing that! I don't know why, but it chooses to put point before the argument initial rather than at the end of the minibuffer. That doesn't seem like a very good default. We could just not use read-file-name, but it is nice to have your special keybindings from minibuffer-local-filename-completion-map present.

How about just forcing the move to the end of line? We can wrap the call to read-file-name in (minibuffer-with-setup-hook #'end-of-line _____).

@minad
Copy link
Owner

minad commented Dec 10, 2020

@tomfitzhenry are you using selectrum or icomplete btw?

@tomfitzhenry
Copy link
Contributor Author

@tomfitzhenry are you using selectrum or icomplete btw?

I can reproduce this issue with emacs -q (so not even icomplete is enabled), and with icomplete. I haven't tried selectrum.

@oantolin
Copy link
Contributor

It's definitely something that read-file-name-default does. Selectrum uses its own setting for read-file-name-function, so it's possible it behaves differently.

@tomfitzhenry
Copy link
Contributor Author

Huh. Like @tomfitzhenry pointed out, it's read-file-name that's doing that! I don't know why, but it chooses to put point before the argument initial rather than at the end of the minibuffer. That doesn't seem like a very good default.

I'll try to reproduce this using just read-file-name, and raise that issue upstream. Working around bugs long-term isn't sustainable.

@minad
Copy link
Owner

minad commented Dec 10, 2020

If it is not our bug, I would not fix it here. As long as we are sure we did everything alright.

@minad minad added the bug Something isn't working label Dec 10, 2020
@tomfitzhenry
Copy link
Contributor Author

The steps to reproduce are simple. I'll raise this upstream.

(read-file-name-default "Read File: " nil nil nil "Initial" nil)

@minad
Copy link
Owner

minad commented Dec 10, 2020

Regarding the initial value - this has been deprecated for the completing-read API, but for the read-file-name API it is fine? The docs only say "Please note: we recommend using default rather than initial in most cases". See https://www.gnu.org/software/emacs/manual/html_node/elisp/Reading-File-Names.html.

@tomfitzhenry
Copy link
Contributor Author

tomfitzhenry commented Dec 10, 2020

Further, that page says "If you specify initial, that is an initial file name to insert in the buffer (after directory, if that is inserted). In this case, point goes at the beginning of initial."

That is, the behaviour we observe is the expected behaviour. I can't tell why that is desirable behaviour (even given the described example of find-alternate-file).

I won't raise this upstream: it's working as intended.

Our options:
i. don't use read-file-name
ii. figure out a way to do this via default. I can't see how we would. default appears to be used for when selection fails, not as a means of pre-populating the minibuffer UI (it doesn't).
iii. It looks like we can include the file name in the dir argument: (read-file-name-default "Read File: " "~/foo" nil nil nil nil) does put point where we expect, and matches file "~/foobar". This appears to be undefined behaviour.
iv. Advise, as in #48 (comment)

@tomfitzhenry
Copy link
Contributor Author

I lean towards (i) since:

  1. It's cleanest.
  2. It's easier to add read-file-name later (if we figure out a clean way to do it), than to remove it later when people may depend on it, if supporting this unclean solution proves too burdensome.

it is nice to have your special keybindings from minibuffer-local-filename-completion-map present

How important is this usecase? Are there file-specific bindings that people would want during a completion-at-point?

@minad
Copy link
Owner

minad commented Dec 10, 2020

Why not raise it upstream, if you think it is bad behavior? Option (i) would revert the special behavior for files, which has been done for consistency with how selectrum. It and it also makes sense to use read-file for the file category, I think. But I was not really involved the design of this function, @oantolin made it and we got some feedback by @clemera.

@tomfitzhenry
Copy link
Contributor Author

tomfitzhenry commented Dec 10, 2020

I think I've found a way to avoid using read-file-name, but keep minibuffer-local-filename-completion-map bindings. It looks like we can set minibuffer-completing-file-name to t to tell the minibuffer to treat this as a filename.

Update: This works, but prompts with a relative path (and so doesn't look like a prompt for a filename). Try to make that an absolute prompt, and then results are absolute. Fixing that partly amounts to reimplementing read-file-name!

@minad
Copy link
Owner

minad commented Dec 10, 2020

@tomfitzhenry Since this already has issues and it won't work nicely with recursive minibuffer I think it would be better to keep using read-file-name or not use it at all. But this has to be discussed. See #31 for the original discussion.

@oantolin
Copy link
Contributor

oantolin commented Dec 10, 2020

Personally, I'd go with @tomfitzhenry's option (iii), use the directory argument: even if this behavior is not documented it seems unlikely to change.

@minad
Copy link
Owner

minad commented Dec 10, 2020

Haha, the undefined behavior. I am fine with it as long as it works. If at some point it stops working we can file a bugreport to upstream 🙈

@oantolin
Copy link
Contributor

Exploiting the undefined behavior seems to work just fine, and it really isn't likely to change any time soon. I'll make a pull request.

@minad
Copy link
Owner

minad commented Dec 13, 2020

Closed by #63

@minad minad closed this as completed Dec 13, 2020
minad pushed a commit that referenced this issue Dec 13, 2020
When completing files with consult-completion-in-region, the point in
the minibuffer gets placed initially at the beginning of the last path
component. With this change it starts at the end of minibuffer
contents, as for other types of completion.
minad pushed a commit that referenced this issue Dec 13, 2020
When completing files with consult-completion-in-region, the point in
the minibuffer gets placed initially at the beginning of the last path
component. With this change it starts at the end of minibuffer
contents, as for other types of completion.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants