zsh-users
 help / color / mirror / code / Atom feed
* VMS Style auto command-complition
@ 2004-11-25 18:29 Ziggy
  2004-11-25 19:46 ` Peter Stephenson
  2004-11-25 20:20 ` Bart Schaefer
  0 siblings, 2 replies; 4+ messages in thread
From: Ziggy @ 2004-11-25 18:29 UTC (permalink / raw)
  To: List: ZSH

[-- Attachment #1: Type: text/plain, Size: 768 bytes --]

Hi.

	Recently I have tried using OpenVMS. So far I pretty much like
everything there.
	One thing that I liked specifically about it is that it completes
commands automatically if there is only one match.
	For example - if I want to purge all the previous versions of all files
in the directory, instead of typing 'PURGE' I can type 'PU' because
there is no any other command that starts with PU, so it knows that I'm
talking about the command PURGE:

$ pu	<- here the command went out fine
$ p 	<- here it says that there are other commands that start with p
%DCL-W-ABVERB, ambiguous command verb - supply more characters
 \P\

I wish you could tell me if it is possible to do with ZSH, because this
feature is simply one of OpenVMS' best features.

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]

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

* Re: VMS Style auto command-complition
  2004-11-25 18:29 VMS Style auto command-complition Ziggy
@ 2004-11-25 19:46 ` Peter Stephenson
  2004-11-25 20:31   ` Bart Schaefer
  2004-11-25 20:20 ` Bart Schaefer
  1 sibling, 1 reply; 4+ messages in thread
From: Peter Stephenson @ 2004-11-25 19:46 UTC (permalink / raw)
  To: List: ZSH

Ziggy wrote:
> 	Recently I have tried using OpenVMS. So far I pretty much like
> everything there.
> 	One thing that I liked specifically about it is that it completes
> commands automatically if there is only one match.
> 	For example - if I want to purge all the previous versions of all files
> in the directory, instead of typing 'PURGE' I can type 'PU' because
> there is no any other command that starts with PU, so it knows that I'm
> talking about the command PURGE:
> 
> $ pu	<- here the command went out fine
> $ p 	<- here it says that there are other commands that start with p
> %DCL-W-ABVERB, ambiguous command verb - supply more characters
>  \P\
> 
> I wish you could tell me if it is possible to do with ZSH, because this
> feature is simply one of OpenVMS' best features.

There are lots of answers to this which deserve thinking about.

First, Unix command names tend to be short and it's much harder to find
unambiguous completions in many cases.

Second, you can explicitly ask for a completion of the command name with
a TAB.  Because of the first point, this is very often more useful than
assuming an unambiguous expansion.

Third, you can assign an explicit alias "alias pu=purge".  Since in
practice you tend to use only one abbreviation, you don't have to go
through the full equivalent ("alias pu=purge pur=purge purg=purge").

If, despite all that, you still want to try it this way, have a go at
the following function.  Assuming it's called autoexpand in your
function path, you activate it with

autoload autoexec
zle -N autoexec
alias -A autoexpand accept-line

and deactivate it with

alias -A .accept-line accept-line

Be careful, since it's not well tested and I'm sure there are additional
safety tests it could usefully have.  However, I don't think it's liable
to reformat your disk.

Instead of trying to execute a command and failing if it finds
multiple possibilities, it outputs an error message underneath and
allows you to edit the line again.  This is likely to be the biggest
source of grief.  You can turn that off by replacing

    zle -M "Multiple $hash matches: $expn"
    return 1

with

    zle .accept-line
    return 0


# start autoexpand
integer curpos len
local hash cmd line expn found

line=(${(z)BUFFER})
len=${#line[1]}
cmd=${(Q)line[1]}

if [[ -z $cmd ]]; then
  zle .accept-line
  return 0
fi

for hash in aliases reswords functions builtins commands; do
  # always accept exact match
  if [[ $hash = reswords ]]; then
    # actually it's an array
    expn=${reswords[(r)$cmd]}
  else
    # expn=${(P)hash[$cmd]} doesn't do the right thing
    eval expn='${(k)'$hash'[$cmd]}'
  fi
  if [[ -n $expn ]]; then
    zle .accept-line
    return 0
  fi
done

for hash in aliases reswords functions builtins commands; do
  if [[ $hash = reswords ]]; then
    # actually it's an array
    expn=(${reswords:#^$cmd*})
  else
    eval expn='(${(k)'$hash'[(I)$cmd*]})'
  fi
  if (( ${#expn} > 1 )); then
    zle -M "Multiple $hash matches: $expn"
    return 1
  elif (( ${#expn} == 1 )); then
    (( curpos = CURSOR ))
    BUFFER[1,$len]="$expn"
    (( curpos <= len )) && (( CURSOR = ${#expn[1]} ))
    zle .accept-line
    return 0
  else
    continue
  fi
done

zle .accept-line
# end autoexpand

-- 
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


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************


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

* Re: VMS Style auto command-complition
  2004-11-25 18:29 VMS Style auto command-complition Ziggy
  2004-11-25 19:46 ` Peter Stephenson
