Subject: Re: Regression: broken completion on modification time
From: Oliver Kiddle <[email-masked]>
To: "Nikolay Aleksandrovich Pavlov (ZyX)" <[email-masked]>
Cc: zsh-workers <[email-masked]>
Date: Sat, 18 Jun 2016 00:02:52 +0200
List-Id: Zsh Workers List <zsh-workers.zsh.org>

"Nikolay Aleksandrovich Pavlov (ZyX)" wrote:
>
> I would say “yes” just to check what possibilities is it talking about. Question is why would I hit `<Tab>` in first place: if I did not see this discussion I would not ever suggest that completing a (mostly) numeric and in any case very short argument to `m` has any sense.

It may not be useful to "complete" short things but the descriptions can
be very useful. There's quite a few cases where this is done, e.g.:
  printf '%<tab>
  : ${(<tab>
  !!:<tab>

> Also if I write `ls *(m)` with cursor after `m` and hit `<Tab>` I get “Completing: digit (invalid time specifier)” (nothing if I use `autoload compinit ; compinit` in `zsh -f`, or “Completing: `files'” with no list after `unsetopt completeinword`):

Stripping suffixes is easily forgotten when writing completion functions
and this was one such case. Patch below should fix this and make
it indicate the default of "days" when there is no time specifier.

With `unsetopt completeinword', you have the equivalent of moving the
cursor to the end of the word. *(m) is an invalid glob matching no
files. You might also want to consider using the _prefix completer which
ignores the entire suffix.

> Particularly, the most failing thing is `ls foo{bar<Tab>}`: this usually either does nothing or expands immediately if I already happened to write a comma.

Are you using the _expand completer or the default expand-or-complete
widget to do expansion.

Braces are largely handled by internal C code: _prefix doesn't seem able
to help here. You can prevent the expansion with something like:
  zstyle -e ':completion:*::::' completer \
    'reply=( _oldlist _complete ); (( $#SUFFIX )) || reply[1]+=( _expand )'

Oliver

diff --git a/Completion/Unix/Type/_files b/Completion/Unix/Type/_files
index fe0780a..6987824 100644
--- a/Completion/Unix/Type/_files
+++ b/Completion/Unix/Type/_files
@@ -7,6 +7,7 @@ local ret=1
 # we don't want to complete them multiple times (for each file pattern).
 if _have_glob_qual $PREFIX; then
   compset -p ${#match[1]}
+  compset -S '[^\)\|\~]#(|\))'
   if [[ $_comp_caller_options[extendedglob] == on ]] && compset -P '\#'; then
     _globflags && ret=0
   else
diff --git a/Completion/Unix/Type/_path_files b/Completion/Unix/Type/_path_files
index 14c4cc7..6a1e89f 100644
--- a/Completion/Unix/Type/_path_files
+++ b/Completion/Unix/Type/_path_files
@@ -17,6 +17,7 @@ local -a match mbegin mend
 if _have_glob_qual $PREFIX; then
   local ret=1
   compset -p ${#match[1]}
+  compset -S '[^\)\|\~]#(|\))'
   if [[ $_comp_caller_options[extendedglob] == on ]] && compset -P '\#'; then
     _globflags && ret=0
   else
diff --git a/Completion/Zsh/Type/_globquals b/Completion/Zsh/Type/_globquals
index 2523eb3..ed9c008 100644
--- a/Completion/Zsh/Type/_globquals
+++ b/Completion/Zsh/Type/_globquals
@@ -125,7 +125,7 @@ while [[ -n $PREFIX ]]; do
         alts+=("senses:sense:compadd -E 0 -d sdisp -S '' - + '' -")
       fi
       specmap=( M months w weeks h hours m minutes s seconds '(|+|-|d)' days)
-      alts+=('digits:digit ('${${specmap[(K)$timespec]}:-invalid time specifier}'):_dates -f ${${timespec/[-+]/d}:-d} -S ""' )
+      alts+=('digits:digit ('${${specmap[(K)${timespec:-d}]}:-invalid time specifier}'):_dates -f ${${timespec/[-+]/d}:-d} -S ""' )
       _alternative $alts
       return
     fi