tauri_plugin_shell/
lib.rs1#![doc(
10 html_logo_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png",
11 html_favicon_url = "https://github.com/tauri-apps/tauri/raw/dev/app-icon.png"
12)]
13
14use std::{
15 collections::HashMap,
16 ffi::OsStr,
17 path::Path,
18 sync::{Arc, Mutex},
19};
20
21use process::{Command, CommandChild};
22use tauri::{
23 AppHandle, Manager, RunEvent, Runtime,
24 plugin::{Builder, TauriPlugin},
25};
26
27mod commands;
28mod error;
29pub mod process;
30mod scope;
31mod scope_entry;
32
33pub use error::Error;
34type Result<T> = std::result::Result<T, Error>;
35
36type ChildStore = Arc<Mutex<HashMap<u32, CommandChild>>>;
37
38pub struct Shell<R: Runtime> {
42 #[allow(dead_code)]
43 app: AppHandle<R>,
44 children: ChildStore,
45}
46
47impl<R: Runtime> Shell<R> {
48 pub fn command(&self, program: impl AsRef<OsStr>) -> Command {
50 Command::new(program)
51 }
52
53 pub fn sidecar(&self, program: impl AsRef<Path>) -> Result<Command> {
58 Command::new_sidecar(program)
59 }
60}
61
62pub trait ShellExt<R: Runtime> {
65 fn shell(&self) -> &Shell<R>;
78}
79
80impl<R: Runtime, T: Manager<R>> ShellExt<R> for T {
81 fn shell(&self) -> &Shell<R> {
82 self.state::<Shell<R>>().inner()
83 }
84}
85
86pub fn init<R: Runtime>() -> TauriPlugin<R> {
87 Builder::new("shell")
88 .initialization_script(include_str!("init-iife.js").to_string())
89 .invoke_handler(tauri::generate_handler![
90 commands::execute,
91 commands::spawn,
92 commands::stdin_write,
93 commands::kill,
94 ])
95 .setup(|app, _api| {
96 app.manage(Shell {
97 app: app.clone(),
98 children: Default::default(),
99 });
100 Ok(())
101 })
102 .on_event(|app, event| {
103 if let RunEvent::Exit = event {
104 let shell = app.state::<Shell<R>>();
105 let children = {
106 let mut lock = shell.children.lock().unwrap();
107 std::mem::take(&mut *lock)
108 };
109 for child in children.into_values() {
110 let _ = child.kill();
111 }
112 }
113 })
114 .build()
115}