zsh-users
 help / color / mirror / code / Atom feed
* Cygwin zsh and command availability
@ 2006-03-04 19:37 Phil Pennock
  0 siblings, 0 replies; only message in thread
From: Phil Pennock @ 2006-03-04 19:37 UTC (permalink / raw)
  To: zsh-users

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 <drive-letter>: 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:]]##\<NO NAME\>*)
		rest="${regout[$i]##[[:blank:]]##<NO NAME>}"
		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


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2006-03-04 19:37 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-03-04 19:37 Cygwin zsh and command availability Phil Pennock

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