From: Adam Spiers <adam@thelonious.new.ox.ac.uk>
To: zsh-workers@sunsite.auc.dk
Subject: PATCH and Re: simulation of dabbrev-expand
Date: Thu, 23 Sep 1999 14:44:53 +0100 [thread overview]
Message-ID: <19990923144453.A5293@thelonious.new.ox.ac.uk> (raw)
In-Reply-To: <199909230838.KAA23316@beta.informatik.hu-berlin.de>
Sven Wischnowsky (wischnow@informatik.hu-berlin.de) wrote:
>
> 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.
>
> 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.
>
> 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 matches
> > which you might want to keep. I can't understand why, as it's only
> > essentially a compadd -X ... -n ''.
>
> That's right. To be able to display the message we have to add a dummy
> 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 == 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]=1 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.
>
> 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
> 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
> 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
> 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
> (that `compgen') and then use `compstate[insert]=-1' (or `...=1' 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
> 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
'^[,') direction='newer'
;;
'^[/') direction='older'
;;
*) print <<EOF
The keypress \`$KEYS\' was not understood by _history_complete_word.
You must alter _history_complete_word if you want to bind it to keys
other than the defaults, so that it knows which direction the key
should move in the history.
EOF
return 1
esac
[[ -z "$compconfig[history_list]" ]] && compstate[list]=''
if [[ -n "$compstate[old_list]" && -n "$compconfig[history_stop]" ]]; then
# array of matches is newest -> oldest (reverse of history order)
if [[ "$direction" == 'older' ]]; then
if [[ compstate[old_insert] -eq $_hist_menu_length ||
"$_hist_stop" == 'oldest' ]]; then
_hist_stop='oldest'
[[ "$compconfig[history_stop]" = verbose ]] &&
_message 'beginning of history reached'
elif [[ "$_hist_stop" == 'newest' ]]; then
zle -Rc
_history_complete_word_gen_matches
else
compstate[old_list]=keep
(( compstate[insert] = compstate[old_insert] + 1 ))
fi
elif [[ "$direction" == 'newer' ]]; then
if [[ compstate[old_insert] -eq 1 || "$_hist_stop" == 'newest' ]]; then
_hist_stop='newest'
[[ "$compconfig[history_stop]" = verbose ]] &&
_message 'end of history reached'
elif [[ "$_hist_stop" == 'oldest' ]]; then
zle -Rc
_history_complete_word_gen_matches
else
compstate[old_list]=keep
(( compstate[insert] = compstate[old_insert] - 1 ))
fi
fi
else
_hist_stop=''
_hist_old_prefix="$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=()
else
expl=('-V' '')
fi
fi
[[ -n "$_hist_stop" ]] && PREFIX="$_hist_old_prefix"
local rem_dups
if [[ -n "$compconfig[history_remove_all_dups]" ]]; then
rem_dups=''
else
rem_dups='-1'
fi
compgen "$expl[@]" $rem_dups -Q -H 0 ''
_hist_menu_length="$compstate[nmatches]"
case "$direction" in
newer) compstate[insert]=$_hist_menu_length
[[ -n "$_hist_stop" ]] && (( compstate[insert]-- ))
;;
older) compstate[insert]=1
[[ -n "$_hist_stop" ]] && (( compstate[insert]++ ))
;;
esac
[[ -n "$_hist_stop" ]] && _hist_stop=''
}
_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!
next prev parent reply other threads:[~1999-09-23 13:45 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
1999-09-23 8:38 Sven Wischnowsky
1999-09-23 13:44 ` Adam Spiers [this message]
1999-09-23 14:23 Sven Wischnowsky
1999-09-25 14:45 ` Adam Spiers
1999-10-11 11:12 Sven Wischnowsky
1999-10-11 21:44 ` Adam Spiers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=19990923144453.A5293@thelonious.new.ox.ac.uk \
--to=adam@thelonious.new.ox.ac.uk \
--cc=adam@spiers.net \
--cc=zsh-workers@sunsite.auc.dk \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).