From: dana <dana@dana.is>
To: Zsh hackers list <zsh-workers@zsh.org>
Subject: [RFC] Case-insensitive path completion in _git
Date: Sat, 12 Dec 2020 22:40:43 -0600 [thread overview]
Message-ID: <B25A8850-A141-4B81-A3E6-017F280B0CC6@dana.is> (raw)
I've had this sitting for a while:
_git has issues completing files case-insensitively (if you have matcher-list
'm:{a-zA-Z}={A-Za-z}' or whatever). Looking into it, i found that __git_files
is trying to pass a glob pattern to `git ls-files`, and this fails if there's
not an exact case match, since ls-files is always case-sensitive.
There is a fall-back to `git ls-files` with no path, but this doesn't always
work either, because it defaults to the CWD, and the file you're trying to
complete may not be under the CWD. Even when the fall-back succeeds, it's not
ideal, because it'll pass every single file in the tree to _multi_parts, which
can be slow.
The following hack solves the problem for me, but it might be too silly to
commit. Can anyone think of a more proper fix? If not, would the hack be
viable (probably gated behind a style)?
dana
diff --git a/Completion/Unix/Command/_git b/Completion/Unix/Command/_git
index 81a060e4d..7d0201efe 100644
--- a/Completion/Unix/Command/_git
+++ b/Completion/Unix/Command/_git
@@ -7138,6 +7138,7 @@ __git_files_relative () {
(( $+functions[__git_files] )) ||
__git_files () {
local compadd_opts opts tag description gittoplevel gitprefix files expl
+ local MATCH MBEGIN MEND
zparseopts -D -E -a compadd_opts V+: J+: 1 2 o+: n f x+: X+: M+: P: S: r: R: q F:
zparseopts -D -E -a opts -- -cached -deleted -modified -others -ignored -unmerged -killed x+: --exclude+:
@@ -7152,14 +7153,26 @@ __git_files () {
# TODO: --directory should probably be added to $opts when --others is given.
+ # ls-files allows the part of the path under the repository directory to be a
+ # glob pattern. However, these patterns are always case-sensitive (even if the
+ # file system is not). This means that if we have a matcher style set to make
+ # path completion case-insensitive, it won't (necessarily) work, because we
+ # won't get any results back from Git. To work around this, we can transform
+ # the pattern from abc to [Aa][Bb][Cc]. This is very dumb, but seemingly
+ # reliable enough
local pref=${(Q)${~PREFIX}}
+ pref=${pref//(#m)[[:alpha:]]/\[${(U)MATCH}${(L)MATCH}\]}
[[ $pref[1] == '/' ]] || pref=$gittoplevel$gitprefix$pref
# First allow ls-files to pattern-match in case of remote repository
files=(${(0)"$(_call_program files git ls-files -z --exclude-standard ${(q)opts} -- ${(q)${pref:+$pref\*}:-.} 2>/dev/null)"})
__git_command_successful $pipestatus || return
- # If ls-files succeeded but returned nothing, try again with no pattern
+ # If ls-files succeeded but returned nothing, try again with no pattern. Note
+ # that ls-files defaults to the CWD if not given a path, so if the file we
+ # were trying to add is in an *adjacent* directory, this won't return anything
+ # helpful. (If it did, the case-sensitivity issue mentioned above would only
+ # be a minor performance issue rather than a complete failure to return)
if [[ -z "$files" && -n "$pref" ]]; then
files=(${(0)"$(_call_program files git ls-files -z --exclude-standard ${(q)opts} -- 2>/dev/null)"})
__git_command_successful $pipestatus || return
next reply other threads:[~2020-12-13 4:41 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-12-13 4:40 dana [this message]
2020-12-13 13:55 ` m0viefreak
2020-12-14 10:25 ` dana
2021-03-27 21:08 ` Daniel Shahaf
2021-03-28 5:07 ` dana
2021-03-28 8:08 ` Oliver Kiddle
2021-03-30 5:59 ` dana
2021-04-10 20:43 ` Lawrence Velázquez
2021-04-10 20:56 ` dana
2021-03-27 20:06 ` Lawrence Velázquez
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=B25A8850-A141-4B81-A3E6-017F280B0CC6@dana.is \
--to=dana@dana.is \
--cc=zsh-workers@zsh.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).