shithub: mc

Download patch

ref: ec5f2d23637dadf6d2893bf6f2f829b070ec3b34
parent: 167228d8551ba8b4dc282489258ad2e50363a56f
author: Ori Bernstein <[email protected]>
date: Mon May 23 17:09:46 EDT 2016

Add suball functionality.

	Search, but with substitution.

--- a/lib/regex/interp.myr
+++ b/lib/regex/interp.myr
@@ -7,6 +7,8 @@
 	const search	: (re : regex#, str : byte[:] -> std.option(byte[:][:]))
 	const sub	: (re : regex#, str : byte[:], subst : byte[:][:] -> std.option(byte[:]))
 	const sbsub	: (sb : std.strbuf#, re : regex#, str : byte[:], subst : byte[:][:] -> bool)
+	const suball	: (re : regex#, str : byte[:], subst : byte[:][:] -> byte[:])
+	const sbsuball	: (sb : std.strbuf#, re : regex#, str : byte[:], subst : byte[:][:] -> void)
 	const matchfree	: (pat : byte[:][:] -> void)
 ;;
 
@@ -69,24 +71,59 @@
 	if thr == Zthr
 		m = false
 	else
-		m = dosubst(sb, re, thr, subst)
+		m = dosubst(sb, re, thr, str, subst)
 	;;
 	cleanup(re)
 	-> m
 }
 
-const dosubst = {sb, re, thr, subst
+const suball = {re, str, subst
+	var sb
+
+	sb = std.mksb()
+	sbsuball(sb, re, str, subst)
+	-> std.sbfin(sb)
+}
+
+const sbsuball = {sb, re, str, subst
+	var thr, len, s, i
+
+	/* we always have m[0] as the full match */
+	if re.nmatch != subst.len + 1
+		-> void
+	;;
+
+	i = 0
+	while i < str.len
+		re.str = str[i:]
+		re.strp = 0
+		thr = run(re, false)
+		if thr == Zthr
+			std.sbputb(sb, str[i])
+			i++
+		else
+			len = thr.mend[0]
+			s = str[i:len + i]
+			dosubst(sb, re, thr, s, subst)
+			i += len
+		;;
+		cleanup(re)
+	;;
+}
+
+
+const dosubst = {sb, re, thr, str, subst
 	var off
 
 	off = 0
 	for var i = 1; i < re.nmatch; i++
 		if thr.mstart[i] != -1 && thr.mend[i] != -1
-			std.sbputs(sb, re.str[off:thr.mstart[i]])
+			std.sbputs(sb, str[off:thr.mstart[i]])
 			std.sbputs(sb, subst[i - 1])
 			off = thr.mend[i]
 		;;
 	;;
-	std.sbputs(sb, re.str[off:])
+	std.sbputs(sb, str[off:])
 	thrfree(re, thr)
 	-> true
 }
--- a/lib/regex/test/subst.myr
+++ b/lib/regex/test/subst.myr
@@ -49,4 +49,10 @@
 		"abc123foobar", \
 		["XYZ", "ABC"][:], \
 		`std.None)
+
+	/* suball */
+	testsuball("([a-z]*)_", \
+		"a_1bb_2ccccccc_12d", \
+		["---"][:], \
+		`std.Some "---_1---_2---_12d")
 }
--- a/lib/regex/test/testmatch.myr
+++ b/lib/regex/test/testmatch.myr
@@ -8,6 +8,12 @@
 		expected : std.option(byte[:][:]) \
 		-> void)
 
+	const testsearch	: ( \
+		pat : byte[:], \
+		text : byte[:], \
+		expected : std.option(byte[:][:]) \
+		-> void)
+
 	const testsub	: ( \
 		pat : byte[:], \
 		text : byte[:], \
@@ -15,10 +21,11 @@
 		expected : std.option(byte[:]) \
 		-> void)
 
-	const testsearch	: ( \
+	const testsuball	: ( \
 		pat : byte[:], \
 		text : byte[:], \
-		expected : std.option(byte[:][:]) \
+		sub : byte[:][:], \
+		expected : std.option(byte[:]) \
 		-> void)
 
 	const dbgmatch	: ( \
@@ -37,18 +44,27 @@
 }
 
 const testsub = {pat, text, sub, expected
-	subst(regex.compile(pat), pat, text, sub, expected)
+	subst(regex.compile(pat), pat, text, sub, expected, false)
 }
 
+const testsuball = {pat, text, sub, expected
+	subst(regex.compile(pat), pat, text, sub, expected, true)
+}
+
 const dbgmatch = {pat, text, expected
 	run(regex.dbgcompile(pat, true), pat, text, expected, false)
 }
 
-const subst = {regex, pat, text, sub, expected
-	var re
+const subst = {regex, pat, text, sub, expected, all
+	var re, r
 
 	re = std.try(regex)
-	match regex.sub(re, text, sub)
+	if all
+		r = `std.Some regex.suball(re, text, sub)
+	else
+		r = regex.sub(re, text, sub)
+	;;
+	match r
 	| `std.Some res:
 		std.put("res: {}\n", res)
 		match expected