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

ivy-completion-in-region: correctly calculate the length of replacement for file category #3051

Closed
wants to merge 1 commit into from

Conversation

kiennq
Copy link
Contributor

@kiennq kiennq commented Jul 6, 2024

  • Ensure accurate calculation of the common length for completion items. The string face may contain only a single completions-first-difference, rather than a list of them.
  • Additionally, when dealing with file category completions, calculate the prefix offset from the file name directory, not the entire input string. This adjustment is necessary because fuzzy completion styles can lead to incorrect common length values. The prefix offset ensures that we replace only the relevant portion of the input when calculating completion items.

@kiennq kiennq force-pushed the fix/completion-prefix-len branch from 7b6a90e to 4f906b7 Compare July 6, 2024 05:37
@basil-conto
Copy link
Collaborator

Thanks! I'll try to have a closer look at this soon.

In the meantime, I'm curious: does this relate at all to the issues described in #1755?

@kiennq
Copy link
Contributor Author

kiennq commented Aug 13, 2024

Thanks! I'll try to have a closer look at this soon.

In the meantime, I'm curious: does this relate at all to the issues described in #1755?

Yes, it should address that issue. The second item is actually used to fix that.

  • Additionally, when dealing with file category completions, calculate the prefix offset from the file name directory, not the entire input string. This adjustment is necessary because fuzzy completion styles can lead to incorrect common length values. The prefix offset ensures that we replace only the relevant portion of the input when calculating completion items.

@TristanCacqueray
Copy link

Hello, this fixes #1755 and #3056 for me too after updating to the emacs-30 branch. Thanks!

TristanCacqueray added a commit to podenv/devenv that referenced this pull request Sep 12, 2024
@offby1
Copy link

offby1 commented Oct 29, 2024

Hello, this fixes #1755 and #3056 for me too after updating to the emacs-30 branch. Thanks!

Same here; I've been using it for a few days with GNU Emacs 30.0.91 (build 1, aarch64-apple-darwin24.0.0, NS appkit-2566.00 Version 15.0.1 (Build 24A348)) of 2024-10-22 and it's fine.

@basil-conto
Copy link
Collaborator

Thanks! I'll try to have a closer look at this soon.

Sorry, life got in the way again.
With a bit more time for Emacs now, and with the Emacs 30 release due in the coming days, I'm reviewing this issue again.

Comment on lines 2698 to +2699
(t
(substring str (- len))))))
(substring target-str (- len))))))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you have any examples where this branch is taken and is useful?
I'm struggling to trigger it in cases other than when len = str-len, where the substring is a no-op.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I ask is because I don't understand why we would be interested in counting len characters from the end of target-str, when len represents an index from the start of (car comps).

