zsh-users
 help / color / mirror / code / Atom feed
* Menu-driven version of history-beginning-search-backward
@ 2006-07-26 16:38 Peter Stephenson
  2006-07-27 16:01 ` Felix Rosencrantz
  0 siblings, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2006-07-26 16:38 UTC (permalink / raw)
  To: Zsh users list

I was too lazy to search the mailing list archive for anything like
this, but in any case it would be good to have something like it in
the distribution.

It would be easy to expand it to allow patterns on the command line,
but it's going a little beyond the original intention.


#Start
# Menu-driven alternative to history-beginning-search-backward.
# As it uses a menu there is no sense of "forward" or "backward", however;
# the entire history is searched.
#
# Configuration:
#   autoload -U history-beginning-search-menu
#   zle -N history-beginning-search-menu
#   bindkey '\eP' history-beginning-search-menu
#
# Example:
#   % /bin/su<ESC-P>
#   Enter digit:
#   1 /bin/su -c 'make install'            4 /bin/su - perforce
#   2 /bin/su                              5 /bin/su -c
#   3 /bin/su -c 'chown pws:pws **/*(u0)'
#
# Typing "1" expands the line to
#   % /bin/su -c 'make install'
#
# With a prefix argument, the search is not anchored to the beginning,
# so for example "/su" could expand to "p4 files //depot/support/..."
#
# If this is bound to a widget containing "-end", e.g.
#   zle -N history-beginning-search-menu-end history-beginning-search-menu
# then the cursor is put at the end of the line, else it is left
# after the matched characters.

emulate -L zsh
setopt extendedglob

zmodload -i zsh/parameter

local -aU matches
local -a display

if (( ${+NUMERIC} )); then
  matches=(${history[(R)*${(q)LBUFFER}*]})
else
  matches=(${history[(R)${(q)LBUFFER}*]})
fi

# Filter out any match that's the same as the original.
# Note this isn't a pattern this time.
matches=(${matches:#${LBUFFER}})

integer n=${#matches}
integer width=${#n}

(( n == 0 )) && return 1

# Hey, this works...
integer i
display=(${matches/(#m)*/${(l.$width..0.):-$((++i))} $MATCH})
zle -R "Enter digit${${width##1}:+s}:" $display

local chars
read -k$width chars

if [[ $chars != [[:digit:]]## || $chars -eq 0 || $chars -gt $n ]]; then
  return 1
fi

if [[ $WIDGET = *-end* ]]; then
  LBUFFER=${matches[$chars]} RBUFFER=
else
  integer newcursor
  if (( ${+NUMERIC} )); then
    # Advance cursor so that it's still after the string typed
    local -a match mbegin mend
    if [[ $matches[$chars] = (#b)(*${LBUFFER})* ]]; then
      newcursor=${#match[1]}
    fi
  fi

  BUFFER=${matches[$chars]}
  (( newcursor )) && CURSOR=$newcursor
fi
#End


-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php


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

* Re: Menu-driven version of history-beginning-search-backward
  2006-07-26 16:38 Menu-driven version of history-beginning-search-backward Peter Stephenson
@ 2006-07-27 16:01 ` Felix Rosencrantz
  2006-07-27 16:53   ` Peter Stephenson
  2006-07-28  4:24   ` Bart Schaefer
  0 siblings, 2 replies; 6+ messages in thread
From: Felix Rosencrantz @ 2006-07-27 16:01 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: Zsh users list

