shithub: mc

Download patch

ref: d5eaba0e687c26c7eb1a7954eda6e82508e0775a
parent: f79cf73913ebc6394f5333440bf6d9312c07719a
author: Ori Bernstein <ori@eigenstate.org>
date: Thu Jun 2 05:31:26 EDT 2016

Add a file walking library.

--- a/lib/bld.sub
+++ b/lib/bld.sub
@@ -3,6 +3,7 @@
 	date
 	cryptohash
 	inifile
+	fileutil
 	regex
 	std
 	sys
--- /dev/null
+++ b/lib/fileutil/bld.sub
@@ -1,0 +1,5 @@
+lib fileutil =
+	walk.myr
+	lib ../std:std
+;;
+
--- /dev/null
+++ b/lib/fileutil/walk.myr
@@ -1,0 +1,61 @@
+use std
+
+pkg fileutil =
+	type walkiter = struct
+		dirstk	: std.dir#[:]
+		curdir	: byte[:][:]
+		iterdir	: bool
+	;;
+
+	impl iterable walkiter -> byte[:]
+	const bywalk	: (dir : std.dir# -> walkiter)
+;;
+
+const bywalk = {d
+	-> [.dirstk = std.sldup([d][:]), .curdir = std.sldup([""][:])]
+}
+
+impl iterable walkiter -> byte[:] =
+	__iternext__ = {itp, valp
+		var cur, p
+
+:nextfile
+		cur = itp.dirstk[itp.dirstk.len - 1]
+		match std.dirread(cur)
+		| `std.Some ".":	goto nextfile
+		| `std.Some "..":	goto nextfile
+		| `std.Some ent:
+			p = std.pathcat(itp.curdir[itp.curdir.len - 1], ent)
+			if std.fisdir(p)
+				match std.diropen(p)
+				| `std.Ok d:	std.slpush(&itp.dirstk, d)
+				| `std.Fail e:	/* ? */
+				;;
+				std.slpush(&itp.curdir, p)
+				goto nextfile
+			else
+				valp# = p
+			;;
+			-> true
+		| `std.None:
+			/* don't close the directory given to us by the user */
+			if itp.dirstk.len > 1
+				std.dirclose(itp.dirstk[itp.dirstk.len - 1])
+				std.slfree(itp.curdir[itp.curdir.len - 1])
+				std.slpop(&itp.curdir)
+				std.slpop(&itp.dirstk)
+				goto nextfile
+			else
+				-> false
+			;;
+		;;
+	}
+
+	__iterfin__ = {itp, valp
+		std.slfree(valp#)
+	}
+;;
+
+generic last = {sl : @a[:]
+	-> sl[sl.len - 1]
+}