Skip to content

Instantly share code, notes, and snippets.

@davehorner
Created April 21, 2025 03:48
Show Gist options
  • Save davehorner/04a771086c1bd846d11d3b07245b4aa4 to your computer and use it in GitHub Desktop.
Save davehorner/04a771086c1bd846d11d3b07245b4aa4 to your computer and use it in GitHub Desktop.

Revisions

  1. davehorner created this gist Apr 21, 2025.
    119 changes: 119 additions & 0 deletions gistfile1.txt
    Original 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()
    }