use std::io::{self, Write};
use lazy_static::lazy_static;
use crate::{
eval::{EvalContext, EvalResult},
parser::{ExprValue, parse_expr},
};
pub(crate) fn write_unescaped(args: Vec<EvalResult>) -> EvalResult {
if let Some(EvalResult::String(s)) = args.get(0) {
io::stdout().write_all(s.as_bytes()).unwrap();
io::stdout().flush().unwrap();
} else {
println!("{:?}", args.get(0));
}
EvalResult::None
}
pub(crate) static write: &str = r#"
io:write_unescaped(string:escape(string:concat(...$arguments)))
"#;
pub(crate) static writeln: &str = r#"
use(["io", "array"], 'write(...append($arguments, lf)))
"#;
pub(crate) static format: &str = r#"
use(["io"], 'write(string:format(...$arguments)))
"#;
lazy_static! {
pub static ref IO: EvalContext<'static> = EvalContext::new()
.with_fn("io:write_unescaped", write_unescaped)
.with_var(
"io:write",
ExprValue::Quote(Box::new(parse_expr(write).unwrap()))
)
.with_var(
"io:writeln",
ExprValue::Quote(Box::new(parse_expr(writeln).unwrap()))
)
.with_var(
"io:format",
ExprValue::Quote(Box::new(parse_expr(format).unwrap()))
);
}
#[cfg(test)]
mod tests {
use crate::{eval_str, io::IO, stdlib::STDLIB};
#[test]
fn test_write_unescaped() {
eval_str(
r#"io:write_unescaped("Hello world")"#,
STDLIB.merge(IO.clone()),
)
.unwrap();
}
#[test]
fn test_write() {
eval_str(r#"io:write("Hello world")"#, STDLIB.merge(IO.clone())).unwrap();
}
#[test]
fn test_writeln() {
eval_str(r#"io:writeln("Hello world")"#, STDLIB.merge(IO.clone())).unwrap();
}
#[test]
fn test_format() {
eval_str(
r#"io:format("Hello {}~n", "world")"#,
STDLIB.merge(IO.clone()),
)
.unwrap();
}
}