From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 8161 invoked by alias); 22 Oct 2010 07:28:13 -0000 Mailing-List: contact zsh-users-help@zsh.org; run by ezmlm Precedence: bulk X-No-Archive: yes List-Id: Zsh Users List List-Post: List-Help: X-Seq: 15469 Received: (qmail 8902 invoked from network); 22 Oct 2010 07:28:09 -0000 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received-SPF: pass (ns1.primenet.com.au: SPF record at _spf.google.com designates 209.85.161.171 as permitted sender) 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= MIME-Version: 1.0 In-Reply-To: <101021210513.ZM30802@torch.brasslantern.com> References: <101021210513.ZM30802@torch.brasslantern.com> Date: Fri, 22 Oct 2010 09:28:04 +0200 Message-ID: Subject: Re: Neat hash -d trick From: Mikael Magnusson To: Zsh Users Content-Type: text/plain; charset=UTF-8 On 22 October 2010 06:05, Bart Schaefer 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