zsh-users
 help / color / mirror / code / Atom feed
* _complete: insert unambiguous when globbing
@ 2022-01-03 12:39 Tomasz Pala
  2022-01-03 15:40 ` Tomasz Pala
  2022-01-04  0:25 ` Bart Schaefer
  0 siblings, 2 replies; 9+ messages in thread
From: Tomasz Pala @ 2022-01-03 12:39 UTC (permalink / raw)
  To: zsh-users

Hello,

I'm struggling with something which felt basic, yet I cannot find a
valid solution (in any combination of remaining styles)...

mkdir empty
cd empty
touch 20{a,b,c,d}.x

ls 2[tab]	==> 20		this is expected
ls 2*[tab]	!=> 20		how to make this to be expanded first to

"20", and then the regular rules to proceed (either menu complete I
always use, or _expand)?

More advanced example:
ls 2*x[tab]	?=> 20[completions]x

And the most advanced:
ls 2*[tab]	?=> 20*.x	with the cursor placed after "*"


In the most advanced form, the _completion expands "2*", finds out there
is unambiguous "20" prefix and ".x" suffix and puts them into ZLE before
performing completion (in my case, menu).

In other words, I want the globbing _complete to behave like non-globbing one.


While the initial case is pointless (simply don't put the "*" at the
end), I'd like to use it when looking for specific file types. I often
look for logs in 2021.*.xz form and when there is too many matches I
want to narrow them down, but I could simply type 2*z[tab] to have the
same effect.

best regards,
-- 
Tomasz Pala <gotar@pld-linux.org>


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

* Re: _complete: insert unambiguous when globbing
  2022-01-03 12:39 _complete: insert unambiguous when globbing Tomasz Pala
@ 2022-01-03 15:40 ` Tomasz Pala
  2022-01-04  0:25 ` Bart Schaefer
  1 sibling, 0 replies; 9+ messages in thread
From: Tomasz Pala @ 2022-01-03 15:40 UTC (permalink / raw)
  To: zsh-users

Sorry for mailing this to @sunsite.dk - please reply using this
forward...

On Mon, Jan 03, 2022 at 13:39:03 +0100, Tomasz Pala wrote:

> I'm struggling with something which felt basic, yet I cannot find a
> valid solution (in any combination of remaining styles)...
> 
> mkdir empty
> cd empty
> touch 20{a,b,c,d}.x
> 
> ls 2[tab]	==> 20		this is expected
> ls 2*[tab]	!=> 20		how to make this to be expanded first to
> 
> "20", and then the regular rules to proceed (either menu complete I
> always use, or _expand)?
> 
> More advanced example:
> ls 2*x[tab]	?=> 20[completions]x
> 
> And the most advanced:
> ls 2*[tab]	?=> 20*.x	with the cursor placed after "*"
> 
> 
> In the most advanced form, the _completion expands "2*", finds out there
> is unambiguous "20" prefix and ".x" suffix and puts them into ZLE before
> performing completion (in my case, menu).
> 
> In other words, I want the globbing _complete to behave like non-globbing one.
> 
> 
> While the initial case is pointless (simply don't put the "*" at the
> end), I'd like to use it when looking for specific file types. I often
> look for logs in 2021.*.xz form and when there is too many matches I
> want to narrow them down, but I could simply type 2*z[tab] to have the
> same effect.

One more note - zsh knows where the first ambiguous character is, even
with globbing, as it's shown with show-ambiguity style.

The question remains: how to make it complete the common parts when
globbing.

-- 
Tomasz Pala <gotar@pld-linux.org>


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

