mailang-stdlib 0.5.0

Standard library for MaìLang
Documentation
//! I/O built-in functions

use super::value_to_string;
use mailang_bytecode::Value;
use std::io::{self, Write};

#[cfg(feature = "capture-output")]
use super::capture;

pub fn builtin_println(args: &[Value]) -> Result<Value, String> {
    let parts: Vec<String> = args.iter().map(value_to_string).collect();
    let line = parts.join(" ");

    #[cfg(feature = "capture-output")]
    {
        if capture::is_captured() {
            capture::push_line(line);
            return Ok(Value::Null);
        }
    }

    println!("{}", line);
    Ok(Value::Null)
}

pub fn builtin_print(args: &[Value]) -> Result<Value, String> {
    let parts: Vec<String> = args.iter().map(value_to_string).collect();
    let text = parts.join(" ");

    #[cfg(feature = "capture-output")]
    {
        if capture::is_captured() {
            capture::push_text(text);
            return Ok(Value::Null);
        }
    }

    print!("{}", text);
    io::stdout().flush().map_err(|e| e.to_string())?;
    Ok(Value::Null)
}

pub fn builtin_input(args: &[Value]) -> Result<Value, String> {
    if !args.is_empty() {
        print!("{}", value_to_string(&args[0]));
        io::stdout().flush().map_err(|e| e.to_string())?;
    }
    let mut input = String::new();
    io::stdin()
        .read_line(&mut input)
        .map_err(|e| e.to_string())?;
    Ok(Value::Str(input.trim_end().into()))
}

/// `read_file(path)` → str contents (host filesystem).
pub fn builtin_read_file(args: &[Value]) -> Result<Value, String> {
    let path = match args.first() {
        Some(Value::Str(p)) => p.to_string(),
        _ => return Err("read_file(path): path must be a string".into()),
    };
    let data = std::fs::read_to_string(&path).map_err(|e| format!("read_file: {e}"))?;
    Ok(Value::Str(data.into()))
}

/// `write_file(path, contents)` → null.
pub fn builtin_write_file(args: &[Value]) -> Result<Value, String> {
    let path = match args.first() {
        Some(Value::Str(p)) => p.to_string(),
        _ => return Err("write_file(path, contents): path must be a string".into()),
    };
    let data = match args.get(1) {
        Some(v) => value_to_string(v),
        None => String::new(),
    };
    std::fs::write(&path, data).map_err(|e| format!("write_file: {e}"))?;
    Ok(Value::Null)
}