Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to print toml::value returned from toml::parse() with fmt::print() properly? #186

Open
hwhsu1231 opened this issue May 15, 2022 · 1 comment

Comments

@hwhsu1231
Copy link

Problem Description

It is related to the issue: fmtlib/fmt#2894

According to vitaut's comment:

{fmt} doesn't provide formatters for toml11 types. You should check which formatter is being used and address your question to its author.

What should I do?

@ToruNiina
Copy link
Owner

First of all, since I'm not an author of {fmt}, I don't know much about the implementation detail of the library. But I took a glance at the code and found that the example code shown in your link seems to use fallback_formatter that internally calls operator<<(ostream&, T). If I'm not mistaken, it does not set std::setw. Since operator<<(ostream&, toml::value) reads width setting in ostream, if width is not set, it does nothing.

There are several options:

  1. implementing {fmt} formatter that parses width specifier and pass it to setw or toml::format. I think this is the most appropriate (but could be painful) way.
  2. wrapping a toml::value by a struct that has width and define operator<< to use width internally. This is easy but makes code messy.

{fmt} documentation explains how to write a formatter: https://fmt.dev/latest/api.html#format-api.

The second option will look like:

#define FMT_DEPRECATED_OSTREAM
#include <fmt/format.h>
#include <fmt/ostream.h>
#include <toml.hpp>
#include <iostream>

struct width_setter
{
    width_setter(std::size_t w, const toml::value& v): width_(w), data_(v) {}
    std::size_t width_;
    toml::value const& data_;
};

template <typename charT, typename traits>
std::basic_ostream<charT, traits>&
operator<<(std::basic_ostream<charT, traits>& os, const width_setter& w)
{
    os << std::setw(w.width_) << w.data_;
    return os;
}

int main(int argc, char **argv)
{
    if(argc != 2)
    {
        fmt::print("usage: ./toml11fmt example.toml\n");
        return 1;
    }
    const auto data = toml::parse(std::string(argv[1]));

    std::cout << std::setw(80) << data << std::endl;
    fmt::print(std::cout, "{}", width_setter(80, data));
    return 0;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants