use crate::{Environment, FALSE_SYMBOL, TRUE_SYMBOL, eval::apply::eval_apply, expand_tilde, value::Value};
pub(crate) fn builtin(args: &[Value], env: Environment) -> Result<Value, std::sync::Arc<str>> {
if let [path, is_append, content] = args {
match (
eval_apply(path, env.clone())?,
eval_apply(is_append, env.clone())?,
eval_apply(content, env)?,
) {
(Value::String(file_path), p @ Value::Atom(_), Value::String(text)) if p == *TRUE_SYMBOL || p == *FALSE_SYMBOL => {
expand_tilde(file_path).and_then(|real_path| {
match std::fs::File::options()
.truncate(p == *FALSE_SYMBOL)
.append(p == *TRUE_SYMBOL)
.write(true)
.create(true)
.open(&real_path)
.and_then(|f| {
std::io::Write::write_all(
&mut std::io::BufWriter::new(f),
&text.bytes().collect::<Vec<u8>>(),
)
}) {
Ok(()) => Ok(Value::Unit),
Err(e) => Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Write]: ",
"Write to file `{}` failed with `{}`."
),
real_path.display(),
e
))),
}
})
}
(Value::String(_), Value::Atom(p), Value::String(_)) => Err(std::sync::Arc::from(format!(
concat!("Error[ksl::builtin::Write]: ", "`#{}` is not a boolean"),
p
))),
(Value::String(_), Value::Atom(_), e) => Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Write]: ",
"Expect a string, but got: `{}`."
),
e
))),
(Value::String(_), e, _) => Err(std::sync::Arc::from(format!(
concat!("Error[ksl::builtin::Write]: ", "Unexpected value: `{}`."),
e
))),
(e, _, _) => Err(std::sync::Arc::from(format!(
concat!("Error[ksl::builtin::Write]: ", "Unexpected value: `{}`."),
e
))),
}
} else {
Err(std::sync::Arc::from(format!(
concat!(
"Error[ksl::builtin::Write]: ",
"Expected 3 parameters, but {} were passed."
),
args.len()
)))
}
}