Skip to content

Commit

Permalink
Support 256-color terminal environments
Browse files Browse the repository at this point in the history
Fixes #110

With this commit, delta enters "24 bit color mode" iff either of the
following are true:

1. The --24-bit-color command line option value is "always"

2. The --24-bit-color command line option value is "auto" and the
   COLORTERM environment variable is set to "truecolor" or "24bit".
   See
   https://gist.github.com/XVilka/8346728#true-color-detection
   https://github.com/sharkdp/bat/blob/7779d9f6221b3e98c43a43ceb5596ba285fdf4f8/src/bin/bat/app.rs#L29-L33

Otherwise, delta enters "8-bit color mode".

In "24 bit color mode", delta will

1. Emit 24-bit RGB color shell escape sequences that will only be
   displayed correctly by a terminal application that supports 24 bit
   colors.

2. Select default background colors that will only be displayed
   correctly by a terminal application that supports 24 bit colors.

In "8-bit color mode", delta will

1. Emit color shell escape sequences specifying the entry in the ANSI
   256 color palette that is closest (according to the ansi_colours
   library) to the requested color.

2. Select default background colors that will work well in a terminal
   application that supports 8-bit color but not 24-bit color.
  • Loading branch information
dandavison committed Mar 1, 2020
1 parent eeee3d4 commit 37cc69e
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 85 deletions.
10 changes: 10 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ name = "delta"
path = "src/main.rs"

[dependencies]
ansi_colours = "1.0.1"
ansi_term = "0.11.0"
atty = "0.2.13"
box_drawing = "0.1.2"
Expand Down
29 changes: 29 additions & 0 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use structopt::StructOpt;
use crate::bat::assets::HighlightingAssets;
use crate::bat::output::PagingMode;
use crate::config;
use crate::env;
use crate::style;

#[derive(StructOpt, Clone, Debug)]
Expand Down Expand Up @@ -155,6 +156,14 @@ pub struct Opt {
#[structopt(long = "max-line-distance", default_value = "0.3")]
pub max_line_distance: f64,

/// Whether to emit 24-bit ("true color") RGB color codes. Options are auto, always, and never.
/// "auto" means that delta will emit 24-bit color codes iff the environment variable COLORTERM
/// has the value "truecolor" or "24bit". If your terminal application (the application you use
/// to enter commands at a shell prompt) supports 24 bit colors, then it probably already sets
/// this environment variable, in which case you don't need to do anything.
#[structopt(long = "24-bit-color", default_value = "auto")]
pub true_color: String,

/// Whether to use a pager when displaying output. Options are: auto, always, and never. The
/// default pager is `less`: this can be altered by setting the environment variables BAT_PAGER
/// or PAGER (BAT_PAGER has priority).
Expand Down Expand Up @@ -257,12 +266,32 @@ pub fn process_command_line_arguments<'a>(
}
};

let true_color = match opt.true_color.as_ref() {
"always" => true,
"never" => false,
"auto" => is_truecolor_terminal(),
_ => {
eprintln!(
"Invalid value for --24-bit-color option: {} (valid values are \"always\", \"never\", and \"auto\")",
opt.true_color
);
process::exit(1);
}
};

config::get_config(
opt,
&assets.syntax_set,
&assets.theme_set,
true_color,
available_terminal_width,
background_color_width,
paging_mode,
)
}

fn is_truecolor_terminal() -> bool {
env::get_env_var("COLORTERM")
.map(|colorterm| colorterm == "truecolor" || colorterm == "24bit")
.unwrap_or(false)
}
44 changes: 14 additions & 30 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use std::str::FromStr;
use syntect::highlighting::{Color, Style, StyleModifier, Theme, ThemeSet};
use syntect::parsing::SyntaxSet;

use crate::bat::output::PagingMode;
use crate::cli;
use crate::env;
use crate::paint;
use crate::style;
use crate::bat::output::{PagingMode};

pub struct Config<'a> {
pub theme: Option<&'a Theme>,
Expand All @@ -22,6 +22,7 @@ pub struct Config<'a> {
pub hunk_color: Color,
pub syntax_set: &'a SyntaxSet,
pub terminal_width: usize,
pub true_color: bool,
pub width: Option<usize>,
pub tab_width: usize,
pub opt: &'a cli::Opt,
Expand All @@ -34,6 +35,7 @@ pub fn get_config<'a>(
opt: &'a cli::Opt,
syntax_set: &'a SyntaxSet,
theme_set: &'a ThemeSet,
true_color: bool,
terminal_width: usize,
width: Option<usize>,
paging_mode: PagingMode,
Expand All @@ -53,11 +55,9 @@ pub fn get_config<'a>(
};

