lukaskalbertodt / bunt Goto Github PK
View Code? Open in Web Editor NEWSimple macros to write colored and formatted text to a terminal. Based on `termcolor`, thus also cross-platform.
License: Apache License 2.0
Simple macros to write colored and formatted text to a terminal. Based on `termcolor`, thus also cross-platform.
License: Apache License 2.0
I'm running into a situation now where I am adding a --color
flag to my CLI to control color output. Currently the bunt docs recommend using write!
with a custom stream then. And sure, it works, but I now want all my bunt
calls to respect that color choice. So maybe it makes sense to add an ability to change the global color choice?
Hi, thanks for creating bunt
(and great name, by the way! ;)).
The following fails:
fn main() -> color_eyre::Result<()> {
// works:
let ok: Result<()> = Ok(());
std::println!("{:?}", ok?);
//failes:
let ok: Result<()> = Ok(());
bunt::println!("{:?}", ok?);
Ok(())
}
The error message is:
error[E0277]: `?` couldn't convert the error to `std::io::Error`
--> abalet_com/src/bin/web_dev_server.rs:94:30
|
94 | bunt::println!("{:?}", ok?);
| ^ the trait `std::convert::From<color_eyre::Report>` is not implemented for `std::io::Error`
|
= note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
= help: the following implementations were found:
<std::io::Error as std::convert::From<getrandom::error::Error>>
<std::io::Error as std::convert::From<openssl::error::ErrorStack>>
<std::io::Error as std::convert::From<rand_core::error::Error>>
<std::io::Error as std::convert::From<serde_json::error::Error>>
and 4 others
= note: required by `std::convert::From::from`
Hi,
At the moment bunt
only allows literals at the format string position. std:println
, however, allows tt
.
Unfortunately, this prevents bunt
users from generating format strings via macros.
For example, I tried the following:
macro_rules! println_with_colored_prefix {
($color:literal, $id:expr, $fmt_str:literal $(, $arg:expr)*) => {
bunt::println!(
concat!("{$", $color, "}[{}][{}]{/$} ", $fmt_str),
BIN.get().expect("Usage before static variable `BIN` set"),
$id
$(, $arg)*
)
};
}
macro_rules! say {
($($arg:expr),+) => {
println_with_colored_prefix!("blue", $($arg),+)
};
}
macro_rules! err {
($($arg:expr),+) => {
println_with_colored_prefix!("red", $($arg),+)
};
}
fn main() {
let name = "foo";
say!(name, "my message.");
err!(name, "my error.");
}
Because concat!("{$", $color, "}[{}][{}]{/$} ", $fmt_str)
isn't a literal, this code doesn't compile.
std
allows this, however (Playground:
macro_rules! my_println {
($fmt_str:literal $(, $arg:expr)*) => {
println!(concat!("my prefix: ", $fmt_str), $(, $arg)*)
};
}
fn main(){
my_println!("foo")
}
From looking at the source code (see links above), it seems bunt
would just have to replace literal
in $format_str:literal
with tt
to support this.
Maybe the tt
would have to be converted to a literal somehow, I'm not sure. The macros above are the only macros I have created so far :)
For example println!()
or writeln!(stream)
would just write a line break.
This mirrors the functionality of the std macros, making these more of a drop in replacement. Note the write_with_newline clippy lint prefers this short form, which can be annoying since it also triggers when using writeln
from this crate.
There was some discussion about this regarding the std
macros. Depending on the reason for deciding against it, maybe bunt
's versions of these two macros should flush automatically.
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 bunt
s 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 bunt
s output.
How hard would it be to add a variant of std::format_args to bunt
?
Do you have any opinions, complaints, suggestions, ideas, ... about this library or its syntax? Let me know :)
I quite like the feature, so it's a shame bunt
doesn't support it yet.
https://rust-lang.github.io/rfcs/2795-format-args-implicit-identifiers.html
Docs says "there is currently no syntax for Color::Ansi256 because I couldn’t come up with a nice syntax and I never used these ansi colors…)". I do need those ones.
What about just using a #123
syntax? If RGB should always be 6-tuple strings, then there is no ambiguity with ANSI's 256 3-tuple.
The meaning should be straigthforward, but may collides in users mind with CSS' short 3-tuple RGB (for which #fff
is a valid shortcut for #ffffff
).
Alternatively, any other prefix may be used, like @
, which reminds the A of ANSI.
The std::fmt
syntax allows to pass the width or precision via parameter. It looks like this:
println!("Hello {1:0$}!", 5, "x");
This is currently unsupported and leads to strange behavior or errors.
I feel like this functionality could be useful to more people. Having it in its own crate would also encourage better testing and a nice API design.
Should be fairly easy to add by copying and slightly modifying the print!
/println!
definition.
Hey there!
I have a string header
with this content: " \tSnippet name: \t Source file:"
(note, that GitHub doesn't really display all the contained whitespace). I'm trying to print this string underlined: bunt::println!("{[underline]}", header);
, but the underlining stops at the tabs. Is this intended behavior? If so, what would be the best workaround here? My output currently looks like this:
As a side note, the line bunt::println!("{[underline]}", header);
gives me an error in VS Code with Rust-Analyzer:
expected none or () delimited group, but found different token tree (note: do not use the macros from `bunt-macros` directly, but only through `bunt`)
rust-analyzer(macro-error)
Is this something that I should post an issue about, or would it rather belong in the Rust-Analyzer repository?
Not an issue, just a question: What's the reason for using this match
construct instead of a simple if elseif else
. There are no new bindings and the compiler can't help with the patterns...
Lines 61 to 81 in 91a65fb
This adds quote a bit of compile time. I don't even need Rust AST types or anything. The only reason for syn is to parse an expression delimited by a comma. I.e. $foo:expr ,
in declarative macro syntax. But I don't really inspect the expression and just treat it as token stream. It's not trivial to parse that yourself, however. Take write!(foo(a, b), "..")
: you can't stop after the first comma.
From #1 (comment):
Could the color and other styles be specified by argument? For example,
bunt::println!("{$*}error:{/$}", Color::Red, ty);In that case I could calculate the color at runtime.
The slight "problem" is that in order to create a Buffer
, we probably want to go through BufferWriter
. And there again we have to specify a color preference, where we would also default to Auto
, I guess.
Hi,
When macro expansion is activated in rust-analyser
in VSCode
, I get the following error, every time I use bunt::println!
:
expected none or () delimited group, but found different token tree (note: do not use the macros from
bunt-macros
directly, but only throughbunt
)
Is this somehow fixable?
Macro expansion is useful for completion of types that are created via proc macros (e.g. typed_builder
), but now my code is littered with error messages that the compiler itself doesn't report as errors.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.