use cli::GlobalArgs;
use crate::home::resolve_paths;
use crate::{cli, style};
pub(crate) fn interpreters_from_config(
shep_toml: Option<&str>,
) -> std::collections::BTreeMap<String, String> {
shep_core::config::DaemonConfig::load(shep_toml, &|_| None)
.map(|cfg| cfg.interpreters)
.unwrap_or_default()
}
pub(crate) fn style_from_config(shep_toml: Option<&str>) -> Option<style::StyleLevel> {
shep_core::config::DaemonConfig::load(shep_toml, &|_| None)
.ok()?
.style
.level
.and_then(|raw| style::StyleLevel::parse(&raw))
}
pub(crate) fn resolve_style(global: &GlobalArgs) -> (style::StyleLevel, style::StyleSource) {
let config_text = resolve_paths(global)
.ok()
.and_then(|paths| std::fs::read_to_string(paths.daemon_config).ok());
style::resolve(
global.style,
std::env::var("SHEP_STYLE").ok().as_deref(),
style_from_config(config_text.as_deref()),
)
}
#[cfg_attr(windows, allow(dead_code))]
pub(crate) fn style_write_is_overridden(source: style::StyleSource) -> bool {
matches!(source, style::StyleSource::Flag | style::StyleSource::Env)
}
pub(crate) fn must_render_bare(stdout_is_terminal: bool, fmt: cli::Format) -> bool {
!stdout_is_terminal || fmt == cli::Format::Json
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn must_render_bare_is_true_exactly_for_a_piped_stdout_or_a_json_format() {
assert!(
!must_render_bare(true, cli::Format::Table),
"a real terminal asking for a table gets to render one"
);
assert!(
must_render_bare(false, cli::Format::Table),
"piped stdout must render bare even under --format table"
);
assert!(
must_render_bare(true, cli::Format::Json),
"--format json must render bare even at a real terminal"
);
assert!(must_render_bare(false, cli::Format::Json));
}
#[test]
fn style_from_config_reads_the_level_and_is_lenient_about_everything_else() {
assert_eq!(
style_from_config(Some("[style]\nlevel = \"plain\"\n")),
Some(style::StyleLevel::Plain)
);
assert_eq!(style_from_config(None), None, "no file at all");
assert_eq!(style_from_config(Some("")), None, "an empty file");
assert_eq!(
style_from_config(Some("[style")),
None,
"a file that will not parse"
);
assert_eq!(
style_from_config(Some("[daemon]\nlog_level = \"info\"\n")),
None,
"a config with no [style] table at all"
);
assert_eq!(
style_from_config(Some("[style]\nlevel = \"loud\"\n")),
None,
"a level this build does not recognise"
);
}
#[test]
fn style_from_config_trims_the_same_way_shep_style_does() {
for raw in ["full", " full ", "\tfull\n", "FULL", " FuLl "] {
assert_eq!(
style_from_config(Some(&format!("[style]\nlevel = {raw:?}\n"))),
Some(style::StyleLevel::Full),
"shep.toml's own level must accept {raw:?} exactly as \
$SHEP_STYLE would"
);
assert_eq!(
style::resolve(None, Some(raw), None),
(style::StyleLevel::Full, style::StyleSource::Env),
"$SHEP_STYLE must accept {raw:?}"
);
}
}
#[test]
fn resolve_style_reads_the_flag_and_the_real_shep_toml_it_names() {
let dir = tempfile::tempdir().unwrap();
std::fs::write(dir.path().join("shep.toml"), "[style]\nlevel = \"plain\"\n").unwrap();
let global = cli::GlobalArgs {
home: Some(dir.path().to_path_buf()),
format: cli::Format::Table,
quiet: false,
style: None,
};
assert_eq!(
resolve_style(&global),
(style::StyleLevel::Plain, style::StyleSource::Config),
"with no flag, shep.toml's own level answers"
);
let global = cli::GlobalArgs {
style: Some(style::StyleLevel::Bare),
..global
};
assert_eq!(
resolve_style(&global),
(style::StyleLevel::Bare, style::StyleSource::Flag),
"the flag wins over the very shep.toml that set plain above"
);
}
#[test]
fn style_write_is_overridden_only_by_flag_or_env() {
assert!(style_write_is_overridden(style::StyleSource::Flag));
assert!(style_write_is_overridden(style::StyleSource::Env));
assert!(!style_write_is_overridden(style::StyleSource::Config));
assert!(!style_write_is_overridden(style::StyleSource::Default));
}
}