@ 2004-11-25 20:20 ` Bart Schaefer
  1 sibling, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2004-11-25 20:20 UTC (permalink / raw)
  To: Ziggy; +Cc: zsh-users

On Thu, 25 Nov 2004, Ziggy wrote:

> For example - if I want to purge all the previous versions of all files
> in the directory, instead of typing 'PURGE' I can type 'PU' because
> there is no any other command that starts with PU
[...]
> %DCL-W-ABVERB, ambiguous command verb - supply more characters
> \P\

In the ambiguous case shown above, is it actually prompting you to input 
more characters, or is that just an error message?

There's a whole lot of subtlety that may be going on here -- for example, 
what happens if the command is part of a complex construct like a "while" 
loop, or is executed from a script or batch file? -- some of which it may 
not be possible to emulate without help from the OS.

However, you could try this:

----------
function conditional-accept-line {
  emulate -L zsh
  if [[ -z "$PREBUFFER" ]]
  then
    local -a words commands
    words=(${(z)BUFFER})
    if [[ $words[1] != *=* && $words[1] != [({})] ]] &&
       ! whence -w $words[1] > /dev/null
    then
      commands=(${${(f)"$(noglob whence -m ${words[1]}* 2>/dev/null)"}:#})
      case $#commands in
      (0) zle -M "no such command: $words[1]"; return 1;;
      (1) BUFFER=${BUFFER/$words[1]/$commands};;
      (*) zle -M "ambiguous: $words[1]"; return 1;;
      esac
    fi
  fi
  zle .accept-line
}

zle -N accept-line conditional-accept-line
----------

Note, however, that this disables zsh's "setopt correct" feature, because 
correction takes place only after the line has been accepted.


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

* Re: VMS Style auto command-complition
  2004-11-25 19:46 ` Peter Stephenson
@ 2004-11-25 20:31   ` Bart Schaefer
  0 siblings, 0 replies; 4+ messages in thread
From: Bart Schaefer @ 2004-11-25 20:31 UTC (permalink / raw)
  To: Peter Stephenson; +Cc: zsh-users

On Thu, 25 Nov 2004, Peter Stephenson wrote:

> autoload autoexec
> zle -N autoexec
> alias -A autoexpand accept-line

Er, surely you mean either

zle -N accept-line autoexec

or

zle -N autoexec
zle -A autoexec accept-line

> and deactivate it with
> 
> alias -A .accept-line accept-line

zle -A .accept-line accept-line

> Instead of trying to execute a command and failing if it finds
> multiple possibilities, it outputs an error message underneath and
> allows you to edit the line again.

Which is also what my conditional-accept-line function does, BTW, though
it makes no effort to reposition the cursor for you.

> for hash in aliases reswords functions builtins commands; do

I like my "whence -w" a lot better here ... it's questionable in the next
loop whether forking "whence -m" is faster, but it's sure more obvious,
and doesn't require the parameter module.

>     (( curpos = CURSOR ))
>     BUFFER[1,$len]="$expn"
>     (( curpos <= len )) && (( CURSOR = ${#expn[1]} ))

Hmm.


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

end of thread, other threads:[~2004-11-25 20:33 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-25 18:29 VMS Style auto command-complition Ziggy
2004-11-25 19:46 ` Peter Stephenson
2004-11-25 20:31   ` Bart Schaefer
2004-11-25 20:20 ` 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).