-
-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
There's a TL;DR go down there if you don't feel like reading all of this.
The problem
Some time ago I was writing a DateTime
struct and stumbled upon a problem when writing the format
method for it. My first idea was to use the [specifier]
parameter to format the fields, and everything looked great until I needed to print a :
(ISO8601 format) because you can't scape it in the [specifier]
. There isn't (that I'm aware of) a solution for this other than to create a function to format the DateTime
and print it's result.
The other thing I felt a bit bothered was the FormatOptions
parameter. IMHO I think that the std.fmt.format
function should be the responsible for the fill
, alignment
and width
parameters, and precision
is a floating point number only parameter (yes, you can find new uses for these in your format
function, but you got the point).
Adding a condition to escape a :
isn't that hard but I don't believe this is the way to go.
Proposal
I'd to propose the following format string {[argument][placement]:[specifier]}
, where placement => '['[fill][alignment][width]']'
(single quote meaning literal).
As I didn't find the issue that explains why any
became obligatory in first place, any
would maintain the status quo, although I personally don't find that it is necessary.
Pros
- Remove unrelated parameters in the types'
format
. Ex: anerror
wouldn't get aprecision
parameter - Remove the necessity of putting
argument
inside brackets[]
when referring to it by name, or whenspecifier
starts with a number - The placement is inside brackets
[]
, symbolizing the box where the value will fit (A really nice way of saying boilerplate) - The implementator of
format
don't need to worry about it's positioning - Remove the necessity of escaping
:
Cons
- This will break things, and broken things must be fixed
- Every implementator of
format
will have to parse its ownspecifier
(status quo, I guess) - This could be (and probably is) a really hard way to add an escape condition (I'm probably giving an edge case too much credit)
Examples
The first line is status quo, the second is the proposal.
// argument by index
print("{0any}", .{ value });
print("{0:any}", .{ value });
// argument by name
print("{[arg]any}", .{ .arg = value });
print("{arg:any}", .{ .arg = value });
// with fill/align/width
print("{any:0<15}", .{ value });
print("{[0<15]:any}", .{ value });
// with index and fill/align/width
print("{0any:0<15}", .{ value });
print("{0[0<15]:any}", .{ value });
// floating point with precision
print("{e:.2}", .{ value });
print("{:e.2}", .{ value });
// when `specifier` starts with a number
print("{[0]555}", .{ value });
print("{:555}", .{ value });
// if we could escape `:` with \\, ISO8601 would look like this
print("{yyyy-MM-dd'T'HH\\:mm\\:ss.fffZ}", .{ value });
// the `specifier` is between the first `:` and `}`
// the only escape needed is for `}`
print("{:yyyy-MM-dd'T'HH:mm:ss.fffZ}", .{ value });
TL;DR
Change the current string format from (values inside ''
are literals)
{[(index|'['name']')][specifier]:[fill][alignment][width].[precision]}
to
{[(index|name)]['['[fill][alignment][width]']']:[specifier]}
so we don't need to escape :
, or to put argument
inside brackets []
when referring to it by name or when its specifier
starts with numbers