* Re: _complete: insert unambiguous when globbing
  2022-01-03 12:39 _complete: insert unambiguous when globbing Tomasz Pala
  2022-01-03 15:40 ` Tomasz Pala
@ 2022-01-04  0:25 ` Bart Schaefer
  2022-01-05 19:46   ` Tomasz Pala
  1 sibling, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2022-01-04  0:25 UTC (permalink / raw)
  To: Tomasz Pala; +Cc: Zsh Users

On Mon, Jan 3, 2022 at 7:24 AM Tomasz Pala <gotar@polanet.pl> wrote:
>
> ls 2[tab]       ==> 20          this is expected
> ls 2*[tab]      !=> 20          how to make this to be expanded first to
>
> "20", and then the regular rules to proceed (either menu complete I
> always use, or _expand)?

The basic problem here is that the set of common prefixes always
includes the string originally on the command line when deciding
whether to insert a partial result, and except in pretty unusual cases
none of the results is going to include the "*" character, so the best
you're going to get is to always immediately enter menu completion.
You can get that with

setopt globcomplete

This varies a bit depending on your key bindings and completer style.
The above is required when you have TAB bound to expand-or-complete,
but for example with

bindkey ^I complete-word
zstyle ':completion:*' completer _complete _expand

you can get a similar set of results, but menu completion is entered
with all possible expansions instead of all matching files.

> One more note - zsh knows where the first ambiguous character is, even
> with globbing, as it's shown with show-ambiguity style.

Hmm.  When I try this with your 20{a,b,c,d}.x example, globcomplete
gives "20" as the unambiguous prefix but my second formulation has
only "2".  This appears to be because with globcomplete on, the set of
glob matches has already been calculated before entering the
completion process; the prefix from the command line is determined
very early in both cases.  This suggests that some fiddling with the
value of compstate[insert] could produce the "show prefix on first
tab, enter menu on second tab" effect that I think you're asking for,
at least some of the time, but I'm not sure where to do that.


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

* Re: _complete: insert unambiguous when globbing
  2022-01-04  0:25 ` Bart Schaefer
@ 2022-01-05 19:46   ` Tomasz Pala
  2022-01-05 20:11     ` Bart Schaefer
  2022-01-05 20:15     ` Tomasz Pala
  0 siblings, 2 replies; 9+ messages in thread
From: Tomasz Pala @ 2022-01-05 19:46 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Mon, Jan 03, 2022 at 16:25:18 -0800, Bart Schaefer wrote:

> The basic problem here is that the set of common prefixes always
> includes the string originally on the command line when deciding
> whether to insert a partial result,

Can I get rid of this "original" string from the set? When backing of
from completion I always use ctrl-g anyway.

> completion process; the prefix from the command line is determined
> very early in both cases.  This suggests that some fiddling with the
> value of compstate[insert] could produce the "show prefix on first
> tab, enter menu on second tab" effect that I think you're asking for,

Yes, something like this - this might happen on one or two tabs or even
on some separate keybinding.


I did some digging and I think I've found a solution for my usecase:


--- /usr/share/zsh/5.8/functions/_main_complete.orig    2020-02-19 00:50:21.000000000 +0100
+++ /usr/share/zsh/5.8/functions/_main_complete    2022-01-05 18:34:57.828262149 +0100
@@ -389,6 +389,12 @@
     unset ZLS_COLORS
   fi
 }
+
+if [[ $PREFIX = *'*'* ]]; then
+    compstate[pattern_insert]=not_menu
+else
+    compstate[old_list]=keep
+fi

 # Now call the post-functions.
===

However since it sacrifices ZLE-provided pattern it's not perfect.

$ cd empty
$ touch 2021.12.29-14:41:02.xz 2021.12.29-19:41:02.xz 2021.12.30-03:41:03.xz 2021.12.30-14:41:04.xz 2021.12.30-19:41:02.xz 2021.12.31-03:41:02.xz 2021.12.31-14:41:04.xz 2021.12.31-19:41:03.xz

$ ls 2*04[tab]	=> 2021.12.3
files
2021.12.30-14:41:04.xz  2021.12.31-14:41:04.xz

so the compstate[old_list]=keep was required for the second [tab] not to
follow the updated ZLE contents. It works like a charm, but I wonder -
what cases would be broken by compstate[old_list]=keep with such a weak
condition? It would be much safer to have something like:

if [[ $PREFIX = *'*'* ]]; then
	compstate[pattern_insert]=not_menu
	compstate[eat_globbing]=yes
elif [ "$compstate[eat_globbing]" = 'true' ]; then
	compstate[old_list]=keep
fi

but I can't find a way to pass this down.

-- 
Tomasz Pala <gotar@pld-linux.org>


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

* Re: _complete: insert unambiguous when globbing
  2022-01-05 19:46   ` Tomasz Pala
