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

bunt::format_args & bunt::format #18

Open
d4h0 opened this issue Oct 15, 2020 · 4 comments
Open

bunt::format_args & bunt::format #18

d4h0 opened this issue Oct 15, 2020 · 4 comments

Comments

@d4h0
Copy link

d4h0 commented Oct 15, 2020

Hi,

Something that sometimes would be useful, is bunt::format_args (and maybe bunt::format).

This would come in handy, for example, to format logging messages with bunt. In this case, a user can't currently use bunts macros without allocating. Another use-case would be to store formatted strings (probably only via bunt::format with an allocation).

The best option I could come up with is to write! to a termcolor::Buffer, but this does allocate.

(By the way, does bunt allocate internally?)

My current use case is, that I have a log macro that accepts a bunt format string and arguments (which prints regular status messages for the user). I also have an option to activate debugging output, which activates tracing.

So basically, there are two different log output formats (my own and tracing).

It would be better if – if debug is activated – my log macro redirects messages to tracing. But, as mentioned above, this is only possible via termcolor::Buffer to which I write bunts output.

How hard would it be to add a variant of std::format_args to bunt?

@d4h0
Copy link
Author

d4h0 commented Oct 15, 2020

Also, ergonomics are not really great, with the workaround mentioned above:

            let mut buf = bunt::termcolor::Buffer::ansi();
            let err = |e: &dyn Debug|
                error!("Error while converting `bunt` format string {:?}: {:?}", $fmt_str, e);
            if let Err(e) = bunt::write!(buf, $fmt_str, $($arg),*) {
                err(&e)
            } else {
                match std::str::from_utf6(buf.as_slice()) {
                    Err(e) => err(&e),
                    Ok(msg) => info!(msg),
                };
            }

😉

(Fortunately, this code only has to exist once)

@LukasKalbertodt
Copy link
Owner

Hi there.

Regarding format!, checkout #2. In summary: we can't really add this to bunt unless we change how the Buffer works in termcolor.

Regarding format_args: to be honest, I am still not 100% sure what this does or how it works. But as far as I understand it, it is quite complicated. It should be possible to implement bunt::format_args though. Again, as far as I currently understand. But that wouldn't be trivial. I don't think I will have time for this anytime soon, but I'll keep the issue open if I (or someone else) ever wants to give it a try.

(By the way, does bunt allocate internally?)

The proc macro code certainly does, but this happens at compile time. The emitted code does not allocate itself, only the called termcolor functions potentially do..

write! to a termcolor::Buffer, but this does allocate.

Are you sure about this? Writing into a standard stream shouldn't allocate, no?

@d4h0
Copy link
Author

d4h0 commented Oct 22, 2020

Are you sure about this? Writing into a standard stream shouldn't allocate, no?

Yes, I'm pretty sure (if I'm not missing anything). Buffer has the following method:

pub fn into_inner(self) -> Vec<u8>

Consume this buffer and return the underlying raw data.

On Windows, this unrecoverably drops all color information associated with the buffer.

And the inner data for ANSI content is InnerBuffer:Ansi(Ansi<Vec<u8>>).

as far as I understand it, it is quite complicated. It should be possible to implement bunt::format_args though. Again, as far as I currently understand. But that wouldn't be trivial.

I didn't study the code of bunt, but I was thinking bunt could just pass the data to std::format_ags! and return the result.

I don't think I will have time for this anytime soon, but I'll keep the issue open if I (or someone else) ever wants to give it a try.

Alright, still thanks for the response!

Unfortunately, I'm also busy with many different projects already...

Btw., are you aware of owo_colors?

owo_colors works with no_std (so doesn't allocate), has a nice API, and probably could be easily used instead of termcolor. I haven't looked at termcolor, but I wouldn't be astonished if the usage of owo_colors would simplify the implementation of bunt significantly.

The next release will even have functionality that makes it easy to create style themes, which I believe is important (a default theme that's optimized for dark backgrounds is often not very readable on white backgrounds).

@LukasKalbertodt
Copy link
Owner

Ah surel, if you need to write to Buffer, that surely allocates, yes.

I was thinking bunt could just pass the data to std::format_ags! and return the result.

We could, but then all the color information is lost. The code bunt emits usually contains more than one std::write! call.

Btw., are you aware of owo_colors?

I didn't know that lib. termcolor has a more low level API which usually is better suited as a base for a library that is "just a convenience layer", like bunt.

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