Created
April 21, 2025 03:48
-
-
Save davehorner/04a771086c1bd846d11d3b07245b4aa4 to your computer and use it in GitHub Desktop.
Revisions
-
davehorner created this gist
Apr 21, 2025 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,119 @@ #!/usr/bin/env rust-script //! ```cargo //! [dependencies] //! cargo-e = { version = "*", features = ["uses_plugins","uses_rhai"] } //! makepad-widgets = "0.6.0" //! num_cpus = "1.16" //! clap = { version = "4.5", features = ["derive"] } //! ``` //! //! A Makepad GUI listing all Cargo-e targets via ExtContext with Run buttons. use clap::Parser; use std::sync::{Arc, Mutex}; use std::thread; use cargo_e::Cli; use cargo_e::ext::ExtContext; use cargo_e::e_processmanager::ProcessManager; use cargo_e::e_target::{CargoTarget, TargetKind}; use makepad_widgets::*; use makepad_widgets::app_main; live_design! { import makepad_widgets::base::*; import makepad_widgets::theme_desktop_dark::*; TargetRow = <View> { height: Fit, flow: Right, spacing: 8., label = <Label> { text: "" }, button = <Button> { text: "▶ Run" } } App = {{App}} { ui: <Window> { show_bg: true, width: Fill, height: Fill, body = <View> { flow: Down, spacing: 10., padding: 10., list = <FlatList> {}, status = <Label> { text: "" } } } } } app_main!(App); #[derive(Live)] pub struct App { #[live] ui: WidgetRef, #[rust] cli: Option<Cli>, #[rust] pm: Option<Arc<ProcessManager>>, #[rust] targets: Arc<Mutex<Vec<CargoTarget>>>, #[rust] status: Arc<Mutex<String>>, } impl LiveHook for App { fn before_live_design(cx: &mut Cx) { makepad_widgets::live_design(cx); } } impl AppMain for App { fn handle_event(&mut self, cx: &mut Cx, event: &Event) { if let Event::Draw(ev) = event { if self.cli.is_none() { // -- Step 1: parse CLI let cli = Cli::parse(); println!("[debug] Parsed CLI: {:?}", cli); // -- Step 2: create ProcessManager let pm = ProcessManager::new(&cli); println!("[debug] Created ProcessManager"); // -- Step 3: collect targets via ExtContext let ctx = ExtContext::new(cli.clone(), pm.clone()).unwrap(); let mut ts = ctx.collect_targets().unwrap(); println!("[debug] Collected {} targets", ts.len()); for t in &ts { println!("[debug] target: {} ({:?})", t.display_name, t.kind); } println!("[debug] {} runnable targets", ts.len()); // store in state self.targets = Arc::new(Mutex::new(ts)); self.cli = Some(cli); self.pm = Some(pm); } let fl = self.ui.flat_list(id!(list)); let actions = self.ui.handle_widget_event(cx, event); let guard = self.targets.lock().unwrap(); for (i, tgt) in guard.iter().enumerate() { println!("[debug] Drawing row {} => {}", i, tgt.display_name); let entry = LiveId(i as u64); let tpl = id!(TargetRow)[0]; if let Some(row) = fl.item(cx, entry, tpl) { row.label(id!(label)).set_text_and_redraw(cx, &tgt.display_name); if row.button(id!(button)).clicked(&actions) { println!("[debug] Run button clicked on {}", tgt.display_name); let sr = self.status.clone(); { *sr.lock().unwrap() = format!("Running {}", tgt.display_name); } if let (Some(cli), Some(pm)) = (self.cli.clone(), self.pm.clone()) { let tclone = tgt.clone(); let run_ref = sr.clone(); thread::spawn(move || { let ctx = ExtContext::new(cli, pm).unwrap(); let res = ctx.run_target(&tclone); *run_ref.lock().unwrap() = match res { Ok(Some(code)) => format!("Exited with {}", code), Ok(None) => format!("Done {}", tclone.display_name), Err(e) => format!("Error {}: {}", tclone.display_name, e), }; }); } } } } self.ui.draw_widget_all(&mut Cx2d::new(cx, ev)); return; } self.ui.handle_widget_event(cx, event); } } fn main(){ app_main() }