use anyhow::{anyhow, Result};
use easy_error::Error as BundError;
use rust_dynamic::types::STRING;
use rust_multistackvm::multistackvm::VM;
use std::cell::RefCell;
thread_local! {
static PRINT_BUFFER: RefCell<String> = const { RefCell::new(String::new()) };
}
pub fn register(vm: &mut VM) -> Result<()> {
vm.register_inline("print".to_string(), ink_print)
.map_err(|e| anyhow!("register print: {e}"))?;
vm.register_inline("println".to_string(), ink_println)
.map_err(|e| anyhow!("register println: {e}"))?;
Ok(())
}
pub fn drain_print_buffer() -> String {
PRINT_BUFFER.with(|b| std::mem::take(&mut *b.borrow_mut()))
}
fn ink_print(vm: &mut VM) -> std::result::Result<&mut VM, BundError> {
capture(vm, false)
}
fn ink_println(vm: &mut VM) -> std::result::Result<&mut VM, BundError> {
capture(vm, true)
}
fn capture(vm: &mut VM, newline: bool) -> std::result::Result<&mut VM, BundError> {
let value = match vm.stack.pull() {
Some(v) => v,
None => {
return Err(easy_error::err_msg(
"PRINT returns: NO DATA",
));
}
};
let str_value = value
.conv(STRING)
.map_err(|e| easy_error::err_msg(format!("PRINT conv: {e}")))?;
let text = str_value
.cast_string()
.map_err(|e| easy_error::err_msg(format!("PRINT cast: {e}")))?;
let routed_to_pane = crate::scripting::with_active_app(|app| {
app.append_to_bund_pane(&text, newline)
})
.unwrap_or(false);
if !routed_to_pane {
PRINT_BUFFER.with(|b| {
let mut g = b.borrow_mut();
g.push_str(&text);
if newline {
g.push('\n');
}
});
}
Ok(vm)
}