I want to use glue
to accomplish sprintf('%02d', x)
but I'm not sure it's possible.
vignette('transformers')
suggests a sprintf
-alike transformer sprintf_transformer
and "front end" wrapper glue_fmt
like this:
sprintf_transformer <- function(text, envir) {
m <- regexpr(":.+$", text)
if (m != -1) {
format <- substring(regmatches(text, m), 2)
regmatches(text, m) <- ""
res <- eval(parse(text = text, keep.source = FALSE), envir)
do.call(sprintf, list(glue("%{format}f"), res))
} else {
eval(parse(text = text, keep.source = FALSE), envir)
}
}
glue_fmt <- function(..., .envir = parent.frame()) {
glue(..., .transformer = sprintf_transformer, .envir = .envir)
}
Then gives a simple example:
glue_fmt("π = {pi:.2}")
#> π = 3.14
This seems to rely on lazy evaluation to split the call pi:.2
(which is valid R syntax) into a call to sprintf
: sprintf('%.2f', pi)
.
However it would appear to me this isn't possible for the case of 0-padding, since the R parser will eliminate any leading 0:
pid = as.integer(pi)
glue_fmt('{pid:02}')
# 3.000000
# vs desired
sprintf('%02d', pid)
# [1] "03"
Looking at sprintf_transformer
, f
is hard-coded, because 02d
and .2f
are not valid R syntax in and of themselves. I guess we could make glue_fmtd
and glue_fmtf
or add an argument to supply 'd'
or 'f'
, but this is already straining the convenience factor of glue_fmt
compared to plain sprintf
.
And this would still not get over the fundamental constraint of the R parser -- as soon as 02
is treated as R code, the parser will drop the leading 0.
So, I'm stuck -- is it possible to use glue
to do a zero-padded format in a way that's not overly convoluted?
I don't think you need valid R syntax in the transfomer. The string is processed as a string. You don't need to hardcore the f or d. For example if you have
sprintf_transformer <- function(text, envir) {
m <- regexpr(":.+$", text)
if (m != -1) {
format <- substring(regmatches(text, m), 2)
regmatches(text, m) <- ""
res <- eval(parse(text = text, keep.source = FALSE), envir)
do.call(sprintf, list(glue("%{format}"), res))
} else {
eval(parse(text = text, keep.source = FALSE), envir)
}
}
Then you can do
glue_fmt('{pid:02d}')
# 03
glue_fmt('{pid:0.02f}')
# 3.00