5 releases

0.1.5 Sep 1, 2020
0.0.0-dev.3 Sep 1, 2020

#644 in Command-line interface

MIT license

23KB
193 lines

tcprint

Structured, colorized printing to the terminal using termcolor.

Copyright 2018-2020 Peter Williams. Licensed under the MIT License. All contributions to this project will be assumed to be licensed under the same terms, unless explicitly otherwise stated.


lib.rs:

Structured, colorized printing to the terminal using termcolor.

The termcolor crate has been carefully designed to allow CLI tools to print colors to the terminal in a cross-platform fashion — while most color-print crates only work with Unix color codes, termcolor also works on Windows. While this is a valuable capability, the termcolor API is fairly low-level.

This crate provides a slightly higher-level interface that aims to be convenient for basic use cases, and extensible when needed. First of all, the relevant state is gathered into a single ColorPrintState structure that can be passed around your application. This comprises (1) handles to color-capable standard output and error streams and (2) a palette of pre-defined colors. Second, macros are provided that make it easier to print output mixing a variety of colors.

Basic Usage

#[macro_use] extern crate tcprint;

use tcprint::{BasicColors, ColorPrintState};

let mut state = ColorPrintState::<BasicColors>::default();
let q = 17;
tcprintln!(state, [red: "oh no:"], (" q is: {}", q));

The above will print the line oh no: q is 17, where the phrase oh no: will appear in red. The arguments to the tcprintln! macro are structured as:

tcprintln!(state_object, clause1, ...clauseN);

Where each clause takes on one of the following forms:

  • (format, args...) to print without applying colorization
  • [colorname: format, args...] to print applying the named color (see BasicColors for a list of what’s available in the simple case)
  • {color_var, {block}: format, args...} to print applying a color that is determined on-the-fly, potentially using local variables to choose the color (see tcprint!() for examples)

Along with tcprintln!(), macros named tcprint!(), etcprintln!(), and etcprint!() are provided, all in analogy with the printing macros provided with the Rust standard library.

Log-Style Messages

An additional macro named tcreport!() is provided to ease the printing of log messages classified as "info", "warning", or "error". TODO: should play nice with the standard log API!:

tcreport!(state, warning: "could not locate puppy");

This will emit the text warning: could not locate puppy, where the portion warning: appears in bold yellow by default. Other allowed prefixes are info: (appearing in green) and error: (appearing in red).

Custom Palettes

To use a custom palette of colors, define your own struct with public fields of type termcolor::ColorSpec. Then use that struct instead of BasicColors when creating the ColorPrintState struct. This crate re-exports Color and ColorSpec from termcolor for convenience in doing so.

#[macro_use] extern crate tcprint;

use std::default::Default;
use tcprint::{Color, ColorSpec, ColorPrintState};

#[derive(Clone, Debug, Eq, PartialEq)]
struct MyPalette {
    /// In this app, pet names should always be printed using this color specification.
    pub pet_name: ColorSpec,
}

impl Default for MyPalette {
    fn default() -> Self {
        // By default, pet names are printed in bold blue.
        let mut pet_name = ColorSpec::new();
        pet_name.set_fg(Some(Color::Blue)).set_bold(true);

        MyPalette { pet_name }
    }
}

fn main() {
    let mut state = ColorPrintState::<MyPalette>::default();

    let name = "Quemmy";
    tcprintln!(state,
         ("the name of my dog is "),
         [pet_name: "{}", name],
         ("!")
    );
}

If you want to use tcreport!() with your custom palette, it must implement the ReportingColors trait.

TODO: figure out locking plan!

Dependencies

~0–6.5MB
~36K SLoC