@ 2022-01-05 20:11     ` Bart Schaefer
  2022-01-06  1:52       ` Tomasz Pala
  2022-01-05 20:15     ` Tomasz Pala
  1 sibling, 1 reply; 9+ messages in thread
From: Bart Schaefer @ 2022-01-05 20:11 UTC (permalink / raw)
  To: Tomasz Pala; +Cc: Zsh Users

On Wed, Jan 5, 2022 at 11:46 AM Tomasz Pala <gotar@polanet.pl> wrote:
>
> I did some digging and I think I've found a solution for my usecase:
>
> +if [[ $PREFIX = *'*'* ]]; then
> +    compstate[pattern_insert]=not_menu
> +else
> +    compstate[old_list]=keep
> +fi

Aha!  That's given me the answer.

You want something along the lines of:

unsetopt globcomplete
zstyle ':completion:*' completer _complete _match _expand
zstyle ':completion::match:*' insert-unambiguous true

The use of insert-unambiguous will set compstate[pattern_insert]
correctly for you.  You might also try the value "pattern" for that
zstyle.


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

* Re: _complete: insert unambiguous when globbing
  2022-01-05 19:46   ` Tomasz Pala
  2022-01-05 20:11     ` Bart Schaefer
@ 2022-01-05 20:15     ` Tomasz Pala
  2022-01-05 20:25       ` Bart Schaefer
  1 sibling, 1 reply; 9+ messages in thread
From: Tomasz Pala @ 2022-01-05 20:15 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Wed, Jan 05, 2022 at 20:46:43 +0100, Tomasz Pala wrote:

> However since it sacrifices ZLE-provided pattern it's not perfect.
> 
> $ cd empty
> $ touch 2021.12.29-14:41:02.xz 2021.12.29-19:41:02.xz 2021.12.30-03:41:03.xz 2021.12.30-14:41:04.xz 2021.12.30-19:41:02.xz 2021.12.31-03:41:02.xz 2021.12.31-14:41:04.xz 2021.12.31-19:41:03.xz
> 
> $ ls 2*04[tab]	=> 2021.12.3
> files
> 2021.12.30-14:41:04.xz  2021.12.31-14:41:04.xz
> 
> so the compstate[old_list]=keep was required for the second [tab] not to
> follow the updated ZLE contents. It works like a charm, but I wonder -
> what cases would be broken by compstate[old_list]=keep with such a weak
> condition? It would be much safer to have something like:
> 
> if [[ $PREFIX = *'*'* ]]; then
> 	compstate[pattern_insert]=not_menu
> 	compstate[eat_globbing]=yes
> elif [ "$compstate[eat_globbing]" = 'true' ]; then
> 	compstate[old_list]=keep
> fi
> 
> but I can't find a way to pass this down.

OK, this was pretty straightforward:

if [[ $PREFIX = *'*'* ]]; then
	compstate[pattern_insert]=not_menu
	_eat_asterisk=true
elif [ "$_eat_asterisk" = 'true' ]; then
	compstate[old_list]=keep
fi


It sacrifices *-using glob only (more robust test required?) because
that signals rough pattern (we do not want to break some refined ones).


And the problem is "provided pattern" vs "unambiguous prefix"...

In general this problem is not trivial, since preserving the ZLE-provided
pattern while completing unambiguous part would require to distinguish,
how much of that pattern was already consumed and needs to be
dropped, preserving the rest; the remaining part must match the same
items being prepended by the unambiguous part.


Having said that - does this behaviour deserve upstreaming with it's own
zstyle, or is it too hacky?

This allows for incremental completion with repeating (manual) globbing
provisioning, which seems fine for some quick and dirty patterns like *z
(for *.xz files), tastes best with undo/redo in finger memory.

-- 
Tomasz Pala <gotar@pld-linux.org>


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

* Re: _complete: insert unambiguous when globbing
  2022-01-05 20:15     ` Tomasz Pala
