Zsh Mailing List Archive
Messages sorted by:
Reverse Date,
Date,
Thread,
Author
Re: Neat hash -d trick
- X-seq: zsh-users 15469
- From: Mikael Magnusson <mikachu@xxxxxxxxx>
- To: Zsh Users <zsh-users@xxxxxxx>
- Subject: Re: Neat hash -d trick
- Date: Fri, 22 Oct 2010 09:28:04 +0200
- Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:content-type; bh=T8Co9Qf0bjDN8XlLWwRGO3Opi994OMF5lJCqkTM2Gjw=; b=vtXPpf8sj5l8zAFuBsdG25pb2H5/qCc2w4/A/gYFgAW6x9sA981CbKjgW2/o6hou3p bf/B2D7W9yI3tsOySe5LILrss+Lq2Ao5p/iXfr7ezQ5baIYKUd7KiuU1kV1WubT60hkM Z75eHVzyGeD+1hRqvrmzcHrMDGGpCMETHNBiY=
- Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :content-type; b=qYnL1Xhka88OiV6toWu0RQEtyZ8Lk0CKte68HHRyKDc3X6Q35VuosKg7ktrx3Kit6W VBksgptX3GY25v12NKpp0qipJB30YEra1cIs3rhQciP+WkqRVPrLhcp3MFGqBXCe1oI8 DmIrv2THXsTJP0KEoFKdCiLRohwqsOEhGCqik=
- In-reply-to: <101021210513.ZM30802@xxxxxxxxxxxxxxxxxxxxxx>
- List-help: <mailto:zsh-users-help@zsh.org>
- List-id: Zsh Users List <zsh-users.zsh.org>
- List-post: <mailto:zsh-users@zsh.org>
- Mailing-list: contact zsh-users-help@xxxxxxx; run by ezmlm
- References: <AANLkTikBOSBNfBHXDFdfiCkijVt5G5+-1UVFz_VqY3wZ@xxxxxxxxxxxxxx> <101021210513.ZM30802@xxxxxxxxxxxxxxxxxxxxxx>
On 22 October 2010 06:05, Bart Schaefer <schaefer@xxxxxxxxxxxxxxxx> wrote:
> [Aside to -workers: This reminds me about Mikael Magnusson's thread
> for his proposed HASH_LOOKUP option, which sort of died out without
> resolution after a discussion of findcmd() behaving oddly.]
[I'm still meaning to look into that, it's just that hacking on zsh C
code requires a pretty rare set of circumstances, being both pretty
bored, but also in a very optimistic mood. :)]
> On Oct 22, 12:34am, Nikolai Weibull wrote:
> }
> } for ((i = 1; i < 9; i++)); do
>
> You probably mean <= 9 there? Or just
>
> for i in {1..9}
>
> } hash -d .$i=${(j:/:)${(l:2::.:)${(s::)${(l:i::.:)}}}}
>
> hash -d .$i=${${(l:i*3::../:)}%/}
>
> } done
> }
> } cd ~.4/dir
>
> A generic word of caution about using "hash -d": if you for any reason
> change the value of $PATH or $path after this, all your custom hash
> entries are lost when the table is rebuilt for the new searchpath.
Hmm? Doesn't seem to happen for me.
> A similar trick:
>
> dotdot() {
> if (( NUMERIC > 0 ))
> then LBUFFER+=..; repeat $((NUMERIC-1)) LBUFFER+=/..
> else LBUFFER+=.
> fi
> }
> zle -N dotdot
> bindkey . dotdot
>
> Now you can type ESC 4 . to insert ../../../.. (or ESC 9 ESC 9 . to
> insert 99 levels, if for some insane reason you need that many).
Doing this actually causes you to be unable to type dots in an isearch
widget, since it aborts on custom bindings. I think pws is partly
responsible for this
# just type '...' to get '../..'
rationalise-dot() {
local MATCH
if [[ $LBUFFER =~ '(^|/| | |'$'\n''|\||;|&)\.\.$' ]]; then
LBUFFER+=/
zle self-insert
zle self-insert
else
zle self-insert
fi
}
zle -N rationalise-dot
bindkey . rationalise-dot
# without this, typing a . aborts incremental history search
bindkey -M isearch . self-insert
You only need the last line to avoid the problem of course.
> } What would be even sweeter is if someone would come up with a way to
> } do this with only one call to hash -d without writing out all the
> } expansions
>
> Because the counter has to be referenced twice in the expansion, I
> don't think there's any way of avoiding the "for" loop that's worth
> the effort to figure out. However,
>
> for i in {1..9}; h+=(.$i=${${(l:i*3::../:)}%/}); hash -d $h
>
> Or to avoid leaving $i and $h with a value at the end,
>
> hash -d $( for i in {1..9}; print .$i=${${(l:i*3::../:)}%/} )
To avoid leaving $i and $h with a value and a fork ;)
% () {local i h; for i in {1..9}; h+=(.$i=${${(l:i*3::../:)}%/}); hash -d $h}
% path+=/tmp
% path[2]=()
% hash -d|head -1
.1=..
I also have a vaguely related custom widget, in case you're unsure
just how many dotdots you need.
function _showcurrargrealpath() {
setopt localoptions nonomatch
local REPLY REALPATH
_split_shell_arguments_under
#zle -M "$(realpath ${(Q)${~REPLY}} 2> /dev/null | head -n1 || echo
1>&2 "No such path")"
REALPATH=( ${(Q)${~REPLY}}(N:A) )
zle -M "${REALPATH:-Path not found: $REPLY}"
}
zle -N _showcurrargrealpath
bindkey "^X." _showcurrargrealpath
# which i now notice in turn relies on this bit:
autoload -U modify-current-argument
autoload -U split-shell-arguments
function _split_shell_arguments_under()
{
local -a reply
integer REPLY2
split-shell-arguments
#have to duplicate some of modify-current-argument to get the word
#_under_ the cursor, not after.
setopt localoptions noksharrays multibyte
if (( REPLY > 1 )); then
if (( REPLY & 1 )); then
(( REPLY-- ))
fi
fi
REPLY=${reply[$REPLY]}
}
I also noticed now that if you mistype a named dir and run that
widget, the whole command line aborted due to the failed $~ expansion,
not sure why it would do that. That's why I added the setopt nonomatch
just now, it'll print the original path with (:A) appended as if it
succeeds but at least better than eating the command line.
[aside to -workers: would it make sense if ~ also checked for
nullglob? i noticed in the code that it checks for nomatch only
(merely looking at zsh C code is possible more often than editing it).
not sure how many different bits use that same function to expand
stuff though.]
--
Mikael Magnusson
Messages sorted by:
Reverse Date,
Date,
Thread,
Author