use crate::scheme::SchemeEngine;
use anyhow::{Context, Result};
use steel::rvals::Custom;
#[derive(Debug, Clone)]
pub struct Sosofo {
text: String,
output_file: Option<String>,
}
impl Sosofo {
pub fn new(text: String) -> Self {
Sosofo {
text,
output_file: None,
}
}
pub fn with_file(text: String, filename: String) -> Self {
Sosofo {
text,
output_file: Some(filename),
}
}
pub fn empty() -> Self {
Sosofo {
text: String::new(),
output_file: None,
}
}
pub fn text(&self) -> &str {
&self.text
}
pub fn output_file(&self) -> Option<&str> {
self.output_file.as_deref()
}
pub fn append(&self, other: &Sosofo) -> Sosofo {
Sosofo {
text: format!("{}{}", self.text, other.text),
output_file: self.output_file.clone().or_else(|| other.output_file.clone()),
}
}
pub fn write_to_file(&self) -> Result<()> {
if let Some(filename) = &self.output_file {
use std::fs;
use std::path::Path;
if let Some(parent) = Path::new(filename).parent() {
fs::create_dir_all(parent)
.with_context(|| format!("Failed to create directory: {}", parent.display()))?;
}
fs::write(filename, &self.text)
.with_context(|| format!("Failed to write file: {}", filename))?;
Ok(())
} else {
Ok(()) }
}
}
impl Custom for Sosofo {}
pub fn register_processing_primitives(engine: &mut SchemeEngine) -> Result<()> {
engine.register_fn("literal", processing_literal);
engine.register_fn("empty-sosofo", processing_empty_sosofo);
engine.register_fn("sosofo-append-two", processing_sosofo_append_two);
engine.register_fn("make-entity", processing_make_entity);
engine.register_fn("make-formatting-instruction", processing_make_formatting_instruction);
engine.register_fn("write-sosofo", processing_write_sosofo);
Ok(())
}
fn processing_literal(text: String) -> Sosofo {
Sosofo::new(text)
}
fn processing_empty_sosofo() -> Sosofo {
Sosofo::empty()
}
fn processing_sosofo_append_two(s1: &Sosofo, s2: &Sosofo) -> Sosofo {
s1.append(s2)
}
fn processing_make_entity(system_id: String, content: &Sosofo) -> Sosofo {
Sosofo::with_file(content.text().to_string(), system_id)
}
fn processing_make_formatting_instruction(data: String) -> Sosofo {
Sosofo::new(data)
}
fn processing_write_sosofo(sosofo: &Sosofo) -> Result<bool, String> {
sosofo
.write_to_file()
.map(|_| true)
.map_err(|e| format!("Failed to write sosofo: {}", e))
}