Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: menu-select interactive mode



On 9 April 2011 22:12, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> On Apr 9,  4:56pm, Mikael Magnusson wrote:
> } Subject: menu-select interactive mode
> }
> } We were talking on irc about this, and I couldn't get it to work.
> } Turns out if you just set
> } zstyle ':completion:*' menu interactive
> } and invoke the menu-select widget, nothing happens.
>
> First of all, make sure you're really invoking _main_complete via the
> menu-select widget, rather than invoking the builtin menu-select.
> The builtin obviously won't pay any attention to the zstyles.  In
> order to get this to work correctly, you have to explicitly load the
> zsh/complist module BEFORE running compinit or compinit won't replace
> the builtin widget.

I'm not sure why I wrote "nothing happens", what I actually meant was
"nothing changes" meaning that it goes into menu-selection as usual,
but not in interactive mode.

My menu-select is a widget, if this output is to be trusted,
% echo $widgets[menu-select]
completion:.menu-select:_main_complete
And I then have bindkey '^[m' menu-select
also this,
% zle -l|grep menu-select
menu-select -C .menu-select _main_complete
which I guess is pretty much the same piece of information.

> I have the feeling this is documented somewhere but I can't find it
> just now.

If you use the menu-select widget, which is part of  the zsh/complist
module,  you should make sure that that module is loaded before the
call to compinit so that that widget is also re-defined.

> The builtin normally doesn't begin selection unless you either always
> do menu completion or it's invoked in a context where menu completion
> would start (such as after a listing has been printed).  Not being in
> the correct context would correspond to your "nothing happens" case.
>
> If I start zsh with a .zshrc that looks like this --
>
> autoload -Uz compinit
> compinit -D
> zmodload zsh/complist
> zstyle ':completion:*' menu interactive
> bindey '\em' menu-select
>
> -- then pressing ESC m does nothing unless I first hit TAB and get a
> listing.  However, if I .zshrc looks like THIS --
>
> zmodload zsh/complist
> autoload -Uz compinit
> compinit -D
> zstyle ':completion:*' menu interactive
> bindey '\em' menu-select
>
> -- then ESC m goes directly into menu selection as I would expect.
>
> However, what it does NOT do is go directly into interactive mode.
> You do need both "select" and "interactive" to get into interactive
> mode, even when the widget is named menu-select.  I'm not sure if
> this is intentional (more below).

Right, this is the case I actually have, sorry about the poor communication.

> } What you have to do is either
> } zstyle ':completion:*' menu select interactive
> } but then you always get menu selection which you might not want
>
> With the exception of what I described above, I don't think that has
> accomplished what you think it has.  I suspect that what this has done
> is to cause a *different* completion widget (one that does go through
> _main_complete) to assign a value to the MENUSELECT variable, which
> then later is observed by the menu-select builtin, which eventually
> results in the builtin doing something.

I'm pretty sure when I tried this, I just pressed alt-m before
anything else and it went into interactive selection. But then again,
maybe not.

> } don't), so I ended up with this instead
> } zle -C menu-select-interactive menu-complete _generic
> } zstyle ':completion:menu-select-interactive:*' menu select interactive
> } bindkey "^[m"  menu-select-interactive
>
> What you've done here (I think) is mimic the setup that compinit would
> have done for you if the complist module was loaded before compinit
> was run.

What I've done here is copy the recipe pws gave me at some point for
setting a different set of completion styles when using another
keybind. Originally it was for making a keybind to complete files
sorted by access time or something like that.

> } Additionally, when you do the second one, ie set both select and
> } interactive, the menu-select widget does invoke interactiveness, so my
> } guess is the code simply checks the style instead of also checking
> } which widget invoked it.
>
> That's sort of the right diagnosis.  There are several possible ways
> to "fix" this if it's wrong, and I don't know which one is correct.
>
> Here's the first, which has the smallest number of side-effects:
>
> Index: Completion/Base/Core/_main_complete
> ===================================================================
> --- _main_complete      21 Dec 2010 16:41:14 -0000      1.12
> +++ _main_complete      9 Apr 2011 19:57:11 -0000
> @@ -284,7 +284,7 @@
>         unset MENUSELECT
>       fi
>     fi
> -    if [[ -n "$MENUSELECT" ]]; then
> +    if [[ -n "$MENUSELECT" || "$WIDGET" = menu-select ]]; then
>       if [[ -n "$_menu_style[(r)interactive*]" ]]; then
>         MENUMODE=interactive
>       elif [[ -n "$_menu_style[(r)search*]" ]]; then
>
> Here's the second, which has the effect of causing MENUSELECT to be
> set and thereby make the "-" line of the above diff true (do *NOT*
> apply both this and the above diff):
>
> Index: Completion/Base/Core/_main_complete
> ===================================================================
> --- _main_complete      21 Dec 2010 16:41:14 -0000      1.12
> +++ _main_complete      9 Apr 2011 19:59:46 -0000
> @@ -249,7 +249,7 @@
>     fi
>   fi
>
> -  if [[ "$compstate[insert]" = *menu* ]]; then
> +  if [[ "$compstate[insert]" = *menu*  || "$WIDGET" = menu-select ]]; then
>     [[ "$MENUSELECT" = 00 ]] && MENUSELECT=0
>     if [[ -n "$_menu_style[(r)no-select*]" ]]; then
>       unset MENUSELECT
>
> A third way might be to change the way _last_menu_style is determined
> in _setup, but that makes me nervous.  PWS, any other ideas/opinions?

I might be getting myself in a confused state by this point, but
neither of these seemed to do it for me with just setting 'menu
interactive' and using menu-complete, I did check that I zmodload
complist first too.

btw, both MENUSELECT and MENUMODE seem to "leak" out into the main
shell environment, is that necessary to keep the state consistent
during completion? I noticed a funny effect where echo $MENU<tab>
would offer some stuff and MENUSELECT, then when I typed s and tab
again, I got no hits, because that invocation of completion ended up
unsetting it again. :)

btw#2, this whole interactive feature is very under-advertised, I've
used zsh since 2003 and even have commit access, and I never heard
about it before today.

ps Sorry if something seems out of order, I went back and forth a few
times and added things, I hope it's not too confused.

-- 
Mikael Magnusson



Messages sorted by: Reverse Date, Date, Thread, Author