I have been playing around with the colorterm crate. I've written a simple program in VS code here:
use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor, BufferWriter};
use std::io::Write;
fn main() {
let quote: &str = "A donkey, a donkey, my kingdom for a donkey!";
let colors: Vec<(u8, u8, u8)> = vec![
(50, 168, 82),
(255, 129, 3),
(32, 72, 145),
(237, 226, 17),
(48, 176, 161),
(166, 28, 111),
(230, 18, 36)
];
let mut stdout = StandardStream::stdout(ColorChoice::Always);
for color in colors {
stdout.set_color(ColorSpec::new().set_fg(
Some(Color::Rgb(
color.0,
color.1,
color.2
))
))
.expect("Failed to set color");
write!(&mut stdout, "{}", quote).expect("failed to write");
println!();
}
}
Everything was going fine testing the output in the VS integrated terminal
However, when I test it on my OS terminal (the Terminal.app that comes with MacOS) I get the following:
The results have the incorrect colours, are italicised in one instance or have no color (well grey I suppose) at all.
I'm thinking this is less a problem with the crate and more with my terminal config?
I use Mac OSX
with a zsh shell
for my normal terminal, no fancy configs but I do use oh my zsh
normally (I tried this on a shell without oh my zsh and got the same result). My first feeling was that it was something to do with the environment variable mentioned in the docs here however I've got TERM set to xterm-256color. I think the answer may lay in the configuration difference between the VS code integrated terminal (there must be something right?) and the vanilla zsh terminal. If anyone is more familiar with the differences between the two, or if you have encountered any similar problems with the crate, or I am missing something entirely here I would be grateful for some help.
Ok, just for completeness I managed to find the answer to this with some digging. The vanilla Terminal.app doesn't support truecolor; checking COLORTERM variables for each terminal (terminal.app, vs code intergrated, and iterm2) clarified this. For terminals that don't support truecolor we can convert our rbg values into a single u8 ansi256 value (for conversion I used this library) and use the appropriate variation of the Color enum to output our coloured content like so:
...
println!("{}", val);
let mut stdout = StandardStream::stdout(ColorChoice::Always);
for color in colors {
let ansi_val: u8 = rgb_to_ansi256(color.0, color.1, color.2);
stdout.set_color(ColorSpec::new().set_fg(
Some(Color::Ansi256(ansi_val))
))
.expect("Failed to set color");
write!(&mut stdout, "{}", quote).expect("failed to write");
println!();
}