[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

pushd/popd/dirs for es



i haven't used a shell with these operations in it for nearly a decade,
but i know many csh users swear by them, so i consed up es versions.
i think they act identically to those in csh, but i'm not sure, since
i only tried a few commands.

the dirs command (which is also invoked by pushd and popd) is too slow
in my opinion because it substituted ~ in the directories it prints, ala
csh.  to do that, it uses sed.  other than that, these things should
run nice and fast.  (i really don't think pattern matching and
substitution belongs in native es, so forking something is just about
required.)

anyway, i now have these in my $autoload directory under the name pushd.
(that is, until a pushd command is given, popd and dirs are not defined;
i wanted it that way, but it might be more consistent to use symbolic
links and load them when any of the three commands is given.)

paul

fn %pwd {
	result `` \n pwd
}

fn dirs {
	echo `` \n {
		{ for (i = <=%pwd $dirstack) echo $i } |
			sed 's,^'^$realhome^'$,~,
			     s,^'^$realhome^'/,~/,'
	}
}

fn pushd dir {
	if {~ $#dir 0} {
		if {~ $#dirstack 0} {
			throw error pushd 'pushd: no other directory'
		}
		let (cwd = <=%pwd) {
			cd $dirstack(1)
			dirstack = $cwd $dirstack(2 ...)
		}
	} {~ $#dir 1} {
		if {~ $dir +[0-9]*} {
			if {~ $dir +0} {
				return <=pushd
			}
			let (h = $dirstack($dir ...); t = <=%pwd $dirstack) {
				cd $h(1)
				dirstack = $h(2 ...) $t(... $dir)
			}
		} {
			let (cwd = <=%pwd) {
				cd $dir
				dirstack = $cwd $dirstack
			}
		}
	} {
		throw error pushd 'usage: pushd [directory | +n]'
	}
	dirs
}

fn popd n {
	if {~ $#n 0} {
		n = +0
	}
	if {!~ $#n 1} {
		throw error popd 'usage: popd [+n]'
	}
	if {~ $n 0 +0} {
		cd $dirstack(1)
		dirstack = $dirstack(2 ...)
	} {
		let (h = - $dirstack; t = $dirstack(2 ...)) {
			dirstack = $h(2 ... $n) $t($n ...)
		}
	}
	dirs
}

dirstack =
realhome = `` \n { $&cd $home; pwd }