From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7900 invoked from network); 23 Sep 1999 13:45:06 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 23 Sep 1999 13:45:06 -0000 Received: (qmail 3738 invoked by alias); 23 Sep 1999 13:44:54 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 8028 Received: (qmail 3730 invoked from network); 23 Sep 1999 13:44:54 -0000 Date: Thu, 23 Sep 1999 14:44:53 +0100 From: Adam Spiers To: zsh-workers@sunsite.auc.dk Subject: PATCH and Re: simulation of dabbrev-expand Message-ID: <19990923144453.A5293@thelonious.new.ox.ac.uk> Reply-To: Adam Spiers Mail-Followup-To: zsh-workers@sunsite.auc.dk References: <199909230838.KAA23316@beta.informatik.hu-berlin.de> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: quoted-printable X-Mailer: Mutt 1.0pre2i In-Reply-To: <199909230838.KAA23316@beta.informatik.hu-berlin.de> X-URL: http://www.new.ox.ac.uk/~adam/ X-OS: Linux 2.2.9 i686 Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote: >=20 > First: there was a buglet in `_history_complete_word' which made it > pretty useless if `history_stop' wasn't set. I hope the patch below > doesn't interfere with your work... Nope -- I ended up rewriting the whole damn thing :-) > Adam Spiers wrote: > > The current situation is that _history_complete_word crawls through > > matching history words, oldest first.=20 >=20 > Now I'm confused. For me it works from the bottom up. Of course I was talking rubbish again here ... but I'm sure you had realised that and were just being polite :-) > *But* words > from the same line are inserted left-to-right. Since the C-code walks > up maybe we should add the words from the end of the line to the > beginning. >=20 > We should then use the hunk for `zle_tricky.c' below. Nice touch. Reminds me of another feature I've wanted in _history_complete_word for ages - would it be possible to modify compgen -H to include words from the currently edited line? > > However, I got stuck when handling the history_stop feature. > > When in verbose mode, history_stop uses _message to indicate that the > > beginning/end of the history has been reached. However, unless I've > > got things really wrong, _message seems to destroy any old list of matc= hes > > which you might want to keep. I can't understand why, as it's only > > essentially a compadd -X ... -n ''.=20 >=20 > That's right. To be able to display the message we have to add a dummy=20 > completion (that empty string) and throw away the old list. Hmm. I'm still puzzled why compadd -X ... -n '' throws away the old list though, since compwidget =3D=3D lastcompwidget and compstate[old_list] is set to keep. > > so that if you hit the oldest match and press M-/ again, it displays > > this message but keeps the oldest match (should I need a > > compstate[insert]=3D1 again, or is it enough to have done that the first > > time the oldest match was displayed?), and if you switch to M-, it > > will keep this old_list again and start moving in the opposite > > direction. >=20 > If I were to implement that, I would use two (global) parameters set > when the end is reached with `verbose' (or always when the end is > reached). Any of the two ends, that is. The first parameter just says > that the end was reached (and could say which end if that is > needed). The other one would contain the value of `BUFFER' at the time=20 > the end was reached. Now if you invoke the widget for the other > direction when an end was reached (the first parameter sayeth so), you=20 > compare the second parameter with the current value of `BUFFER'. If > they are equal, the thing was just invoked (hm, maybe we shouldn't > compare `BUFFER', maybe we should check `LASTWIDGET'; or both; and if > you use the numeric argument thing, the latter may also need to have > to take that into its calculation). Anyway, the test would say that we=20 > just reached one of the ends by the history_complete function for the > other direction and if we find that out, we just call completion again=20 > (that `compgen') and then use `compstate[insert]=3D-1' (or `...=3D1' for > the other direction). Getting words to complete from the history > should be fast enough so that the user doesn't really notice that a > new list was created. For this we would also have to keep the original=20 > values of `PREFIX' and `SUFFIX' -- and set them anew in the right > place. Yep, a similar approach had occurred to me after my last post on the subject. > Anyway, I think it can be done... It can and it has :-) Here's a full replacement for Completion/Commands/_history_complete_word. -------- 8< -------- 8< -------- #compdef -k complete-word \e/ \e, # # Complete words from the history # # by Adam Spiers, with help gratefully received from # Sven Wischnowsky and Bart Schaefer # # Available configuration keys: # # history_list -- display lists of available matches # history_stop -- prevent looping at beginning and end of matches # during menu-completion # history_sort -- sort matches lexically (default is to sort by age) # history_remove_all_dups -- # remove /all/ duplicate matches rather than just # consecutives # _history_complete_word () { local expl direction case "$KEYS" in=20 '=1B,') direction=3D'newer' ;; '=1B/') direction=3D'older' ;; *) print < oldest (reverse of history order) if [[ "$direction" =3D=3D 'older' ]]; then if [[ compstate[old_insert] -eq $_hist_menu_length || "$_hist_stop" =3D=3D 'oldest' ]]; then _hist_stop=3D'oldest' [[ "$compconfig[history_stop]" =3D verbose ]] && _message 'beginning of history reached' elif [[ "$_hist_stop" =3D=3D 'newest' ]]; then zle -Rc _history_complete_word_gen_matches else compstate[old_list]=3Dkeep (( compstate[insert] =3D compstate[old_insert] + 1 )) fi elif [[ "$direction" =3D=3D 'newer' ]]; then if [[ compstate[old_insert] -eq 1 || "$_hist_stop" =3D=3D 'newest' ]]= ; then _hist_stop=3D'newest' [[ "$compconfig[history_stop]" =3D verbose ]] && _message 'end of history reached' elif [[ "$_hist_stop" =3D=3D 'oldest' ]]; then zle -Rc _history_complete_word_gen_matches else compstate[old_list]=3Dkeep (( compstate[insert] =3D compstate[old_insert] - 1 )) fi fi else _hist_stop=3D'' _hist_old_prefix=3D"$PREFIX" _history_complete_word_gen_matches fi [[ -n "$compstate[nmatches]" ]] } _history_complete_word_gen_matches () { if [[ -n "$compconfig[history_list]" ]]; then if [[ -n "$compconfig[history_sort]" ]]; then _description expl 'history word' else _description -V expl 'history word' fi else if [[ -n "$compconfig[history_sort]" ]]; then expl=3D() else expl=3D('-V' '') fi fi [[ -n "$_hist_stop" ]] && PREFIX=3D"$_hist_old_prefix" local rem_dups if [[ -n "$compconfig[history_remove_all_dups]" ]]; then rem_dups=3D'' else rem_dups=3D'-1' fi compgen "$expl[@]" $rem_dups -Q -H 0 '' _hist_menu_length=3D"$compstate[nmatches]" case "$direction" in=20 newer) compstate[insert]=3D$_hist_menu_length [[ -n "$_hist_stop" ]] && (( compstate[insert]-- )) ;; older) compstate[insert]=3D1 [[ -n "$_hist_stop" ]] && (( compstate[insert]++ )) ;; esac [[ -n "$_hist_stop" ]] && _hist_stop=3D'' } _history_complete_word "$@" -------- 8< -------- 8< -------- Please have a play with the different options and see how robust it is (not very, probably!) Known problems: - Doesn't cope with numeric arguments yet. - Whenever duplicates get removed, it breaks. It looks like compstate[nmatches] corresponds with the number of matches /including/ duplicates, even if some/all duplicates have been removed. - The error message given when unknown keys are bound to the widget doesn't work. Should I be using zle -R here? > I hope it helped. It did. Thanks!