zsh-workers
 help / color / mirror / code / Atom feed
* [RFC] Case-insensitive path completion in _git
@ 2020-12-13  4:40 dana
  2020-12-13 13:55 ` m0viefreak
  2021-03-27 20:06 ` Lawrence Velázquez
  0 siblings, 2 replies; 10+ messages in thread
From: dana @ 2020-12-13  4:40 UTC (permalink / raw)
  To: Zsh hackers list

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



^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2021-04-10 20:56 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-12-13  4:40 [RFC] Case-insensitive path completion in _git dana
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

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