Hello, I'm back with round 2 of QStringFormatter =====
The WIP is still located over here: https://codereview.qt-project.org/#/c/192873/ Name ----- I think it would be nice to change the class' name as typing QStringFormatter repeatedly is fairly cumbersome. One suggestion was QFormat (unless it's already used, though I haven't seen any uses from searching). If there're no objections or other suggestions then I will rename the class. API ----- Changes since I last wrote about QStringFormatter on the mailing list: - the in-string formatting's separator was changed from '$' to ':' to match other string formatting APIs. - ::multiArg was introduced - Variadic template which simply forwards each parameter to a separate ::arg-call - Currently returns a QString directly. Should it return QStringFormatter& like ::arg? - Static function ::format - Another variadic template, instantiates QStringFormatter and forwards arguments to multiArg - example: `QStringFormatter::format("{} {}", "Hello,", "World!");` - Remove? Nice to have? - (QStringFormatter::)Formatting - ::arg methods have an optional Formatting argument which can be used to override or augment any previously specified in-string formatting - Can be constructed from a string of formatting options (e.g. "L<10") or using its methods (e.g. setLocale, setJustification) - Named replacements uses an alias for QPair<QString, T> called Argument. - e.g. `QStringFormatter("Hello, {Name}").arg({"Name", "World"});` - A qMakePair-style function called `qArg` for use in situations with template argument deduction trouble. - e.g. `QStringFormatter("Hello, {Name}").arg(QStringFormatter::qArg("Name", 47));` Any feedback on API is appreciated. A proposal for the API for formatting custom types follows. Replacement format ----- The replacement options now have formatting features matching QString::arg. The current options (open to change) are: - `L` for localization (localize numbers, like in QString::arg) - `</>/=` for justification. Left, right and center justification - Followed by an optional padding character (excluding 1-9) - Followed by field-width - e.g. "==16" (pad using '=', centered, field-width 16), "<10" (left-justify using spaces, field-width 10), ">-3" (right-justify using '-', field-width 3) - `f/g/G/e/E` for floating-point number formatting (https://doc.qt.io/qt-5/qstring.html#argument-formats) - followed by a dot and then precision - e.g. "f.2" - `b/B` for setting base. Supports bases 2-36. Using 'b' produces lower-case letters for digits 10-35, and 'B' produces upper-case. For bases 2-10 they make no difference. - `:` everything after the colon gets put into an 'extra' field, more on this later.. - e.g. `{:<10:this is the extra field}` - or `{::yyyy-MM-dd HH:mm:ss}` Currently the formatting options can come in any order (e.g. "L<10" and "<10L" does the same, the only exception being ':'). However it would be good to enforce some sort of order for the sake of consistency. With a defined order we could also change justification format from [<>=]cn to c[<>=]n, which would allow people to use 1-9 as a fill-character. If this is done, what should the order be like? QString::arg compatibility ----- Currently QString::arg compatibility is activated using a parameter in the constructor. All this does is let you use %nn style tokens and 'disable' use of the brace-style tokens. It also supports `%L` to enable localization of numbers, but any other formatting must be done using the `QStringFormatter::Formatting` class. API for formatting custom types ----- One idea I've been experimenting with a little bit is using template specialization to deal with formatting custom types. To support a custom type you'd create a specialization of a struct called `Formatter`. It would use the `extra` field in `Formatting` which you could optionally parse for custom formatting options. The parser would be a separate class inheriting `Formatting` and be specified in the Formatter using a typedef. E.g. `struct QStringFormatter::Formatter<QDateTime> { typedef DateTimeInfo FormatType; QString operator()(const QDateTime &dateTime, const FormatType &format); }` `QStringFormatter` will then instantiate this struct when it receives a `QDateTime` object, and create a `FormatType` object to parse the data located in the `extra` field of formatting options. The `FormatType` object is then expected to store whatever info it needs and then the `Formatter` will use it later. Feedback on the approach, pitfalls etc. is much appreciated! Thanks, -- Mårten Nordheim _______________________________________________ Development mailing list [email protected] http://lists.qt-project.org/mailman/listinfo/development
