Skip to content

Commit

Permalink
docs: new formatting syntax ideas
Browse files Browse the repository at this point in the history
  • Loading branch information
mpusz committed Feb 16, 2024
1 parent 0035015 commit 2e03bde
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 28 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ int main()
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{::N[.2f]}", v5); // 30.56 m/s
std::println("{::N[.2f]U[n]}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
Expand Down
8 changes: 4 additions & 4 deletions docs/getting_started/look_and_feel.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,8 @@ performed without sacrificing accuracy. Please see the below example for a quick
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{::N[.2f]}", v5); // 30.56 m/s
std::println("{::N[.2f]U[n]}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
Expand Down Expand Up @@ -144,8 +144,8 @@ performed without sacrificing accuracy. Please see the below example for a quick
std::cout << std::setw(10) << std::setfill('*') << v2 << '\n'; // ***70 mi/h
std::cout << std::format("{:*^10}\n", v3); // *110 km/h*
std::println("{:%N in %U}", v4); // 70 in mi/h
std::println("{:{%N:.2f}%?%U}", v5); // 30.56 m/s
std::println("{:{%N:.2f}%?{%U:n}}", v6); // 31.29 m s⁻¹
std::println("{::N[.2f]}", v5); // 30.56 m/s
std::println("{::N[.2f]U[n]}", v6); // 31.29 m s⁻¹
std::println("{:%N}", v7); // 31
}
```
Expand Down
4 changes: 2 additions & 2 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
std::println("Harvard Bridge length = {::N[.5]} ({::N[.5]}, {::N[.5]}) ± 1 εar",
dist, dist.in(usc::foot), dist.in(si::metre));
}
```
Expand All @@ -72,7 +72,7 @@ The library source code is hosted on [GitHub](https://github.com/mpusz/mp-units)
int main()
{
constexpr quantity dist = 364.4 * smoot;
std::println("Harvard Bridge length = {:{%N:.5} %U} ({:{%N:.5} %U}, {:{%N:.5} %U}) ± 1 εar",
std::println("Harvard Bridge length = {::N[.5]} ({::N[.5]}, {::N[.5]}) ± 1 εar",
dist, dist.in(usc::foot), dist.in(si::metre));
}
```
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ constexpr auto speed_of_light_in_vacuum = 1 * si::si2019::speed_of_light_in_vacu
QuantityOf<isq::permittivity_of_vacuum> auto q = 1 / (permeability_of_vacuum * pow<2>(speed_of_light_in_vacuum));
std::println("permittivity of vacuum = {} = {:{%N:.3e} %U}", q, q.in(F / m));
std::println("permittivity of vacuum = {} = {::N[.3e]}", q, q.in(F / m));
```

The above first prints the following:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ Here is a simple example showing how to deal with such quantities:
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);

std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
distance, duration, speed, speed.in(km / h));
}
```
Expand Down Expand Up @@ -103,7 +103,7 @@ Here is a simple example showing how to deal with such quantities:
const quantity duration = 2 * h;
const quantity speed = avg_speed(distance, duration);

std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
distance, duration, speed, speed.in(km / h));
}
```
Expand Down Expand Up @@ -193,7 +193,7 @@ The previous example can be re-typed using typed quantities in the following way
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);

