ok/jj
1
0
Fork 0
forked from mirrors/jj

cli: error out if colors section isn't of map type

This commit is contained in:
Yuya Nishihara 2023-01-18 10:20:27 +09:00
parent 7b24df25e4
commit 797189b106
3 changed files with 76 additions and 71 deletions

View file

@ -1717,7 +1717,7 @@ fn handle_early_args(
}
if !args.config_toml.is_empty() {
layered_configs.parse_config_args(&args.config_toml)?;
ui.reset(&layered_configs.merge());
ui.reset(&layered_configs.merge())?;
}
Ok(())
}
@ -1899,7 +1899,7 @@ impl CliRunner {
let cwd = env::current_dir().unwrap(); // TODO: maybe map_err to CommandError?
layered_configs.read_user_config()?;
let config = layered_configs.merge();
ui.reset(&config);
ui.reset(&config)?;
let string_args = expand_args(&self.app, std::env::args_os(), &config)?;
let (matches, args) = parse_args(
ui,
@ -1915,7 +1915,7 @@ impl CliRunner {
layered_configs.read_repo_config(loader.repo_path())?;
}
let config = layered_configs.merge();
ui.reset(&config);
ui.reset(&config)?;
let settings = UserSettings::from_config(config);
let command_helper = CommandHelper::new(
self.app,
@ -1932,7 +1932,8 @@ impl CliRunner {
#[must_use]
pub fn run(self) -> ExitCode {
let layered_configs = LayeredConfigs::from_environment();
let mut ui = Ui::with_config(&layered_configs.merge());
let mut ui = Ui::with_config(&layered_configs.merge())
.expect("default config should be valid, env vars are stringly typed");
let result = self.run_internal(&mut ui, layered_configs);
let exit_code = handle_command_result(&mut ui, result);
ui.finalize_writes();

View file

@ -98,16 +98,20 @@ enum FormatterFactoryKind {
}
impl FormatterFactory {
pub fn prepare(config: &config::Config, color: bool, sanitized: bool) -> Self {
pub fn prepare(
config: &config::Config,
color: bool,
sanitized: bool,
) -> Result<Self, config::ConfigError> {
let kind = if color {
let rules = Arc::new(rules_from_config(config));
let rules = Arc::new(rules_from_config(config)?);
FormatterFactoryKind::Color { rules }
} else if sanitized {
FormatterFactoryKind::Sanitized
} else {
FormatterFactoryKind::PlainText
};
FormatterFactory { kind }
Ok(FormatterFactory { kind })
}
pub fn new_formatter<'output, W: Write + 'output>(
@ -232,9 +236,9 @@ impl<W: Write> ColorFormatter<W> {
}
}
pub fn for_config(output: W, config: &config::Config) -> ColorFormatter<W> {
let rules = rules_from_config(config);
Self::new(output, Arc::new(rules))
pub fn for_config(output: W, config: &config::Config) -> Result<Self, config::ConfigError> {
let rules = rules_from_config(config)?;
Ok(Self::new(output, Arc::new(rules)))
}
fn requested_style(&mut self) -> Style {
@ -316,53 +320,52 @@ impl<W: Write> ColorFormatter<W> {
}
}
fn rules_from_config(config: &config::Config) -> Rules {
fn rules_from_config(config: &config::Config) -> Result<Rules, config::ConfigError> {
let mut result = vec![];
if let Ok(table) = config.get_table("colors") {
for (key, value) in table {
let labels = key
.split_whitespace()
.map(ToString::to_string)
.collect_vec();
match value.kind {
config::ValueKind::String(color_name) => {
let style = Style {
fg_color: color_for_name(&color_name),
bg_color: None,
bold: None,
underlined: None,
};
result.push((labels, style));
}
config::ValueKind::Table(style_table) => {
let mut style = Style::default();
if let Some(value) = style_table.get("fg") {
if let config::ValueKind::String(color_name) = &value.kind {
style.fg_color = color_for_name(color_name);
}
}
if let Some(value) = style_table.get("bg") {
if let config::ValueKind::String(color_name) = &value.kind {
style.bg_color = color_for_name(color_name);
}
}
if let Some(value) = style_table.get("bold") {
if let config::ValueKind::Boolean(value) = &value.kind {
style.bold = Some(*value);
}
}
if let Some(value) = style_table.get("underlined") {
if let config::ValueKind::Boolean(value) = &value.kind {
style.underlined = Some(*value);
}
}
result.push((labels, style));
}
_ => {}
let table = config.get_table("colors")?;
for (key, value) in table {
let labels = key
.split_whitespace()
.map(ToString::to_string)
.collect_vec();
match value.kind {
config::ValueKind::String(color_name) => {
let style = Style {
fg_color: color_for_name(&color_name),
bg_color: None,
bold: None,
underlined: None,
};
result.push((labels, style));
}
config::ValueKind::Table(style_table) => {
let mut style = Style::default();
if let Some(value) = style_table.get("fg") {
if let config::ValueKind::String(color_name) = &value.kind {
style.fg_color = color_for_name(color_name);
}
}
if let Some(value) = style_table.get("bg") {
if let config::ValueKind::String(color_name) = &value.kind {
style.bg_color = color_for_name(color_name);
}
}
if let Some(value) = style_table.get("bold") {
if let config::ValueKind::Boolean(value) = &value.kind {
style.bold = Some(*value);
}
}
if let Some(value) = style_table.get("underlined") {
if let config::ValueKind::Boolean(value) = &value.kind {
style.underlined = Some(*value);
}
}
result.push((labels, style));
}
_ => {}
}
}
result
Ok(result)
}
fn color_for_name(color_name: &str) -> Option<Color> {
@ -540,7 +543,7 @@ mod tests {
}
let mut output: Vec<u8> = vec![];
let mut formatter =
ColorFormatter::for_config(&mut output, &config_builder.build().unwrap());
ColorFormatter::for_config(&mut output, &config_builder.build().unwrap()).unwrap();
for color in colors {
formatter.push_label(&color.replace(' ', "-")).unwrap();
formatter.write_str(&format!(" {color} ")).unwrap();
@ -577,7 +580,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.write_str(" before ").unwrap();
formatter.push_label("inside").unwrap();
formatter.write_str(" inside ").unwrap();
@ -600,7 +603,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("red_fg").unwrap();
formatter.write_str(" fg only ").unwrap();
formatter.pop_label().unwrap();
@ -647,7 +650,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("not_bold").unwrap();
formatter.write_str(" not bold ").unwrap();
formatter.push_label("bold_font").unwrap();
@ -668,7 +671,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.write_str("before").unwrap();
formatter.push_label("red").unwrap();
formatter.write_str("first").unwrap();
@ -689,7 +692,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("red").unwrap();
formatter
.write_str("\x1b[1mnot actually bold\x1b[0m")
@ -711,7 +714,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.write_str(" before outer ").unwrap();
formatter.push_label("outer").unwrap();
formatter.write_str(" before inner ").unwrap();
@ -734,7 +737,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("outer").unwrap();
formatter.write_str(" not colored ").unwrap();
formatter.push_label("inner").unwrap();
@ -756,7 +759,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("outer").unwrap();
formatter.write_str(" red before ").unwrap();
formatter.push_label("inner").unwrap();
@ -778,7 +781,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("outer1").unwrap();
formatter.push_label("inner2").unwrap();
formatter.write_str(" hello ").unwrap();
@ -797,7 +800,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("outer").unwrap();
formatter.push_label("inner").unwrap();
formatter.write_str(" hello ").unwrap();
@ -818,7 +821,7 @@ mod tests {
"#,
);
let mut output: Vec<u8> = vec![];
let mut formatter = ColorFormatter::for_config(&mut output, &config);
let mut formatter = ColorFormatter::for_config(&mut output, &config).unwrap();
formatter.push_label("a").unwrap();
formatter.write_str(" a1 ").unwrap();
formatter.push_label("b").unwrap();

View file

@ -107,29 +107,30 @@ fn pager_setting(config: &config::Config) -> FullCommandArgs {
}
impl Ui {
pub fn with_config(config: &config::Config) -> Ui {
pub fn with_config(config: &config::Config) -> Result<Ui, config::ConfigError> {
let color = use_color(color_setting(config));
// Sanitize ANSI escape codes if we're printing to a terminal. Doesn't affect
// ANSI escape codes that originate from the formatter itself.
let sanitize = io::stdout().is_tty();
let formatter_factory = FormatterFactory::prepare(config, color, sanitize);
let formatter_factory = FormatterFactory::prepare(config, color, sanitize)?;
let progress_indicator = progress_indicator_setting(config);
Ui {
Ok(Ui {
color,
formatter_factory,
pager_cmd: pager_setting(config),
paginate: PaginationChoice::Auto,
progress_indicator,
output: UiOutput::new_terminal(),
}
})
}
pub fn reset(&mut self, config: &config::Config) {
pub fn reset(&mut self, config: &config::Config) -> Result<(), config::ConfigError> {
self.color = use_color(color_setting(config));
self.pager_cmd = pager_setting(config);
self.progress_indicator = progress_indicator_setting(config);
let sanitize = io::stdout().is_tty();
self.formatter_factory = FormatterFactory::prepare(config, self.color, sanitize);
self.formatter_factory = FormatterFactory::prepare(config, self.color, sanitize)?;
Ok(())
}
/// Sets the pagination value.