zsh-workers
 help / color / mirror / code / Atom feed
* accept-and-hold in interactive mode of menu select
@ 2014-12-16 14:18 Jun T.
  2014-12-16 16:45 ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Jun T. @ 2014-12-16 14:18 UTC (permalink / raw)
  To: zsh-workers

In the interactive mode of menu select, accept-and-hold
does not work as I expect. In the worst case, it results in
an infinite loop.

### create a file with the following contents:

$ cat init
zmodload zsh/complist
autoload -Uz compinit
compinit
zstyle ':completion:*' menu on select=2
bindkey '^K' vi-insert
bindkey '^L' accept-and-hold

### create a test directory and a few files:

$ mkdir test
$ touch test/{aaaa,abbb,abbc}

### Start a new shell, and setup menu select:

$ zsh -f
% source init

### Test-1:

% ls test/
>>> hit TAB
% ls test/aaaa
aaaa  abbb  abbc  abbd

>>> hit ^K to go into the interactive mode:

% ls test/
interactive: test/[]
aaaa*  abbb  abbc
 ('*' indicates where the selection in the list)

>>> type ab

% ls test/ab
interactive: test/abb[]
abbb*  abbc

>>> hit ^L

% ls test/ab test/abbc
abbb  abbc*

Note that the 1st word on the command line is not updated to test/abbb.

### Test-2:

% ls test/{

>>> hit TAB

% ls test/{aaaa
aaaa* abbb abbc

>>> hit ^K

% ls test/{
interactive: test/[]
aaaa  abbb  abbc

>>> type ab

% ls test/{ab
interactive: test/{abb[]
abbb* abbc

>>> hit ^L

then zsh goes into an infinite loop; ^C does not work.

gdb indicates that it is looping in a "do {...} while(...)" loop at
lines 1222-1240 of compresult.c, in function do_menucmp(). It seems
the 1st condition in while() is always true; menuacc==1 and hasbrpsfx()
always returns 0.

It seems the real problem is that, as the Test-1 indicates, accept-and-
hold does not update the command line. I tried the patch below, and it
does avoid the infinite loop. But it is far from sufficient; for example,
the ^L above now gives (as I expect)

% ls test/{abbb,abbc

but if I hit ^K to go to the interactive mode again, then I get

% ls test/{ab



diff --git a/Src/Zle/complist.c b/Src/Zle/complist.c
index c129940..80f8dd5 100644
--- a/Src/Zle/complist.c
+++ b/Src/Zle/complist.c
@@ -2790,6 +2790,8 @@ domenuselect(Hookdef dummy, Chdata dat)
 	    Menustack s = (Menustack) zhalloc(sizeof(*s));
 	    int ol;
 
+	    if (mode == MM_INTER)
+		do_single(*minfo.cur);
             mode = 0;
 	    s->prev = u;
 	    u = s;






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

* Re: accept-and-hold in interactive mode of menu select
  2014-12-16 14:18 accept-and-hold in interactive mode of menu select Jun T.
@ 2014-12-16 16:45 ` Bart Schaefer
  2014-12-16 19:11   ` Oliver Kiddle
  0 siblings, 1 reply; 4+ messages in thread
From: Bart Schaefer @ 2014-12-16 16:45 UTC (permalink / raw)
  To: zsh-workers

On Dec 16, 11:18pm, Jun T. wrote:
}
} >>> type ab
} 
} % ls test/ab
} interactive: test/abb[]
} abbb*  abbc
} 
} >>> hit ^L
} 
} % ls test/ab test/abbc
} abbb  abbc*
} 
} Note that the 1st word on the command line is not updated to test/abbb.

I'm not entirely sure that's wrong; accept means to accept what is on the
command line, not to accept what is highlighted in the menu.  You have to
finish the action of choosing one of the menu items so that the command
line is updated, before you accept.

On the other hand I can see where there might be confusion about that,
and this is a little-used and therefore little-tested corner of complist,
so implicitly choosing the currently highlighted item (even though in
this situation it will always be whichever one came first in sort order)
may be a reasonable thing to do.

} >>> type ab
} 
} % ls test/{ab
} interactive: test/{abb[]
} abbb* abbc
} 
} >>> hit ^L
} 
} then zsh goes into an infinite loop; ^C does not work.

