use super::Valuable;
use super::*;
use crate::ast::*;
use ansi_term::Colour::Red;
use regex::Regex;
use Event::*;
macro_rules! error {
($format: expr, $($args: expr),*) => {
{
eprint!("{}{}", color!(Red, format!($format, $($args),*)), nl!());
return
}
}
}
pub fn print(expr: &Expression, env: &mut Environment) {
env.print(&mut format!("{}{}", expr.to_value(env), nl!()).as_bytes());
}
pub fn quit(env: &mut Environment) {
env.quit()
}
pub fn subst(regex: &Regex, expr: &Expression, env: &mut Environment) {
env.replace_line(|env, line| {
regex
.replace(&line, |caps: &Captures| {
env.eval(Scope::from_captures(regex, caps), expr)
})
.into_owned()
});
}
pub fn gsubst(regex: &Regex, expr: &Expression, env: &mut Environment) {
env.replace_line(|env, line| {
regex
.replace_all(&line, |caps: &Captures| {
env.eval(Scope::from_captures(regex, caps), expr)
})
.into_owned()
});
}
pub fn read(expr: &Expression, env: &mut Environment) {
let mut file = match std::fs::File::open(expr.to_value(env)) {
Ok(f) => f,
Err(msg) => error!("Error open file {}", msg),
};
env.print(&mut file);
}
pub fn write(expr: &Expression, env: &mut Environment) {
if let Line(line) = &env.event {
let mut file = match std::fs::OpenOptions::new()
.write(true)
.append(true)
.create(true)
.open(expr.to_value(env))
{
Ok(f) => f,
Err(msg) => error!("Error opening file {}", msg),
};
match write!(file, "{}{}", line, nl!()) {
Ok(_) => (),
Err(msg) => error!("Error writing to file {}", msg),
}
}
}
pub fn exec(expr: &Expression, env: &mut Environment) {
match shell(&expr.to_value(env)) {
Err(msg) => {
let message = format!("unable to execute: {}", msg);
eprint!("{}{}", color!(Red, message), nl!());
}
Ok(child) => {
env.print(&mut child.stdout.unwrap());
}
}
}
pub fn append(expr: &Expression, env: &mut Environment) {
env.replace_line(|env, line| format!("{}{}", line, expr.to_value(&env)));
}
pub fn set(expr: &Expression, env: &mut Environment) {
env.replace_line(|env, _| expr.to_value(env))
}
#[cfg(feature = "bind")]
pub fn bind(id: &str, env: &mut Environment) {
env.bind_variable(id);
}
#[cfg(not(target_os = "windows"))]
fn shell(cmd: &str) -> Result<std::process::Child, std::io::Error> {
Command::new("sh")
.arg("-c")
.arg(cmd)
.stdout(Stdio::piped())
.spawn()
}
#[cfg(target_os = "windows")]
fn shell(cmd: &str) -> Result<std::process::Child, std::io::Error> {
Command::new("cmd")
.arg("/C")
.arg(cmd)
.stdout(Stdio::piped())
.spawn()
}