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

Re: Limitations of menuselect



Hi,

On Wed, Feb 27, 2013 at 6:27 PM, Oliver Kiddle <okiddle@xxxxxxxxxxx> wrote:
>> 1) Custom bindings don't work. You can try it with the following:
>>     my-widget() { zle down-line-or-history }; zle -N my-widget;
>> bindkey -M menuselect k my-widget
>> (replacing "my-widget" with "down-line-or-history" in the bindkey
>> command works as expected).
>
> Yes, unfortunately it isn't possible.

Are there plans to implement this in the future?

On Thu, Feb 28, 2013 at 2:07 AM, Oliver Kiddle <okiddle@xxxxxxxxxxx> wrote:
> I wrote:
> > Was this perhaps a bug introduced later
> > such as when local keymaps were added?
>
> It does work correctly as mentioned by Peter so sorry for the
> misinformation. I think I got mixed up between
> accept-line-and-down-history and accept-and-infer-next-history. It then
> seems that the intention is to enable the features on logical keys from
> the main keymap.

I understand the intention, but IMVHO this adds a lot of complexity
(and confusion), just to avoid a few explicit bindings. And I wonder
what the '.' widgets (e.g.: .up-line-or-history) would mean, if custom
widgets could be used in menuselect mode: would they refer to the
menuselect "original override" or to the original version from main?

>> 2) Moving the selected menu item line by line is nice, but scrolling
>> several lines at a time would be nicer (that's what I would expect
>> PageUp and PageDown to do by default in menuselect, for example). I
>> couldn't find an existing widget for that.
>
> You can do some hacks with bindkey -s. For example:
>   bindkey -M menuselect j down-line-or-history
>   bindkey -M menuselect -s n 'jj'
> What you can do with that is limited. Also, it doesn't cope well with putting
> escapes in the latter string.

That's a great idea! It works fine for this case.

> > > 3) When using the reverse-menu-complete widget to open menuselect, I
> > > would like to select the last result, not the first one (otherwise I
> > > can use menu-complete directly...). It doesn't sem to be possible at
> > > the moment.
>
> This doesn't seem to be easy to solve. It seems to be in the
> REVERSEMENUHOOK where it fixes things to go backwards but the initial
> call to reversemenucomplete is not returning from menucomplete() until
> it is too late.

The clean fix in zsh may not be easy, but bindkey -s gives a rather
simple work-around (sacrificing the ^P binding):
bindkey "^P" reverse-menu-complete
bindkey -s "\e[Z" "^P^P"
bindkey -M menuselect "\e[Z" reverse-menu-complete

The last line is there to restore the expected behavior of
reverse-menu-complete in menuselect mode, otherwise the selection
moves 2 lines at a time.
Unfortunately, this is a bit invasive if you don't use menu completion
all the time, since "\e[Z" is bound unconditionally.

>> 4) [...]
>
> This probably wouldn't be hard to implement if we keep to the scheme of
> overloading existing widgets.
>
> You can abuse the behaviour I described earlier to make Enter really
> accept the line:
>   bindkey -M menuselect -r '^M'
>   zle -N new-accept-line
>   new-accept-line() {
>     zle .accept-line
>   }
>   bindkey '^M' new-accept-line
>
> But don't do this because it'll break the enter key in other contexts
> (reading from the mini-buffer). To replace accept-line without breaking
> things you need to use zle -A but that won't work here.

Inspired by your idea, I got a working solution:
really-accept-line() {
    zle .accept-line
}
zle -N really-accept-line
bindkey -M menuselect '^M' really-accept-line

Binding "^M" only in menuselect avoids the problem you mentioned.

> > > 5) [...]
>>
>> Actually, this is possible. Bind a key to vi-insert in menuselect and
>> you get "interactive" mode which does this. Still, there is a lot of
>> ways this could be better. Unfortunately, you stay in the menuselect
>> keymap at this point which is irritating if you've, for example, bound /
>> to history-incremental-search-forward.
>>
>> I can't think of a way to go straight into this mode. The bindkey -s
>> trick stuck it in an infinite loop.
>
> Actually, it turns out this is as simple as including the word
> "interactive" in the menu style. For example:
>   zstyle ':completion*:default' menu select=0 interactive

I need to play more with it, but it looks very promising.
Minor usability suggestion: a accept-selection-or-line widget could be
handy here. It would accept the selection (i.e. insert text and leave
menuselect) when no text has been inserted, and it would leave
menuselect and accept the line, as described in item 4 above, when the
selected text is already inserted (in pure menuselect mode, or when
moving the selection around in "interactive" mode). At the moment,
this behavior seems impossible to achieve.

>> accept-line-and-infer-history maybe?), while still allowing to select
>
> That also does something similar already:
>   bindkey -M menuselect '^M' accept-and-infer-next-history
> then enter will keep in menu selection.
>
>> I hope that these remarks make sense and that I haven't overlooked
>> some existing features...
>
> It certainly makes sense and is quite thought provoking. I'm only sorry
> that my answers aren't especially helpful.

They turned out to be very helpful, thanks.

What are the next steps here? The work-arounds given in this thread
are mostly enough for my needs, but IMHO several things should be
improved in zsh itself. Should I file formal bug reports and/or
feature requests somewhere?

Best regards,
--
Olivier



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