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

Re: menu-select interactive mode



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 have the feeling this is documented somewhere but I can't find it
just now.

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

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

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

} 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?



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