@ 2022-01-05 20:25       ` Bart Schaefer
  0 siblings, 0 replies; 9+ messages in thread
From: Bart Schaefer @ 2022-01-05 20:25 UTC (permalink / raw)
  To: Tomasz Pala; +Cc: Zsh Users

On Wed, Jan 5, 2022 at 12:15 PM Tomasz Pala <gotar@polanet.pl> wrote:
>
> OK, this was pretty straightforward:
>
> if [[ $PREFIX = *'*'* ]]; then
>         compstate[pattern_insert]=not_menu
>         _eat_asterisk=true
> elif [ "$_eat_asterisk" = 'true' ]; then
>         compstate[old_list]=keep
> fi

If the solution with the _match completer doesn't work for you, my
suggestion for the above would be to use

if [[ $PREFIX = *[*?\[\]]* ]]; then

to cover more glob operators than just "*".

> Having said that - does this behaviour deserve upstreaming with it's own
> zstyle, or is it too hacky?

I'd say you need to demonstrate how this differs from the
insert-unambiguous style before we can make a determination.


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

* Re: _complete: insert unambiguous when globbing
  2022-01-05 20:11     ` Bart Schaefer
@ 2022-01-06  1:52       ` Tomasz Pala
  2022-01-06 10:38         ` Tomasz Pala
  0 siblings, 1 reply; 9+ messages in thread
From: Tomasz Pala @ 2022-01-06  1:52 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Wed, Jan 05, 2022 at 12:11:54 -0800, Bart Schaefer wrote:

> Aha!  That's given me the answer.
> 
> You want something along the lines of:
> 
> unsetopt globcomplete
> zstyle ':completion:*' completer _complete _match _expand
> zstyle ':completion::match:*' insert-unambiguous true

Smart one! This is nice, but this time I got other issues:

$ rpm --*er[tab]

without glob_complete, this method of finding options for SOME commands
stops working. What's the difference between ps --* and ls --* that the
latter still works?


And back to my example:

$ touch 2021.12.29-14:41:02.xz 2021.12.29-19:41:02.xz 2021.12.30-03:41:03.xz 2021.12.30-14:41:04.xz 2021.12.30-19:41:02.xz 2021.12.31-03:41:02.xz 2021.12.31-14:41:04.xz 2021.12.31-19:41:03.xz
$ ls *04[tab]
- this one is much nicer than my version, goes directly to:
$ ls 2021.12.3-14:41:04.xz		(note the suffix)
with cursor __^__ placed here, on dash. However, unless I move cursor
left+right manually, pressing tab second time moves cursor to the end
with uncompletable line...

And following one fails miserably...
$ ls *z[tab]
$ ls 2021.12.-

See the dash at the end? From now on, no completion... This problem is
solved by alternating order to _expand _complete _match.

Apparently _complete _match parts doesn't work well here in that order,
however _match _complete (only!) works just like my solution without
compstate[old_list]=keep, therefore one of the following seems to work fine:

zstyle ':completion:*' completer	 _match _oldlist _complete
zstyle ':completion:*' completer _expand _match _oldlist _complete _prefix

But no suffix added, just like in my version.
Moreover, in this order there's no need to unsetopt glob_complete.

Am I missing something?


There is still one issue with coloring completions, that works fine with
my approach, but seems to be stuck on _oldlist:

highlights='${PREFIX:+=(*/|)(#bi)($PREFIX|$PREFIX:t)(?)(*(${LASTSEARCH})*)#*==1;32=1;31==1;32}':${(s.:.)LS_COLORS}
zstyle -e ':completion:*:*' list-colors 'reply=( "'$highlights'" "ma=44;1;33")'

With _oldlist in action the colors are not updated after prepending the
unambiguous part.

