[Development] Introducing discussion about QStringFormatter

Mårten Nordheim marten.nordheim at qt.io
Mon May 15 14:49:19 CEST 2017

This discussion's about a proposed 'QStringFormatter' class (for which I put up an early WIP for here: https://codereview.qt-project.org/#/c/192873/ )

QStringFormatter is currently intended as a class to format strings and replace placeholders, like QString::arg does.
But without the issues that QString::arg has. Such as the lack of an end-delimiter (enabling issues such as QString("%2%1").arg(1).arg(1) == "1"), having to parse the string multiple times (if using .arg-chaining).
However, it also adds new features:
- More formatting options, currently QString::arg only has a few options, with QStringFormatter we should initially match the options from QString and then extend the amount of options/features available.
                - Instead of only taking formatting options as arguments as in QString::arg, QStringFormatter will support taking formatting options as either in-string formatting or later (exact implementation not yet decided (see notes further down))
                - Python:              '{:>30}'.format('right aligned')
                - C#:                       String.Format("{0,30}", "right aligned");
                - fmt(c++)           fmt::format("{:>30}", "right aligned");
                - Currently the WIP-version uses '$' as a separator between options and the identifier (i.e. "{1$>30}"), but this may change to match others such as python and fmt.
- New, but familiar syntax. In various languages and libraries the curly braces are used to delimit replacement fields when formatting strings, for example:
                - Python:             'Hello, {0}'.format('World')
                - C#:                       String.Format("Hello, {0}", "World");
                - fmt(c++):          fmt::format("Hello, {0}", "World");
                - Note: To print a curly brace they have to be doubled (same as in all of the above) ( "{{", "}}" )
- Named replacement fields. i.e. QStringFormatter("Hello, {name}").arg("name", "World");
                - Python:             'Hello, {name}'.format(name='world')
                - C#:                       string name = "World"; $"Hello, {name}"; // uses string interpolation
                - fmt(c++):          fmt::format("Hello, {name}, fmt::arg("name", "World"));

While this makes it a 'replacement' for QString::arg, we are not going to remove QString::arg (at least not until *much* later.)

1. Why do we [not] want QStringFormatter in the library?

2. If QStringFormatter gets implemented, what are its hard requirements?

3. What are its soft requirements?

And here are some notes I made for myself during the last week:

- In-string formatting options are fine, but can not be the only way to specify formatting (bad for i18n because it becomes part of the text to translate)
                - Because of this I could implement a function, i.e. "setFormatting(QString id, QString options)" where 'options' gets parsed the same way as it would if it was in-string
                                - (would also need an overload which takes 'int' for id)
                                - could also have a separate function for each formatting option, e.g. "setPadding(id, amount)"
                - And/or add an overload of the ::arg functions with an extra argument for formatting, i.e "arg(id, string, format-string)"
                                - wouldn't work work because of arg(QString, QString, QString)

- Backwards compatibility with QString::arg
                - Since users would have to make source changes to start using QStringFormatter anyway I propose putting this BC-functionality behind a constructor-argument.
                                - This should also disable parsing replacement fields with the '{...}'-syntax
                                                - Would avoid forcing them to change the string in case they already have curly-braces in any strings
                                - Alternatively: put all BC functionality behind 'arg' and use another function-name for the new formatting style/functionality (e.g. '.format', '.subs')
                                                - pros:
                                                                - clear distinction between the functions
                                                                                - the BC arg-overloads won't cause any issues with new functionality
                                                                - No need to disable/enable anything
                                                - cons:
                                                                - ??? (can’t think of any at the moment)
                                                - This is probably the better choice of the two..
                - ::arg needs to return/be assignable to a QString (can be done using an implicit cast operator or by adding a new (non-explicit) constructor to QString)

- i18n could be in a separate class/child-class
                - but it should be kept in mind during the design and implementation of this class to make i18n easier to implement

- Mårten Nordheim
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20170515/9bd309ec/attachment.html>

More information about the Development mailing list