From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 6840 invoked from network); 4 Mar 2006 19:37:53 -0000 X-Spam-Checker-Version: SpamAssassin 3.1.0 (2005-09-13) on f.primenet.com.au X-Spam-Level: X-Spam-Status: No, score=-2.5 required=5.0 tests=BAYES_00,FORGED_RCVD_HELO autolearn=ham version=3.1.0 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by ns1.primenet.com.au with SMTP; 4 Mar 2006 19:37:53 -0000 Received: (qmail 70063 invoked from network); 4 Mar 2006 19:37:45 -0000 Received: from sunsite.dk (130.225.247.90) by a.mx.sunsite.dk with SMTP; 4 Mar 2006 19:37:45 -0000 Received: (qmail 3366 invoked by alias); 4 Mar 2006 19:37:36 -0000 Mailing-List: contact zsh-users-help@sunsite.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 9993 Received: (qmail 3357 invoked from network); 4 Mar 2006 19:37:36 -0000 Received: from news.dotsrc.org (HELO a.mx.sunsite.dk) (130.225.247.88) by sunsite.dk with SMTP; 4 Mar 2006 19:37:36 -0000 Received: (qmail 68867 invoked from network); 4 Mar 2006 19:37:35 -0000 Received: from parhelion.firedrake.org (193.201.200.77) by a.mx.sunsite.dk with SMTP; 4 Mar 2006 19:37:34 -0000 Received: from phil by parhelion.firedrake.org with local (Exim 4.50 #1 (Debian)) id 1FFcZJ-0006F9-Ga for ; Sat, 04 Mar 2006 19:37:33 +0000 Date: Sat, 4 Mar 2006 20:37:33 +0100 From: Phil Pennock To: zsh-users@sunsite.dk Subject: Cygwin zsh and command availability Message-ID: <20060304193733.GA22944@parhelion.globnix.org> Mail-Followup-To: zsh-users@sunsite.dk Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Sender: Phil Pennock Posting this in the hope that it might prove useful to others. Under Windows, commands run by ShellExecute() look in multiple places, including doing a registry key lookup under: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\ According to MSDN, the priority ordering of ShellExecute() varies by Windows version, but as of WinXP SP1 the App Path items come before %PATH%. This is how you can do things like Start->Run "firefox" and get a web-browser, despite Firefox not being in %PATH%. This zsh solution is not perfectly robust but it appears to work for me. It does not favour conciseness. Because I wanted to keep everything safe, the script generates zsh command-lines. Rather than re-work it, I've decided that I'm happy with: function load_win32_registry_paths { local t /cygdrive/X/path/to/win32_registry_paths | while read t do eval $t; done } Comments & improvements welcome. Command dependency is "reg", which I think is a standard Windows component; it says: Console Registry Tool for Windows - version 3.0 Copyright (C) Microsoft Corp. 1981-2001. All rights reserved -----------------------------< cut here >------------------------------- #!/usr/bin/zsh -f setopt extended_glob typeset -a regout oIFS="$IFS" IFS=$'\n' regout=($(reg query \ "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths" /s | \ sed 's/\\/\\\\/g')) IFS="$oIFS" function path_convert_backslash { local loc="$1" loc=${(Q)loc} loc=${loc:gs,\\,/} # for some reason, that results in // in the result, so: # loc=${loc:gs,//,/} print -r -- ${(q)loc} } function path_convert_drive { local loc="$1" loc=${(Q)loc} if [[ $loc == ?:* ]] then drive=${loc%%:*} loc="/cygdrive/${drive}${loc#?:}" fi print -r -- ${(q)loc} } function path_expand_var { # %ProgramFiles% -> $PROGRAMFILES local t="$1" while [[ $t == *%*%* ]] do local prefix suffix var prefix=${t%%\%*} var=${t#${prefix}\%} suffix=${var#*%} var=${var%%\%*} t="$(path_convert_backslash "${(qP)${(U)var}}")" t="$(path_convert_drive "$t")" t="${prefix}${t}${suffix}" done print -r -- $t return 0 } function get_path_expanded { #local src="${(p)1:gs/\t/ /}" local src="$1" # we actually can just split on a tab, at present local p t what drive typeset -a list newlist # Get the type and the rest list=(${(ps:\t:)src}) what=$list[1] list[1]=() t="$(path_convert_backslash "${list[*]}")" # expand out : for each element in the ;-list list=(${(s:;:)t}) newlist=() for p in $list do newlist+=("$(path_convert_drive $p)") done t="${(j:;:)newlist[*]}" case $what in (REG_SZ) print $t return 0 ;; (REG_EXPAND_SZ) # XXX: this probably doesn't deal well with variables whose value contains %, # which shouldn't happen but we should protect against it anyway. list=() for p in $newlist do list+=("$(path_expand_var $p)") done print "${(j:;:)list}" return 0 ;; (*) print -u2 "Unhandled registry type: $what" ;; esac return 1 } print "zmodload -i zsh/parameter" typeset -A state local rest n t for ((i=0; i < ${#regout}; i++)) do case ":${regout[$i]}:" in (:HKEY*) if [[ -n $state[name] && -n $state[cmd] ]] then n="${${(L)state[name]}%.exe}" if [[ -n $state[path_add] ]] then t="\"${(j:" ":)${(qs:;:)state[path_add]}}\"" print "function $n { ( path=($t \$path); \"${state[cmd]}\" \\\"\$@\\\" ) }" else print "commands[$n]=\"${state[cmd]}\"" fi fi state=() state[name]=${regout[$i]:t} # print "NAME: $state[name]" ;; (:[[:blank:]]##\*) rest="${regout[$i]##[[:blank:]]##}" state[cmd]=$(get_path_expanded $rest) # print " cmd: $state[cmd]" ;; (:[[:blank:]]##Path[[:blank:]]*) rest="${regout[$i]##[[:blank:]]##Path}" state[path_add]=$(get_path_expanded $rest) # print "path: $state[path_add]" ;; # Alas, we lost the blank lines, so accumulate in HKEY # (:[[:blank:]]#:) # ;; (*) # Oooh, look at all those undocumented fields: # print -u2 "Unhandled registry item for ${state[name]}: $regout[$i]" ;; esac done