##// END OF EJS Templates
stream-clone-test: simplify the case where server disabled it...
stream-clone-test: simplify the case where server disabled it We have an option to disable it, we don't need to test it with all protocol variants. In addition there is little value in looking at the bytes to bytes details of the reply. Such check is very fragile and consume a lot of time for little value when adjusting formats, caches, and protocol.

File last commit:

r50826:fba29dee default
r52365:749e7685 default
Show More
color.rs
250 lines | 7.3 KiB | application/rls-services+xml | RustLexer
use crate::ui::formatted;
use crate::ui::plain;
use format_bytes::write_bytes;
use hg::config::Config;
use hg::config::ConfigOrigin;
use hg::errors::HgError;
use std::collections::HashMap;
pub type Effect = u32;
pub type EffectsMap = HashMap<Vec<u8>, Vec<Effect>>;
macro_rules! effects {
($( $name: ident: $value: expr ,)+) => {
#[allow(non_upper_case_globals)]
mod effects {
$(
pub const $name: super::Effect = $value;
)+
}
fn effect(name: &[u8]) -> Option<Effect> {
$(
if name == stringify!($name).as_bytes() {
Some(effects::$name)
} else
)+
{
None
}
}
};
}
effects! {
none: 0,
black: 30,
red: 31,
green: 32,
yellow: 33,
blue: 34,
magenta: 35,
cyan: 36,
white: 37,
bold: 1,
italic: 3,
underline: 4,
inverse: 7,
dim: 2,
black_background: 40,
red_background: 41,
green_background: 42,
yellow_background: 43,
blue_background: 44,
purple_background: 45,
cyan_background: 46,
white_background: 47,
}
macro_rules! default_styles {
($( $key: expr => [$($value: expr),*],)+) => {
fn default_styles() -> EffectsMap {
use effects::*;
let mut map = HashMap::new();
$(
map.insert($key[..].to_owned(), vec![$( $value ),*]);
)+
map
}
};
}
default_styles! {
b"grep.match" => [red, bold],
b"grep.linenumber" => [green],
b"grep.rev" => [blue],
b"grep.sep" => [cyan],
b"grep.filename" => [magenta],
b"grep.user" => [magenta],
b"grep.date" => [magenta],
b"grep.inserted" => [green, bold],
b"grep.deleted" => [red, bold],
b"bookmarks.active" => [green],
b"branches.active" => [none],
b"branches.closed" => [black, bold],
b"branches.current" => [green],
b"branches.inactive" => [none],
b"diff.changed" => [white],
b"diff.deleted" => [red],
b"diff.deleted.changed" => [red, bold, underline],
b"diff.deleted.unchanged" => [red],
b"diff.diffline" => [bold],
b"diff.extended" => [cyan, bold],
b"diff.file_a" => [red, bold],
b"diff.file_b" => [green, bold],
b"diff.hunk" => [magenta],
b"diff.inserted" => [green],
b"diff.inserted.changed" => [green, bold, underline],
b"diff.inserted.unchanged" => [green],
b"diff.tab" => [],
b"diff.trailingwhitespace" => [bold, red_background],
b"changeset.public" => [],
b"changeset.draft" => [],
b"changeset.secret" => [],
b"diffstat.deleted" => [red],
b"diffstat.inserted" => [green],
b"formatvariant.name.mismatchconfig" => [red],
b"formatvariant.name.mismatchdefault" => [yellow],
b"formatvariant.name.uptodate" => [green],
b"formatvariant.repo.mismatchconfig" => [red],
b"formatvariant.repo.mismatchdefault" => [yellow],
b"formatvariant.repo.uptodate" => [green],
b"formatvariant.config.special" => [yellow],
b"formatvariant.config.default" => [green],
b"formatvariant.default" => [],
b"histedit.remaining" => [red, bold],
b"ui.addremove.added" => [green],
b"ui.addremove.removed" => [red],
b"ui.error" => [red],
b"ui.prompt" => [yellow],
b"log.changeset" => [yellow],
b"patchbomb.finalsummary" => [],
b"patchbomb.from" => [magenta],
b"patchbomb.to" => [cyan],
b"patchbomb.subject" => [green],
b"patchbomb.diffstats" => [],
b"rebase.rebased" => [blue],
b"rebase.remaining" => [red, bold],
b"resolve.resolved" => [green, bold],
b"resolve.unresolved" => [red, bold],
b"shelve.age" => [cyan],
b"shelve.newest" => [green, bold],
b"shelve.name" => [blue, bold],
b"status.added" => [green, bold],
b"status.clean" => [none],
b"status.copied" => [none],
b"status.deleted" => [cyan, bold, underline],
b"status.ignored" => [black, bold],
b"status.modified" => [blue, bold],
b"status.removed" => [red, bold],
b"status.unknown" => [magenta, bold, underline],
b"tags.normal" => [green],
b"tags.local" => [black, bold],
b"upgrade-repo.requirement.preserved" => [cyan],
b"upgrade-repo.requirement.added" => [green],
b"upgrade-repo.requirement.removed" => [red],
}
fn parse_effect(config_key: &[u8], effect_name: &[u8]) -> Option<Effect> {
let found = effect(effect_name);
if found.is_none() {
// TODO: have some API for warnings
// TODO: handle IO errors during warnings
let stderr = std::io::stderr();
let _ = write_bytes!(
&mut stderr.lock(),
b"ignoring unknown color/effect '{}' \
(configured in color.{})\n",
effect_name,
config_key,
);
}
found
}
fn effects_from_config(config: &Config) -> EffectsMap {
let mut styles = default_styles();
for (key, _value) in config.iter_section(b"color") {
if !key.contains(&b'.')
|| key.starts_with(b"color.")
|| key.starts_with(b"terminfo.")
{
continue;
}
// `unwrap` shouldn’t panic since we just got this key from
// iteration
let list = config.get_list(b"color", key).unwrap();
let parsed = list
.iter()
.filter_map(|name| parse_effect(key, name))
.collect();
styles.insert(key.to_owned(), parsed);
}
styles
}
enum ColorMode {
// TODO: support other modes
Ansi,
}
impl ColorMode {
// Similar to _modesetup in mercurial/color.py
fn get(config: &Config) -> Result<Option<Self>, HgError> {
if plain(Some("color")) {
return Ok(None);
}
let enabled_default = b"auto";
// `origin` is only used when `!auto`, so its default doesn’t matter
let (enabled, origin) = config
.get_with_origin(b"ui", b"color")
.unwrap_or((enabled_default, &ConfigOrigin::CommandLineColor));
if enabled == b"debug" {
return Err(HgError::unsupported("debug color mode"));
}
let auto = enabled == b"auto";
let always = if !auto {
let enabled_bool = config.get_bool(b"ui", b"color")?;
if !enabled_bool {
return Ok(None);
}
enabled == b"always" || *origin == ConfigOrigin::CommandLineColor
} else {
false
};
let formatted = always
|| (std::env::var_os("TERM").unwrap_or_default() != "dumb"
&& formatted(config)?);
let mode_default = b"auto";
let mode = config.get(b"color", b"mode").unwrap_or(mode_default);
if formatted {
match mode {
b"ansi" | b"auto" => Ok(Some(ColorMode::Ansi)),
// TODO: support other modes
_ => Err(HgError::UnsupportedFeature(format!(
"color mode {}",
String::from_utf8_lossy(mode)
))),
}
} else {
Ok(None)
}
}
}
pub struct ColorConfig {
pub styles: EffectsMap,
}
impl ColorConfig {
// Similar to _modesetup in mercurial/color.py
pub fn new(config: &Config) -> Result<Option<Self>, HgError> {
Ok(ColorMode::get(config)?.map(|ColorMode::Ansi| ColorConfig {
styles: effects_from_config(config),
}))
}
}