Simple macros to write colored and formatted text to a terminal. Based on `termcolor`, thus also cross-platform.

Related tags

Command-line bunt

Bunt: simple macro-based terminal colors and styles

CI status of master Version

bunt offers macros to easily print colored and formatted text to a terminal. It is just a convenience API on top of termcolor. bunt is implemented using procedural macros, but it does not depend on syn and compiles fairly quickly.

Minimum Supported Rust Version: 1.46.0

// Style tags will color/format text between the tags.
bunt::println!("I really like {$yellow}lemons{/$}! Like, {$blue+italic}a lot{/$}.");

// To style a single argument, you can also use the `{[style]...}` syntax. This
// can be combined with style tags.
let v = vec![1, 2, 3];
bunt::println!("Here is some data: {[green]:?}. {$bold}Length: {[cyan]}{/$}", v, v.len());

See the documentation for more information.

Status of this project

This is still a young project, but I already use it in two applications of mine. The syntax is certainly not final yet. Seeking feedback from the community!


Licensed under either of Apache License, Version 2.0 or MIT license at your option. Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in this project by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

  • "expected none or () delimited group, but found different token tree (note: do not use the macros from `bunt-macros` directly, but only through `bunt`)"


    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 through bunt)

    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.

    opened by d4h0 10
  • Add `format!` macro to create a termcolor::Buffer

    Add `format!` macro to create a termcolor::Buffer

    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.

    opened by LukasKalbertodt 5
  • Multiple fmt strings

    Multiple fmt strings

    Closes #15

    This is a workaround for the use cases where you want to pass the result of concat! as format string.

    @d4h0 Again, if you have the time, I would appreciate feedback if this works for your use case. I will test a similar use case in an app of mine soon-ish, too.

    opened by LukasKalbertodt 3
  • Feature request: Allow `tt` at format string position

    Feature request: Allow `tt` at format string position


    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)*) => {
                concat!("{$", $color, "}[{}][{}]{/$} ", $fmt_str),
                BIN.get().expect("Usage before static variable `BIN` set"),
                $(, $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(){

    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 :)

    opened by d4h0 3
  • Underlining tabs

    Underlining tabs

    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`) 

    Is this something that I should post an issue about, or would it rather belong in the Rust-Analyzer repository?

    opened by LeCyberDucky 2
  • Fix `?` in arguments

    Fix `?` in arguments

    Fixes #14

    @d4h0 If you have the time, could you please test this branch in your project to confirm this fixes your problem? This should work:

    bunt = { git = "", branch="fix-questionmark-in-argument" }
    opened by LukasKalbertodt 2
  • Fails to compile if `?` is used in macro with error that isn't `std::io::Error`

    Fails to compile if `?` is used in macro with error that isn't `std::io::Error`

    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?);
        let ok: Result<()> = Ok(());
        bunt::println!("{:?}", ok?);

    The error message is:

    error[E0277]: `?` couldn't convert the error to `std::io::Error`
      --> abalet_com/src/bin/
    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`
    opened by d4h0 2
  • Just a question

    Just a question

    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...

    opened by lukaslueg 2
  • Add option to set `ColorChoice` globally for `[e]print[ln]`?

    Add option to set `ColorChoice` globally for `[e]print[ln]`?

    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?

    opened by LukasKalbertodt 1
  • Support omitting format string

    Support omitting format string

    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.

    opened by andrewhickman 1
  • Add support for width and precision parameters

    Add support for width and precision parameters

    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.

    opened by LukasKalbertodt 0
  • ANSI 256 as #3-tuples

    ANSI 256 as #3-tuples

    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.

    opened by nojhan 9
  • Pass style as argument to be able to calculate it at runtime

    Pass style as argument to be able to calculate it at runtime


    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.

    opened by LukasKalbertodt 0
  • bunt::format_args & bunt::format

    bunt::format_args & bunt::format


    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?

    opened by d4h0 4
  • Should `print!` and `write!` flush automatically?

    Should `print!` and `write!` flush automatically?

    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.

    opened by LukasKalbertodt 0
Lukas Kalbertodt
I like teaching and coding.
Lukas Kalbertodt
Write simple proc-macros inline with other source code.

script-macro An experimental way to write simple proc-macros inline with other source code. Did you ever end up getting frustrated at the boilerplate

Markus Unterwaditzer 17 Jun 10, 2023
That program use on platform windows. And if you write any text on uncorrect keyboard layout, that program for that.

?? This program is designed to translate text into the correct layout when typing is incorrect. ?? Example ghbdtn -> привет Just (by default) pressing

Gest Se 5 Jan 26, 2023
Make beautiful colored code listings in LaTeX with the power of TreeSitter.

What is this? This is a CLI tool that consumes TreeSitter's output and transforms it into LaTeX code that will produce syntax-colored code listing. If

Tomáš Lebeda 11 Sep 4, 2023
Write Cross-platform application with React-like decralative UI framework and scalable ECS architecture all in Rust.

bevy_dioxus Dioxus Plugin for Bevy Write Cross-platform application with React-like decralative UI framework and scalable ECS architecture all in Rust

Junichi Sugiura 269 Dec 29, 2022
Js-macros - Quickly prototype Rust procedural macros using JavaScript or TypeScript!

js-macros Quickly prototype Rust procedural macros using JavaScript or TypeScript! Have you ever thought "this would be a great use case for a procedu

null 15 Jun 17, 2022 AI terminal assistant that can read and write your terminal directly! AI terminal assistant that read from & write to your terminal is an AI terminal assistant based on OpenAI APIs such as GPT-3.5/4! What'

hmirin 5 Jun 20, 2023
Native cross-platform full feature terminal-based sequence editor for git interactive rebase.

Native cross-platform full feature terminal-based sequence editor for git interactive rebase.

Tim Oram 1.2k Jan 2, 2023
A cross platform minimalistic text user interface

titik Titik is a crossplatform TUI widget library with the goal of being able to interact intuitively on these widgets. It uses crossterm as the under

Jovansonlee Cesar 113 Dec 31, 2022
Cross-platform Rust library for coloring and formatting terminal output

Coloring terminal output Documentation term-painter is a cross-platform (i.e. also non-ANSI terminals) Rust library for coloring and formatting termin

Lukas Kalbertodt 75 Jul 28, 2022
Cross platform terminal library rust

Cross-platform Terminal Manipulation Library Crossterm is a pure-rust, terminal manipulation library that makes it possible to write cross-platform te

crossterm-rs 2.1k Jan 2, 2023
Alacritty - A fast, cross-platform, OpenGL terminal emulator

Alacritty is a modern terminal emulator that comes with sensible defaults, but allows for extensive configuration. By integrating with other applications, rather than reimplementing their functionality, it manages to provide a flexible set of features with high performance. The supported platforms currently consist of BSD, Linux, macOS and Windows.

Alacritty 43.8k Dec 31, 2022
Cross-platform terminal screen clearing library

ClearScreen Cross-platform terminal screen clearing library. API documentation. Dual-licensed with Apache 2.0 and MIT. Uses Caretaker Maintainership.

null 23 Dec 30, 2022
Cross-platform terminal program to download IEEE journals

IEEE Journal Downloader A cross-platform terminal program which tries to download every article in a specified journal and merge the documents into on

Fong Chien Yoong 18 Jul 23, 2022
glicol cli: cross-platform music live coding in terminal

glicol-cli What's this? It's a command line interface that you can use for music live coding with Glicol. It watches a file changes and then update th

Glicol 70 Apr 14, 2023
colorStyle is a library of styles for command-line text write in Rust.

Colorstyle colorStyle is a library of styles for command-line text. Inspired by flylog/colorstyle (golang) Example let text = colorstyle::green("gre

Code Translation 6 Nov 12, 2022
Rust-based language and runtime for cross-platform app development

Pax Pax is a cross-platform rendering engine & Rust framework for interactive graphics, animations, and GUIs. Pax extends the Rust programming languag

Pax 75 Dec 19, 2022
A simple cross-platform easy to use STL Viewer with GUI and CLI options

Stlvi STL viewer written in Rust. This project is still in development. It is available in both CLI and GUI mode. Supported OS Linux Windows Mac Scree

Mantresh Khurana 4 Mar 2, 2023
Build light & secure cross-platform applications with a web-based UI

Millennium Icon by XFaon. *Stats are from Tauri and may not be fully accurate. Millennium is a cross-platform webview framework written in Rust. With

pyke 20 Dec 29, 2022
Advent of Code 2021, also an attempt to practice a bit of Rust.

Advent of Code 2021 Advent of Code 2021 (my first one!), also an attempt to practice a bit of Rust. Running (Assuming that the respective inputs are i

Edoardo Debenedetti 1 Dec 3, 2021