[Development] Introducing discussion about QStringFormatter

Sze Howe Koh szehowe.koh at gmail.com
Fri Aug 11 02:53:39 CEST 2017


Hello,


On 10 August 2017 at 20:41, Mårten Nordheim <marten.nordheim at qt.io> wrote:
>
> 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.

IMHO, "QFormat" isn't a suitable name. First, this class itself does
not describe a format, unlike:

* QTextFormat
* Qt::DateFormat
* QSettings::Format
* QAudioFormat
* QImage::Format
* QPixelFormat
* QVideoFrame::PixelFormat
* QVideoSurfaceFormat
* QSurfaceFormat
* QOpenGLFramebufferObjectFormat

So, at the very least, call it "QFormatter"


Second, from a quick glance of the list above, I can guess the type of
format that most the classes/enums above describe.
"QFormat"/"QFormatter" doesn't contain any clues that it's related to
string formatting. (Minor tangent: I feel that QTextFormat and
QText(Char|Block|List|Table)Format would be clearer if renamed to
QTextDocumentFormat and QTextDocument(Char|Block|List|Table)Format
respectively)

Finally, one of the guidelines in
https://wiki.qt.io/API_Design_Principles#The_Art_of_Naming is "Do not
abbreviate".

For these reasons, I'd personally prefer sticking to "QStringFormatter".


Having said that, the verbosity of a name is a valid concern. It is
the reason why I personally prefer to write raw C string literals
instead of wrapping them in QStringLiteral, unless the performance
penalty is noticeable. I can't think of a better name than
"QStringFormatter" though. Perhaps, in our documentation/examples, we
can suggest that the user introduce a typedef in their own code (as
opposed to adding an official abbreviation) to shorten things?

    typedef QStringFormatter QSF;
    QSF formatter(...);


> 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


Regards,
Sze-Howe Koh



More information about the Development mailing list