[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):