//! The smallest slag consumer: one bundled component, one custom host //! function, no icons, no async effects. Demonstrates the wiring an app owns — //! build the host module, the runtime, a config, the components, the shell. use std::rc::Rc; use gpui::{px, size, AppContext, Bounds, WindowBounds, WindowOptions}; use slag_core::host::{self, with_ctx}; use slag_core::steel::rvals::SteelVal; use slag_core::steel::steel_vm::builtin::BuiltInModule; use slag_core::steel::steel_vm::register_fn::RegisterFn; use slag_core::{Bundled, PackLoader, ScriptRuntime}; use slag_gpui::{SchemeComponent, Shell, UiConfig}; /// The app's host module: the framework builtins plus one app function. fn host_module() -> BuiltInModule { let mut module = BuiltInModule::new("hello/host".to_string()); host::register_builtins(&mut module); module.register_fn("motd", || -> SteelVal { // Host functions capture nothing (Steel demands Send + Sync); they // reach their component through the thread-local registry. let clicks = with_ctx(|c| c.state.borrow().len()).unwrap_or(0); SteelVal::StringV(format!("state slots in play: {clicks}").as_str().into()) }); module } fn main() { gpui_platform::application().run(|cx: &mut gpui::App| { gpui_component::init(cx); let bounds = Bounds::centered(None, size(px(480.0), px(320.0)), cx); cx.open_window( WindowOptions { window_bounds: Some(WindowBounds::Windowed(bounds)), ..Default::default() }, |window, cx| { let runtime = Rc::new(ScriptRuntime::new( PackLoader::bundled_only(Bundled { components: &[("hello", include_str!("../packs/hello.scm"))], libs: &[], }), host_module(), &[], )); let config = Rc::new(UiConfig { env_prefix: "HELLO", icons: Rc::new(|_| None), video_frames: None, }); // No app context needed: `()` fills the type-erased slot. let hello = cx.new(|cx| { SchemeComponent::new(Rc::new(()), runtime.clone(), config, "hello", cx) }); let shell = cx.new(|cx| Shell::new(vec![("hello".into(), hello)], "hello", cx)); cx.new(|cx| gpui_component::Root::new(shell, window, cx)) }, ) .expect("failed to open window"); cx.activate(true); }); }