Interesting.  It covers some items I mention in the ideas on
incremental history search (
http://zshwiki.org/ImprovedIncrementalSearch )

I tried this function.  One problem is it doesn't seem to work if the
line (your search string) contains a space.  It would be nice if the
user says "foo bar" it matches lines that matches line that match
foo*bar

-FR.

On 7/26/06, Peter Stephenson <pws@csr.com> wrote:
> I was too lazy to search the mailing list archive for anything like
> this, but in any case it would be good to have something like it in
> the distribution.
>
> It would be easy to expand it to allow patterns on the command line,
> but it's going a little beyond the original intention.
>
>
> #Start
> # Menu-driven alternative to history-beginning-search-backward.
> # As it uses a menu there is no sense of "forward" or "backward", however;
> # the entire history is searched.
> #
> # Configuration:
> #   autoload -U history-beginning-search-menu
> #   zle -N history-beginning-search-menu
> #   bindkey '\eP' history-beginning-search-menu
> #
> # Example:
> #   % /bin/su<ESC-P>
> #   Enter digit:
> #   1 /bin/su -c 'make install'            4 /bin/su - perforce
> #   2 /bin/su                              5 /bin/su -c
> #   3 /bin/su -c 'chown pws:pws **/*(u0)'
> #
> # Typing "1" expands the line to
> #   % /bin/su -c 'make install'
> #
> # With a prefix argument, the search is not anchored to the beginning,
> # so for example "/su" could expand to "p4 files //depot/support/..."
> #
> # If this is bound to a widget containing "-end", e.g.
> #   zle -N history-beginning-search-menu-end history-beginning-search-menu
> # then the cursor is put at the end of the line, else it is left
> # after the matched characters.
>
> emulate -L zsh
> setopt extendedglob
>
> zmodload -i zsh/parameter
>
> local -aU matches
> local -a display
>
> if (( ${+NUMERIC} )); then
>   matches=(${history[(R)*${(q)LBUFFER}*]})
> else
>   matches=(${history[(R)${(q)LBUFFER}*]})
> fi
>
> # Filter out any match that's the same as the original.
> # Note this isn't a pattern this time.
> matches=(${matches:#${LBUFFER}})
>
> integer n=${#matches}
> integer width=${#n}
>
> (( n == 0 )) && return 1
>
> # Hey, this works...
> integer i
> display=(${matches/(#m)*/${(l.$width..0.):-$((++i))} $MATCH})
> zle -R "Enter digit${${width##1}:+s}:" $display
>
> local chars
> read -k$width chars
>
> if [[ $chars != [[:digit:]]## || $chars -eq 0 || $chars -gt $n ]]; then
>   return 1
> fi
>
> if [[ $WIDGET = *-end* ]]; then
>   LBUFFER=${matches[$chars]} RBUFFER=
> else
>   integer newcursor
>   if (( ${+NUMERIC} )); then
>     # Advance cursor so that it's still after the string typed
>     local -a match mbegin mend
>     if [[ $matches[$chars] = (#b)(*${LBUFFER})* ]]; then
>       newcursor=${#match[1]}
>     fi
>   fi
>
>   BUFFER=${matches[$chars]}
>   (( newcursor )) && CURSOR=$newcursor
> fi
> #End
>
>
> --
> Peter Stephenson <pws@csr.com>                  Software Engineer
> CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
> Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070
>
>
> To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php
>


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

* Re: Menu-driven version of history-beginning-search-backward
  2006-07-27 16:01 ` Felix Rosencrantz
@ 2006-07-27 16:53   ` Peter Stephenson
  2006-07-31 14:38     ` Andy Spiegl
  2006-07-28  4:24   ` Bart Schaefer
  1 sibling, 1 reply; 6+ messages in thread
From: Peter Stephenson @ 2006-07-27 16:53 UTC (permalink / raw)
  To: Zsh users list

"Felix Rosencrantz" wrote:
> I tried this function.  One problem is it doesn't seem to work if the
> line (your search string) contains a space.

Grrr... the quoting of patterns in associative array subscripts is
screwy.  You *can* quote the pattern characters, but if you quote any
other characters too they stay quoted.  I've tried to quote only pattern
characters.  This isn't very programmer-friendly.

> It would be nice if the
> user says "foo bar" it matches lines that matches line that match
> foo*bar

I've done it so you do this by including "-space" in the name of the
widget.

#BEGIN
# Menu-driven alternative to history-beginning-search-backward.
# As it uses a menu there is no sense of "forward" or "backward", however;
# the entire history is searched.
#
# Configuration:
#   autoload -U history-beginning-search-menu
#   zle -N history-beginning-search-menu
#   bindkey '\eP' history-beginning-search-menu
#
# Example:
#   % /bin/su<ESC-P>
#   Enter digit:
#   1 /bin/su -c 'make install'            4 /bin/su - perforce
#   2 /bin/su                              5 /bin/su -c
#   3 /bin/su -c 'chown pws:pws **/*(u0)'
#
# Typing "1" expands the line to
#   % /bin/su -c 'make install'
#
# With a prefix argument, the search is not anchored to the beginning,
# so for example "/su" could expand to "p4 files //depot/support/..."
#
# If this is bound to a widget containing "-end", e.g.
#   zle -N history-beginning-search-menu-end history-beginning-search-menu
# then the cursor is put at the end of the line, else it is left
# after the matched characters.
#
# If this is bound to a widget containing "-space", then any space in
# the line so far is matched as a wildcard.  (This means putting a space
# at the start of the line is equivalent to specifying a prefix
# argument.)

emulate -L zsh
setopt extendedglob

zmodload -i zsh/parameter

local -aU matches
local -a display

local search=$LBUFFER

if [[ $WIDGET = *-space* ]]; then
  search=${search//(#m)[*?#<>]/\\$MATCH/}
  search=${search// /*}
fi

if (( ${+NUMERIC} )); then
  matches=(${(o)history[(R)*${search}*]})
else
  matches=(${(o)history[(R)${search}*]})
fi

# Filter out any match that's the same as the original.
# Note this isn't a pattern this time.
matches=(${matches:#${LBUFFER}})

integer n=${#matches}
integer width=${#n}

(( n == 0 )) && return 1

# Hey, this works...
integer i
display=(${matches/(#m)*/${(l.$width..0.):-$((++i))} $MATCH})
zle -R "Enter digit${${width##1}:+s}:" $display

local chars
read -k$width chars

if [[ $chars != [[:digit:]]## || $chars -eq 0 || $chars -gt $n ]]; then
  return 1
fi

if [[ $WIDGET = *-end* ]]; then
  LBUFFER=${matches[$chars]} RBUFFER=
else
  integer newcursor
  if (( ${+NUMERIC} )); then
    # Advance cursor so that it's still after the string typed
    local -a match mbegin mend
    if [[ $matches[$chars] = (#b)(*${LBUFFER})* ]]; then
      newcursor=${#match[1]}
    fi
  fi

  BUFFER=${matches[$chars]}
  (( newcursor )) && CURSOR=$newcursor
fi
#END

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php


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

* Re: Menu-driven version of history-beginning-search-backward
  2006-07-27 16:01 ` Felix Rosencrantz
  2006-07-27 16:53   ` Peter Stephenson
@ 2006-07-28  4:24   ` Bart Schaefer
  1 sibling, 0 replies; 6+ messages in thread
From: Bart Schaefer @ 2006-07-28  4:24 UTC (permalink / raw)
  To: Felix Rosencrantz, Peter Stephenson; +Cc: Zsh users list

(I'm just back from a week's vacation.)

On 7/26/06, Peter Stephenson <pws@csr.com> wrote:
> I was too lazy to search the mailing list archive for anything like
> this, but in any case it would be good to have something like it in
> the distribution.

April 2004, zsh-users/7370.

On Jul 27,  9:01am, Felix Rosencrantz wrote:
}
} I tried this function.  One problem is it doesn't seem to work if the
} line (your search string) contains a space.

We had this same discussion two years ago, you and I. :-)


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

* Re: Menu-driven version of history-beginning-search-backward
  2006-07-27 16:53   ` Peter Stephenson
@ 2006-07-31 14:38     ` Andy Spiegl
  2006-07-31 14:55       ` Peter Stephenson
  0 siblings, 1 reply; 6+ messages in thread
From: Andy Spiegl @ 2006-07-31 14:38 UTC (permalink / raw)
  To: Zsh users list

Hi Peter,

great stuff, I love it!

Is it very hard to make it use a menu where you can move around the
possible completions with the cursor keys, instead of having to type the
corresponding number?  I mean, just like the "normal" completion menu.

Thanks,
 Andy.

-- 
 If only women came with pull-down menus & online help.


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

* Re: Menu-driven version of history-beginning-search-backward
  2006-07-31 14:38     ` Andy Spiegl
@ 2006-07-31 14:55       ` Peter Stephenson
  0 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2006-07-31 14:55 UTC (permalink / raw)
  To: Zsh users list

Andy Spiegl wrote:
> Is it very hard to make it use a menu where you can move around the
> possible completions with the cursor keys, instead of having to type the
> corresponding number?  I mean, just like the "normal" completion menu.

Unfortunately, yes.  Bart's version of menu-driven history (which he
posted a pointer to) does this because it uses a completion widget; but
using a completion widget gives you less flexibility about altering the
command line, so it can't fully emulate the "history-beginning-..."
behaviour.

As I briefly mentioned to zsh-workers, there is nothing so sophisticated
as an API to use the menu selection code for completion from outside it.
It would be nice to have, though.

-- 
Peter Stephenson <pws@csr.com>                  Software Engineer
CSR PLC, Churchill House, Cambridge Business Park, Cowley Road
Cambridge, CB4 0WZ, UK                          Tel: +44 (0)1223 692070


To access the latest news from CSR copy this link into a web browser:  http://www.csr.com/email_sig.php


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

end of thread, other threads:[~2006-07-31 15:02 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-07-26 16:38 Menu-driven version of history-beginning-search-backward Peter Stephenson
2006-07-27 16:01 ` Felix Rosencrantz
2006-07-27 16:53   ` Peter Stephenson
2006-07-31 14:38     ` Andy Spiegl
2006-07-31 14:55       ` Peter Stephenson
2006-07-28  4:24   ` 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).