(This is unrelated to your patch BTW - I'm trying to understand how initial is calculated in general.)

Copy link
Collaborator

@basil-conto basil-conto Feb 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I think it's for cases like completing ./foo where the first candidate is foobar. foobar presumably has a matching prefix of foo, so the last three characters of ./foo are deleted and replaced with the entire candidate foobar.

Even so, it strikes me as odd to take a prefix length of one string and assume it corresponds to a suffix length of a potentially unrelated string.

Perhaps we should only remove the suffix of str when it's equal to the common prefix of (car comps)?

Still not sure if this branch is taken outside of file name completion.

Comment on lines +2659 to +2663
(defun ivy--completion-prefix-offset (str md)
"Return the offset of the completion prefix in STR with its metadata MD."
(pcase (cdr (assoc 'category md))
(`file (length (file-name-directory str)))
(_ 0)))
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine this doesn't handle completing e.g. ~/a/b/c to ~/aaa/bbb/ccc, right?

I think we can avoid the need for this function by instead taking advantage of the base-size already returned by completion-all-completions; stay tuned.

basil-conto added a commit that referenced this pull request Feb 24, 2025
Thanks to Kien Nguyen <[email protected]> and
Madhu <[email protected]> for suggestions.

Fixes parts of #1361, #1755, #2879, #3051, #3056,
and https://bugs.gnu.org/76440.
Relates to https://bugs.gnu.org/71419.

* ivy.el (ivy--face-list-p): New compatibility shim.
(ivy-completion-common-length): Use it to handle both atom and list
values for the face property, since it varies across Emacs versions.
Use previous-single-property-change instead of iterating by char.
Improve documentation.
(ivy-completion-in-region): Translate a 'not found' result of
ivy-completion-common-length into a first difference at index 0, not
at the end of the string.  That means, interpret a lack of
completions-first-difference as no commonality.  This is more
consistent with both the definition of ivy-completion-common-length
and completion changes in Emacs 30.

* ivy-test.el (ivy-completion-common-length): Extend tests.
basil-conto added a commit that referenced this pull request Feb 24, 2025
The latter is very problematic: it is specific to a single
candidate, does not necessarily correspond to the string being
completed, complicates bounds calculations, relies on only partially
documented presentation details rather than the usual API, etc.

When completion-all-completions returns a base-size (which in
practice seems to be most if not all the time), it corresponds more
closely to the substring that is being completed and will be
replaced.

This should address most of the remaining issues in #1361, #1755,

* ivy.el (ivy-completion-common-length): Discourage use.
(ivy-completion-in-region): When completion-all-completions
returns a base-size, prefer that over the
completions-first-difference face to determine the completion
boundaries and initial-input.

Fixes #1755.
Fixes #2879.
Closes #3051.
Fixes #3056.
basil-conto added a commit that referenced this pull request Feb 24, 2025
The latter is very problematic: it is specific to a single
candidate, does not necessarily correspond to the string being
completed, complicates bounds calculations, relies on only partially
documented presentation details rather than the usual API, etc.

When completion-all-completions returns a base-size (which in
practice seems to be most if not all the time), it corresponds more
closely to the substring that is being completed and will be
replaced.

This should address most of the remaining issues in #1361, #1755,

* ivy.el (ivy-completion-common-length): Discourage use.
(ivy-completion-in-region): When completion-all-completions
returns a base-size, prefer that over the
completions-first-difference face to determine the completion
boundaries and initial-input.

Fixes #1755.
Fixes #2879.
Closes #3051.
Fixes #3056.
@basil-conto
Copy link
Collaborator

Thanks again for this PR, and apologies for the long delay in reviewing it.

I think PR #3065 takes a slightly more general approach, which doesn't need to determine whether we are completing a file. It also addresses several other issues I encountered while investigating this.

I welcome everyone to try that PR and report back. TIA.

basil-conto added a commit that referenced this pull request Feb 24, 2025
The latter is very problematic: it is specific to a single
candidate, does not necessarily correspond to the string being
completed, complicates bounds calculations, relies on only partially
documented presentation details rather than the usual API, etc.

When completion-all-completions returns a base-size (which in
practice seems to be most if not all the time), it corresponds more
closely to the substring that is being completed and will be
replaced.

This should address most of the remaining issues in #1361, #1755,

* ivy.el (ivy-completion-common-length): Discourage use.
(ivy-completion-in-region): When completion-all-completions
returns a base-size, prefer that over the
completions-first-difference face to determine the completion
boundaries and initial-input.

Fixes #1755.
Fixes #2879.
Closes #3051.
Fixes #3056.
basil-conto added a commit that referenced this pull request Feb 24, 2025
The latter is very problematic: it is specific to a single
candidate, does not necessarily correspond to the string being
completed, complicates bounds calculations, relies on only partially
documented presentation details rather than the usual API, etc.

When completion-all-completions returns a base-size (which in
practice seems to be most if not all the time), it corresponds more
closely to the substring that is being completed and will be
replaced.

This should address most of the remaining issues in
reports #1361, #1755, #2879, #3051, #3056, and
https://bugs.gnu.org/76440.

* ivy.el (ivy-completion-common-length): Discourage use.
(ivy-completion-in-region): When completion-all-completions
returns a base-size, prefer that over the
completions-first-difference face to determine the completion
boundaries and initial-input.

Fixes #1755.
Fixes #2879.
Closes #3051.
Fixes #3056.
@basil-conto basil-conto self-assigned this Feb 27, 2025
@basil-conto basil-conto added bug compat Issues relating to backward/forward compatibility labels Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug compat Issues relating to backward/forward compatibility
Projects
None yet
Development

Successfully merging this pull request may close these issues.

File name completion overwrites already entered path in shell-mode
4 participants