[PATCH 2/2] Allow formatting arguments from variables
[Thread Prev] | [Thread Next]
- Subject: [PATCH 2/2] Allow formatting arguments from variables
- From: "S. Gilles" <sgilles@xxxxxxx>
- Reply-to: myrddin-dev@xxxxxxxxxxxxxx
- Date: Sat, 23 Nov 2019 17:29:04 -0500
- To: "myrddin-dev" <myrddin-dev@xxxxxxxxxxxxxx>
- Cc: "S. Gilles" <sgilles@xxxxxxx>
So I can write
std.put("{w=?}{w=?}\n", max_width, field_a, max_width, field_b)
---
lib/std/fmt.myr | 32 +++++++++++++++++++++++++++-----
lib/std/test/fmt.myr | 36 ++++++++++++++++++++++++++++++++++--
2 files changed, 61 insertions(+), 7 deletions(-)
diff --git a/lib/std/fmt.myr b/lib/std/fmt.myr
index c4c3797e..8f0a632a 100644
--- a/lib/std/fmt.myr
+++ b/lib/std/fmt.myr
@@ -163,10 +163,11 @@ const sbfmt = {sb, fmt, args
}
const sbfmtv = {sb, fmt, ap -> size
- var buf : byte[256], param : (byte[:], byte[:])[8]
+ var buf : byte[256], param : (byte[:], byte[:])[8], arg
var state, startp, endp, starta, nbuf
- var nfmt, nvarargs, nparam
+ var nfmt, npulled, nvarargs, nparam
var b, i
+ var temps : byte[:][:] = [][:]
nvarargs = ap.tc.nelt
nfmt = 0
@@ -174,6 +175,7 @@ const sbfmtv = {sb, fmt, ap -> size
starta = 0
nparam = 0
nbuf = 0
+ npulled = 0
endp = 0
state = `Copy
i = 0
@@ -229,13 +231,15 @@ const sbfmtv = {sb, fmt, ap -> size
/* {param=arg} */
| (`ParamArg, ','):
state = `ParamOpt
- param[nparam++] = (buf[startp:endp], buf[starta:nbuf])
+ arg = maybepullarg(buf[starta:nbuf], &temps, &npulled, ap)
+ param[nparam++] = (buf[startp:endp], arg)
startp = nbuf
endp = nbuf
| (`ParamArg, '}'):
state = `Copy
if startp != nbuf
- param[nparam++] = (buf[startp:endp], buf[starta:nbuf])
+ arg = maybepullarg(buf[starta:nbuf], &temps, &npulled, ap)
+ param[nparam++] = (buf[startp:endp], arg)
;;
fmtval(sb, vatype(ap), ap, param[:nparam])
nfmt++
@@ -245,12 +249,30 @@ const sbfmtv = {sb, fmt, ap -> size
buf[nbuf++] = b
;;
;;
- if nfmt != nvarargs
+ if nfmt + npulled != nvarargs
die("too many values for fmt\n")
;;
+ for t : temps
+ slfree(t)
+ ;;
+ slfree(temps)
-> sb.len
}
+/* Distinguish between things like {w=5} and {w=?} */
+const maybepullarg = {default : byte[:], storage : byte[:][:]#, npulled : size#, ap
+ if !std.eq(default, "?")
+ -> default
+ ;;
+
+ var pulled_arg : strbuf# = mksb()
+ fallbackfmt(pulled_arg, [][:], vatype(ap), ap)
+ var arg = sbfin(pulled_arg)
+ slpush(storage, arg)
+ npulled#++
+ -> arg
+}
+
const fmtval = {sb, ty, ap, params
match htget(fmtmap, ty)
| `Some f:
diff --git a/lib/std/test/fmt.myr b/lib/std/test/fmt.myr
index b80bafc6..e19a5543 100644
--- a/lib/std/test/fmt.myr
+++ b/lib/std/test/fmt.myr
@@ -4,8 +4,11 @@ use testr
const main = {
testr.run([
- [.name="builtins", .fn=builtins ],
- [.name="installed", .fn=installed],
+ [.name="builtins", .fn=builtins ],
+ [.name="question-marks", .fn=questionmarks],
+
+ /* This one has to go at the end, since it clobbers default formatters */
+ [.name="installed", .fn=installed],
][:])
}
@@ -151,7 +154,36 @@ const installed = {c
/* in aggregates */
check(c, "[formatted a pair: [-10, -10]]", "{}", [p])
check(c, "[formatted a pair: [-10, -10]]", "{}", [p][:])
+}
+
+const questionmarks = {c
+ check(c, "x", "{w=1,p=x}", "")
+ check(c, "x", "{w=?,p=x}", 1, "")
+ check(c, "x", "{w=?,p=?}", 1, "x", "")
+ check(c, "x", "{w=1,p=?}", "x", "")
+
+ check(c, " 8", "{w=3,p= }", 8)
+ check(c, " 8", "{w=3,p= }", "8")
+ check(c, " 8", "{w=?,p= }", 3, 8)
+ check(c, " 8", "{w=?,p= }", 3, "8")
+ check(c, " 8", "{w=?,p= }", "3", 8)
+ check(c, " 8", "{w=?,p= }", "3", "8")
+
+ check(c, "8.00", "{s=3}", 8.0)
+ check(c, "8.00", "{s=?}", 3, 8.0)
+
+ check(c, "x", "{w=?}", 0, "x")
+ check(c, "x", "{w=?}", -20, "x")
+ check(c, " x", "{w=?}", 28, "x")
+ check(c, "???????????????????????????x", "{w=?,p=?}", 28, "?", "x")
+ check(c, "???????????????????????????x", "{w=?,p=?}", 28, "?anddiscardtherest", "x")
+
+ check(c, "yyyyyyyyyyfoo..bar..xxxxxxxxxxxxxxxxbaz", "{w=?,p=?,p=?}..{w=3,p=?,p=x}..{w=?,p=x}", "13", "x", "y", "foo", 10, "bar", "19", "baz")
+
+ check(c, "a1xy2xy3xy4b", "a{j=?}b", "xy", [ 1, 2, 3, 4 ][:])
+ check(c, "1.111", "{s=?}", 4, 1.11111111)
+ check(c, "1.111", "{s=?}", "4", 1.11111111)
}
const intfmt = {sb, ap, opts
--
2.24.0
| [PATCH 0/2] Use ? in format specifiers | "S. Gilles" <sgilles@xxxxxxx> |
- Prev by Date: [PATCH 1/2] Convert lib/test/fmt.myr to use testr
- Next by Date: [PATCH] Document ? in format specifiers, e.g. {w=?}
- Previous by thread: [PATCH 1/2] Convert lib/test/fmt.myr to use testr
- Next by thread: Re: [PATCH 0/2] Use ? in format specifiers
- Index(es):