let minus_style_modifier = StyleModifier {
background: Some(color_from_arg_or_mode_default(
background: Some(color_from_arg(
opt.minus_color.as_ref(),
is_light_mode,
style::LIGHT_THEME_MINUS_COLOR,
style::DARK_THEME_MINUS_COLOR,
style::get_minus_color_default(is_light_mode, true_color),
)),
foreground: if opt.highlight_removed {
None
Expand All @@ -68,11 +68,9 @@ pub fn get_config<'a>(
};

let minus_emph_style_modifier = StyleModifier {
background: Some(color_from_arg_or_mode_default(
background: Some(color_from_arg(
opt.minus_emph_color.as_ref(),
is_light_mode,
style::LIGHT_THEME_MINUS_EMPH_COLOR,
style::DARK_THEME_MINUS_EMPH_COLOR,
style::get_minus_emph_color_default(is_light_mode, true_color),
)),
foreground: if opt.highlight_removed {
None
Expand All @@ -83,22 +81,18 @@ pub fn get_config<'a>(
};

let plus_style_modifier = StyleModifier {
background: Some(color_from_arg_or_mode_default(
background: Some(color_from_arg(
opt.plus_color.as_ref(),
is_light_mode,
style::LIGHT_THEME_PLUS_COLOR,
style::DARK_THEME_PLUS_COLOR,
style::get_plus_color_default(is_light_mode, true_color),
)),
foreground: None,
font_style: None,
};

let plus_emph_style_modifier = StyleModifier {
background: Some(color_from_arg_or_mode_default(
background: Some(color_from_arg(
opt.plus_emph_color.as_ref(),
is_light_mode,
style::LIGHT_THEME_PLUS_EMPH_COLOR,
style::DARK_THEME_PLUS_EMPH_COLOR,
style::get_plus_emph_color_default(is_light_mode, true_color),
)),
foreground: None,
font_style: None,
Expand All @@ -114,6 +108,7 @@ pub fn get_config<'a>(
commit_color: color_from_rgb_or_ansi_code(&opt.commit_color),
file_color: color_from_rgb_or_ansi_code(&opt.file_color),
hunk_color: color_from_rgb_or_ansi_code(&opt.hunk_color),
true_color,
terminal_width,
width,
tab_width: opt.tab_width,
Expand Down Expand Up @@ -192,20 +187,9 @@ fn color_from_rgb_or_ansi_code(s: &str) -> Color {
}
}

fn color_from_arg_or_mode_default(
arg: Option<&String>,
is_light_mode: bool,
light_theme_default: Color,
dark_theme_default: Color,
) -> Color {
fn color_from_arg(arg: Option<&String>, default: Color) -> Color {
match arg {
Some(string) => color_from_rgb_or_ansi_code(&string),
None => {
if is_light_mode {
light_theme_default
} else {
dark_theme_default
}
}
None => default,
}
}
32 changes: 13 additions & 19 deletions src/delta.rs
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ fn handle_commit_meta_header_line(
config.terminal_width,
config.commit_color,
true,
config.true_color,
)?;
Ok(())
}
Expand Down Expand Up @@ -234,10 +235,11 @@ fn handle_generic_file_meta_header_line(
writeln!(painter.writer)?;
draw_fn(
painter.writer,
&paint::paint_text_foreground(line, config.file_color),
&paint::paint_text_foreground(line, config.file_color, config.true_color),
config.terminal_width,
config.file_color,
false,
config.true_color,
)?;
Ok(())
}
Expand Down Expand Up @@ -279,13 +281,14 @@ fn handle_hunk_meta_line(
config.terminal_width,
config.hunk_color,
false,
config.true_color,
)?;
painter.output_buffer.clear();
}
writeln!(
painter.writer,
"\n{}",
paint::paint_text_foreground(line_number, config.hunk_color)
paint::paint_text_foreground(line_number, config.hunk_color, config.true_color)
)?;
Ok(())
}
Expand Down Expand Up @@ -431,6 +434,7 @@ mod tests {

#[test]
fn test_theme_selection() {
#[derive(PartialEq)]
enum Mode {
Light,
Dark,
Expand Down Expand Up @@ -496,6 +500,7 @@ mod tests {
} else {
env::set_var("BAT_THEME", bat_theme_env_var);
}
let is_true_color = true;
let mut options = get_command_line_options();
options.theme = theme_option;
match mode_option {
Expand All @@ -521,31 +526,19 @@ mod tests {
}
assert_eq!(
config.minus_style_modifier.background.unwrap(),
match expected_mode {
Mode::Light => style::LIGHT_THEME_MINUS_COLOR,
Mode::Dark => style::DARK_THEME_MINUS_COLOR,
}
style::get_minus_color_default(expected_mode == Mode::Light, is_true_color)
);
assert_eq!(
config.minus_emph_style_modifier.background.unwrap(),
match expected_mode {
Mode::Light => style::LIGHT_THEME_MINUS_EMPH_COLOR,
Mode::Dark => style::DARK_THEME_MINUS_EMPH_COLOR,
}
style::get_minus_emph_color_default(expected_mode == Mode::Light, is_true_color)
);
assert_eq!(
config.plus_style_modifier.background.unwrap(),
match expected_mode {
Mode::Light => style::LIGHT_THEME_PLUS_COLOR,
Mode::Dark => style::DARK_THEME_PLUS_COLOR,
}
style::get_plus_color_default(expected_mode == Mode::Light, is_true_color)
);
assert_eq!(
config.plus_emph_style_modifier.background.unwrap(),
match expected_mode {
Mode::Light => style::LIGHT_THEME_PLUS_EMPH_COLOR,
Mode::Dark => style::DARK_THEME_PLUS_EMPH_COLOR,
}
style::get_plus_emph_color_default(expected_mode == Mode::Light, is_true_color)
);
}
}
Expand Down Expand Up @@ -580,7 +573,7 @@ mod tests {
fn paint_text(input: &str, style_modifier: StyleModifier, config: &Config) -> String {
let mut output = String::new();
let style = config.no_style.apply(style_modifier);
paint::paint_text(&input, style, &mut output);
paint::paint_text(&input, style, &mut output, config.true_color);
output
}

Expand Down Expand Up @@ -623,6 +616,7 @@ mod tests {
file_color: "Blue".to_string(),
hunk_style: cli::SectionStyle::Box,
hunk_color: "blue".to_string(),
true_color: "always".to_string(),
width: Some("variable".to_string()),
paging_mode: "auto".to_string(),
tab_width: 4,
Expand Down
Loading

0 comments on commit 37cc69e

Please sign in to comment.