use shep_core::config::{APPLY_NEXT_COMMAND, APPLY_RELOAD, APPLY_RESTART, APPLY_WHISTLE};
use crate::commands::settings::{STYLE_LEVEL_KEY, SettingEdit};
use crate::lookout::field::shep_toml_shape;
use crate::style::StyleSource;
const OUTRANKED_AT_BOOT: [&str; 4] = [
"daemon.log_level",
"daemon.log_json",
"daemon.socket",
"daemon.max_cron_sleep",
];
pub(super) fn confirm_text(edit: &SettingEdit, source: StyleSource) -> String {
let key = edit.key();
match edit {
SettingEdit::Set { value, .. } if key == STYLE_LEVEL_KEY => {
style_confirm_text(value, source)
}
SettingEdit::Set { value, .. } => {
format!("set {key} to {value}? {}{}", cost(&key), outranked(&key))
}
SettingEdit::Unset { .. } if shep_toml_shape().fields.by_key(&key).is_some() => format!(
"unset {key}? it goes back to the default, and {}",
cost(&key)
),
SettingEdit::Unset { .. } => format!("remove {key}? {}", cost(&key)),
}
}
pub(crate) fn apply_needs(apply: Option<&str>) -> &'static str {
match apply {
Some(APPLY_RELOAD) => "needs shep daemon reload",
Some(APPLY_RESTART) => "needs the shepherd stopped and started",
Some(APPLY_WHISTLE) => "needs shep whistle restarted",
Some(APPLY_NEXT_COMMAND) => "the next command reads it",
_ => "takes hold when shep.toml is next read",
}
}
fn cost(key: &str) -> String {
let shape = shep_toml_shape();
let field = shape.fields.by_key(key).or_else(|| {
key.rsplit_once('.')
.and_then(|(map, _)| shape.fields.by_key(map))
});
let apply = field.and_then(|field| field.apply.as_deref());
let needs = apply_needs(apply);
if apply == Some(APPLY_RESTART) {
format!("{needs}; a reload will not move it")
} else {
needs.to_owned()
}
}
fn outranked(key: &str) -> String {
let Some(name) = OUTRANKED_AT_BOOT
.contains(&key)
.then(|| key.rsplit('.').next())
.flatten()
else {
return String::new();
};
format!(
", and will not apply if the shepherd was booted with SHEP_{} or --{}",
name.to_uppercase(),
name.replace('_', "-")
)
}
fn style_confirm_text(value: &str, source: StyleSource) -> String {
match source {
StyleSource::Config | StyleSource::Default => {
format!("set style level to {value}? the next command reads it")
}
StyleSource::Env => format!(
"set style level to {value}? it goes in the file, but $SHEP_STYLE is set and keeps winning until it is unset"
),
StyleSource::Flag => format!(
"set style level to {value}? it goes in the file, but --style was passed to this lookout and keeps winning for as long as it runs"
),
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::commands::settings::Shape;
#[test]
fn the_confirm_for_a_map_entry_names_the_cost_its_map_row_shows() {
let map = shep_toml_shape().fields.by_key("interpreters").unwrap();
let shown = apply_needs(map.apply.as_deref());
let entry = |edit: SettingEdit| confirm_text(&edit, StyleSource::Default);
let set = entry(SettingEdit::Set {
path: vec!["interpreters".into(), "py".into()],
shape: Shape::Text,
value: "python3".into(),
});
let remove = entry(SettingEdit::Unset {
path: vec!["interpreters".into(), "py".into()],
});
assert_eq!(set, format!("set interpreters.py to python3? {shown}"));
assert_eq!(remove, format!("remove interpreters.py? {shown}"));
}
}