From ff0411b0402fba7bd7c6bf4b9da6a87c1902da95 Mon Sep 17 00:00:00 2001 From: Condorra Date: Sat, 14 Sep 2024 21:51:37 +1000 Subject: [PATCH] Set up frameroutes to route MUD messages to termframes --- Cargo.lock | 2 +- Cargo.toml | 2 +- src/lua_engine.rs | 202 ++++++++++++++++--------- src/lua_engine/frameroutes.rs | 58 +++++++ src/lua_engine/frames.rs | 2 +- src/lua_engine/muds.rs | 275 ++++++++++++++++++++++++++++------ src/term_view.rs | 3 - 7 files changed, 421 insertions(+), 123 deletions(-) create mode 100644 src/lua_engine/frameroutes.rs diff --git a/Cargo.lock b/Cargo.lock index 66a3a88..16d442c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -747,7 +747,7 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "minicrossterm" version = "0.28.1" -source = "git+https://git.blastmud.org/blasthavers/minicrossterm.git?rev=494f89daef41162fbd89d5266e261018ed5ff6dc#494f89daef41162fbd89d5266e261018ed5ff6dc" +source = "git+https://git.blastmud.org/blasthavers/minicrossterm.git?rev=0c8c6d4f0cf445adf7bb957811081a1b710bd933#0c8c6d4f0cf445adf7bb957811081a1b710bd933" dependencies = [ "bitflags", ] diff --git a/Cargo.toml b/Cargo.toml index 1cfac65..35684d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,7 +15,7 @@ unicode-width = "0.1.13" wasm-bindgen = "0.2.92" web-sys = { version = "0.3.69", features = ["ResizeObserver", "DomRect", "CssStyleDeclaration"] } yew = { version = "0.21.0", features = ["csr"] } -minicrossterm = { git = "https://git.blastmud.org/blasthavers/minicrossterm.git", rev = "494f89daef41162fbd89d5266e261018ed5ff6dc" } +minicrossterm = { git = "https://git.blastmud.org/blasthavers/minicrossterm.git", rev = "0c8c6d4f0cf445adf7bb957811081a1b710bd933" } thiserror = "1.0.63" console_error_panic_hook = "0.1.7" anyhow = "1.0.86" diff --git a/src/lua_engine.rs b/src/lua_engine.rs index 628ad94..cfe314a 100644 --- a/src/lua_engine.rs +++ b/src/lua_engine.rs @@ -1,7 +1,8 @@ -use self::{frames::*, muds::*}; +use self::{frameroutes::*, frames::*, muds::*}; use anyhow::Error; use piccolo::{ - Callback, Closure, Context, Executor, ExternError, FromValue, Function, Lua, StashedExecutor, + async_callback::Locals, meta_ops::MetaResult, Callback, Closure, Context, Executor, + ExternError, FromValue, Function, Lua, MetaMethod, Stack, StashedExecutor, StashedFunction, Table, Value, Variadic, }; use yew::UseStateSetter; @@ -14,7 +15,8 @@ pub struct LuaState { pub exec: StashedExecutor, } -mod frames; +mod frameroutes; +pub mod frames; pub mod muds; impl LuaState { @@ -94,78 +96,119 @@ pub fn install_lua_globals( global_memo: &GlobalMemoCell, global_layout: UseStateSetter, ) -> Result<(), String> { - global_memo.lua_engine.borrow_mut().interp.try_enter(|ctx| { - let cmd_table = Table::new(&ctx); - macro_rules! register_command { - ($sym: ident) => { - cmd_table - .set( - ctx, - ctx.intern_static(stringify!($sym).as_bytes()), - $sym(ctx, &global_memo, &global_layout), - ) - .map_err(|_| Error::msg("Can't add command"))?; - }; - } + global_memo + .lua_engine + .borrow_mut() + .interp + .try_enter(|ctx| { + let cmd_table = Table::new(&ctx); + macro_rules! register_command { + ($sym: ident) => { + cmd_table + .set( + ctx, + ctx.intern_static(stringify!($sym).as_bytes()), + $sym(ctx, &global_memo, &global_layout), + ) + .map_err(|_| Error::msg("Can't add command"))?; + }; + } - register_command!(echo); - register_command!(echo_frame); - register_command!(echo_frame_raw); - register_command!(connect_mud); - register_command!(delete_mud); - register_command!(close_mud); - register_command!(sendmud_raw); - register_command!(hsplit); - register_command!(panel_merge); - register_command!(vsplit); - ctx.set_global("commands", cmd_table); - let info_table = Table::new(&ctx); - ctx.set_global("info", info_table); - let muds_table = Table::new(&ctx); - ctx.set_global("muds", muds_table); + register_command!(echo); + register_command!(echo_frame); + register_command!(echo_frame_raw); + register_command!(connect_mud); + register_command!(delete_mud); + register_command!(close_mud); + register_command!(sendmud_raw); + register_command!(hsplit); + register_command!(panel_merge); + register_command!(vsplit); + ctx.set_global("commands", cmd_table); + let info_table = Table::new(&ctx); + ctx.set_global("info", info_table); + let muds_table = Table::new(&ctx); + ctx.set_global("muds", muds_table); - let handlers_table = Table::new(&ctx); - ctx.set_global("handlers", handlers_table); - macro_rules! register_handler { - ($sym: ident) => { - handlers_table - .set( - ctx, - ctx.intern_static(stringify!($sym).as_bytes()), - $sym(ctx, &global_memo), - ) - .map_err(|_| Error::msg("Can't add handler"))?; - }; - } - register_handler!(mudoutput); - register_handler!(mudoutput_line); - register_handler!(mudoutput_prompt); - register_handler!(mudoutput_will); - register_handler!(mudoutput_wont); - register_handler!(mudoutput_do); - register_handler!(mudoutput_dont); - register_handler!(mudoutput_subnegotiation); + let handlers_table = Table::new(&ctx); + ctx.set_global("handlers", handlers_table); + macro_rules! register_handler { + ($sym: ident) => { + handlers_table + .set( + ctx, + ctx.intern_static(stringify!($sym).as_bytes()), + $sym(ctx, &global_memo), + ) + .map_err(|_| Error::msg("Can't add handler"))?; + }; + } + register_handler!(mudoutput); - macro_rules! register_nop_handler { - ($sym: ident) => { - handlers_table - .set( - ctx, - ctx.intern_static(stringify!($sym).as_bytes()), - lua_nop(ctx), - ) - .map_err(|_| Error::msg("Can't add handler"))?; - }; - } + let classes_table = Table::new(&ctx); + ctx.set_global("classes", classes_table); - register_nop_handler!(mudoutput_break); - register_nop_handler!(mudoutput_sync); - register_nop_handler!(mudoutput_interrupt); - register_nop_handler!(mudoutput_abort_output); - register_nop_handler!(mudoutput_areyouthere); + let mud_class_table = Table::new(&ctx); + classes_table.set(ctx, "mud", mud_class_table)?; + mud_class_table.set(ctx, MetaMethod::Index, mud_class_table)?; - Ok(()) - }); + macro_rules! register_class_function { + ($class_table: ident, $sym: ident) => { + $class_table + .set( + ctx, + ctx.intern_static(stringify!($sym).as_bytes()), + $sym(ctx, &global_memo), + ) + .map_err(|_| Error::msg("Can't add handler"))?; + }; + ($class_table: ident, $name: literal, $sym: ident) => { + $class_table + .set( + ctx, + ctx.intern_static($name.as_bytes()), + $sym(ctx, &global_memo), + ) + .map_err(|_| Error::msg("Can't add handler"))?; + }; + } + + register_class_function!(mud_class_table, mudoutput_line); + register_class_function!(mud_class_table, mudoutput_prompt); + register_class_function!(mud_class_table, mudoutput_will); + register_class_function!(mud_class_table, mudoutput_wont); + register_class_function!(mud_class_table, mudoutput_do); + register_class_function!(mud_class_table, mudoutput_dont); + register_class_function!(mud_class_table, mudoutput_subnegotiation); + register_class_function!(mud_class_table, "new", new_mud); + + macro_rules! register_class_nop { + ($class_table: ident, $sym: ident) => { + $class_table + .set( + ctx, + ctx.intern_static(stringify!($sym).as_bytes()), + lua_nop(ctx), + ) + .map_err(|_| Error::msg("Can't add handler"))?; + }; + } + + register_class_nop!(mud_class_table, mudoutput_break); + register_class_nop!(mud_class_table, mudoutput_sync); + register_class_nop!(mud_class_table, mudoutput_interrupt); + register_class_nop!(mud_class_table, mudoutput_abort_output); + register_class_nop!(mud_class_table, mudoutput_areyouthere); + + let frameroute_class_table = Table::new(&ctx); + classes_table.set(ctx, "frameroute", frameroute_class_table)?; + frameroute_class_table.set(ctx, MetaMethod::Index, frameroute_class_table)?; + register_class_function!(frameroute_class_table, "new", new_frameroute); + register_class_function!(frameroute_class_table, "route", frameroute_route); + + Ok(()) + }) + .map_err(|e| e.to_string())?; Ok(()) } @@ -175,3 +218,22 @@ pub fn lua_nop(ctx: Context<'_>) -> Callback<'_> { Ok(piccolo::CallbackReturn::Return) }) } + +// Borrowed from piccolo source. +pub fn prep_metaop_call<'gc, const N: usize>( + ctx: Context<'gc>, + mut stack: Stack<'gc, '_>, + locals: Locals<'gc, '_>, + res: MetaResult<'gc, N>, +) -> Option { + match res { + MetaResult::Value(v) => { + stack.push_back(v); + None + } + MetaResult::Call(call) => { + stack.extend(call.args); + Some(locals.stash(&ctx, call.function)) + } + } +} diff --git a/src/lua_engine/frameroutes.rs b/src/lua_engine/frameroutes.rs new file mode 100644 index 0000000..e95e5e6 --- /dev/null +++ b/src/lua_engine/frameroutes.rs @@ -0,0 +1,58 @@ +use piccolo::{Callback, CallbackReturn, Context, FromValue, Table}; + +use crate::{echo_to_term_frame, id_intern::intern_id, GlobalMemoCell, TermFrame}; + +use super::try_unwrap_frame; + +pub(super) fn new_frameroute<'gc>( + ctx: Context<'gc>, + _global_memo: &GlobalMemoCell, +) -> Callback<'gc> { + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let frameroute: Table = Table::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("classes.frameroute:new missing object!"))?, + )?; + let frame: TermFrame = try_unwrap_frame( + ctx, + &stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("classes.frameroute:new missing frame!"))?, + )?; + // We re-intern it to ensure we always point at the userdata. + let frame = intern_id(ctx, frame); + + frameroute.set(ctx, ctx.intern_static(b"frame"), frame)?; + + Ok(piccolo::CallbackReturn::Return) + }) +} + +pub(super) fn frameroute_route<'gc>( + ctx: Context<'gc>, + global_memo: &GlobalMemoCell, +) -> Callback<'gc> { + let global_memo = global_memo.clone(); + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let frameroute = Table::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("frameroute:route called without self!"))?, + )?; + let line = piccolo::String::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("frameroute:route called without line!"))?, + )?; + let frame: TermFrame = + try_unwrap_frame(ctx, &frameroute.get(ctx, ctx.intern_static(b"frame"))?)?; + + // We ignore errors with the term frame to avoid breaking the entire client for one closed frame. + echo_to_term_frame(&global_memo, &frame, &String::from_utf8_lossy(&line)).unwrap_or(()); + Ok(CallbackReturn::Return) + }) +} diff --git a/src/lua_engine/frames.rs b/src/lua_engine/frames.rs index c6f0558..3dc2758 100644 --- a/src/lua_engine/frames.rs +++ b/src/lua_engine/frames.rs @@ -151,7 +151,7 @@ pub fn panel_merge<'gc>( }) } -fn try_unwrap_frame<'gc>( +pub fn try_unwrap_frame<'gc>( ctx: Context<'gc>, value: &Value<'gc>, ) -> Result> { diff --git a/src/lua_engine/muds.rs b/src/lua_engine/muds.rs index a6058c8..f32908e 100644 --- a/src/lua_engine/muds.rs +++ b/src/lua_engine/muds.rs @@ -1,8 +1,8 @@ use anyhow::Error; use gc_arena::{Gc, Rootable}; use piccolo::{ - self, Callback, CallbackReturn, Context, FromValue, Function, IntoValue, StashedValue, Table, - UserData, Value, + self, async_sequence, meta_ops, Callback, CallbackReturn, Context, FromValue, Function, + IntoValue, MetaMethod, SequenceReturn, StashedValue, Table, UserData, Value, }; use wasm_bindgen::JsValue; use web_sys::console; @@ -16,7 +16,7 @@ use crate::{ GlobalLayoutCell, GlobalMemoCell, }; -use super::LuaState; +use super::{prep_metaop_call, LuaState}; fn try_unwrap_socketid<'gc>( ctx: Context<'gc>, @@ -163,10 +163,49 @@ pub(super) fn connect_mud<'gc>( muds.set(ctx, name, new_socket)?; + let mud_class: Table = ctx + .get_global::("classes")? + .get(ctx, ctx.intern_static(b"mud"))?; + let conntab = Table::new(&ctx); muds.set(ctx, new_socket, conntab)?; + conntab.set(ctx, ctx.intern_static(b"socket"), new_socket)?; + conntab.set(ctx, ctx.intern_static(b"buffer"), ctx.intern_static(b""))?; + let conntab_meta = Table::new(&ctx); + conntab_meta.set(ctx, MetaMethod::Index, mud_class)?; + conntab.set_metatable(&ctx, Some(conntab_meta)); - Ok(piccolo::CallbackReturn::Return) + let seq = async_sequence(&ctx, |locals, mut seq| { + let conntab = locals.stash(&ctx, conntab); + async move { + let call = seq.try_enter(|ctx, locals, _execution, mut stack| { + let conntab = locals.fetch(&conntab); + stack.consume(ctx)?; + Ok(prep_metaop_call( + ctx, + stack, + locals, + meta_ops::index( + ctx, + conntab.into_value(ctx), + ctx.intern_static(b"new").into_value(ctx), + )?, + )) + })?; + if let Some(call) = call { + seq.call(&call, 0).await?; + } + let new_fn = seq.try_enter(|ctx, locals, _execution, mut stack| { + let new_fn: Function = stack.consume(ctx)?; + stack.push_back(locals.fetch(&conntab).into_value(ctx)); + Ok(locals.stash(&ctx, new_fn)) + })?; + seq.call(&new_fn, 0).await?; + Ok(SequenceReturn::Return) + } + }); + + Ok(piccolo::CallbackReturn::Sequence(seq)) }) } @@ -257,16 +296,59 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) - .as_bytes(); let mut cur_buf: Vec = [buf, output].concat(); - let handlers = Table::from_value(ctx, ctx.get_global("handlers")?)?; - - let mut fns: Vec<(&'static [u8], Vec)> = vec![]; + let mut fns: Vec<(&'static [u8], Vec)> = vec![]; loop { match parse_telnet_buf(&cur_buf) { (new_buf, None) => { conntab.set(ctx, ctx.intern_static(b"buffer"), ctx.intern(&new_buf))?; - let seq = piccolo::async_sequence(&ctx, |locals, seq| async { - Ok(piccolo::SequenceReturn::Return) + let seq = piccolo::async_sequence(&ctx, |locals, mut seq| { + let conntab = locals.stash(&ctx, conntab); + let fns: Vec<(&'static [u8], Vec)> = fns + .into_iter() + .map(|fnv| { + ( + fnv.0, + fnv.1.into_iter().map(|v| locals.stash(&ctx, v)).collect(), + ) + }) + .collect(); + async move { + for (func_name, params) in fns { + let call = + seq.try_enter(|ctx, locals, _execution, mut stack| { + let conntab = locals.fetch(&conntab); + stack.consume(ctx)?; + Ok(prep_metaop_call( + ctx, + stack, + locals, + meta_ops::index( + ctx, + conntab.into_value(ctx), + ctx.intern_static(func_name).into_value(ctx), + )?, + )) + })?; + if let Some(call) = call { + seq.call(&call, 0).await?; + } + let call = seq.try_enter(|ctx, locals, _, mut stack| { + let value = stack.pop_back().ok_or_else(|| { + anyhow::Error::msg("Index didn't return value") + })?; + stack.consume(ctx)?; + stack.push_back(locals.fetch(&conntab).into_value(ctx)); + for param in ¶ms { + stack.push_back(locals.fetch(param)); + } + + Ok(locals.stash(&ctx, Function::from_value(ctx, value)?)) + })?; + seq.call(&call, 0).await?; + } + Ok(piccolo::SequenceReturn::Return) + } }); return Ok(piccolo::CallbackReturn::Sequence(seq)); @@ -274,47 +356,32 @@ pub(super) fn mudoutput<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) - (new_buf, Some(cmd)) => { cur_buf = new_buf; match cmd { - TelnetOutput::Line(l) => fns.push(( - b"mudoutput_line", - vec![ctx.stash(mud), ctx.stash(ctx.intern(&l).into_value(ctx))], - )), - TelnetOutput::Prompt(p) => fns.push(( - b"mudoutput_prompt", - vec![ctx.stash(mud), ctx.stash(ctx.intern(&p).into_value(ctx))], - )), + TelnetOutput::Line(l) => { + fns.push((b"mudoutput_line", vec![ctx.intern(&l).into_value(ctx)])) + } + TelnetOutput::Prompt(p) => { + fns.push((b"mudoutput_prompt", vec![ctx.intern(&p).into_value(ctx)])) + } TelnetOutput::Nop => {} - TelnetOutput::Break => fns.push((b"mudoutput_break", vec![ctx.stash(mud)])), - TelnetOutput::Sync => fns.push((b"mudoutput_sync", vec![ctx.stash(mud)])), - TelnetOutput::Interrupt => { - fns.push((b"mudoutput_interrupt", vec![ctx.stash(mud)])) - } + TelnetOutput::Break => fns.push((b"mudoutput_break", vec![])), + TelnetOutput::Sync => fns.push((b"mudoutput_sync", vec![])), + TelnetOutput::Interrupt => fns.push((b"mudoutput_interrupt", vec![])), - TelnetOutput::AbortOutput => { - fns.push((b"mudoutput_abort_output", vec![ctx.stash(mud)])) + TelnetOutput::AbortOutput => fns.push((b"mudoutput_abort_output", vec![])), + TelnetOutput::AreYouThere => fns.push((b"mudoutput_areyouthere", vec![])), + TelnetOutput::Will(v) => { + fns.push((b"mudoutput_will", vec![v.into_value(ctx)])) } - TelnetOutput::AreYouThere => { - fns.push((b"mudoutput_areyouthere", vec![ctx.stash(mud)])) + TelnetOutput::Wont(v) => { + fns.push((b"mudoutput_wont", vec![v.into_value(ctx)])) + } + TelnetOutput::Do(v) => fns.push((b"mudoutput_do", vec![v.into_value(ctx)])), + TelnetOutput::Dont(v) => { + fns.push((b"mudoutput_dont", vec![v.into_value(ctx)])) + } + TelnetOutput::Subnegotiation(t) => { + fns.push((b"mudoutput_subnegotiation", vec![t.into_value(ctx)])) } - TelnetOutput::Will(v) => fns.push(( - b"mudoutput_will", - vec![ctx.stash(mud), ctx.stash(v.into_value(ctx))], - )), - TelnetOutput::Wont(v) => fns.push(( - b"mudoutput_wont", - vec![ctx.stash(mud), ctx.stash(v.into_value(ctx))], - )), - TelnetOutput::Do(v) => fns.push(( - b"mudoutput_do", - vec![ctx.stash(mud), ctx.stash(v.into_value(ctx))], - )), - TelnetOutput::Dont(v) => fns.push(( - b"mudoutput_dont", - vec![ctx.stash(mud), ctx.stash(v.into_value(ctx))], - )), - TelnetOutput::Subnegotiation(t) => fns.push(( - b"mudoutput_subnegotiation", - vec![ctx.stash(mud), ctx.stash(t.into_value(ctx))], - )), } } } @@ -326,7 +393,61 @@ pub(super) fn mudoutput_line<'gc>( ctx: Context<'gc>, _global_memo: &GlobalMemoCell, ) -> Callback<'gc> { - Callback::from_fn(&ctx, move |_ctx, _ex, _stack| Ok(CallbackReturn::Return)) + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let mud = Table::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("Missing muds:mudoutput_line self"))?, + )?; + let line = piccolo::String::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("Missing muds:mudoutput_line line"))?, + )?; + + let frameroutes: Table = mud.get(ctx, "frameroutes")?; + + let seq = async_sequence(&ctx, |locals, mut seq| { + let frameroutes: Vec = frameroutes + .iter() + .map(|fr| locals.stash(&ctx, fr.1)) + .collect(); + let line = locals.stash(&ctx, line); + async move { + for frameroute in frameroutes { + let call = seq.try_enter(|ctx, locals, _execution, mut stack| { + let frameroute = locals.fetch(&frameroute); + stack.consume(ctx)?; + Ok(prep_metaop_call( + ctx, + stack, + locals, + meta_ops::index( + ctx, + frameroute.into_value(ctx), + ctx.intern_static(b"route").into_value(ctx), + )?, + )) + })?; + if let Some(call) = call { + seq.call(&call, 0).await?; + } + let route_fn = seq.try_enter(|ctx, locals, _execution, mut stack| { + let route_fn: Function = stack.consume(ctx)?; + stack.push_back(locals.fetch(&frameroute).into_value(ctx)); + stack.push_back(locals.fetch(&line).into_value(ctx)); + Ok(locals.stash(&ctx, route_fn)) + })?; + seq.call(&route_fn, 0).await?; + } + Ok(SequenceReturn::Return) + } + }); + + Ok(CallbackReturn::Sequence(seq)) + }) } pub(super) fn mudoutput_prompt<'gc>( ctx: Context<'gc>, @@ -361,3 +482,63 @@ pub(super) fn mudoutput_subnegotiation<'gc>( ) -> Callback<'gc> { Callback::from_fn(&ctx, move |_ctx, _ex, _stack| Ok(CallbackReturn::Return)) } + +pub(super) fn new_mud<'gc>(ctx: Context<'gc>, _global_memo: &GlobalMemoCell) -> Callback<'gc> { + Callback::from_fn(&ctx, move |ctx, _ex, mut stack| { + let mud: Table = Table::from_value( + ctx, + stack + .pop_front() + .ok_or_else(|| anyhow::Error::msg("classes.mud:new missing object!"))?, + )?; + let frameroutes: Table = Table::new(&ctx); + let frameroute: Table = Table::new(&ctx); + frameroutes.set(ctx, 0, frameroute)?; + frameroute.set_metatable( + &ctx, + Some( + ctx.get_global::
("classes")? + .get(ctx, ctx.intern_static(b"frameroute"))?, + ), + ); + mud.set(ctx, ctx.intern_static(b"frameroutes"), frameroutes)?; + + // And call new on the frameroute, for the current frame. + let seq = async_sequence(&ctx, |locals, mut seq| { + let frameroute = locals.stash(&ctx, frameroute); + async move { + let call = seq.try_enter(|ctx, locals, _execution, mut stack| { + let frameroute = locals.fetch(&frameroute); + stack.consume(ctx)?; + Ok(prep_metaop_call( + ctx, + stack, + locals, + meta_ops::index( + ctx, + frameroute.into_value(ctx), + ctx.intern_static(b"new").into_value(ctx), + )?, + )) + })?; + if let Some(call) = call { + seq.call(&call, 0).await?; + } + let new_fn = seq.try_enter(|ctx, locals, _execution, mut stack| { + let new_fn: Function = stack.consume(ctx)?; + stack.push_back(locals.fetch(&frameroute).into_value(ctx)); + stack.push_back( + ctx.get_global::
("info")? + .get(ctx, ctx.intern_static(b"current_frame"))?, + ); + Ok(locals.stash(&ctx, new_fn)) + })?; + seq.call(&new_fn, 0).await?; + + Ok(SequenceReturn::Return) + } + }); + + Ok(piccolo::CallbackReturn::Sequence(seq)) + }) +} diff --git a/src/term_view.rs b/src/term_view.rs index 1a0c885..1dfb183 100644 --- a/src/term_view.rs +++ b/src/term_view.rs @@ -120,9 +120,6 @@ fn get_or_make_term_frame<'a>( term.open(&element); term.loadAddon(&fit); fit.fit(); - for i in 0..100 { - term.write(&format!("{} Hello world\r\n", i)); - } let term_for_readline: Terminal = Terminal { obj: term.clone() }; let initial_size = (term.cols(), term.rows()); let mut new_data: TermFrameData = TermFrameData {