`Writable` & `Writer` & Template Engines

Proposal PR link

1 Like

In my opinion, the most important thing is that "...".format(..., formatter=MyFormatter()) or equivalent hands the string literal to MyFormatter. Without this, everyone is stuck with whatever the stdlib provides as far as formatting. We can provide something that does a StringLiteral -> Tuple[Iterator[StringSpan], Iterator[FormatSpec]] mapping for things which are only slightly different from the stdlib version (ex: internationalization), as well as one which parses a single format spec.

I very strongly agree on buffer reservation, the Formatter should control how things get passed to the underlying writer (ex: vectored IO, making it all one buffer, etc). I would also like this to be lazy if possible, with an implicit conversion to String for usecases which need that. I expect many uses of string formatting to immediately write the result out to print or a file write, which should enable a lot of optimizations if we do laziness correctly.

Overall, I’m of the opinion that there needs to be an interface that is quite low level, where you get a variadic of some sort and a string literal, and then we can make a nice wrapper using trait default functions for a StdlibLikeFormatter that automatically handles the format spec for people just focusing on internationalization.

The one issue I have with this is that I don’t think f[HTMLTemplateEngine] as a syntax will work, because we’re going to want formatters with runtime state.

1 Like

I see it more like a “plan” step before actually running TemplateEngine(compiled_plan).format(values), so I think the TemplateEngine could very easily have runtime state.

I think we’ll want to go even further than that, we’ll want different formatters for different types. I think each type should have a default formatter but somehow be able to be overwritten by any given templating engine. So I think each type in a single .format() call should have an associated format spec type or a formatter (again the exact mechanics are TBD).

For example

"{:.3f}".format(1.34345) # allowed
"{:.3f}".format("1.5456") # format spec not supported for strings
 # some spec that allows stuff to be converted to a float
"{!f:.3f}".format[spec=CustomFloatableSpec]("1.5456")
"{!f:.3f}".format(Formatter[CustomFloatableSpec]("1.5456"))

I think the plan phase might also want runtime state, especially if someone whats to build something that’s designed more for runtime config than compile-time config.

That can be built from composition of normal formatters, so I don’t think we need special support for it.