std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
distance, duration, speed, speed.in(km / h));
}
```
Expand Down Expand Up @@ -221,7 +221,7 @@ The previous example can be re-typed using typed quantities in the following way
const quantity duration = isq::time(2 * h);
const quantity speed = avg_speed(distance, duration);

std::println("A car driving {} in {} has an average speed of {:{%N:.4} %U} ({:{%N:.4} %U})",
std::println("A car driving {} in {} has an average speed of {::N[.4]} ({::N[.4]})",
distance, duration, speed, speed.in(km / h));
}
```
Expand Down
2 changes: 1 addition & 1 deletion docs/users_guide/framework_basics/the_affine_space.md
Original file line number Diff line number Diff line change
Expand Up @@ -540,7 +540,7 @@ std::println("| {:<14} | {:^18} | {:^18} | {:^18} |",
std::println("|{0:=^16}|{0:=^20}|{0:=^20}|{0:=^20}|", "");

auto print = [&](std::string_view label, auto v) {
std::println("| {:<14} | {:^18} | {:^18} | {:^18{%N:.2f} %U} |", label,
std::println("| {:<14} | {:^18} | {:^18} | {:^18:N[.2f]} |", label,
v - room_reference_temp, (v - si::ice_point).in(deg_C), (v - si::absolute_zero).in(deg_C));
};

Expand Down
54 changes: 40 additions & 14 deletions src/core/include/mp-units/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,9 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
using format_specs = mp_units::detail::fill_align_width_format_specs<Char>;

std::basic_string_view<Char> modifiers_format_str_;
std::basic_string_view<Char> default_number_format_str_ = {};
std::basic_string_view<Char> default_unit_format_str_ = {};
std::basic_string_view<Char> default_dimension_format_str_ = {};
std::vector<size_t> format_str_lengths_;
format_specs specs_{};

Expand Down Expand Up @@ -355,16 +358,25 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
quantity_formatter(OutputIt, Args...) -> quantity_formatter<OutputIt>;

template<typename Handler>
constexpr const Char* parse_quantity_specs(const Char* begin, const Char* end, Handler&& handler) const
constexpr const Char* parse_format_spec(const Char* begin, const Char* end, Handler&& handler) const
{
if (begin == end || *begin == '}') return begin;
if (begin == end || *begin == ':' || *begin == '}') return begin;
if (*begin != '%' && *begin != '{')
throw MP_UNITS_STD_FMT::format_error(
"`quantity-specs` should start with a `conversion-spec` ('%' or '{' characters expected)})");
auto ptr = begin;
while (ptr != end) {
auto c = *ptr;
if (c == '}') break;
if (c == ":") {
if (ptr + 1 != end && *(ptr + 1) == ":") {
handler.on_text(begin, ++ptr); // account for ':'
++ptr; // consume the second ':'
continue;
} else
// default specs started
break;
}
if (c == '{') {
if (begin != ptr) handler.on_text(begin, ptr);
begin = ptr = mp_units::detail::parse_subentity_replacement_field(ptr, end, handler);
Expand All @@ -381,13 +393,13 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
c = *ptr++;
switch (c) {
case 'N':
handler.on_number("{}");
handler.on_number(default_number_format_str_);
break;
case 'U':
handler.on_unit("{}");
handler.on_unit(default_unit_format_str_);
break;
case 'D':
handler.on_dimension("{}");
handler.on_dimension(default_dimension_format_str_);
break;
case '?':
handler.on_maybe_space();
Expand All @@ -401,19 +413,33 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
begin = ptr;
}
if (begin != ptr) handler.on_text(begin, ptr);
if (ptr != end&&* ptr = ':') {
}
return ptr;
}

template<typename Handler>
constexpr const Char* parse_default_specs(const Char* begin, const Char* end, Handler&& handler) const
{
}

template<typename Handler>
constexpr const Char* parse_quantity_specs(const Char* begin, const Char* end, Handler&& handler) const
{
auto it = parse_format_spec(begin, end, handler);
}

template<typename OutputIt, typename FormatContext>
OutputIt format_quantity(OutputIt out, const quantity_t& q, FormatContext& ctx) const
{
std::locale locale = MP_UNITS_FMT_LOCALE(ctx.locale());
if (modifiers_format_str_.empty()) {
// default format should print value followed by the unit separated with 1 space
out = MP_UNITS_STD_FMT::vformat_to(out, locale, "{}",
out = MP_UNITS_STD_FMT::vformat_to(out, locale, default_number_format_str_,
MP_UNITS_STD_FMT::make_format_args(q.numerical_value_ref_in(q.unit)));
if constexpr (mp_units::space_before_unit_symbol<unit>) *out++ = ' ';
return MP_UNITS_STD_FMT::vformat_to(out, locale, "{}", MP_UNITS_STD_FMT::make_format_args(q.unit));
return MP_UNITS_STD_FMT::vformat_to(out, locale, default_unit_format_str_,
MP_UNITS_STD_FMT::make_format_args(q.unit));
} else {
// user provided format
quantity_formatter f{out, q, format_str_lengths_.cbegin(), locale};
Expand All @@ -425,16 +451,16 @@ class MP_UNITS_STD_FMT::formatter<mp_units::quantity<Reference, Rep>, Char> {
public:
constexpr auto parse(MP_UNITS_STD_FMT::basic_format_parse_context<Char>& ctx) -> decltype(ctx.begin())
{
const auto begin = ctx.begin();
auto end = ctx.end();
auto begin = ctx.begin(), end = ctx.end();

auto it = parse_fill_align_width(ctx, begin, end, specs_, mp_units::detail::fmt_align::right);
if (it == end) return it;
auto begin = parse_fill_align_width(ctx, begin, end, specs_, mp_units::detail::fmt_align::right);
if (begin == end) return begin;

format_checker checker{ctx, format_str_lengths_};
end = parse_quantity_specs(it, end, checker);
modifiers_format_str_ = {it, end};
return end;
auto it = parse_quantity_specs(begin, end, checker);
modifiers_format_str_ = {begin, it};

return parse_default_specs(it, end, handler);
}

template<typename FormatContext>
Expand Down

0 comments on commit 2e03bde

Please sign in to comment.