* 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