> The use of insert-unambiguous will set compstate[pattern_insert]
> correctly for you.  You might also try the value "pattern" for that
> zstyle.

-- 
Tomasz Pala <gotar@pld-linux.org>


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

* Re: _complete: insert unambiguous when globbing
  2022-01-06  1:52       ` Tomasz Pala
@ 2022-01-06 10:38         ` Tomasz Pala
  0 siblings, 0 replies; 9+ messages in thread
From: Tomasz Pala @ 2022-01-06 10:38 UTC (permalink / raw)
  To: Bart Schaefer; +Cc: Zsh Users

On Thu, Jan 06, 2022 at 02:52:21 +0100, Tomasz Pala wrote:

>> unsetopt globcomplete
>> zstyle ':completion:*' completer _complete _match _expand
>> zstyle ':completion::match:*' insert-unambiguous true
> 
> Smart one! This is nice, but this time I got other issues:
> 
> $ rpm --*er[tab]
> 
> without glob_complete, this method of finding options for SOME commands
> stops working. What's the difference between ps --* and ls --* that the
> latter still works?

This is weird - it's broken only when both styles are set:

zstyle ':completion:*:descriptions' format '%B%d%b'
zstyle ':completion:*:messages' format ':%d'

> And back to my example:
> 
> $ touch 2021.12.29-14:41:02.xz 2021.12.29-19:41:02.xz 2021.12.30-03:41:03.xz 2021.12.30-14:41:04.xz 2021.12.30-19:41:02.xz 2021.12.31-03:41:02.xz 2021.12.31-14:41:04.xz 2021.12.31-19:41:03.xz
> $ ls *04[tab]
> - this one is much nicer than my version, goes directly to:
> $ ls 2021.12.3-14:41:04.xz		(note the suffix)
> with cursor __^__ placed here, on dash. However, unless I move cursor
> left+right manually, pressing tab second time moves cursor to the end
> with uncompletable line...

This exposes some general issue - I don't know which part inserts
unambiguous SUFFIX into the ZLE, but obviously it should be done only
when completeinword is set.

> And following one fails miserably...
> $ ls *z[tab]
> $ ls 2021.12.-
> 
> See the dash at the end? From now on, no completion... This problem is

This is probably some deeper bug somewhere, still happens with --norcs
followed by settings from this thread.

> There is still one issue with coloring completions, that works fine with
> my approach, but seems to be stuck on _oldlist:
> 
> highlights='${PREFIX:+=(*/|)(#bi)($PREFIX|$PREFIX:t)(?)(*(${LASTSEARCH})*)#*==1;32=1;31==1;32}':${(s.:.)LS_COLORS}
> zstyle -e ':completion:*:*' list-colors 'reply=( "'$highlights'" "ma=44;1;33")'
> 
> With _oldlist in action the colors are not updated after prepending the
> unambiguous part.

In my solution compstate[old_list]=keep is set on second tab strike and
the colors are recalculated at this point; is it because this is done
AFTER "# Stuff we always do to clean up" which restores ZLS_COLORS?
Any way to simulate this for _oldlist?


And one more final note - I said all of those sacrifice pattern from ZLE
(which might get people angry if they loose some hand-crafted fine-tuned
one and are unfamiliar with undo), however without globcomplete this
pattern is also lost.

-- 
Tomasz Pala <gotar@pld-linux.org>


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

end of thread, other threads:[~2022-01-06 10:39 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-01-03 12:39 _complete: insert unambiguous when globbing Tomasz Pala
2022-01-03 15:40 ` Tomasz Pala
2022-01-04  0:25 ` Bart Schaefer
2022-01-05 19:46   ` Tomasz Pala
2022-01-05 20:11     ` Bart Schaefer
2022-01-06  1:52       ` Tomasz Pala
2022-01-06 10:38         ` Tomasz Pala
2022-01-05 20:15     ` Tomasz Pala
2022-01-05 20:25       ` Bart Schaefer

Code repositories for project(s) associated with this 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).