(&mut self, cmd: &str)
| 28 | } |
| 29 | |
| 30 | pub fn execute(&mut self, cmd: &str) -> String { |
| 31 | let cmd = cmd.to_string(); |
| 32 | let tx = self.tx.clone(); |
| 33 | self.history.push(TerminalEntry { |
| 34 | command: cmd.clone(), |
| 35 | output: "Running...".into(), |
| 36 | is_error: false, |
| 37 | }); |
| 38 | |
| 39 | tokio::spawn(async move { |
| 40 | let output = if cfg!(target_os = "windows") { |
| 41 | Command::new("cmd").args(["/C", &cmd]).output().await |
| 42 | } else { |
| 43 | Command::new("sh").args(["-c", &cmd]).output().await |
| 44 | }; |
| 45 | |
| 46 | let entry = match output { |
| 47 | Ok(out) => { |
| 48 | let stdout = String::from_utf8_lossy(&out.stdout).to_string(); |
| 49 | let stderr = String::from_utf8_lossy(&out.stderr).to_string(); |
| 50 | let is_error = !out.status.success(); |
| 51 | let result = if is_error && !stderr.is_empty() { |
| 52 | stderr |
| 53 | } else { |
| 54 | stdout |
| 55 | }; |
| 56 | TerminalEntry { |
| 57 | command: cmd, |
| 58 | output: result, |
| 59 | is_error, |
| 60 | } |
| 61 | } |
| 62 | Err(e) => TerminalEntry { |
| 63 | command: cmd, |
| 64 | output: format!("Execution error: {e}"), |
| 65 | is_error: true, |
| 66 | }, |
| 67 | }; |
| 68 | |
| 69 | let _ = tx.send(entry); |
| 70 | }); |
| 71 | |
| 72 | "Running...".into() |
| 73 | } |
| 74 | |
| 75 | pub fn poll_completed(&mut self) { |
| 76 | while let Ok(entry) = self.rx.try_recv() { |
no test coverage detected