I'm not able to reproduce this with a completion that does not use a
brace expansion, so I wonder if there's something about that which is
involved.  Brace expansion has always been a bit of a problem child,
and in a brace expansion you're accepting a partial completion rather
than an entire command-line "word", so we try to re-enter selection
in a different state.

} I tried the patch below, and it does avoid the infinite loop. But it
} is far from sufficient; for example, the ^L above now gives (as I
} expect)
} 
} % ls test/{abbb,abbc
} 
} but if I hit ^K to go to the interactive mode again, then I get
} 
} % ls test/{ab

Entering interactive mode always returns to the original state of the
command line before menu-selection was started.   I don't remember why
this is the case, or if it was intentional.

-- 
Barton E. Schaefer


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

* Re: accept-and-hold in interactive mode of menu select
  2014-12-16 16:45 ` Bart Schaefer
@ 2014-12-16 19:11   ` Oliver Kiddle
  2014-12-17  3:07     ` Bart Schaefer
  0 siblings, 1 reply; 4+ messages in thread
From: Oliver Kiddle @ 2014-12-16 19:11 UTC (permalink / raw)
  To: zsh-workers

Bart wrote:
> 
> I'm not entirely sure that's wrong; accept means to accept what is on the
> command line, not to accept what is highlighted in the menu.  You have to
> finish the action of choosing one of the menu items so that the command
> line is updated, before you accept.

No, with menu selection many widgets have quite different behaviour. The
documented behaviour of accept-and-hold is to insert the currently
selected match but keep the menu active so that you can select another
match. accept-line-and-down-history does the same but doesn't seem to be
documented. It's a useful feature.

Coopting existing widgets in this way allows existing key bindings to
automatically pick up related behaviour but it does mean that they
aren't quite doing what their name would imply.

In a separate thread Bart recently wrote:
> I hadn't seen auto-fu before but it appears to be a rewrite of the old
> incremental-complete-word functions.  I'm mildly surprised to see that
> it's using the keymap+widget technique, I didn't think anyone had even
> noticed that existed.

The keymap+widget technique is somewhat related. I was aware of it but
haven't applied it because it involves rebinding lots of core widgets.
A number of omz plugins rebind stuff en-masse and I suspect that's one
reason why people turn up on IRC wondering why things are broken when
they enable too many plugins.

At its basic level keymap+widget seems to just be a way to define the
behaviour of a widget for a particular keymap separately so you can have
one function for say ucase and another for say lcase and you can use one
without the other.

Perhaps a more generic mechanism would be to allow zle widget aliases to
be keymap specific. (Or possibly conditional on a selection of things
using zstyle as a backend.)

We could then make, e.g vi-up-line-or-history an explicit alias for a
new menuselect+prev-entry widget in the menuselect keymap.

For the too many omz plugins case, we'd need to somehow allow the
aliases to be chained so I'm not sure that this is a complete solution.

Oliver


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

* Re: accept-and-hold in interactive mode of menu select
  2014-12-16 19:11   ` Oliver Kiddle
@ 2014-12-17  3:07     ` Bart Schaefer
  0 siblings, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2014-12-17  3:07 UTC (permalink / raw)
  To: zsh-workers

On Dec 16,  8:11pm, Oliver Kiddle wrote:
}
} Bart wrote:
} > 
} > I'm not entirely sure that's wrong; accept means to accept what is on the
} > command line, not to accept what is highlighted in the menu.  You have to
} > finish the action of choosing one of the menu items so that the command
} > line is updated, before you accept.
} 
} No, with menu selection many widgets have quite different behaviour. The
} documented behaviour of accept-and-hold is to insert the currently
} selected match but keep the menu active so that you can select another
} match.

Yes, but my point is that in the interactive sub-mode, so to speak, there
is no "currently selected match" -- there's a highlighted item in the
menu, but in the example given the interactively-entered prefix is still
ambiguous, so nothing has been "selected" until that's resolved.  In this
sense the interactive mode is different from the navigation mode.

In the navigation mode the command line and the menu highlight are always
in sync so this distinction doesn't matter.

I acknowledge that this is being pedantic and that seeing a highlighted
item could lead one to believe it has been "selected" and it's probably
better to have the interactive mode behave that way.

} In a separate thread Bart recently wrote:
} > I hadn't seen auto-fu before but it appears to be a rewrite of the old
} > incremental-complete-word functions.  I'm mildly surprised to see that
} > it's using the keymap+widget technique
} 
} At its basic level keymap+widget seems to just be a way to define the
} behaviour of a widget for a particular keymap separately so you can have
} one function for say ucase and another for say lcase and you can use one
} without the other.

Something like that; it's an attempt to get behavior a bit more similar
to an emacs minor mode.  The examples only deal with rebinding self-insert
and accept-line but you could do a whole suite of related bindings.  I
started rewriting predict-on with it but didn't ever finish; auto-fu seems
to have done a much more thorough job.

} Perhaps a more generic mechanism would be to allow zle widget aliases to
} be keymap specific. (Or possibly conditional on a selection of things
} using zstyle as a backend.)

If at some point I get especially ambitious, I'd like to use zstyles to
create something like emacs "advice" hooks.

} For the too many omz plugins case, we'd need to somehow allow the
} aliases to be chained so I'm not sure that this is a complete solution.

We might learn a lot by looking at the way emacs and Xwindows manage
key bindings.


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

end of thread, other threads:[~2014-12-17  3:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-16 14:18 accept-and-hold in interactive mode of menu select Jun T.
2014-12-16 16:45 ` Bart Schaefer
2014-12-16 19:11   ` Oliver Kiddle
2014-12-17  3:07     ` Bart Schaefer

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