From 44cef22183a33f3769757b8d8deadf4619d41fd1 Mon Sep 17 00:00:00 2001 From: Byson94 Date: Sat, 23 Aug 2025 08:54:42 +0530 Subject: [PATCH] feat: reduced max_width to 100 and ran cargo fmt --- crates/ewwii/src/app.rs | 161 ++++--- crates/ewwii/src/application_lifecycle.rs | 3 +- crates/ewwii/src/client.rs | 13 +- crates/ewwii/src/config/ewwii_config.rs | 12 +- crates/ewwii/src/config/scss.rs | 11 +- crates/ewwii/src/daemon_response.rs | 13 +- crates/ewwii/src/display_backend.rs | 62 ++- crates/ewwii/src/dynval.rs | 32 +- crates/ewwii/src/error_handling_ctx.rs | 15 +- crates/ewwii/src/file_database.rs | 37 +- crates/ewwii/src/ipc_server.rs | 23 +- crates/ewwii/src/main.rs | 70 ++- crates/ewwii/src/opts.rs | 54 ++- crates/ewwii/src/paths.rs | 7 +- crates/ewwii/src/server.rs | 93 ++-- crates/ewwii/src/util.rs | 4 +- crates/ewwii/src/widgets/build_widget.rs | 46 +- .../ewwii/src/widgets/circular_progressbar.rs | 61 ++- crates/ewwii/src/widgets/graph.rs | 36 +- crates/ewwii/src/widgets/transform.rs | 28 +- .../ewwii/src/widgets/widget_definitions.rs | 413 +++++++++++++----- .../src/widgets/widget_definitions_helper.rs | 24 +- .../src/window/backend_window_options.rs | 24 +- crates/ewwii/src/window/coords.rs | 15 +- crates/ewwii/src/window/window_definition.rs | 11 +- crates/ewwii/src/window/window_geometry.rs | 10 +- crates/ewwii/src/window_arguments.rs | 5 +- crates/ewwii/src/window_initiator.rs | 28 +- .../ewwii_shared_util/src/general_helper.rs | 43 +- crates/ewwii_shared_util/src/locale.rs | 7 +- crates/ewwii_shared_util/src/wrappers.rs | 30 +- crates/iirhai/src/builtins.rs | 20 +- crates/iirhai/src/error.rs | 155 ++++--- crates/iirhai/src/helper.rs | 10 +- crates/iirhai/src/module_resolver.rs | 21 +- crates/iirhai/src/parser.rs | 10 +- crates/iirhai/src/providers/apilib/wifi.rs | 29 +- crates/iirhai/src/providers/stdlib/env.rs | 4 +- crates/iirhai/src/providers/stdlib/json.rs | 4 +- crates/iirhai/src/providers/stdlib/mod.rs | 4 +- crates/iirhai/src/providers/stdlib/monitor.rs | 6 +- crates/iirhai/src/providers/stdlib/text.rs | 10 +- crates/iirhai/src/updates/listen.rs | 7 +- crates/iirhai/src/updates/mod.rs | 8 +- crates/iirhai/src/updates/poll.rs | 7 +- crates/iirhai/src/widgetnode.rs | 8 +- crates/notifier_host/src/host.rs | 21 +- crates/notifier_host/src/icon.rs | 12 +- crates/notifier_host/src/item.rs | 46 +- crates/notifier_host/src/watcher.rs | 30 +- rustfmt.toml | 2 +- 51 files changed, 1345 insertions(+), 460 deletions(-) diff --git a/crates/ewwii/src/app.rs b/crates/ewwii/src/app.rs index ba5609a..28d992a 100644 --- a/crates/ewwii/src/app.rs +++ b/crates/ewwii/src/app.rs @@ -3,11 +3,16 @@ use crate::{ daemon_response::DaemonResponseSender, display_backend::DisplayBackend, error_handling_ctx, - gtk::prelude::{ContainerExt, CssProviderExt, GtkWindowExt, MonitorExt, StyleContextExt, WidgetExt}, + gtk::prelude::{ + ContainerExt, CssProviderExt, GtkWindowExt, MonitorExt, StyleContextExt, WidgetExt, + }, paths::EwwPaths, widgets::window::Window, // dynval::DynVal, - widgets::{build_widget::build_gtk_widget, build_widget::WidgetInput, widget_definitions::WidgetRegistry}, + widgets::{ + build_widget::build_gtk_widget, build_widget::WidgetInput, + widget_definitions::WidgetRegistry, + }, window::{ coords::Coords, monitor::MonitorIdentifier, @@ -139,8 +144,8 @@ async fn wait_for_monitor_model() { let display = gdk::Display::default().expect("could not get default display"); let start = std::time::Instant::now(); loop { - let all_monitors_set = - (0..display.n_monitors()).all(|i| display.monitor(i).and_then(|monitor| monitor.model()).is_some()); + let all_monitors_set = (0..display.n_monitors()) + .all(|i| display.monitor(i).and_then(|monitor| monitor.model()).is_some()); if all_monitors_set { break; } @@ -241,13 +246,24 @@ impl App { let result = if should_toggle && is_open { self.close_window(&instance_id, false) } else { - self.open_window(&WindowArguments { instance_id, window_name, pos, size, monitor, anchor, duration }) + self.open_window(&WindowArguments { + instance_id, + window_name, + pos, + size, + monitor, + anchor, + duration, + }) }; sender.respond_with_result(result)?; } DaemonCommand::CloseWindows { windows, auto_reopen, sender } => { - let errors = windows.iter().map(|window| self.close_window(window, auto_reopen)).filter_map(Result::err); + let errors = windows + .iter() + .map(|window| self.close_window(window, auto_reopen)) + .filter_map(Result::err); // Ignore sending errors, as the channel might already be closed let _ = sender.respond_with_error_list(errors); } @@ -256,7 +272,11 @@ impl App { sender.send_success(output)? } DaemonCommand::ListActiveWindows(sender) => { - let output = self.open_windows.iter().map(|(id, window)| format!("{id}: {}", window.name)).join("\n"); + let output = self + .open_windows + .iter() + .map(|(id, window)| format!("{id}: {}", window.name)) + .join("\n"); sender.send_success(output)? } DaemonCommand::PrintDebug(sender) => { @@ -282,10 +302,9 @@ impl App { if let Some(old_abort_send) = self.window_close_timer_abort_senders.remove(instance_id) { _ = old_abort_send.send(()); } - let ewwii_window = self - .open_windows - .remove(instance_id) - .with_context(|| format!("Tried to close window with id '{instance_id}', but no such window was open"))?; + let ewwii_window = self.open_windows.remove(instance_id).with_context(|| { + format!("Tried to close window with id '{instance_id}', but no such window was open") + })?; // let scope_index = ewwii_window.scope_index; ewwii_window.close(); @@ -324,7 +343,10 @@ impl App { let window_name: &str = &window_args.window_name; let window_def = self.ewwii_config.get_window(window_name)?.clone(); - assert_eq!(window_def.name, window_name, "window definition name did not equal the called window"); + assert_eq!( + window_def.name, window_name, + "window definition name did not equal the called window" + ); let initiator = WindowInitiator::new(&window_def, window_args)?; @@ -332,7 +354,8 @@ impl App { // It is critical for supporting dynamic updates let mut widget_reg_store = WidgetRegistry::new(Some(&window_def.root_widget)); - let root_widget = build_gtk_widget(WidgetInput::Window(window_def), &mut widget_reg_store)?; + let root_widget = + build_gtk_widget(WidgetInput::Window(window_def), &mut widget_reg_store)?; root_widget.style_context().add_class(window_name); @@ -344,14 +367,16 @@ impl App { let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::(); let config_path = self.paths.get_rhai_path(); let compiled_ast = self.ewwii_config.get_owned_compiled_ast(); - let store = iirhai::updates::handle_state_changes(self.ewwii_config.get_root_node()?, tx); + let store = + iirhai::updates::handle_state_changes(self.ewwii_config.get_root_node()?, tx); glib::MainContext::default().spawn_local(async move { while let Some(var_name) = rx.recv().await { log::debug!("Received update for var: {}", var_name); let vars = store.read().unwrap().clone(); - match generate_new_widgetnode(&vars, &config_path, compiled_ast.as_ref()).await { + match generate_new_widgetnode(&vars, &config_path, compiled_ast.as_ref()).await + { Ok(new_widget) => { let _ = widget_reg_store.update_widget_tree(new_widget); } @@ -375,8 +400,11 @@ impl App { // becomes available again move |auto_reopen| { let (response_sender, _) = daemon_response::create_pair(); - let command = - DaemonCommand::CloseWindows { windows: vec![instance_id.clone()], auto_reopen, sender: response_sender }; + let command = DaemonCommand::CloseWindows { + windows: vec![instance_id.clone()], + auto_reopen, + sender: response_sender, + }; if let Err(err) = app_evt_sender.send(command) { log::error!("Error sending close window command: {}", err); } @@ -386,26 +414,28 @@ impl App { let closed_by_user = Rc::new(Cell::new(false)); // handling users close request - ewwii_window.delete_event_handler_id = Some(ewwii_window.gtk_window.connect_delete_event({ - let handler = gtk_close_handler.clone(); - let closed_by_user = closed_by_user.clone(); - move |_, _| { - handler(false); // -- false: don't reopen window to respect users intent - closed_by_user.set(true); - glib::Propagation::Proceed - } - })); + ewwii_window.delete_event_handler_id = + Some(ewwii_window.gtk_window.connect_delete_event({ + let handler = gtk_close_handler.clone(); + let closed_by_user = closed_by_user.clone(); + move |_, _| { + handler(false); // -- false: don't reopen window to respect users intent + closed_by_user.set(true); + glib::Propagation::Proceed + } + })); // handling destory request - ewwii_window.destroy_event_handler_id = Some(ewwii_window.gtk_window.connect_destroy({ - let handler = gtk_close_handler.clone(); - let closed_by_user = closed_by_user.clone(); - move |_| { - if !closed_by_user.get() { - handler(true); + ewwii_window.destroy_event_handler_id = + Some(ewwii_window.gtk_window.connect_destroy({ + let handler = gtk_close_handler.clone(); + let closed_by_user = closed_by_user.clone(); + move |_| { + if !closed_by_user.get() { + handler(true); + } } - } - })); + })); let duration = window_args.duration; if let Some(duration) = duration { @@ -430,7 +460,10 @@ impl App { } }); - if let Some(old_abort_send) = self.window_close_timer_abort_senders.insert(instance_id.to_string(), abort_send) { + if let Some(old_abort_send) = self + .window_close_timer_abort_senders + .insert(instance_id.to_string(), abort_send) + { _ = old_abort_send.send(()); } } @@ -454,8 +487,13 @@ impl App { self.ewwii_config = config; - let open_window_ids: Vec = - self.open_windows.keys().cloned().chain(self.failed_windows.iter().cloned()).dedup().collect(); + let open_window_ids: Vec = self + .open_windows + .keys() + .cloned() + .chain(self.failed_windows.iter().cloned()) + .dedup() + .collect(); for instance_id in &open_window_ids { let window_arguments = self.instance_id_to_args.get(instance_id).with_context(|| { format!("Cannot reopen window, initial parameters were not saved correctly for {instance_id}") @@ -468,7 +506,8 @@ impl App { /// Load a given CSS string into the gtk css provider, returning a nicely formatted [`DiagError`] when GTK errors out pub fn load_css(&mut self, file_id: usize, css: &str) -> Result<()> { if let Err(err) = self.css_provider.load_from_data(css.as_bytes()) { - static PATTERN: Lazy = Lazy::new(|| regex::Regex::new(r"[^:]*:(\d+):(\d+)(.*)$").unwrap()); + static PATTERN: Lazy = + Lazy::new(|| regex::Regex::new(r"[^:]*:(\d+):(\d+)(.*)$").unwrap()); let nice_error_option: Option<_> = (|| { let captures = PATTERN.captures(err.message())?; let line = captures.get(1).unwrap().as_str().parse::().ok()?; @@ -501,8 +540,9 @@ fn initialize_window( } _ => (None, 0, 0), }; - let window = B::initialize_window(window_init, monitor_geometry, x, y) - .with_context(|| format!("monitor {} is unavailable", window_init.monitor.clone().unwrap()))?; + let window = B::initialize_window(window_init, monitor_geometry, x, y).with_context(|| { + format!("monitor {} is unavailable", window_init.monitor.clone().unwrap()) + })?; window.set_title(&format!("Ewwii - {}", window_init.name)); window.set_position(gtk::WindowPosition::None); @@ -528,7 +568,9 @@ fn initialize_window( if B::IS_X11 { if let Some(geometry) = window_init.geometry { let _ = apply_window_position(geometry, monitor_geometry, &window); - if window_init.backend_options.x11.window_type != crate::window::backend_window_options::X11WindowType::Normal { + if window_init.backend_options.x11.window_type + != crate::window::backend_window_options::X11WindowType::Normal + { let last_pos = Rc::new(RefCell::new(None)); window.connect_configure_event({ let last_pos = last_pos.clone(); @@ -583,7 +625,11 @@ async fn generate_new_widgetnode( /// Apply the provided window-positioning rules to the window. #[cfg(feature = "x11")] -fn apply_window_position(mut window_geometry: WindowGeometry, monitor_geometry: gdk::Rectangle, window: &Window) -> Result<()> { +fn apply_window_position( + mut window_geometry: WindowGeometry, + monitor_geometry: gdk::Rectangle, + window: &Window, +) -> Result<()> { let gdk_window = window.window().context("Failed to get gdk window from gtk window")?; window_geometry.size = crate::window::window_geometry::Coords::from_pixels(window.size()); let actual_window_rect = get_window_rectangle(window_geometry, monitor_geometry); @@ -598,8 +644,9 @@ fn apply_window_position(mut window_geometry: WindowGeometry, monitor_geometry: } fn on_screen_changed(window: &Window, _old_screen: Option<&gdk::Screen>) { - let visual = gtk::prelude::GtkWindowExt::screen(window) - .and_then(|screen| screen.rgba_visual().filter(|_| screen.is_composited()).or_else(|| screen.system_visual())); + let visual = gtk::prelude::GtkWindowExt::screen(window).and_then(|screen| { + screen.rgba_visual().filter(|_| screen.is_composited()).or_else(|| screen.system_visual()) + }); window.set_visual(visual.as_ref()); } @@ -633,7 +680,10 @@ fn get_gdk_monitor(identifier: Option) -> Result { fn get_monitor_plug_name(display: &gdk::Display, monitor_num: i32) -> Option<&str> { unsafe { use glib::translate::ToGlibPtr; - let plug_name_pointer = gdk_sys::gdk_screen_get_monitor_plug_name(display.default_screen().to_glib_none().0, monitor_num); + let plug_name_pointer = gdk_sys::gdk_screen_get_monitor_plug_name( + display.default_screen().to_glib_none().0, + monitor_num, + ); use std::ffi::CStr; CStr::from_ptr(plug_name_pointer).to_str().ok() } @@ -641,7 +691,10 @@ fn get_monitor_plug_name(display: &gdk::Display, monitor_num: i32) -> Option<&st /// Returns the [Monitor][gdk::Monitor] structure corresponding to the identifer. /// Outside of x11, only [MonitorIdentifier::Numeric] is supported -pub fn get_monitor_from_display(display: &gdk::Display, identifier: &MonitorIdentifier) -> Option { +pub fn get_monitor_from_display( + display: &gdk::Display, + identifier: &MonitorIdentifier, +) -> Option { match identifier { MonitorIdentifier::List(list) => { for ident in list { @@ -666,10 +719,18 @@ pub fn get_monitor_from_display(display: &gdk::Display, identifier: &MonitorIden } } -pub fn get_window_rectangle(geometry: WindowGeometry, screen_rect: gdk::Rectangle) -> gdk::Rectangle { - let (offset_x, offset_y) = geometry.offset.relative_to(screen_rect.width(), screen_rect.height()); +pub fn get_window_rectangle( + geometry: WindowGeometry, + screen_rect: gdk::Rectangle, +) -> gdk::Rectangle { + let (offset_x, offset_y) = + geometry.offset.relative_to(screen_rect.width(), screen_rect.height()); let (width, height) = geometry.size.relative_to(screen_rect.width(), screen_rect.height()); - let x = screen_rect.x() + offset_x + geometry.anchor_point.x.alignment_to_coordinate(width, screen_rect.width()); - let y = screen_rect.y() + offset_y + geometry.anchor_point.y.alignment_to_coordinate(height, screen_rect.height()); + let x = screen_rect.x() + + offset_x + + geometry.anchor_point.x.alignment_to_coordinate(width, screen_rect.width()); + let y = screen_rect.y() + + offset_y + + geometry.anchor_point.y.alignment_to_coordinate(height, screen_rect.height()); gdk::Rectangle::new(x, y, width, height) } diff --git a/crates/ewwii/src/application_lifecycle.rs b/crates/ewwii/src/application_lifecycle.rs index dae01be..22368f5 100644 --- a/crates/ewwii/src/application_lifecycle.rs +++ b/crates/ewwii/src/application_lifecycle.rs @@ -6,7 +6,8 @@ use anyhow::{Context, Result}; use once_cell::sync::Lazy; use tokio::sync::broadcast; -pub static APPLICATION_EXIT_SENDER: Lazy> = Lazy::new(|| broadcast::channel(2).0); +pub static APPLICATION_EXIT_SENDER: Lazy> = + Lazy::new(|| broadcast::channel(2).0); /// Notify all listening tasks of the termination of the eww application process. pub fn send_exit() -> Result<()> { diff --git a/crates/ewwii/src/client.rs b/crates/ewwii/src/client.rs index 616c387..3d69ef6 100644 --- a/crates/ewwii/src/client.rs +++ b/crates/ewwii/src/client.rs @@ -26,18 +26,25 @@ pub fn handle_client_only_action(paths: &EwwPaths, action: ActionClientOnly) -> /// Connect to the daemon and send the given request. /// Returns the response from the daemon, or None if the daemon did not provide any useful response. An Ok(None) response does _not_ indicate failure. -pub fn do_server_call(stream: &mut UnixStream, action: &opts::ActionWithServer) -> Result> { +pub fn do_server_call( + stream: &mut UnixStream, + action: &opts::ActionWithServer, +) -> Result> { log::debug!("Forwarding options to server"); stream.set_nonblocking(false).context("Failed to set stream to non-blocking")?; let message_bytes = bincode::serialize(&action)?; - stream.write(&(message_bytes.len() as u32).to_be_bytes()).context("Failed to send command size header to IPC stream")?; + stream + .write(&(message_bytes.len() as u32).to_be_bytes()) + .context("Failed to send command size header to IPC stream")?; stream.write_all(&message_bytes).context("Failed to write command to IPC stream")?; let mut buf = Vec::new(); - stream.set_read_timeout(Some(std::time::Duration::from_millis(100))).context("Failed to set read timeout")?; + stream + .set_read_timeout(Some(std::time::Duration::from_millis(100))) + .context("Failed to set read timeout")?; stream.read_to_end(&mut buf).context("Error reading response from server")?; Ok(if buf.is_empty() { diff --git a/crates/ewwii/src/config/ewwii_config.rs b/crates/ewwii/src/config/ewwii_config.rs index 378b2ed..95c8430 100644 --- a/crates/ewwii/src/config/ewwii_config.rs +++ b/crates/ewwii/src/config/ewwii_config.rs @@ -56,7 +56,11 @@ impl EwwiiConfig { // get the iirhai widget tree let compiled_ast = config_parser.compile_code(&rhai_code)?; let poll_listen_scope = ParseConfig::initial_poll_listen_scope(&rhai_code)?; - let config_tree = config_parser.eval_code_with(&rhai_code, Some(poll_listen_scope), Some(&compiled_ast))?; + let config_tree = config_parser.eval_code_with( + &rhai_code, + Some(poll_listen_scope), + Some(&compiled_ast), + )?; let mut window_definitions = HashMap::new(); @@ -76,7 +80,11 @@ impl EwwiiConfig { bail!("Expected root node to be `Enter`, but got something else."); } - Ok(EwwiiConfig { windows: window_definitions, root_node: Some(config_tree), compiled_ast: Some(compiled_ast) }) + Ok(EwwiiConfig { + windows: window_definitions, + root_node: Some(config_tree), + compiled_ast: Some(compiled_ast), + }) } pub fn get_windows(&self) -> &HashMap { diff --git a/crates/ewwii/src/config/scss.rs b/crates/ewwii/src/config/scss.rs index 61fb19f..9df8890 100644 --- a/crates/ewwii/src/config/scss.rs +++ b/crates/ewwii/src/config/scss.rs @@ -11,7 +11,9 @@ pub fn parse_scss_from_config(path: &Path) -> anyhow::Result<(usize, String)> { let css_file = path.join("ewwii.css"); let scss_file = path.join("ewwii.scss"); if css_file.exists() && scss_file.exists() { - return Err(anyhow!("Encountered both an SCSS and CSS file. Only one of these may exist at a time")); + return Err(anyhow!( + "Encountered both an SCSS and CSS file. Only one of these may exist at a time" + )); } let (s_css_path, css) = if css_file.exists() { @@ -20,11 +22,12 @@ pub fn parse_scss_from_config(path: &Path) -> anyhow::Result<(usize, String)> { let css = replace_env_var_references(css_file_content); (css_file, css) } else { - let scss_file_content = - std::fs::read_to_string(&scss_file).with_context(|| format!("Given SCSS file doesn't exist! {}", path.display()))?; + let scss_file_content = std::fs::read_to_string(&scss_file) + .with_context(|| format!("Given SCSS file doesn't exist! {}", path.display()))?; let file_content = replace_env_var_references(scss_file_content); let grass_config = grass::Options::default().load_path(path); - let css = grass::from_string(file_content, &grass_config).map_err(|err| anyhow!("SCSS parsing error: {}", err))?; + let css = grass::from_string(file_content, &grass_config) + .map_err(|err| anyhow!("SCSS parsing error: {}", err))?; (scss_file, css) }; diff --git a/crates/ewwii/src/daemon_response.rs b/crates/ewwii/src/daemon_response.rs index c60deeb..223fe42 100644 --- a/crates/ewwii/src/daemon_response.rs +++ b/crates/ewwii/src/daemon_response.rs @@ -28,15 +28,22 @@ pub fn create_pair() -> (DaemonResponseSender, mpsc::UnboundedReceiver Result<()> { - self.0.send(DaemonResponse::Success(s)).context("Failed to send success response from application thread") + self.0 + .send(DaemonResponse::Success(s)) + .context("Failed to send success response from application thread") } pub fn send_failure(&self, s: String) -> Result<()> { - self.0.send(DaemonResponse::Failure(s)).context("Failed to send failure response from application thread") + self.0 + .send(DaemonResponse::Failure(s)) + .context("Failed to send failure response from application thread") } /// Given a list of errors, respond with an error value if there are any errors, and respond with success otherwise. - pub fn respond_with_error_list(&self, errors: impl IntoIterator) -> Result<()> { + pub fn respond_with_error_list( + &self, + errors: impl IntoIterator, + ) -> Result<()> { let errors = errors.into_iter().map(|e| error_handling_ctx::format_error(&e)).join("\n"); if errors.is_empty() { self.send_success(String::new()) diff --git a/crates/ewwii/src/display_backend.rs b/crates/ewwii/src/display_backend.rs index 73a603e..bb3a10e 100644 --- a/crates/ewwii/src/display_backend.rs +++ b/crates/ewwii/src/display_backend.rs @@ -12,7 +12,12 @@ pub trait DisplayBackend: Send + Sync + 'static { const IS_X11: bool; const IS_WAYLAND: bool; - fn initialize_window(window_init: &WindowInitiator, monitor: gdk::Rectangle, x: i32, y: i32) -> Option; + fn initialize_window( + window_init: &WindowInitiator, + monitor: gdk::Rectangle, + x: i32, + y: i32, + ) -> Option; } pub struct NoBackend; @@ -21,7 +26,12 @@ impl DisplayBackend for NoBackend { const IS_X11: bool = false; const IS_WAYLAND: bool = false; - fn initialize_window(_window_init: &WindowInitiator, _monitor: gdk::Rectangle, x: i32, y: i32) -> Option { + fn initialize_window( + _window_init: &WindowInitiator, + _monitor: gdk::Rectangle, + x: i32, + y: i32, + ) -> Option { Some(Window::new(gtk::WindowType::Toplevel, x, y)) } } @@ -43,7 +53,12 @@ mod platform_wayland { const IS_X11: bool = false; const IS_WAYLAND: bool = true; - fn initialize_window(window_init: &WindowInitiator, monitor: gdk::Rectangle, x: i32, y: i32) -> Option { + fn initialize_window( + window_init: &WindowInitiator, + monitor: gdk::Rectangle, + x: i32, + y: i32, + ) -> Option { let window = Window::new(gtk::WindowType::Toplevel, x, y); // Initialising a layer shell surface window.init_layer_shell(); @@ -155,9 +170,17 @@ mod platform_x11 { const IS_X11: bool = true; const IS_WAYLAND: bool = false; - fn initialize_window(window_init: &WindowInitiator, _monitor: gdk::Rectangle, x: i32, y: i32) -> Option { - let window_type = - if window_init.backend_options.x11.wm_ignore { gtk::WindowType::Popup } else { gtk::WindowType::Toplevel }; + fn initialize_window( + window_init: &WindowInitiator, + _monitor: gdk::Rectangle, + x: i32, + y: i32, + ) -> Option { + let window_type = if window_init.backend_options.x11.wm_ignore { + gtk::WindowType::Popup + } else { + gtk::WindowType::Toplevel + }; let window = Window::new(window_type, x, y); window.set_resizable(window_init.resizable); window.set_keep_above(window_init.stacking == WindowStacking::Foreground); @@ -171,7 +194,11 @@ mod platform_x11 { } } - pub fn set_xprops(window: &Window, monitor: Monitor, window_init: &WindowInitiator) -> Result<()> { + pub fn set_xprops( + window: &Window, + monitor: Monitor, + window_init: &WindowInitiator, + ) -> Result<()> { let backend = X11BackendConnection::new()?; backend.set_xprops_for(window, monitor, window_init)?; Ok(()) @@ -191,12 +218,19 @@ mod platform_x11 { Ok(X11BackendConnection { conn, root_window: screen.root, atoms }) } - fn set_xprops_for(&self, window: &Window, monitor: Monitor, window_init: &WindowInitiator) -> Result<()> { + fn set_xprops_for( + &self, + window: &Window, + monitor: Monitor, + window_init: &WindowInitiator, + ) -> Result<()> { let monitor_rect = monitor.geometry(); let scale_factor = monitor.scale_factor() as u32; let gdk_window = window.window().context("Couldn't get gdk window from gtk window")?; - let win_id = - gdk_window.downcast_ref::().context("Failed to get x11 window for gtk window")?.xid() as u32; + let win_id = gdk_window + .downcast_ref::() + .context("Failed to get x11 window for gtk window")? + .xid() as u32; let strut_def = window_init.backend_options.x11.struts; let root_window_geometry = self.conn.get_geometry(self.root_window)?.reply()?; @@ -206,8 +240,12 @@ mod platform_x11 { let mon_end_y = scale_factor * (monitor_rect.y() + monitor_rect.height()) as u32 - 1u32; let dist = match strut_def.side { - Side::Left | Side::Right => strut_def.distance.pixels_relative_to(monitor_rect.width()) as u32, - Side::Top | Side::Bottom => strut_def.distance.pixels_relative_to(monitor_rect.height()) as u32, + Side::Left | Side::Right => { + strut_def.distance.pixels_relative_to(monitor_rect.width()) as u32 + } + Side::Top | Side::Bottom => { + strut_def.distance.pixels_relative_to(monitor_rect.height()) as u32 + } }; // don't question it,..... diff --git a/crates/ewwii/src/dynval.rs b/crates/ewwii/src/dynval.rs index cbac5af..2075be5 100644 --- a/crates/ewwii/src/dynval.rs +++ b/crates/ewwii/src/dynval.rs @@ -18,7 +18,11 @@ pub struct ConversionError { pub struct DurationParseError; impl ConversionError { - pub fn new(value: DynVal, target_type: &'static str, source: impl std::error::Error + 'static + Sync + Send) -> Self { + pub fn new( + value: DynVal, + target_type: &'static str, + source: impl std::error::Error + 'static + Sync + Send, + ) -> Self { ConversionError { value, target_type, source: Some(Box::new(source)) } } } @@ -113,7 +117,11 @@ impl TryFrom for DynVal { impl From> for DynVal { fn from(v: Vec) -> Self { - let span = if let (Some(first), Some(last)) = (v.first(), v.last()) { first.span().to(last.span()) } else { Span::DUMMY }; + let span = if let (Some(first), Some(last)) = (v.first(), v.last()) { + first.span().to(last.span()) + } else { + Span::DUMMY + }; let elements = v.into_iter().map(|x| x.as_string().unwrap()).collect::>(); DynVal(serde_json::to_string(&elements).unwrap(), span) } @@ -174,10 +182,15 @@ impl DynVal { let s = &self.0; if s.ends_with("ms") { Ok(Duration::from_millis( - s.trim_end_matches("ms").parse().map_err(|e| ConversionError::new(self.clone(), "integer", e))?, + s.trim_end_matches("ms") + .parse() + .map_err(|e| ConversionError::new(self.clone(), "integer", e))?, )) } else if s.ends_with('s') { - let secs = s.trim_end_matches('s').parse::().map_err(|e| ConversionError::new(self.clone(), "number", e))?; + let secs = s + .trim_end_matches('s') + .parse::() + .map_err(|e| ConversionError::new(self.clone(), "number", e))?; Ok(Duration::from_millis(f64::floor(secs * 1000f64) as u64)) } else if s.ends_with('m') || s.ends_with("min") { let minutes = s @@ -187,12 +200,19 @@ impl DynVal { .map_err(|e| ConversionError::new(self.clone(), "number", e))?; Ok(Duration::from_secs(f64::floor(minutes * 60f64) as u64)) } else if s.ends_with('h') { - let hours = s.trim_end_matches('h').parse::().map_err(|e| ConversionError::new(self.clone(), "number", e))?; + let hours = s + .trim_end_matches('h') + .parse::() + .map_err(|e| ConversionError::new(self.clone(), "number", e))?; Ok(Duration::from_secs(f64::floor(hours * 60f64 * 60f64) as u64)) } else if let Ok(millis) = s.parse() { Ok(Duration::from_millis(millis)) } else { - Err(ConversionError { value: self.clone(), target_type: "duration", source: Some(Box::new(DurationParseError)) }) + Err(ConversionError { + value: self.clone(), + target_type: "duration", + source: Some(Box::new(DurationParseError)), + }) } } diff --git a/crates/ewwii/src/error_handling_ctx.rs b/crates/ewwii/src/error_handling_ctx.rs index c4bb226..db22506 100644 --- a/crates/ewwii/src/error_handling_ctx.rs +++ b/crates/ewwii/src/error_handling_ctx.rs @@ -13,7 +13,8 @@ use codespan_reporting::{ use ewwii_shared_util::Span; use once_cell::sync::Lazy; -pub static FILE_DATABASE: Lazy>> = Lazy::new(|| Arc::new(RwLock::new(FileDatabase::new()))); +pub static FILE_DATABASE: Lazy>> = + Lazy::new(|| Arc::new(RwLock::new(FileDatabase::new()))); // pub fn clear_files() { // *FILE_DATABASE.write().unwrap() = FileDatabase::new(); @@ -30,7 +31,9 @@ pub fn print_error(err: anyhow::Error) { } pub fn format_error(err: &anyhow::Error) -> String { - anyhow_err_to_diagnostic(err).and_then(|diag| stringify_diagnostic(diag).ok()).unwrap_or_else(|| format!("{:?}", err)) + anyhow_err_to_diagnostic(err) + .and_then(|diag| stringify_diagnostic(diag).ok()) + .unwrap_or_else(|| format!("{:?}", err)) } // * OLD @@ -63,8 +66,12 @@ pub fn anyhow_err_to_diagnostic(err: &anyhow::Error) -> Option } } -pub fn stringify_diagnostic(mut diagnostic: codespan_reporting::diagnostic::Diagnostic) -> anyhow::Result { - diagnostic.labels.retain(|label| !Span(label.range.start, label.range.end, label.file_id).is_dummy()); +pub fn stringify_diagnostic( + mut diagnostic: codespan_reporting::diagnostic::Diagnostic, +) -> anyhow::Result { + diagnostic + .labels + .retain(|label| !Span(label.range.start, label.range.end, label.file_id).is_dummy()); let mut config = term::Config::default(); let mut chars = Chars::box_drawing(); diff --git a/crates/ewwii/src/file_database.rs b/crates/ewwii/src/file_database.rs index bd477cf..1b09ea5 100644 --- a/crates/ewwii/src/file_database.rs +++ b/crates/ewwii/src/file_database.rs @@ -40,7 +40,12 @@ impl FileDatabase { pub fn insert_string(&mut self, name: String, content: String) -> Result { let line_starts = codespan_reporting::files::line_starts(&content).collect(); - let code_file = CodeFile { name, line_starts, source_len_bytes: content.len(), source: CodeSource::Literal(content) }; + let code_file = CodeFile { + name, + line_starts, + source_len_bytes: content.len(), + source: CodeSource::Literal(content), + }; let file_id = self.insert_code_file(code_file); Ok(file_id) } @@ -55,12 +60,23 @@ impl<'a> Files<'a> for FileDatabase { Ok(&self.get_file(id)?.name) } - fn source(&'a self, id: Self::FileId) -> Result { + fn source( + &'a self, + id: Self::FileId, + ) -> Result { self.get_file(id)?.source.read_content().map_err(codespan_reporting::files::Error::Io) } - fn line_index(&self, id: Self::FileId, byte_index: usize) -> Result { - Ok(self.get_file(id)?.line_starts.binary_search(&byte_index).unwrap_or_else(|next_line| next_line - 1)) + fn line_index( + &self, + id: Self::FileId, + byte_index: usize, + ) -> Result { + Ok(self + .get_file(id)? + .line_starts + .binary_search(&byte_index) + .unwrap_or_else(|next_line| next_line - 1)) } fn line_range( @@ -90,11 +106,16 @@ impl CodeFile { use std::cmp::Ordering; match line_index.cmp(&self.line_starts.len()) { - Ordering::Less => Ok(self.line_starts.get(line_index).cloned().expect("failed despite previous check")), + Ordering::Less => Ok(self + .line_starts + .get(line_index) + .cloned() + .expect("failed despite previous check")), Ordering::Equal => Ok(self.source_len_bytes), - Ordering::Greater => { - Err(codespan_reporting::files::Error::LineTooLarge { given: line_index, max: self.line_starts.len() - 1 }) - } + Ordering::Greater => Err(codespan_reporting::files::Error::LineTooLarge { + given: line_index, + max: self.line_starts.len() - 1, + }), } } } diff --git a/crates/ewwii/src/ipc_server.rs b/crates/ewwii/src/ipc_server.rs index 98344be..ca76182 100644 --- a/crates/ewwii/src/ipc_server.rs +++ b/crates/ewwii/src/ipc_server.rs @@ -32,7 +32,10 @@ pub async fn run_ewwii_server>( } /// Handle a single IPC connection from start to end. -async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: UnboundedSender) -> Result<()> { +async fn handle_connection( + mut stream: tokio::net::UnixStream, + evt_send: UnboundedSender, +) -> Result<()> { let (mut stream_read, mut stream_write) = stream.split(); let action: opts::ActionWithServer = read_ewwii_action_from_stream(&mut stream_read).await?; @@ -45,7 +48,9 @@ async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: Unbound if let Some(mut response_recv) = maybe_response_recv { log::debug!("Waiting for response for IPC client"); - if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), response_recv.recv()).await { + if let Ok(Some(response)) = + tokio::time::timeout(Duration::from_millis(100), response_recv.recv()).await + { let response = bincode::serialize(&response)?; let result = &stream_write.write_all(&response).await; crate::print_result_err!("sending text response to ipc client", &result); @@ -57,13 +62,21 @@ async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: Unbound /// Read a single message from a unix stream, and parses it into a `ActionWithServer` /// The format here requires the first 4 bytes to be the size of the rest of the message (in big-endian), followed by the rest of the message. -async fn read_ewwii_action_from_stream(stream_read: &'_ mut tokio::net::unix::ReadHalf<'_>) -> Result { +async fn read_ewwii_action_from_stream( + stream_read: &'_ mut tokio::net::unix::ReadHalf<'_>, +) -> Result { let mut message_byte_length = [0u8; 4]; - stream_read.read_exact(&mut message_byte_length).await.context("Failed to read message size header in IPC message")?; + stream_read + .read_exact(&mut message_byte_length) + .await + .context("Failed to read message size header in IPC message")?; let message_byte_length = u32::from_be_bytes(message_byte_length); let mut raw_message = Vec::::with_capacity(message_byte_length as usize); while raw_message.len() < message_byte_length as usize { - stream_read.read_buf(&mut raw_message).await.context("Failed to read actual IPC message")?; + stream_read + .read_buf(&mut raw_message) + .await + .context("Failed to read actual IPC message")?; } bincode::deserialize(&raw_message).context("Failed to parse client message") diff --git a/crates/ewwii/src/main.rs b/crates/ewwii/src/main.rs index fa9e5b7..6d1fbbe 100644 --- a/crates/ewwii/src/main.rs +++ b/crates/ewwii/src/main.rs @@ -83,7 +83,12 @@ fn main() { } if let opts::Action::ShellCompletions { shell } = opts.action { - clap_complete::generate(shell, &mut opts::RawOpt::command(), "ewwii", &mut std::io::stdout()); + clap_complete::generate( + shell, + &mut opts::RawOpt::command(), + "ewwii", + &mut std::io::stdout(), + ); return; } @@ -92,10 +97,18 @@ fn main() { let use_wayland = opts.force_wayland || detected_wayland; #[cfg(all(feature = "wayland", feature = "x11"))] let result = if use_wayland { - log::debug!("Running on wayland. force_wayland={}, detected_wayland={}", opts.force_wayland, detected_wayland); + log::debug!( + "Running on wayland. force_wayland={}, detected_wayland={}", + opts.force_wayland, + detected_wayland + ); run::(opts, eww_binary_name) } else { - log::debug!("Running on X11. force_wayland={}, detected_wayland={}", opts.force_wayland, detected_wayland); + log::debug!( + "Running on X11. force_wayland={}, detected_wayland={}", + opts.force_wayland, + detected_wayland + ); run::(opts, eww_binary_name) }; @@ -123,7 +136,8 @@ fn main() { fn detect_wayland() -> bool { let session_type = std::env::var("XDG_SESSION_TYPE").unwrap_or_default(); let wayland_display = std::env::var("WAYLAND_DISPLAY").unwrap_or_default(); - session_type.contains("wayland") || (!wayland_display.is_empty() && !session_type.contains("x11")) + session_type.contains("wayland") + || (!wayland_display.is_empty() && !session_type.contains("x11")) } fn run(opts: opts::Opt, eww_binary_name: String) -> Result<()> { @@ -165,14 +179,19 @@ fn run(opts: opts::Opt, eww_binary_name: String) -> Result<() let _ = std::fs::remove_file(paths.get_ipc_socket_file()); if !opts.show_logs { - println!("Run `{} logs` to see any errors while editing your configuration.", eww_binary_name); + println!( + "Run `{} logs` to see any errors while editing your configuration.", + eww_binary_name + ); } - let fork_result = server::initialize_server::(paths.clone(), None, !opts.no_daemonize)?; + let fork_result = + server::initialize_server::(paths.clone(), None, !opts.no_daemonize)?; opts.no_daemonize || fork_result == ForkResult::Parent } opts::Action::WithServer(ActionWithServer::KillServer) => { - if let Some(response) = handle_server_command(&paths, &ActionWithServer::KillServer, 1)? { + if let Some(response) = handle_server_command(&paths, &ActionWithServer::KillServer, 1)? + { handle_daemon_response(response); } false @@ -191,15 +210,22 @@ fn run(opts: opts::Opt, eww_binary_name: String) -> Result<() Err(err) if action.can_start_daemon() && !opts.no_daemonize => { // connecting to the daemon failed. Thus, start the daemon here! log::warn!("Failed to connect to daemon: {}", err); - log::info!("Initializing ewwii server. ({})", paths.get_ipc_socket_file().display()); + log::info!( + "Initializing ewwii server. ({})", + paths.get_ipc_socket_file().display() + ); let _ = std::fs::remove_file(paths.get_ipc_socket_file()); if !opts.show_logs { - println!("Run `{} logs` to see any errors while editing your configuration.", eww_binary_name); + println!( + "Run `{} logs` to see any errors while editing your configuration.", + eww_binary_name + ); } let (command, response_recv) = action.into_daemon_command(); // start the daemon and give it the command - let fork_result = server::initialize_server::(paths.clone(), Some(command), true)?; + let fork_result = + server::initialize_server::(paths.clone(), Some(command), true)?; let is_parent = fork_result == ForkResult::Parent; if let (Some(recv), true) = (response_recv, is_parent) { listen_for_daemon_response(recv); @@ -224,16 +250,26 @@ fn listen_for_daemon_response(mut recv: DaemonResponseReceiver) { .build() .expect("Failed to initialize tokio runtime"); rt.block_on(async { - if let Ok(Some(response)) = tokio::time::timeout(Duration::from_millis(100), recv.recv()).await { + if let Ok(Some(response)) = + tokio::time::timeout(Duration::from_millis(100), recv.recv()).await + { println!("{}", response); } }) } /// attempt to send a command to the daemon and send it the given action repeatedly. -fn handle_server_command(paths: &EwwPaths, action: &ActionWithServer, connect_attempts: usize) -> Result> { - log::debug!("Trying to find server process at socket {}", paths.get_ipc_socket_file().display()); - let mut stream = attempt_connect(paths.get_ipc_socket_file(), connect_attempts).context("Failed to connect to daemon")?; +fn handle_server_command( + paths: &EwwPaths, + action: &ActionWithServer, + connect_attempts: usize, +) -> Result> { + log::debug!( + "Trying to find server process at socket {}", + paths.get_ipc_socket_file().display() + ); + let mut stream = attempt_connect(paths.get_ipc_socket_file(), connect_attempts) + .context("Failed to connect to daemon")?; log::debug!("Connected to Ewwii server ({}).", &paths.get_ipc_socket_file().display()); client::do_server_call(&mut stream, action).context("Error while forwarding command to server") } @@ -262,8 +298,8 @@ fn attempt_connect(socket_path: impl AsRef, attempts: usize) -> Option) -> bool { - let response = net::UnixStream::connect(socket_path) - .ok() - .and_then(|mut stream| client::do_server_call(&mut stream, &opts::ActionWithServer::Ping).ok()); + let response = net::UnixStream::connect(socket_path).ok().and_then(|mut stream| { + client::do_server_call(&mut stream, &opts::ActionWithServer::Ping).ok() + }); response.is_some() } diff --git a/crates/ewwii/src/opts.rs b/crates/ewwii/src/opts.rs index f191586..8583d06 100644 --- a/crates/ewwii/src/opts.rs +++ b/crates/ewwii/src/opts.rs @@ -197,8 +197,17 @@ impl Opt { impl From for Opt { fn from(other: RawOpt) -> Self { - let RawOpt { log_debug, force_wayland, config, show_logs, no_daemonize, restart, action } = other; - Opt { log_debug, force_wayland, show_logs, restart, config_path: config, action, no_daemonize } + let RawOpt { log_debug, force_wayland, config, show_logs, no_daemonize, restart, action } = + other; + Opt { + log_debug, + force_wayland, + show_logs, + restart, + config_path: config, + action, + no_daemonize, + } } } @@ -234,7 +243,9 @@ impl ActionWithServer { matches!(self, ActionWithServer::OpenWindow { .. }) } - pub fn into_daemon_command(self) -> (app::DaemonCommand, Option) { + pub fn into_daemon_command( + self, + ) -> (app::DaemonCommand, Option) { let command = match self { ActionWithServer::OpenInspector => app::DaemonCommand::OpenInspector, @@ -248,7 +259,16 @@ impl ActionWithServer { // ActionWithServer::OpenMany { windows, should_toggle } => { // return with_response_channel(|sender| app::DaemonCommand::OpenMany { windows, should_toggle, sender }); // } - ActionWithServer::OpenWindow { window_name, id, pos, size, screen, anchor, should_toggle, duration } => { + ActionWithServer::OpenWindow { + window_name, + id, + pos, + size, + screen, + anchor, + should_toggle, + duration, + } => { return with_response_channel(|sender| app::DaemonCommand::OpenWindow { window_name, instance_id: id, @@ -263,18 +283,32 @@ impl ActionWithServer { }); } ActionWithServer::CloseWindows { windows } => { - return with_response_channel(|sender| app::DaemonCommand::CloseWindows { windows, auto_reopen: false, sender }); + return with_response_channel(|sender| app::DaemonCommand::CloseWindows { + windows, + auto_reopen: false, + sender, + }); + } + ActionWithServer::Reload => { + return with_response_channel(app::DaemonCommand::ReloadConfigAndCss) + } + ActionWithServer::ListWindows => { + return with_response_channel(app::DaemonCommand::ListWindows) + } + ActionWithServer::ListActiveWindows => { + return with_response_channel(app::DaemonCommand::ListActiveWindows) + } + ActionWithServer::ShowDebug => { + return with_response_channel(app::DaemonCommand::PrintDebug) } - ActionWithServer::Reload => return with_response_channel(app::DaemonCommand::ReloadConfigAndCss), - ActionWithServer::ListWindows => return with_response_channel(app::DaemonCommand::ListWindows), - ActionWithServer::ListActiveWindows => return with_response_channel(app::DaemonCommand::ListActiveWindows), - ActionWithServer::ShowDebug => return with_response_channel(app::DaemonCommand::PrintDebug), }; (command, None) } } -fn with_response_channel(f: F) -> (O, Option>) +fn with_response_channel( + f: F, +) -> (O, Option>) where F: FnOnce(DaemonResponseSender) -> O, { diff --git a/crates/ewwii/src/paths.rs b/crates/ewwii/src/paths.rs index a1efec2..797930b 100644 --- a/crates/ewwii/src/paths.rs +++ b/crates/ewwii/src/paths.rs @@ -55,7 +55,12 @@ impl EwwPaths { std::fs::create_dir_all(&log_dir)?; } - Ok(EwwPaths { config_dir, log_file: log_dir.join(format!("eww_{}.log", daemon_id)), log_dir, ipc_socket_file }) + Ok(EwwPaths { + config_dir, + log_file: log_dir.join(format!("eww_{}.log", daemon_id)), + log_dir, + ipc_socket_file, + }) } pub fn default() -> Result { diff --git a/crates/ewwii/src/server.rs b/crates/ewwii/src/server.rs index 7641579..3bfae7a 100644 --- a/crates/ewwii/src/server.rs +++ b/crates/ewwii/src/server.rs @@ -25,8 +25,9 @@ pub fn initialize_server( ) -> Result { let (ui_send, mut ui_recv) = tokio::sync::mpsc::unbounded_channel(); - std::env::set_current_dir(paths.get_config_dir()) - .with_context(|| format!("Failed to change working directory to {}", paths.get_config_dir().display()))?; + std::env::set_current_dir(paths.get_config_dir()).with_context(|| { + format!("Failed to change working directory to {}", paths.get_config_dir().display()) + })?; log::info!("Loading paths: {}", &paths); @@ -63,13 +64,16 @@ pub fn initialize_server( "# ); - simple_signal::set_handler(&[simple_signal::Signal::Int, simple_signal::Signal::Term], move |_| { - log::info!("Shutting down ewwii daemon..."); - if let Err(e) = crate::application_lifecycle::send_exit() { - log::error!("Failed to send application shutdown event to workers: {:?}", e); - std::process::exit(1); - } - }); + simple_signal::set_handler( + &[simple_signal::Signal::Int, simple_signal::Signal::Term], + move |_| { + log::info!("Shutting down ewwii daemon..."); + if let Err(e) = crate::application_lifecycle::send_exit() { + log::error!("Failed to send application shutdown event to workers: {:?}", e); + std::process::exit(1); + } + }, + ); if B::IS_WAYLAND { std::env::set_var("GDK_BACKEND", "wayland") @@ -89,7 +93,11 @@ pub fn initialize_server( }; if let Some(screen) = gtk::gdk::Screen::default() { - gtk::StyleContext::add_provider_for_screen(&screen, &app.css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk::StyleContext::add_provider_for_screen( + &screen, + &app.css_provider, + gtk::STYLE_PROVIDER_PRIORITY_APPLICATION, + ); } if let Ok((file_id, css)) = config::scss::parse_scss_from_config(app.paths.get_config_dir()) { @@ -156,7 +164,10 @@ fn reload_config_and_css(ui_send: &UnboundedSender) -> Result<()> Ok(()) } -fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender) -> tokio::runtime::Handle { +fn init_async_part( + paths: EwwPaths, + ui_send: UnboundedSender, +) -> tokio::runtime::Handle { let rt = tokio::runtime::Builder::new_multi_thread() .thread_name("main-async-runtime") .enable_all() @@ -176,7 +187,9 @@ fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender let ipc_server_join_handle = { let ui_send = ui_send.clone(); - tokio::spawn(async move { ipc_server::run_ewwii_server(ui_send, paths.get_ipc_socket_file()).await }) + tokio::spawn(async move { + ipc_server::run_ewwii_server(ui_send, paths.get_ipc_socket_file()).await + }) }; let forward_exit_to_app_handle = { @@ -190,7 +203,11 @@ fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender }) }; - let result = tokio::try_join!(filewatch_join_handle, ipc_server_join_handle, forward_exit_to_app_handle); + let result = tokio::try_join!( + filewatch_join_handle, + ipc_server_join_handle, + forward_exit_to_app_handle + ); if let Err(e) = result { log::error!("Ewwii exiting with error: {:?}", e); @@ -203,25 +220,29 @@ fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender } /// Watch configuration files for changes, sending reload events to the eww app when the files change. -async fn run_filewatch>(config_dir: P, evt_send: UnboundedSender) -> Result<()> { +async fn run_filewatch>( + config_dir: P, + evt_send: UnboundedSender, +) -> Result<()> { use notify::{RecommendedWatcher, RecursiveMode, Watcher}; let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel(); - let mut watcher: RecommendedWatcher = notify::recommended_watcher(move |res: notify::Result| match res { - Ok(notify::Event { kind: notify::EventKind::Modify(_), paths, .. }) => { - let relevant_files_changed = paths.iter().any(|path| { - let ext = path.extension().unwrap_or_default(); - ext == "rhai" || ext == "scss" || ext == "css" - }); - if relevant_files_changed { - if let Err(err) = tx.send(()) { - log::warn!("Error forwarding file update event: {:?}", err); + let mut watcher: RecommendedWatcher = + notify::recommended_watcher(move |res: notify::Result| match res { + Ok(notify::Event { kind: notify::EventKind::Modify(_), paths, .. }) => { + let relevant_files_changed = paths.iter().any(|path| { + let ext = path.extension().unwrap_or_default(); + ext == "rhai" || ext == "scss" || ext == "css" + }); + if relevant_files_changed { + if let Err(err) = tx.send(()) { + log::warn!("Error forwarding file update event: {:?}", err); + } } } - } - Ok(_) => {} - Err(e) => log::error!("Encountered Error While Watching Files: {}", e), - })?; + Ok(_) => {} + Err(e) => log::error!("Encountered Error While Watching Files: {}", e), + })?; watcher.watch(config_dir.as_ref(), RecursiveMode::Recursive)?; // make sure to not trigger reloads too much by only accepting one reload every 500ms. @@ -271,11 +292,15 @@ fn do_detach(log_file_path: impl AsRef) -> Result { } } - let file = std::fs::OpenOptions::new() - .create(true) - .append(true) - .open(&log_file_path) - .unwrap_or_else(|_| panic!("Error opening log file ({}), for writing", log_file_path.as_ref().to_string_lossy())); + let file = + std::fs::OpenOptions::new().create(true).append(true).open(&log_file_path).unwrap_or_else( + |_| { + panic!( + "Error opening log file ({}), for writing", + log_file_path.as_ref().to_string_lossy() + ) + }, + ); let fd = file.as_raw_fd(); if nix::unistd::isatty(1)? { @@ -297,7 +322,9 @@ fn cleanup_log_dir(log_dir: impl AsRef) -> Result<()> { let entry = entry.ok()?; let path = entry.path(); if let Some(file_name) = path.file_name() { - if file_name.to_string_lossy().starts_with("ewwii_") && file_name.to_string_lossy().ends_with(".log") { + if file_name.to_string_lossy().starts_with("ewwii_") + && file_name.to_string_lossy().ends_with(".log") + { Some(path) } else { None diff --git a/crates/ewwii/src/util.rs b/crates/ewwii/src/util.rs index 0f4be35..3cd001d 100644 --- a/crates/ewwii/src/util.rs +++ b/crates/ewwii/src/util.rs @@ -108,7 +108,9 @@ impl> T { /// reference with an empty string. pub fn replace_env_var_references(input: String) -> String { regex!(r"\$\{([^\s]*)\}") - .replace_all(&input, |var_name: ®ex::Captures| std::env::var(var_name.get(1).unwrap().as_str()).unwrap_or_default()) + .replace_all(&input, |var_name: ®ex::Captures| { + std::env::var(var_name.get(1).unwrap().as_str()).unwrap_or_default() + }) .into_owned() } diff --git a/crates/ewwii/src/widgets/build_widget.rs b/crates/ewwii/src/widgets/build_widget.rs index 7829b43..2802545 100644 --- a/crates/ewwii/src/widgets/build_widget.rs +++ b/crates/ewwii/src/widgets/build_widget.rs @@ -13,7 +13,10 @@ pub enum WidgetInput { Window(WindowDefinition), } -pub fn build_gtk_widget(input: WidgetInput, widget_reg: &mut WidgetRegistry) -> Result { +pub fn build_gtk_widget( + input: WidgetInput, + widget_reg: &mut WidgetRegistry, +) -> Result { let node = match input { WidgetInput::Node(n) => n, WidgetInput::Window(w) => w.root_widget, @@ -22,7 +25,10 @@ pub fn build_gtk_widget(input: WidgetInput, widget_reg: &mut WidgetRegistry) -> } // TODO: implement the commented lines -fn build_gtk_widget_from_node(root_node: WidgetNode, widget_reg: &mut WidgetRegistry) -> Result { +fn build_gtk_widget_from_node( + root_node: WidgetNode, + widget_reg: &mut WidgetRegistry, +) -> Result { /* When a a new widget is added to the build process, make sure to update get_id_to_props_map() found in @@ -32,10 +38,18 @@ fn build_gtk_widget_from_node(root_node: WidgetNode, widget_reg: &mut WidgetRegi let gtk_widget = match root_node { WidgetNode::Box { props, children } => build_gtk_box(props, children, widget_reg)?.upcast(), - WidgetNode::CenterBox { props, children } => build_center_box(props, children, widget_reg)?.upcast(), - WidgetNode::EventBox { props, children } => build_gtk_event_box(props, children, widget_reg)?.upcast(), - WidgetNode::ToolTip { props, children } => build_tooltip(props, children, widget_reg)?.upcast(), - WidgetNode::CircularProgress { props } => build_circular_progress_bar(props, widget_reg)?.upcast(), + WidgetNode::CenterBox { props, children } => { + build_center_box(props, children, widget_reg)?.upcast() + } + WidgetNode::EventBox { props, children } => { + build_gtk_event_box(props, children, widget_reg)?.upcast() + } + WidgetNode::ToolTip { props, children } => { + build_tooltip(props, children, widget_reg)?.upcast() + } + WidgetNode::CircularProgress { props } => { + build_circular_progress_bar(props, widget_reg)?.upcast() + } WidgetNode::Graph { props } => build_graph(props, widget_reg)?.upcast(), WidgetNode::Transform { props } => build_transform(props, widget_reg)?.upcast(), WidgetNode::Slider { props } => build_gtk_scale(props, widget_reg)?.upcast(), @@ -47,14 +61,24 @@ fn build_gtk_widget_from_node(root_node: WidgetNode, widget_reg: &mut WidgetRegi WidgetNode::Input { props } => build_gtk_input(props, widget_reg)?.upcast(), WidgetNode::Calendar { props } => build_gtk_calendar(props, widget_reg)?.upcast(), WidgetNode::ColorButton { props } => build_gtk_color_button(props, widget_reg)?.upcast(), - WidgetNode::Expander { props, children } => build_gtk_expander(props, children, widget_reg)?.upcast(), + WidgetNode::Expander { props, children } => { + build_gtk_expander(props, children, widget_reg)?.upcast() + } WidgetNode::ColorChooser { props } => build_gtk_color_chooser(props, widget_reg)?.upcast(), WidgetNode::ComboBoxText { props } => build_gtk_combo_box_text(props, widget_reg)?.upcast(), WidgetNode::Checkbox { props } => build_gtk_checkbox(props, widget_reg)?.upcast(), - WidgetNode::Revealer { props, children } => build_gtk_revealer(props, children, widget_reg)?.upcast(), - WidgetNode::Scroll { props, children } => build_gtk_scrolledwindow(props, children, widget_reg)?.upcast(), - WidgetNode::OverLay { props, children } => build_gtk_overlay(props, children, widget_reg)?.upcast(), - WidgetNode::Stack { props, children } => build_gtk_stack(props, children, widget_reg)?.upcast(), + WidgetNode::Revealer { props, children } => { + build_gtk_revealer(props, children, widget_reg)?.upcast() + } + WidgetNode::Scroll { props, children } => { + build_gtk_scrolledwindow(props, children, widget_reg)?.upcast() + } + WidgetNode::OverLay { props, children } => { + build_gtk_overlay(props, children, widget_reg)?.upcast() + } + WidgetNode::Stack { props, children } => { + build_gtk_stack(props, children, widget_reg)?.upcast() + } // WIDGET_NAME_SYSTRAY => build_systray(node)?.upcast(), unknown => { return Err(anyhow::anyhow!("Cannot build GTK widget from node: {:?}", unknown)); diff --git a/crates/ewwii/src/widgets/circular_progressbar.rs b/crates/ewwii/src/widgets/circular_progressbar.rs index 9e1baf6..ed22a52 100644 --- a/crates/ewwii/src/widgets/circular_progressbar.rs +++ b/crates/ewwii/src/widgets/circular_progressbar.rs @@ -13,13 +13,37 @@ wrapper! { #[derive(Properties)] #[properties(wrapper_type = CircProg)] pub struct CircProgPriv { - #[property(get, set, nick = "Starting at", blurb = "Starting at", minimum = 0f64, maximum = 100f64, default = 0f64)] + #[property( + get, + set, + nick = "Starting at", + blurb = "Starting at", + minimum = 0f64, + maximum = 100f64, + default = 0f64 + )] start_at: RefCell, - #[property(get, set, nick = "Value", blurb = "The value", minimum = 0f64, maximum = 100f64, default = 0f64)] + #[property( + get, + set, + nick = "Value", + blurb = "The value", + minimum = 0f64, + maximum = 100f64, + default = 0f64 + )] value: RefCell, - #[property(get, set, nick = "Thickness", blurb = "Thickness", minimum = 0f64, maximum = 100f64, default = 1f64)] + #[property( + get, + set, + nick = "Thickness", + blurb = "Thickness", + minimum = 0f64, + maximum = 100f64, + default = 1f64 + )] thickness: RefCell, #[property(get, set, nick = "Clockwise", blurb = "Clockwise", default = true)] @@ -98,7 +122,9 @@ impl ContainerImpl for CircProgPriv { fn add(&self, widget: >k::Widget) { if let Some(content) = &*self.content.borrow() { // TODO: Handle this error when populating children widgets instead - error_handling_ctx::print_error(anyhow!("Error, trying to add multiple children to a circular-progress widget")); + error_handling_ctx::print_error(anyhow!( + "Error, trying to add multiple children to a circular-progress widget" + )); self.parent_remove(content); } self.parent_add(widget); @@ -125,9 +151,13 @@ impl WidgetImpl for CircProgPriv { if let Some(child) = &*self.content.borrow() { let (min_child, natural_child) = calc_widget_lowest_preferred_dimension(child); - (min_child + margin.right as i32 + margin.left as i32, natural_child + margin.right as i32 + margin.left as i32) + ( + min_child + margin.right as i32 + margin.left as i32, + natural_child + margin.right as i32 + margin.left as i32, + ) } else { - let empty_width = (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32; + let empty_width = + (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32; (empty_width, empty_width) } } @@ -142,9 +172,13 @@ impl WidgetImpl for CircProgPriv { if let Some(child) = &*self.content.borrow() { let (min_child, natural_child) = calc_widget_lowest_preferred_dimension(child); - (min_child + margin.bottom as i32 + margin.top as i32, natural_child + margin.bottom as i32 + margin.top as i32) + ( + min_child + margin.bottom as i32 + margin.top as i32, + natural_child + margin.bottom as i32 + margin.top as i32, + ) } else { - let empty_height = (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32; + let empty_height = + (2 * *self.thickness.borrow() as i32) + margin.right as i32 + margin.left as i32; (empty_height, empty_height) } } @@ -164,9 +198,14 @@ impl WidgetImpl for CircProgPriv { let margin = styles.margin(gtk::StateFlags::NORMAL); // Padding is not supported yet let fg_color: gdk::RGBA = styles.color(gtk::StateFlags::NORMAL); - let bg_color: gdk::RGBA = styles.style_property_for_state("background-color", gtk::StateFlags::NORMAL).get()?; - let (start_angle, end_angle) = - if clockwise { (0.0, perc_to_rad(value)) } else { (perc_to_rad(100.0 - value), 2f64 * std::f64::consts::PI) }; + let bg_color: gdk::RGBA = styles + .style_property_for_state("background-color", gtk::StateFlags::NORMAL) + .get()?; + let (start_angle, end_angle) = if clockwise { + (0.0, perc_to_rad(value)) + } else { + (perc_to_rad(100.0 - value), 2f64 * std::f64::consts::PI) + }; let total_width = self.obj().allocated_width() as f64; let total_height = self.obj().allocated_height() as f64; diff --git a/crates/ewwii/src/widgets/graph.rs b/crates/ewwii/src/widgets/graph.rs index 0d5f46f..0f11dc9 100644 --- a/crates/ewwii/src/widgets/graph.rs +++ b/crates/ewwii/src/widgets/graph.rs @@ -79,7 +79,9 @@ impl GraphPriv { *last_updated_at = std::time::Instant::now(); while let Some(entry) = history.front() { - if last_updated_at.duration_since(entry.0).as_millis() as u64 > *self.time_range.borrow() { + if last_updated_at.duration_since(entry.0).as_millis() as u64 + > *self.time_range.borrow() + { *last_value = history.pop_front(); } else { break; @@ -243,14 +245,24 @@ impl WidgetImpl for GraphPriv { .iter() .map(|(instant, value)| { let t = last_updated_at.duration_since(*instant).as_millis() as f64; - self.value_to_point(width, height, t / time_range, (value - min) / value_range) + self.value_to_point( + width, + height, + t / time_range, + (value - min) / value_range, + ) }) .collect::>(); // Aad an extra point outside of the graph to extend the line to the left if let Some((instant, value)) = extra_point { let t = last_updated_at.duration_since(instant).as_millis() as f64; - let (x, y) = self.value_to_point(width, height, (t - time_range) / time_range, (value - min) / value_range); + let (x, y) = self.value_to_point( + width, + height, + (t - time_range) / time_range, + (value - min) / value_range, + ); points.push_front(if *self.vertical.borrow() { (x, -y) } else { (-x, y) }); } points @@ -263,7 +275,9 @@ impl WidgetImpl for GraphPriv { cr.clip(); // Draw Background - let bg_color: gdk::RGBA = styles.style_property_for_state("background-color", gtk::StateFlags::NORMAL).get()?; + let bg_color: gdk::RGBA = styles + .style_property_for_state("background-color", gtk::StateFlags::NORMAL) + .get()?; if bg_color.alpha() > 0.0 { if let Some(first_point) = points.front() { cr.line_to(first_point.0, height + margin_bottom); @@ -273,7 +287,12 @@ impl WidgetImpl for GraphPriv { } cr.line_to(width, height); - cr.set_source_rgba(bg_color.red(), bg_color.green(), bg_color.blue(), bg_color.alpha()); + cr.set_source_rgba( + bg_color.red(), + bg_color.green(), + bg_color.blue(), + bg_color.alpha(), + ); cr.fill()?; } @@ -288,7 +307,12 @@ impl WidgetImpl for GraphPriv { let line_style = &*self.line_style.borrow(); apply_line_style(line_style.as_str(), cr)?; cr.set_line_width(thickness); - cr.set_source_rgba(line_color.red(), line_color.green(), line_color.blue(), line_color.alpha()); + cr.set_source_rgba( + line_color.red(), + line_color.green(), + line_color.blue(), + line_color.alpha(), + ); cr.stroke()?; } diff --git a/crates/ewwii/src/widgets/transform.rs b/crates/ewwii/src/widgets/transform.rs index d9eedae..7749bac 100644 --- a/crates/ewwii/src/widgets/transform.rs +++ b/crates/ewwii/src/widgets/transform.rs @@ -126,7 +126,9 @@ impl ContainerImpl for TransformPriv { fn add(&self, widget: >k::Widget) { if let Some(content) = &*self.content.borrow() { // TODO: Handle this error when populating children widgets instead - error_handling_ctx::print_error(anyhow!("Error, trying to add multiple children to a circular-progress widget")); + error_handling_ctx::print_error(anyhow!( + "Error, trying to add multiple children to a circular-progress widget" + )); self.parent_remove(content); } self.parent_add(widget); @@ -145,31 +147,43 @@ impl WidgetImpl for TransformPriv { cr.save()?; let transform_origin_x = match &*self.transform_origin_x.borrow() { - Some(rcx) => NumWithUnit::from_str(rcx)?.pixels_relative_to(total_width as i32) as f64, + Some(rcx) => { + NumWithUnit::from_str(rcx)?.pixels_relative_to(total_width as i32) as f64 + } None => 0.0, }; let transform_origin_y = match &*self.transform_origin_y.borrow() { - Some(rcy) => NumWithUnit::from_str(rcy)?.pixels_relative_to(total_height as i32) as f64, + Some(rcy) => { + NumWithUnit::from_str(rcy)?.pixels_relative_to(total_height as i32) as f64 + } None => 0.0, }; let translate_x = match &*self.translate_x.borrow() { - Some(tx) => NumWithUnit::from_str(tx)?.pixels_relative_to(total_width as i32) as f64, + Some(tx) => { + NumWithUnit::from_str(tx)?.pixels_relative_to(total_width as i32) as f64 + } None => 0.0, }; let translate_y = match &*self.translate_y.borrow() { - Some(ty) => NumWithUnit::from_str(ty)?.pixels_relative_to(total_height as i32) as f64, + Some(ty) => { + NumWithUnit::from_str(ty)?.pixels_relative_to(total_height as i32) as f64 + } None => 0.0, }; let scale_x = match &*self.scale_x.borrow() { - Some(sx) => NumWithUnit::from_str(sx)?.perc_relative_to(total_width as i32) as f64 / 100.0, + Some(sx) => { + NumWithUnit::from_str(sx)?.perc_relative_to(total_width as i32) as f64 / 100.0 + } None => 1.0, }; let scale_y = match &*self.scale_y.borrow() { - Some(sy) => NumWithUnit::from_str(sy)?.perc_relative_to(total_height as i32) as f64 / 100.0, + Some(sy) => { + NumWithUnit::from_str(sy)?.perc_relative_to(total_height as i32) as f64 / 100.0 + } None => 1.0, }; diff --git a/crates/ewwii/src/widgets/widget_definitions.rs b/crates/ewwii/src/widgets/widget_definitions.rs index c5cbb21..eefdfad 100644 --- a/crates/ewwii/src/widgets/widget_definitions.rs +++ b/crates/ewwii/src/widgets/widget_definitions.rs @@ -80,12 +80,15 @@ impl WidgetRegistry { for patch_req in patches { match patch_req { PatchGtkWidget::Create(wdgt_node, wdgt_id, parent_id) => { - self.create_widget(wdgt_node, wdgt_id, parent_id).expect("failed to create new gtk widget"); + self.create_widget(wdgt_node, wdgt_id, parent_id) + .expect("failed to create new gtk widget"); } PatchGtkWidget::Update(widget_id, new_props) => { self.update_props(widget_id, new_props); } - PatchGtkWidget::Remove(widget_id, parent_id) => self.remove_widget(widget_id, parent_id), + PatchGtkWidget::Remove(widget_id, parent_id) => { + self.remove_widget(widget_id, parent_id) + } } } @@ -124,24 +127,31 @@ impl WidgetRegistry { // Removals for (id, new_info) in &old_map { if !new_map.contains_key(id) { - patch.push(PatchGtkWidget::Remove(*id, new_info.parent_id.expect("Parent ID must exist"))); + patch.push(PatchGtkWidget::Remove( + *id, + new_info.parent_id.expect("Parent ID must exist"), + )); } } patch } - pub fn create_widget(&mut self, widget_node: WidgetNode, widget_id: u64, parent_id: u64) -> Result<()> { + pub fn create_widget( + &mut self, + widget_node: WidgetNode, + widget_id: u64, + parent_id: u64, + ) -> Result<()> { log::trace!("Creating '{}'", widget_id); if let Some(parent) = self.widgets.get(&parent_id) { let parent_widget = parent.widget.clone(); if let Some(container) = parent_widget.dynamic_cast::().ok() { // check if the widget already exists - let position = self - .widgets - .get(&widget_id) - .and_then(|old_entry| container.children().iter().position(|w| w == &old_entry.widget)); + let position = self.widgets.get(&widget_id).and_then(|old_entry| { + container.children().iter().position(|w| w == &old_entry.widget) + }); // obliterate that widget.... // how dare it try to create duplication... @@ -200,7 +210,11 @@ impl WidgetRegistry { } } -pub(super) fn build_gtk_box(props: Map, children: Vec, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_box( + props: Map, + children: Vec, + widget_registry: &mut WidgetRegistry, +) -> Result { // Parse initial props to create the widget: let orientation = props .get("orientation") @@ -209,7 +223,8 @@ pub(super) fn build_gtk_box(props: Map, children: Vec, widget_regist .transpose()? .unwrap_or(gtk::Orientation::Horizontal); - let spacing = props.get("spacing").and_then(|v| v.clone().try_cast::()).unwrap_or(0) as i32; + let spacing = + props.get("spacing").and_then(|v| v.clone().try_cast::()).unwrap_or(0) as i32; let space_evenly = get_bool_prop(&props, "space_evenly", Some(true))?; @@ -224,7 +239,9 @@ pub(super) fn build_gtk_box(props: Map, children: Vec, widget_regist let gtk_widget_clone = gtk_widget.clone(); let update_fn: UpdateFn = Box::new(move |props: &Map| { - if let Some(orientation_str) = props.get("orientation").and_then(|v| v.clone().try_cast::()) { + if let Some(orientation_str) = + props.get("orientation").and_then(|v| v.clone().try_cast::()) + { if let Ok(orientation) = parse_orientation(&orientation_str) { gtk_widget_clone.set_orientation(orientation); } @@ -239,14 +256,18 @@ pub(super) fn build_gtk_box(props: Map, children: Vec, widget_regist } // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Box"); - widget_registry.widgets.insert(id, WidgetEntry { widget: gtk_widget.clone().upcast(), update_fn }); + widget_registry + .widgets + .insert(id, WidgetEntry { widget: gtk_widget.clone().upcast(), update_fn }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -266,7 +287,9 @@ pub(super) fn build_gtk_overlay( bail!("overlay must contain at least one element"); } - let mut children = children.into_iter().map(|child| build_gtk_widget(WidgetInput::Node(child), widget_registry)); + let mut children = children + .into_iter() + .map(|child| build_gtk_widget(WidgetInput::Node(child), widget_registry)); // we have more than one child, we can unwrap let first = children.next().unwrap()?; @@ -284,7 +307,11 @@ pub(super) fn build_gtk_overlay( Ok(gtk_widget) } -pub(super) fn build_tooltip(props: Map, children: Vec, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_tooltip( + props: Map, + children: Vec, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Box::new(gtk::Orientation::Horizontal, 0); gtk_widget.set_has_tooltip(true); @@ -304,8 +331,11 @@ pub(super) fn build_tooltip(props: Map, children: Vec, widget_regist gtk_widget.add(&content_widget); let tooltip_node = Rc::new(tooltip_node); - let tooltip_widget = build_gtk_widget(WidgetInput::Node(Rc::clone(&tooltip_node).as_ref().clone()), widget_registry) - .expect("Failed to build tooltip widget"); + let tooltip_widget = build_gtk_widget( + WidgetInput::Node(Rc::clone(&tooltip_node).as_ref().clone()), + widget_registry, + ) + .expect("Failed to build tooltip widget"); gtk_widget.connect_query_tooltip(move |_widget, _x, _y, _keyboard_mode, tooltip| { tooltip.set_custom(Some(&tooltip_widget)); @@ -317,7 +347,11 @@ pub(super) fn build_tooltip(props: Map, children: Vec, widget_regist Ok(gtk_widget) } -pub(super) fn build_center_box(props: Map, children: Vec, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_center_box( + props: Map, + children: Vec, + widget_registry: &mut WidgetRegistry, +) -> Result { let orientation = props .get("orientation") .and_then(|v| v.clone().try_cast::()) @@ -374,14 +408,18 @@ pub(super) fn build_center_box(props: Map, children: Vec, widget_reg gtk_widget_clone.set_orientation(orientation); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "CenterBox"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -435,7 +473,11 @@ pub(super) fn build_gtk_event_box( let delta = evt.delta().1; if delta != 0f64 { // Ignore the first event https://bugzilla.gnome.org/show_bug.cgi?id=675959 - run_command(timeout, &onscroll, &[if delta < 0f64 { "up" } else { "down" }]); + run_command( + timeout, + &onscroll, + &[if delta < 0f64 { "up" } else { "down" }], + ); } glib::Propagation::Proceed }) @@ -482,7 +524,8 @@ pub(super) fn build_gtk_event_box( let display = gdk::Display::default(); let gdk_window = widget.window(); if let (Some(display), Some(gdk_window)) = (display, gdk_window) { - gdk_window.set_cursor(gdk::Cursor::from_name(&display, &cursor).as_ref()); + gdk_window + .set_cursor(gdk::Cursor::from_name(&display, &cursor).as_ref()); } } glib::Propagation::Proceed @@ -507,20 +550,38 @@ pub(super) fn build_gtk_event_box( widget.drag_dest_set( DestDefaults::ALL, &[ - TargetEntry::new("text/uri-list", gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, 0), - TargetEntry::new("text/plain", gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, 0), + TargetEntry::new( + "text/uri-list", + gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, + 0, + ), + TargetEntry::new( + "text/plain", + gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, + 0, + ), ], gdk::DragAction::COPY, ); connect_signal_handler!( widget, - widget.connect_drag_data_received(move |_, _, _x, _y, selection_data, _target_type, _timestamp| { - if let Some(data) = selection_data.uris().first() { - run_command(timeout, &ondropped, &[data.to_string(), "file".to_string()]); - } else if let Some(data) = selection_data.text() { - run_command(timeout, &ondropped, &[data.to_string(), "text".to_string()]); + widget.connect_drag_data_received( + move |_, _, _x, _y, selection_data, _target_type, _timestamp| { + if let Some(data) = selection_data.uris().first() { + run_command( + timeout, + &ondropped, + &[data.to_string(), "file".to_string()], + ); + } else if let Some(data) = selection_data.text() { + run_command( + timeout, + &ondropped, + &[data.to_string(), "text".to_string()], + ); + } } - }) + ) ); } @@ -534,12 +595,16 @@ pub(super) fn build_gtk_event_box( widget.drag_source_unset(); } else { let target_entry = match dragtype { - DragEntryType::File => { - TargetEntry::new("text/uri-list", gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, 0) - } - DragEntryType::Text => { - TargetEntry::new("text/plain", gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, 0) - } + DragEntryType::File => TargetEntry::new( + "text/uri-list", + gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, + 0, + ), + DragEntryType::Text => TargetEntry::new( + "text/plain", + gtk::TargetFlags::OTHER_APP | gtk::TargetFlags::OTHER_WIDGET, + 0, + ), }; widget.drag_source_set( ModifierType::BUTTON1_MASK, @@ -588,7 +653,9 @@ pub(super) fn build_gtk_event_box( let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -608,21 +675,29 @@ pub(super) fn build_gtk_event_box( let id = hash_props_and_type(&props, "EventBox"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_stack(props: Map, children: Vec, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_stack( + props: Map, + children: Vec, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Stack::new(); if children.is_empty() { return Err(anyhow!("stack must contain at least one element")); } - let children = children.into_iter().map(|child| build_gtk_widget(WidgetInput::Node(child), widget_registry)); + let children = children + .into_iter() + .map(|child| build_gtk_widget(WidgetInput::Node(child), widget_registry)); for (i, child) in children.enumerate() { let child = child?; @@ -652,21 +727,28 @@ pub(super) fn build_gtk_stack(props: Map, children: Vec, widget_regi let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Stack"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_transform(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_transform( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let widget = Transform::new(); let apply_props = |props: &Map, widget: &Transform| -> Result<()> { @@ -715,7 +797,9 @@ pub(super) fn build_transform(props: Map, widget_registry: &mut WidgetRegistry) let _ = apply_props(props, &widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -729,7 +813,10 @@ pub(super) fn build_transform(props: Map, widget_registry: &mut WidgetRegistry) Ok(widget) } -pub(super) fn build_circular_progress_bar(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_circular_progress_bar( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let widget = CircProg::new(); let apply_props = |props: &Map, widget: &CircProg| -> Result<()> { @@ -759,7 +846,9 @@ pub(super) fn build_circular_progress_bar(props: Map, widget_registry: &mut Widg let _ = apply_props(props, &widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -773,7 +862,10 @@ pub(super) fn build_circular_progress_bar(props: Map, widget_registry: &mut Widg Ok(widget) } -pub(super) fn build_graph(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_graph( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let widget = super::graph::Graph::new(); let apply_props = |props: &Map, widget: &super::graph::Graph| -> Result<()> { @@ -842,7 +934,9 @@ pub(super) fn build_graph(props: Map, widget_registry: &mut WidgetRegistry) -> R let _ = apply_props(props, &widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(&widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -856,7 +950,10 @@ pub(super) fn build_graph(props: Map, widget_registry: &mut WidgetRegistry) -> R Ok(widget) } -pub(super) fn build_gtk_progress(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_progress( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::ProgressBar::new(); let apply_props = |props: &Map, widget: >k::ProgressBar| -> Result<()> { @@ -887,21 +984,28 @@ pub(super) fn build_gtk_progress(props: Map, widget_registry: &mut WidgetRegistr let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Progress"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_image(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_image( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Image::new(); let apply_props = |props: &Map, widget: >k::Image| -> Result<()> { @@ -916,7 +1020,8 @@ pub(super) fn build_gtk_image(props: Map, widget_registry: &mut WidgetRegistry) } if path.ends_with(".gif") { - let pixbuf_animation = gtk::gdk_pixbuf::PixbufAnimation::from_file(std::path::PathBuf::from(path))?; + let pixbuf_animation = + gtk::gdk_pixbuf::PixbufAnimation::from_file(std::path::PathBuf::from(path))?; widget.set_from_animation(&pixbuf_animation); } else { let pixbuf; @@ -931,7 +1036,9 @@ pub(super) fn build_gtk_image(props: Map, widget_registry: &mut WidgetRegistry) let reg = regex::Regex::new(r"(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Image"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_button(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_button( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Button::new(); let apply_props = |props: &Map, widget: >k::Button| -> Result<()> { @@ -1043,21 +1157,28 @@ pub(super) fn build_gtk_button(props: Map, widget_registry: &mut WidgetRegistry) let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Button"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_label(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_label( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Label::new(None); let apply_props = |props: &Map, widget: >k::Label| -> Result<()> { @@ -1080,7 +1201,13 @@ pub(super) fn build_gtk_label(props: Map, widget_registry: &mut WidgetRegistry) } else { widget.set_max_width_chars(limit_width); } - apply_ellipsize_settings(&widget, truncate, limit_width, truncate_left, show_truncated); + apply_ellipsize_settings( + &widget, + truncate, + limit_width, + truncate_left, + show_truncated, + ); text } else { widget.set_ellipsize(pango::EllipsizeMode::None); @@ -1098,7 +1225,8 @@ pub(super) fn build_gtk_label(props: Map, widget_registry: &mut WidgetRegistry) } }; - let unescaped = unescape::unescape(&t).ok_or_else(|| anyhow!("Failed to unescape..."))?; + let unescaped = + unescape::unescape(&t).ok_or_else(|| anyhow!("Failed to unescape..."))?; let final_text = if unindent { util::unindent(&unescaped) } else { unescaped }; widget.set_text(&final_text); } else if has_markup { @@ -1148,21 +1276,28 @@ pub(super) fn build_gtk_label(props: Map, widget_registry: &mut WidgetRegistry) let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Label"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_input(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_input( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Entry::new(); let apply_props = |props: &Map, widget: >k::Entry| -> Result<()> { @@ -1203,21 +1338,28 @@ pub(super) fn build_gtk_input(props: Map, widget_registry: &mut WidgetRegistry) let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Input"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_calendar(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_calendar( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::Calendar::new(); let apply_props = |props: &Map, widget: >k::Calendar| -> Result<()> { @@ -1271,7 +1413,9 @@ pub(super) fn build_gtk_calendar(props: Map, widget_registry: &mut WidgetRegistr if let Ok(onclick) = get_string_prop(&props, "onclick", None) { connect_signal_handler!( widget, - widget.connect_day_selected(move |w| { run_command(timeout, &onclick, &[w.day(), w.month(), w.year()]) }) + widget.connect_day_selected(move |w| { + run_command(timeout, &onclick, &[w.day(), w.month(), w.year()]) + }) ); } Ok(()) @@ -1284,21 +1428,28 @@ pub(super) fn build_gtk_calendar(props: Map, widget_registry: &mut WidgetRegistr let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Calendar"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_combo_box_text(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_combo_box_text( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::ComboBoxText::new(); let apply_props = |props: &Map, widget: >k::ComboBoxText| -> Result<()> { @@ -1315,7 +1466,11 @@ pub(super) fn build_gtk_combo_box_text(props: Map, widget_registry: &mut WidgetR connect_signal_handler!( widget, widget.connect_changed(move |widget| { - run_command(timeout, &onchange, &[widget.active_text().unwrap_or_else(|| "".into())]); + run_command( + timeout, + &onchange, + &[widget.active_text().unwrap_or_else(|| "".into())], + ); }) ); @@ -1329,14 +1484,18 @@ pub(super) fn build_gtk_combo_box_text(props: Map, widget_registry: &mut WidgetR let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "ComboBoxText"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -1382,14 +1541,18 @@ pub(super) fn build_gtk_expander( let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Expander"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -1425,7 +1588,9 @@ pub(super) fn build_gtk_revealer( let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -1433,7 +1598,8 @@ pub(super) fn build_gtk_revealer( match children.len() { 0 => { /* maybe warn? */ } 1 => { - let child_widget = build_gtk_widget(WidgetInput::Node(children[0].clone()), widget_registry)?; + let child_widget = + build_gtk_widget(WidgetInput::Node(children[0].clone()), widget_registry)?; gtk_widget.set_child(Some(&child_widget)); } n => { @@ -1443,14 +1609,19 @@ pub(super) fn build_gtk_revealer( let id = hash_props_and_type(&props, "Revealer"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_checkbox(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_checkbox( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::CheckButton::new(); let apply_props = |props: &Map, widget: >k::CheckButton| -> Result<()> { @@ -1464,7 +1635,11 @@ pub(super) fn build_gtk_checkbox(props: Map, widget_registry: &mut WidgetRegistr connect_signal_handler!( widget, widget.connect_toggled(move |widget| { - run_command(timeout, if widget.is_active() { &onchecked } else { &onunchecked }, &[] as &[&str]); + run_command( + timeout, + if widget.is_active() { &onchecked } else { &onunchecked }, + &[] as &[&str], + ); }) ); @@ -1478,21 +1653,28 @@ pub(super) fn build_gtk_checkbox(props: Map, widget_registry: &mut WidgetRegistr let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Checkbox"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_color_button(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_color_button( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::ColorButton::builder().build(); let apply_props = |props: &Map, widget: >k::ColorButton| -> Result<()> { @@ -1524,21 +1706,28 @@ pub(super) fn build_gtk_color_button(props: Map, widget_registry: &mut WidgetReg let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "ColorButton"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_color_chooser(props: Map, widget_registry: &mut WidgetRegistry) -> Result { +pub(super) fn build_gtk_color_chooser( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { let gtk_widget = gtk::ColorChooserWidget::new(); let apply_props = |props: &Map, widget: >k::ColorChooserWidget| -> Result<()> { @@ -1570,22 +1759,32 @@ pub(super) fn build_gtk_color_chooser(props: Map, widget_registry: &mut WidgetRe let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "ColorChooser"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; Ok(gtk_widget) } -pub(super) fn build_gtk_scale(props: Map, widget_registry: &mut WidgetRegistry) -> Result { - let gtk_widget = gtk::Scale::new(gtk::Orientation::Horizontal, Some(>k::Adjustment::new(0.0, 0.0, 100.0, 1.0, 1.0, 1.0))); +pub(super) fn build_gtk_scale( + props: Map, + widget_registry: &mut WidgetRegistry, +) -> Result { + let gtk_widget = gtk::Scale::new( + gtk::Orientation::Horizontal, + Some(>k::Adjustment::new(0.0, 0.0, 100.0, 1.0, 1.0, 1.0)), + ); // Reusable closure for applying props let apply_props = |props: &Map, widget: >k::Scale| -> Result<()> { @@ -1617,14 +1816,18 @@ pub(super) fn build_gtk_scale(props: Map, widget_registry: &mut WidgetRegistry) let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); let id = hash_props_and_type(&props, "Slider"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -1662,7 +1865,9 @@ pub(super) fn build_gtk_scrolledwindow( let _ = apply_props(props, >k_widget_clone); // now re-apply generic widget attrs - if let Err(err) = resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) { + if let Err(err) = + resolve_rhai_widget_attrs(>k_widget_clone.clone().upcast::(), &props) + { eprintln!("Failed to update widget attrs: {:?}", err); } }); @@ -1682,7 +1887,9 @@ pub(super) fn build_gtk_scrolledwindow( let id = hash_props_and_type(&props, "ScrolledWindow"); - widget_registry.widgets.insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); + widget_registry + .widgets + .insert(id, WidgetEntry { update_fn, widget: gtk_widget.clone().upcast() }); resolve_rhai_widget_attrs(>k_widget.clone().upcast::(), &props)?; @@ -1730,14 +1937,20 @@ pub(super) fn resolve_rhai_widget_attrs(gtk_widget: >k::Widget, props: &Map) - if let Ok(style_str) = get_string_prop(&props, "style", None) { let css_provider = gtk::CssProvider::new(); let scss = format!("* {{ {} }}", style_str); - css_provider.load_from_data(grass::from_string(scss, &grass::Options::default())?.as_bytes())?; - gtk_widget.style_context().add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); + css_provider + .load_from_data(grass::from_string(scss, &grass::Options::default())?.as_bytes())?; + gtk_widget + .style_context() + .add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); } if let Ok(css_str) = get_string_prop(&props, "css", None) { let css_provider = gtk::CssProvider::new(); - css_provider.load_from_data(grass::from_string(css_str, &grass::Options::default())?.as_bytes())?; - gtk_widget.style_context().add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); + css_provider + .load_from_data(grass::from_string(css_str, &grass::Options::default())?.as_bytes())?; + gtk_widget + .style_context() + .add_provider(&css_provider, gtk::STYLE_PROVIDER_PRIORITY_APPLICATION); } if let Ok(valign) = get_string_prop(&props, "valign", None) { diff --git a/crates/ewwii/src/widgets/widget_definitions_helper.rs b/crates/ewwii/src/widgets/widget_definitions_helper.rs index 651e89f..751cd41 100644 --- a/crates/ewwii/src/widgets/widget_definitions_helper.rs +++ b/crates/ewwii/src/widgets/widget_definitions_helper.rs @@ -14,7 +14,11 @@ where std::thread::Builder::new() .name("command-execution-thread".to_string()) .spawn(move || { - log::debug!("Running command from widget [timeout: {}ms]: {}", timeout.as_millis(), cmd); + log::debug!( + "Running command from widget [timeout: {}ms]: {}", + timeout.as_millis(), + cmd + ); let child = Command::new("/bin/sh").arg("-c").arg(&cmd).spawn(); match child { Ok(mut child) => match child.wait_timeout(timeout) { @@ -89,10 +93,20 @@ pub(super) fn parse_orientation(ori: &str) -> Result { } /// Gtk Label -pub(super) fn apply_ellipsize_settings(label: >k::Label, truncate: bool, limit_width: i32, truncate_left: bool, show: bool) { +pub(super) fn apply_ellipsize_settings( + label: >k::Label, + truncate: bool, + limit_width: i32, + truncate_left: bool, + show: bool, +) { if (truncate || limit_width != i32::MAX) && show { label.set_max_width_chars(if limit_width == i32::MAX { -1 } else { limit_width }); - label.set_ellipsize(if truncate_left { pango::EllipsizeMode::Start } else { pango::EllipsizeMode::End }); + label.set_ellipsize(if truncate_left { + pango::EllipsizeMode::Start + } else { + pango::EllipsizeMode::End + }); } else { label.set_ellipsize(pango::EllipsizeMode::None); } @@ -146,7 +160,9 @@ where { if !args.is_empty() { let cmd = cmd.replace("{}", &format!("{}", args[0])); - args.iter().enumerate().fold(cmd, |acc, (i, arg)| acc.replace(&format!("{{{}}}", i), &format!("{}", arg))) + args.iter() + .enumerate() + .fold(cmd, |acc, (i, arg)| acc.replace(&format!("{{{}}}", i), &format!("{}", arg))) } else { cmd.to_string() } diff --git a/crates/ewwii/src/window/backend_window_options.rs b/crates/ewwii/src/window/backend_window_options.rs index 21932d2..dbf637d 100644 --- a/crates/ewwii/src/window/backend_window_options.rs +++ b/crates/ewwii/src/window/backend_window_options.rs @@ -37,7 +37,10 @@ pub struct BackendWindowOptionsDef { impl BackendWindowOptionsDef { pub fn eval(&self, properties: Map) -> Result { - Ok(BackendWindowOptions { wayland: self.wayland.eval(properties.clone())?, x11: self.x11.eval(properties)? }) + Ok(BackendWindowOptions { + wayland: self.wayland.eval(properties.clone())?, + x11: self.x11.eval(properties)?, + }) } // pub fn from_attrs(attrs: &mut Attributes) -> DiagResult { @@ -119,13 +122,22 @@ impl X11BackendWindowOptionsDef { struts: match properties.get("reserve") { Some(dynval) => { - let obj_map = dynval.read_lock::().ok_or(Error::EnumParseErrorMessage("Expected map for reserve"))?; + let obj_map = dynval + .read_lock::() + .ok_or(Error::EnumParseErrorMessage("Expected map for reserve"))?; - let distance_str = obj_map.get("distance").ok_or(Error::MissingField("distance"))?.clone_cast::(); + let distance_str = obj_map + .get("distance") + .ok_or(Error::MissingField("distance"))? + .clone_cast::(); let distance = NumWithUnit::from_str(&distance_str)?; - let side = obj_map.get("side").map(|s| s.clone_cast::()).map(|s| Side::from_str(&s)).transpose()?; + let side = obj_map + .get("side") + .map(|s| s.clone_cast::()) + .map(|s| Side::from_str(&s)) + .transpose()?; X11StrutDefinition { distance, side: side.unwrap_or(Side::default()) } } @@ -142,7 +154,9 @@ impl X11BackendWindowOptionsDef { wm_ignore: { let wm_ignore = properties.get("wm_ignore").map(|d| d.clone_cast::()); - wm_ignore.unwrap_or_else(|| properties.get("windowtype").is_none() && properties.get("reserve").is_none()) + wm_ignore.unwrap_or_else(|| { + properties.get("windowtype").is_none() && properties.get("reserve").is_none() + }) }, }) } diff --git a/crates/ewwii/src/window/coords.rs b/crates/ewwii/src/window/coords.rs index 991dce9..944c0d3 100644 --- a/crates/ewwii/src/window/coords.rs +++ b/crates/ewwii/src/window/coords.rs @@ -45,10 +45,16 @@ impl FromStr for NumWithUnit { type Err = Error; fn from_str(s: &str) -> Result { - static PATTERN: Lazy = Lazy::new(|| regex::Regex::new("^(-?\\d+(?:.\\d+)?)(.*)$").unwrap()); + static PATTERN: Lazy = + Lazy::new(|| regex::Regex::new("^(-?\\d+(?:.\\d+)?)(.*)$").unwrap()); let captures = PATTERN.captures(s).ok_or_else(|| Error::NumParseFailed(s.to_string()))?; - let value = captures.get(1).unwrap().as_str().parse::().map_err(|_| Error::NumParseFailed(s.to_string()))?; + let value = captures + .get(1) + .unwrap() + .as_str() + .parse::() + .map_err(|_| Error::NumParseFailed(s.to_string()))?; match captures.get(2).unwrap().as_str() { "px" | "" => Ok(NumWithUnit::Pixels(value.floor() as i32)), "%" => Ok(NumWithUnit::Percent(value)), @@ -109,7 +115,10 @@ mod test { #[test] fn test_parse_coords() { - assert_eq!(Coords { x: NumWithUnit::Pixels(50), y: NumWithUnit::Pixels(60) }, Coords::from_str("50x60").unwrap()); + assert_eq!( + Coords { x: NumWithUnit::Pixels(50), y: NumWithUnit::Pixels(60) }, + Coords::from_str("50x60").unwrap() + ); assert!(Coords::from_str("5060").is_err()); } } diff --git a/crates/ewwii/src/window/window_definition.rs b/crates/ewwii/src/window/window_definition.rs index b495a04..8984a37 100644 --- a/crates/ewwii/src/window/window_definition.rs +++ b/crates/ewwii/src/window/window_definition.rs @@ -12,7 +12,16 @@ impl Display for EnumParseError { } } -#[derive(Debug, Clone, Copy, PartialEq, Eq, derive_more::Display, smart_default::SmartDefault, serde::Serialize)] +#[derive( + Debug, + Clone, + Copy, + PartialEq, + Eq, + derive_more::Display, + smart_default::SmartDefault, + serde::Serialize, +)] pub enum WindowStacking { #[default] Foreground, diff --git a/crates/ewwii/src/window/window_geometry.rs b/crates/ewwii/src/window/window_geometry.rs index 190826d..5b424e3 100644 --- a/crates/ewwii/src/window/window_geometry.rs +++ b/crates/ewwii/src/window/window_geometry.rs @@ -35,7 +35,8 @@ impl FromStr for Coords { type Err = Error; fn from_str(s: &str) -> Result { - let (sx, sy) = s.split_once(|c: char| c == 'x' || c == '*').ok_or(Error::MalformedCoords)?; + let (sx, sy) = + s.split_once(|c: char| c == 'x' || c == '*').ok_or(Error::MalformedCoords)?; Ok(Coords { x: sx.parse()?, y: sy.parse()? }) } } @@ -113,9 +114,10 @@ impl std::str::FromStr for AnchorPoint { type Err = EnumParseError; fn from_str(s: &str) -> Result { - let (x_str, y_str) = s - .split_once(' ') - .ok_or_else(|| EnumParseError { input: s.to_string(), expected: vec![" "] })?; + let (x_str, y_str) = s.split_once(' ').ok_or_else(|| EnumParseError { + input: s.to_string(), + expected: vec![" "], + })?; let x = AnchorAlignment::from_x_alignment(x_str)?; let y = AnchorAlignment::from_y_alignment(y_str)?; diff --git a/crates/ewwii/src/window_arguments.rs b/crates/ewwii/src/window_arguments.rs index 14db677..8797aff 100644 --- a/crates/ewwii/src/window_arguments.rs +++ b/crates/ewwii/src/window_arguments.rs @@ -1,4 +1,7 @@ -use crate::{window::coords::Coords, window::monitor::MonitorIdentifier, window::window_geometry::AnchorPoint}; +use crate::{ + window::coords::Coords, window::monitor::MonitorIdentifier, + window::window_geometry::AnchorPoint, +}; /// This stores the arguments given in the command line to create a window /// While creating a window, we combine this with information from the diff --git a/crates/ewwii/src/window_initiator.rs b/crates/ewwii/src/window_initiator.rs index 483199d..6e7d736 100644 --- a/crates/ewwii/src/window_initiator.rs +++ b/crates/ewwii/src/window_initiator.rs @@ -41,10 +41,13 @@ impl WindowInitiator { // Some(geo) => Some(geo.eval(&vars)?.override_if_given(args.anchor, args.pos, args.size)), None => None, }; - let monitor = args - .monitor - .clone() - .or_else(|| properties.get("monitor")?.clone().try_cast::().map(|n| MonitorIdentifier::Numeric(n as i32))); + let monitor = args.monitor.clone().or_else(|| { + properties + .get("monitor")? + .clone() + .try_cast::() + .map(|n| MonitorIdentifier::Numeric(n as i32)) + }); Ok(WindowInitiator { backend_options: window_def.backend_options.eval(properties.clone())?, geometry, @@ -63,15 +66,23 @@ impl WindowInitiator { // } } -fn parse_geometry(val: &Dynamic, args: &WindowArguments, override_geom: bool) -> Result { +fn parse_geometry( + val: &Dynamic, + args: &WindowArguments, + override_geom: bool, +) -> Result { let map = val.clone().cast::(); - let anchor = map.get("anchor").map(|dyn_value| anchor_point_from_str(&dyn_value.to_string())).transpose()?; + let anchor = map + .get("anchor") + .map(|dyn_value| anchor_point_from_str(&dyn_value.to_string())) + .transpose()?; let mut geom = WindowGeometry { offset: get_coords_from_map(&map, "x", "y")?, size: get_coords_from_map(&map, "width", "height")?, - anchor_point: anchor.unwrap_or(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::START }), + anchor_point: anchor + .unwrap_or(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::START }), }; if override_geom { @@ -111,7 +122,8 @@ fn anchor_point_from_str(s: &str) -> Result { match parts.as_slice() { [single] => { // Apply to both x and y - let alignment = AnchorAlignment::from_x_alignment(single).or_else(|_| AnchorAlignment::from_y_alignment(single))?; + let alignment = AnchorAlignment::from_x_alignment(single) + .or_else(|_| AnchorAlignment::from_y_alignment(single))?; Ok(AnchorPoint { x: alignment, y: alignment }) } [y_part, x_part] => { diff --git a/crates/ewwii_shared_util/src/general_helper.rs b/crates/ewwii_shared_util/src/general_helper.rs index befa5e9..a8f4ea6 100644 --- a/crates/ewwii_shared_util/src/general_helper.rs +++ b/crates/ewwii_shared_util/src/general_helper.rs @@ -5,15 +5,23 @@ use std::time::Duration; /// General purpose helpers pub fn get_string_prop(props: &Map, key: &str, default: Option<&str>) -> Result { if let Some(value) = props.get(key) { - value.clone().try_cast::().ok_or_else(|| anyhow!("Expected property `{}` to be a string", key)) + value + .clone() + .try_cast::() + .ok_or_else(|| anyhow!("Expected property `{}` to be a string", key)) } else { - default.map(|s| s.to_string()).ok_or_else(|| anyhow!("Missing required string property `{}`", key)) + default + .map(|s| s.to_string()) + .ok_or_else(|| anyhow!("Missing required string property `{}`", key)) } } pub fn get_bool_prop(props: &Map, key: &str, default: Option) -> Result { if let Some(value) = props.get(key) { - value.clone().try_cast::().ok_or_else(|| anyhow!("Expected property `{}` to be a bool", key)) + value + .clone() + .try_cast::() + .ok_or_else(|| anyhow!("Expected property `{}` to be a bool", key)) } else { default.map(|s| s).ok_or_else(|| anyhow!("Missing required bool property `{}`", key)) } @@ -23,7 +31,8 @@ pub fn get_i64_prop(props: &Map, key: &str, default: Option) -> Result if let Some(v) = value.clone().try_cast::() { Ok(v) } else if let Some(s) = value.clone().try_cast::() { - s.parse::().map_err(|_| anyhow!("Expected property `{}` to be an i64 or numeric string", key)) + s.parse::() + .map_err(|_| anyhow!("Expected property `{}` to be an i64 or numeric string", key)) } else { Err(anyhow!("Expected property `{}` to be an i64 or numeric string", key)) } @@ -39,7 +48,9 @@ pub fn get_f64_prop(props: &Map, key: &str, default: Option) -> Result } else if let Some(v) = value.clone().try_cast::() { Ok(v as f64) } else if let Some(s) = value.clone().try_cast::() { - s.parse::().map_err(|_| anyhow!("Expected property `{}` to be an f64, i64, or numeric string", key)) + s.parse::().map_err(|_| { + anyhow!("Expected property `{}` to be an f64, i64, or numeric string", key) + }) } else { Err(anyhow!("Expected property `{}` to be an f64, i64, or numeric string", key)) } @@ -53,7 +64,8 @@ pub fn get_i32_prop(props: &Map, key: &str, default: Option) -> Result if let Some(v) = value.clone().try_cast::() { Ok(v) } else if let Some(s) = value.clone().try_cast::() { - s.parse::().map_err(|_| anyhow!("Expected property `{}` to be an i32 or numeric string", key)) + s.parse::() + .map_err(|_| anyhow!("Expected property `{}` to be an i32 or numeric string", key)) } else { Err(anyhow!("Expected property `{}` to be an i32 or numeric string", key)) } @@ -62,13 +74,23 @@ pub fn get_i32_prop(props: &Map, key: &str, default: Option) -> Result } } -pub fn get_vec_string_prop(props: &Map, key: &str, default: Option>) -> Result> { +pub fn get_vec_string_prop( + props: &Map, + key: &str, + default: Option>, +) -> Result> { if let Some(value) = props.get(key) { - let array = value.clone().try_cast::>().ok_or_else(|| anyhow!("Expected property `{}` to be a vec", key))?; + let array = value + .clone() + .try_cast::>() + .ok_or_else(|| anyhow!("Expected property `{}` to be a vec", key))?; array .into_iter() - .map(|d| d.try_cast::().ok_or_else(|| anyhow!("Expected all elements of `{}` to be strings", key))) + .map(|d| { + d.try_cast::() + .ok_or_else(|| anyhow!("Expected all elements of `{}` to be strings", key)) + }) .collect() } else { default.ok_or_else(|| anyhow!("Missing required vec property `{}`", key)) @@ -88,7 +110,8 @@ pub fn get_duration_prop(props: &Map, key: &str, default: Option) -> R Ok(Duration::from_secs(s)) } else if key_str.ends_with("min") { let num = &key_str[..key_str.len() - 3]; - let mins = num.parse::().map_err(|_| anyhow!("Invalid min value: '{}'", key_str))?; + let mins = + num.parse::().map_err(|_| anyhow!("Invalid min value: '{}'", key_str))?; Ok(Duration::from_secs(mins * 60)) } else if key_str.ends_with("h") { let num = &key_str[..key_str.len() - 1]; diff --git a/crates/ewwii_shared_util/src/locale.rs b/crates/ewwii_shared_util/src/locale.rs index 08184dc..2018f5f 100644 --- a/crates/ewwii_shared_util/src/locale.rs +++ b/crates/ewwii_shared_util/src/locale.rs @@ -5,8 +5,7 @@ use std::env::var; /// that order, which is the precedence order prescribed by Section 8.2 of POSIX.1-2017. /// If the environment variable is not defined or is malformed use the POSIX locale. pub fn get_locale() -> Locale { - var("LC_ALL") - .or_else(|_| var("LC_TIME")) - .or_else(|_| var("LANG")) - .map_or(Locale::POSIX, |v| v.split('.').next().and_then(|x| x.try_into().ok()).unwrap_or_default()) + var("LC_ALL").or_else(|_| var("LC_TIME")).or_else(|_| var("LANG")).map_or(Locale::POSIX, |v| { + v.split('.').next().and_then(|x| x.try_into().ok()).unwrap_or_default() + }) } diff --git a/crates/ewwii_shared_util/src/wrappers.rs b/crates/ewwii_shared_util/src/wrappers.rs index c9beb80..64e86c9 100644 --- a/crates/ewwii_shared_util/src/wrappers.rs +++ b/crates/ewwii_shared_util/src/wrappers.rs @@ -4,7 +4,20 @@ use serde::{Deserialize, Serialize}; /// The name of a variable #[repr(transparent)] -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, Debug, RefCast)] +#[derive( + Clone, + Hash, + PartialEq, + Eq, + Serialize, + Deserialize, + AsRef, + From, + FromStr, + Display, + Debug, + RefCast, +)] #[debug("VarName({})", _0)] pub struct VarName(pub String); @@ -34,7 +47,20 @@ impl From for VarName { /// The name of an attribute #[repr(transparent)] -#[derive(Clone, Hash, PartialEq, Eq, Serialize, Deserialize, AsRef, From, FromStr, Display, Debug, RefCast)] +#[derive( + Clone, + Hash, + PartialEq, + Eq, + Serialize, + Deserialize, + AsRef, + From, + FromStr, + Display, + Debug, + RefCast, +)] #[debug("AttrName({})", _0)] pub struct AttrName(pub String); diff --git a/crates/iirhai/src/builtins.rs b/crates/iirhai/src/builtins.rs index 18ec094..3d3d3a7 100644 --- a/crates/iirhai/src/builtins.rs +++ b/crates/iirhai/src/builtins.rs @@ -91,15 +91,21 @@ pub fn register_all_widgets(engine: &mut Engine) { // } // }); - engine.register_fn("defwindow", |name: &str, props: Map, node: WidgetNode| WidgetNode::DefWindow { - name: name.to_string(), - props, - node: Box::new(node), + engine.register_fn("defwindow", |name: &str, props: Map, node: WidgetNode| { + WidgetNode::DefWindow { name: name.to_string(), props, node: Box::new(node) } }); - engine.register_fn("poll", |var: &str, props: Map| WidgetNode::Poll { var: var.to_string(), props }); + engine.register_fn("poll", |var: &str, props: Map| WidgetNode::Poll { + var: var.to_string(), + props, + }); - engine.register_fn("listen", |var: &str, props: Map| WidgetNode::Listen { var: var.to_string(), props }); + engine.register_fn("listen", |var: &str, props: Map| WidgetNode::Listen { + var: var.to_string(), + props, + }); - engine.register_fn("enter", |children: Array| WidgetNode::Enter(children.into_iter().map(|v| v.cast()).collect())); + engine.register_fn("enter", |children: Array| { + WidgetNode::Enter(children.into_iter().map(|v| v.cast()).collect()) + }); } diff --git a/crates/iirhai/src/error.rs b/crates/iirhai/src/error.rs index 3d23adb..378262e 100644 --- a/crates/iirhai/src/error.rs +++ b/crates/iirhai/src/error.rs @@ -33,7 +33,13 @@ impl<'a> Diagnostic<'a> { // bar seperator out.push_str(&format!(" {bar}\n", bar = "|".dimmed())); - out.push_str(&format!("{:>width$} {sep} {}\n", self.line, self.line_text, width = num_width, sep = "|".dimmed(),)); + out.push_str(&format!( + "{:>width$} {sep} {}\n", + self.line, + self.line_text, + width = num_width, + sep = "|".dimmed(), + )); // The caret line, pointing at the column let caret_padding = " ".repeat(self.column.saturating_sub(1)); @@ -72,7 +78,12 @@ impl<'a> Diagnostic<'a> { )); for line in note_lines { - out.push_str(&format!("{v} {line:(err: &'a EvalAltResult) -> &'a EvalAltResult { } } -fn get_error_info(root_err: &EvalAltResult, outer_err: &EvalAltResult, engine: &Engine, code: &str) -> ErrorHelp { +fn get_error_info( + root_err: &EvalAltResult, + outer_err: &EvalAltResult, + engine: &Engine, + code: &str, +) -> ErrorHelp { let (help, hint) = match root_err { EvalAltResult::ErrorParsing(..) => ( "Syntax error encountered while parsing.".into(), "Check for unmatched tokens, invalid constructs, or misplaced punctuation.".into(), ), - EvalAltResult::ErrorVariableExists(name, ..) => { - (format!("Variable '{}' is already defined.", name), "Remove or rename the duplicate declaration.".into()) - } - EvalAltResult::ErrorForbiddenVariable(name, ..) => { - (format!("Usage of forbidden variable '{}'.", name), "Avoid using reserved or protected variable names.".into()) - } - EvalAltResult::ErrorVariableNotFound(name, ..) => { - (format!("Unknown variable '{}'.", name), "Check for typos or ensure the variable is initialized before use.".into()) - } + EvalAltResult::ErrorVariableExists(name, ..) => ( + format!("Variable '{}' is already defined.", name), + "Remove or rename the duplicate declaration.".into(), + ), + EvalAltResult::ErrorForbiddenVariable(name, ..) => ( + format!("Usage of forbidden variable '{}'.", name), + "Avoid using reserved or protected variable names.".into(), + ), + EvalAltResult::ErrorVariableNotFound(name, ..) => ( + format!("Unknown variable '{}'.", name), + "Check for typos or ensure the variable is initialized before use.".into(), + ), EvalAltResult::ErrorPropertyNotFound(name, ..) => ( format!("Property '{}' not found on this object.", name), "Verify the property name and the object’s available fields.".into(), @@ -177,7 +196,10 @@ fn get_error_info(root_err: &EvalAltResult, outer_err: &EvalAltResult, engine: & format!("Did you mean one of:\n {}", candidates.join("\n ")), ) } else { - (format!("Function '{}' is not defined.", fn_sig), "Check spelling, module path, or argument count.".into()) + ( + format!("Function '{}' is not defined.", fn_sig), + "Check spelling, module path, or argument count.".into(), + ) } } EvalAltResult::ErrorModuleNotFound(name, ..) => ( @@ -188,12 +210,14 @@ fn get_error_info(root_err: &EvalAltResult, outer_err: &EvalAltResult, engine: & format!("Error inside function '{}': {}", fn_name, msg), "Inspect the function implementation and arguments passed.".into(), ), - EvalAltResult::ErrorInModule(name, ..) => { - (format!("Error while loading module '{}'.", name), "Check the module code for syntax or runtime errors.".into()) - } - EvalAltResult::ErrorUnboundThis(..) => { - ("`this` is unbound in this context.".into(), "Only use `this` inside methods or bound closures.".into()) - } + EvalAltResult::ErrorInModule(name, ..) => ( + format!("Error while loading module '{}'.", name), + "Check the module code for syntax or runtime errors.".into(), + ), + EvalAltResult::ErrorUnboundThis(..) => ( + "`this` is unbound in this context.".into(), + "Only use `this` inside methods or bound closures.".into(), + ), EvalAltResult::ErrorMismatchDataType(found, expected, ..) => ( format!("Data type mismatch: found '{}', expected '{}'.", found, expected), "Convert or cast values to the required type.".into(), @@ -206,9 +230,10 @@ fn get_error_info(root_err: &EvalAltResult, outer_err: &EvalAltResult, engine: & format!("Cannot index into value of type '{}'.", typ), "Only arrays, maps, bitfields, or strings support indexing.".into(), ), - EvalAltResult::ErrorArrayBounds(len, idx, ..) => { - (format!("Array index {} out of bounds (0..{}).", idx, len), "Use a valid index within the array’s range.".into()) - } + EvalAltResult::ErrorArrayBounds(len, idx, ..) => ( + format!("Array index {} out of bounds (0..{}).", idx, len), + "Use a valid index within the array’s range.".into(), + ), EvalAltResult::ErrorStringBounds(len, idx, ..) => ( format!("String index {} out of bounds (0..{}).", idx, len), "Ensure you index only valid character positions.".into(), @@ -217,47 +242,61 @@ fn get_error_info(root_err: &EvalAltResult, outer_err: &EvalAltResult, engine: & format!("Bitfield index {} out of bounds (0..{}).", idx, len), "Use a valid bit position within the bitfield’s size.".into(), ), - EvalAltResult::ErrorFor(..) => { - ("`for` loop value is not iterable.".into(), "Iterate only over arrays, strings, ranges, or iterators.".into()) + EvalAltResult::ErrorFor(..) => ( + "`for` loop value is not iterable.".into(), + "Iterate only over arrays, strings, ranges, or iterators.".into(), + ), + EvalAltResult::ErrorDataRace(name, ..) => ( + format!("Data race detected on '{}'.", name), + "Avoid shared mutable data or use synchronization primitives.".into(), + ), + EvalAltResult::ErrorAssignmentToConstant(name, ..) => ( + format!("Cannot assign to constant '{}'.", name), + "Constants cannot be reassigned after declaration.".into(), + ), + EvalAltResult::ErrorDotExpr(field, ..) => ( + format!("Invalid member access '{}'.", field), + "Verify the object has this member or method.".into(), + ), + EvalAltResult::ErrorArithmetic(msg, ..) => { + ("Arithmetic error encountered.".into(), msg.clone()) } - EvalAltResult::ErrorDataRace(name, ..) => { - (format!("Data race detected on '{}'.", name), "Avoid shared mutable data or use synchronization primitives.".into()) - } - EvalAltResult::ErrorAssignmentToConstant(name, ..) => { - (format!("Cannot assign to constant '{}'.", name), "Constants cannot be reassigned after declaration.".into()) - } - EvalAltResult::ErrorDotExpr(field, ..) => { - (format!("Invalid member access '{}'.", field), "Verify the object has this member or method.".into()) - } - EvalAltResult::ErrorArithmetic(msg, ..) => ("Arithmetic error encountered.".into(), msg.clone()), EvalAltResult::ErrorTooManyOperations(..) => ( "Script exceeded the maximum number of operations.".into(), "Break complex expressions into smaller steps or increase the limit.".into(), ), - EvalAltResult::ErrorTooManyModules(..) => { - ("Too many modules have been loaded.".into(), "Use fewer modules or increase the module limit.".into()) - } - EvalAltResult::ErrorStackOverflow(..) => { - ("Call stack overflow detected.".into(), "Check for infinite recursion or deeply nested calls.".into()) - } - EvalAltResult::ErrorDataTooLarge(name, ..) => { - (format!("Data '{}' is too large to handle.", name), "Use smaller data sizes or adjust engine limits.".into()) - } - EvalAltResult::ErrorTerminated(..) => { - ("Script execution was terminated.".into(), "This occurs when a `stop` or external termination is triggered.".into()) - } - EvalAltResult::ErrorCustomSyntax(msg, options, ..) => { - (format!("Custom syntax error: {}.", msg), format!("Expected one of: {}.", options.join(", "))) - } - EvalAltResult::ErrorRuntime(..) => { - ("Runtime error encountered.".into(), "Inspect the error message and script logic for issues.".into()) - } - EvalAltResult::LoopBreak(..) => { - ("`break` used outside of a loop.".into(), "Only use `break` inside `for` or `while` loops.".into()) - } - EvalAltResult::Return(..) => { - ("`return` statement encountered.".into(), "Script terminated with an explicit return value.".into()) - } + EvalAltResult::ErrorTooManyModules(..) => ( + "Too many modules have been loaded.".into(), + "Use fewer modules or increase the module limit.".into(), + ), + EvalAltResult::ErrorStackOverflow(..) => ( + "Call stack overflow detected.".into(), + "Check for infinite recursion or deeply nested calls.".into(), + ), + EvalAltResult::ErrorDataTooLarge(name, ..) => ( + format!("Data '{}' is too large to handle.", name), + "Use smaller data sizes or adjust engine limits.".into(), + ), + EvalAltResult::ErrorTerminated(..) => ( + "Script execution was terminated.".into(), + "This occurs when a `stop` or external termination is triggered.".into(), + ), + EvalAltResult::ErrorCustomSyntax(msg, options, ..) => ( + format!("Custom syntax error: {}.", msg), + format!("Expected one of: {}.", options.join(", ")), + ), + EvalAltResult::ErrorRuntime(..) => ( + "Runtime error encountered.".into(), + "Inspect the error message and script logic for issues.".into(), + ), + EvalAltResult::LoopBreak(..) => ( + "`break` used outside of a loop.".into(), + "Only use `break` inside `for` or `while` loops.".into(), + ), + EvalAltResult::Return(..) => ( + "`return` statement encountered.".into(), + "Script terminated with an explicit return value.".into(), + ), _ => ("Unknown error".into(), "No additional information available for this error.".into()), }; diff --git a/crates/iirhai/src/helper.rs b/crates/iirhai/src/helper.rs index 652c745..f0dfc1f 100644 --- a/crates/iirhai/src/helper.rs +++ b/crates/iirhai/src/helper.rs @@ -73,7 +73,13 @@ struct TempSignal { fn register_temp_poll_listen(engine: &mut rhai::Engine) { engine.register_type::(); - engine.register_fn("poll", |var: &str, props: rhai::Map| TempSignal { var: var.to_string(), props }); + engine.register_fn("poll", |var: &str, props: rhai::Map| TempSignal { + var: var.to_string(), + props, + }); - engine.register_fn("listen", |var: &str, props: rhai::Map| TempSignal { var: var.to_string(), props }); + engine.register_fn("listen", |var: &str, props: rhai::Map| TempSignal { + var: var.to_string(), + props, + }); } diff --git a/crates/iirhai/src/module_resolver.rs b/crates/iirhai/src/module_resolver.rs index 90698dd..59aa8d6 100644 --- a/crates/iirhai/src/module_resolver.rs +++ b/crates/iirhai/src/module_resolver.rs @@ -21,21 +21,26 @@ impl ModuleResolver for SimpleFileResolver { let base_dir = if let Some(src) = source_path { PathBuf::from(src).parent().map(|p| p.to_path_buf()).unwrap_or( - std::env::current_dir().map_err(|e| EvalAltResult::ErrorSystem("getting current_dir".into(), e.into()))?, + std::env::current_dir().map_err(|e| { + EvalAltResult::ErrorSystem("getting current_dir".into(), e.into()) + })?, ) } else { - std::env::current_dir().map_err(|e| EvalAltResult::ErrorSystem("getting current_dir".into(), e.into()))? + std::env::current_dir() + .map_err(|e| EvalAltResult::ErrorSystem("getting current_dir".into(), e.into()))? }; if !file_path.is_absolute() { file_path = base_dir.join(file_path); } - let full_path = - file_path.canonicalize().map_err(|e| EvalAltResult::ErrorSystem(format!("resolving path: {path}"), e.into()))?; + let full_path = file_path + .canonicalize() + .map_err(|e| EvalAltResult::ErrorSystem(format!("resolving path: {path}"), e.into()))?; - let script = fs::read_to_string(&full_path) - .map_err(|e| EvalAltResult::ErrorSystem(format!("reading file: {full_path:?}"), e.into()))?; + let script = fs::read_to_string(&full_path).map_err(|e| { + EvalAltResult::ErrorSystem(format!("reading file: {full_path:?}"), e.into()) + })?; let ast: AST = engine.compile(&script)?; let scope = Scope::new(); @@ -59,7 +64,9 @@ impl ModuleResolver for ChainedResolver< path: &str, pos: Position, ) -> Result, Box> { - self.first.resolve(engine, source_path, path, pos).or_else(|_| self.second.resolve(engine, source_path, path, pos)) + self.first + .resolve(engine, source_path, path, pos) + .or_else(|_| self.second.resolve(engine, source_path, path, pos)) } } diff --git a/crates/iirhai/src/parser.rs b/crates/iirhai/src/parser.rs index fd11a82..44b6f86 100644 --- a/crates/iirhai/src/parser.rs +++ b/crates/iirhai/src/parser.rs @@ -36,7 +36,12 @@ impl ParseConfig { Ok(self.engine.compile(code)?) } - pub fn eval_code_with(&mut self, code: &str, rhai_scope: Option, compiled_ast: Option<&AST>) -> Result { + pub fn eval_code_with( + &mut self, + code: &str, + rhai_scope: Option, + compiled_ast: Option<&AST>, + ) -> Result { let mut scope = match rhai_scope { Some(s) => s, None => Scope::new(), @@ -55,7 +60,8 @@ impl ParseConfig { } pub fn code_from_file>(&mut self, file_path: P) -> Result { - Ok(fs::read_to_string(&file_path).map_err(|e| anyhow!("Failed to read {:?}: {}", file_path.as_ref(), e))?) + Ok(fs::read_to_string(&file_path) + .map_err(|e| anyhow!("Failed to read {:?}: {}", file_path.as_ref(), e))?) } pub fn initial_poll_listen_scope(code: &str) -> Result { diff --git a/crates/iirhai/src/providers/apilib/wifi.rs b/crates/iirhai/src/providers/apilib/wifi.rs index de981a3..e9d031a 100644 --- a/crates/iirhai/src/providers/apilib/wifi.rs +++ b/crates/iirhai/src/providers/apilib/wifi.rs @@ -15,7 +15,8 @@ pub mod wifi { .output() .map_err(|e| format!("Failed to run nmcli: {e}"))?; - let stdout = String::from_utf8(output.stdout).map_err(|e| format!("Invalid UTF-8 output from nmcli: {e}"))?; + let stdout = String::from_utf8(output.stdout) + .map_err(|e| format!("Invalid UTF-8 output from nmcli: {e}"))?; let mut result = Array::new(); for line in stdout.lines() { @@ -40,7 +41,8 @@ pub mod wifi { .output() .map_err(|e| format!("Failed to run airport: {e}"))?; - let stdout = String::from_utf8(output.stdout).map_err(|e| format!("Invalid UTF-8 output from airport: {e}"))?; + let stdout = String::from_utf8(output.stdout) + .map_err(|e| format!("Invalid UTF-8 output from airport: {e}"))?; let mut result = Array::new(); for line in stdout.lines().skip(1) { @@ -100,7 +102,8 @@ pub mod wifi { .args(&["-t", "-f", "ACTIVE,SSID,SIGNAL,SECURITY", "device", "wifi", "list"]) .output() .map_err(|e| format!("Failed to run nmcli: {e}"))?; - let stdout = String::from_utf8(output.stdout).map_err(|e| format!("Invalid UTF-8 output: {}", e))?; + let stdout = + String::from_utf8(output.stdout).map_err(|e| format!("Invalid UTF-8 output: {}", e))?; let mut map = Map::new(); if let Some(line) = stdout.lines().find(|l| l.starts_with("yes:")) { let parts: Vec<&str> = line.split(':').collect(); @@ -144,7 +147,10 @@ pub mod wifi { args.push("password"); args.push(pw); } - let status = Command::new("nmcli").args(&args).status().map_err(|e| format!("Failed to run nmcli: {e}"))?; + let status = Command::new("nmcli") + .args(&args) + .status() + .map_err(|e| format!("Failed to run nmcli: {e}"))?; if status.success() { Ok(()) } else { @@ -196,7 +202,8 @@ pub mod wifi { .output() .map_err(|e| format!("Failed to run nmcli: {e}"))?; - let stdout = String::from_utf8(output.stdout).map_err(|e| format!("Invalid UTF-8 from nmcli: {e}"))?; + let stdout = String::from_utf8(output.stdout) + .map_err(|e| format!("Invalid UTF-8 from nmcli: {e}"))?; let ssid = stdout .lines() @@ -243,8 +250,10 @@ pub mod wifi { pub fn disable_adapter() -> Result<(), Box> { #[cfg(target_os = "linux")] { - let status = - Command::new("nmcli").args(&["networking", "off"]).status().map_err(|e| format!("Failed to run nmcli: {e}"))?; + let status = Command::new("nmcli") + .args(&["networking", "off"]) + .status() + .map_err(|e| format!("Failed to run nmcli: {e}"))?; if status.success() { Ok(()) } else { @@ -275,8 +284,10 @@ pub mod wifi { pub fn enable_adapter() -> Result<(), Box> { #[cfg(target_os = "linux")] { - let status = - Command::new("nmcli").args(&["networking", "on"]).status().map_err(|e| format!("Failed to run nmcli: {e}"))?; + let status = Command::new("nmcli") + .args(&["networking", "on"]) + .status() + .map_err(|e| format!("Failed to run nmcli: {e}"))?; if status.success() { Ok(()) } else { diff --git a/crates/iirhai/src/providers/stdlib/env.rs b/crates/iirhai/src/providers/stdlib/env.rs index c90538e..f6b16dd 100644 --- a/crates/iirhai/src/providers/stdlib/env.rs +++ b/crates/iirhai/src/providers/stdlib/env.rs @@ -21,7 +21,9 @@ pub mod env { pub fn get_current_dir() -> Result> { std::env::current_dir() .map_err(|e| format!("Failed to get CURRENT DIRECTORY: {e}").into()) - .and_then(|p| p.into_os_string().into_string().map_err(|_| "Invalid path encoding".into())) + .and_then(|p| { + p.into_os_string().into_string().map_err(|_| "Invalid path encoding".into()) + }) } #[rhai_fn(return_raw)] diff --git a/crates/iirhai/src/providers/stdlib/json.rs b/crates/iirhai/src/providers/stdlib/json.rs index 3edcb02..cfccab8 100644 --- a/crates/iirhai/src/providers/stdlib/json.rs +++ b/crates/iirhai/src/providers/stdlib/json.rs @@ -8,7 +8,9 @@ pub mod json { // parse a JSON string into a Dynamic representing serde_json::Value #[rhai_fn(return_raw)] pub fn parse_json(json_str: &str) -> Result> { - serde_json::from_str::(json_str).map(Dynamic::from).map_err(|e| format!("Failed to parse JSON: {e}").into()) + serde_json::from_str::(json_str) + .map(Dynamic::from) + .map_err(|e| format!("Failed to parse JSON: {e}").into()) } // Turn a dyn JSON val back to a string diff --git a/crates/iirhai/src/providers/stdlib/mod.rs b/crates/iirhai/src/providers/stdlib/mod.rs index c19193e..58c41ea 100644 --- a/crates/iirhai/src/providers/stdlib/mod.rs +++ b/crates/iirhai/src/providers/stdlib/mod.rs @@ -8,7 +8,9 @@ use rhai::exported_module; use rhai::module_resolvers::StaticModuleResolver; pub fn register_stdlib(resolver: &mut StaticModuleResolver) { - use crate::providers::stdlib::{env::env, json::json, math::math, monitor::monitor, text::text}; + use crate::providers::stdlib::{ + env::env, json::json, math::math, monitor::monitor, text::text, + }; // adding modules let text_mod = exported_module!(text); diff --git a/crates/iirhai/src/providers/stdlib/monitor.rs b/crates/iirhai/src/providers/stdlib/monitor.rs index 3257f1f..120adb4 100644 --- a/crates/iirhai/src/providers/stdlib/monitor.rs +++ b/crates/iirhai/src/providers/stdlib/monitor.rs @@ -22,7 +22,11 @@ pub mod monitor { } pub fn all_resolutions_str() -> String { - get_all_monitor_resolutions().into_iter().map(|(w, h)| format!("{w}x{h}")).collect::>().join(", ") + get_all_monitor_resolutions() + .into_iter() + .map(|(w, h)| format!("{w}x{h}")) + .collect::>() + .join(", ") } pub fn dimensions(index: i64) -> (i64, i64, i64, i64) { diff --git a/crates/iirhai/src/providers/stdlib/text.rs b/crates/iirhai/src/providers/stdlib/text.rs index 39655d4..ce236ad 100644 --- a/crates/iirhai/src/providers/stdlib/text.rs +++ b/crates/iirhai/src/providers/stdlib/text.rs @@ -5,7 +5,10 @@ pub mod text { pub fn to_slug(text: &str) -> String { let lower = text.to_lowercase(); - let sanitized: String = lower.chars().map(|c| if c.is_alphanumeric() || c.is_whitespace() { c } else { ' ' }).collect(); + let sanitized: String = lower + .chars() + .map(|c| if c.is_alphanumeric() || c.is_whitespace() { c } else { ' ' }) + .collect(); let words = sanitized.split_whitespace(); let slug = words.collect::>().join("-"); @@ -14,7 +17,10 @@ pub mod text { } pub fn to_camel_case(text: &str) -> String { - let cleaned: String = text.chars().map(|c| if c.is_alphanumeric() || c.is_whitespace() { c } else { ' ' }).collect(); + let cleaned: String = text + .chars() + .map(|c| if c.is_alphanumeric() || c.is_whitespace() { c } else { ' ' }) + .collect(); let words = cleaned.split_whitespace(); diff --git a/crates/iirhai/src/updates/listen.rs b/crates/iirhai/src/updates/listen.rs index beefd0d..45d6bc4 100644 --- a/crates/iirhai/src/updates/listen.rs +++ b/crates/iirhai/src/updates/listen.rs @@ -22,7 +22,12 @@ use tokio::io::BufReader; use tokio::process::Command; use tokio::sync::watch; -pub fn handle_listen(var_name: String, props: Map, store: ReactiveVarStore, tx: tokio::sync::mpsc::UnboundedSender) { +pub fn handle_listen( + var_name: String, + props: Map, + store: ReactiveVarStore, + tx: tokio::sync::mpsc::UnboundedSender, +) { let cmd = match get_string_prop(&props, "cmd", Some("")) { Ok(c) => c, Err(e) => { diff --git a/crates/iirhai/src/updates/mod.rs b/crates/iirhai/src/updates/mod.rs index 8b515a0..86a4381 100644 --- a/crates/iirhai/src/updates/mod.rs +++ b/crates/iirhai/src/updates/mod.rs @@ -27,9 +27,13 @@ use tokio::sync::mpsc::UnboundedSender; use tokio::sync::watch; pub type ReactiveVarStore = Arc>>; -pub static SHUTDOWN_REGISTRY: Lazy>>> = Lazy::new(|| Mutex::new(Vec::new())); +pub static SHUTDOWN_REGISTRY: Lazy>>> = + Lazy::new(|| Mutex::new(Vec::new())); -pub fn handle_state_changes(enter_node: WidgetNode, tx: UnboundedSender) -> ReactiveVarStore { +pub fn handle_state_changes( + enter_node: WidgetNode, + tx: UnboundedSender, +) -> ReactiveVarStore { // Enter node is the WidgetNode of Enter() // it is the very root of every config. let store: ReactiveVarStore = Arc::new(RwLock::new(HashMap::new())); diff --git a/crates/iirhai/src/updates/poll.rs b/crates/iirhai/src/updates/poll.rs index 2b2bae6..c8d0e5e 100644 --- a/crates/iirhai/src/updates/poll.rs +++ b/crates/iirhai/src/updates/poll.rs @@ -22,7 +22,12 @@ use tokio::process::Command; use tokio::sync::watch; use tokio::time::sleep; -pub fn handle_poll(var_name: String, props: Map, store: ReactiveVarStore, tx: tokio::sync::mpsc::UnboundedSender) { +pub fn handle_poll( + var_name: String, + props: Map, + store: ReactiveVarStore, + tx: tokio::sync::mpsc::UnboundedSender, +) { // Parse polling interval let interval = get_duration_prop(&props, "interval", Some(Duration::from_secs(1))); let interval = interval.expect("Error parsing interval property of poll"); diff --git a/crates/iirhai/src/widgetnode.rs b/crates/iirhai/src/widgetnode.rs index e24e9b7..20b35a9 100644 --- a/crates/iirhai/src/widgetnode.rs +++ b/crates/iirhai/src/widgetnode.rs @@ -188,7 +188,13 @@ fn insert_wdgt_info( id_to_info: &mut HashMap, ) -> Result<()> { let id = hash_props_and_type(props, widget_type); - let info = WidgetInfo { node: node.clone(), props: props.clone(), widget_type: widget_type.to_string(), children, parent_id }; + let info = WidgetInfo { + node: node.clone(), + props: props.clone(), + widget_type: widget_type.to_string(), + children, + parent_id, + }; id_to_info.insert(id, info); Ok(()) } diff --git a/crates/notifier_host/src/host.rs b/crates/notifier_host/src/host.rs index b937395..e2557d8 100644 --- a/crates/notifier_host/src/host.rs +++ b/crates/notifier_host/src/host.rs @@ -28,7 +28,8 @@ pub trait Host { /// removed items. pub async fn register_as_host( con: &zbus::Connection, -) -> zbus::Result<(zbus::names::WellKnownName<'static>, proxy::StatusNotifierWatcherProxy<'static>)> { +) -> zbus::Result<(zbus::names::WellKnownName<'static>, proxy::StatusNotifierWatcherProxy<'static>)> +{ let snw = proxy::StatusNotifierWatcherProxy::new(con).await?; // get a well-known name @@ -39,14 +40,17 @@ pub async fn register_as_host( i += 1; let wellknown = format!("org.freedesktop.StatusNotifierHost-{}-{}", pid, i); - let wellknown: zbus::names::WellKnownName = wellknown.try_into().expect("generated well-known name is invalid"); + let wellknown: zbus::names::WellKnownName = + wellknown.try_into().expect("generated well-known name is invalid"); let flags = [zbus::fdo::RequestNameFlags::DoNotQueue]; match con.request_name_with_flags(&wellknown, flags.into_iter().collect()).await? { PrimaryOwner => break wellknown, Exists => {} AlreadyOwner => {} - InQueue => unreachable!("request_name_with_flags returned InQueue even though we specified DoNotQueue"), + InQueue => unreachable!( + "request_name_with_flags returned InQueue even though we specified DoNotQueue" + ), }; }; @@ -64,7 +68,10 @@ pub async fn register_as_host( /// This async function runs forever, and only returns if it gets an error! As such, it is /// recommended to call this via something like `tokio::spawn` that runs this in the /// background. -pub async fn run_host(host: &mut dyn Host, snw: &proxy::StatusNotifierWatcherProxy<'static>) -> zbus::Error { +pub async fn run_host( + host: &mut dyn Host, + snw: &proxy::StatusNotifierWatcherProxy<'static>, +) -> zbus::Error { // Replacement for ? operator since we're not returning a Result. macro_rules! try_ { ($e:expr) => { @@ -116,7 +123,11 @@ pub async fn run_host(host: &mut dyn Host, snw: &proxy::StatusNotifierWatcherPro host.add_item(svc, item); } Err(e) => { - log::warn!("Could not create StatusNotifierItem from address {:?}: {:?}", svc, e); + log::warn!( + "Could not create StatusNotifierItem from address {:?}: {:?}", + svc, + e + ); } } } diff --git a/crates/notifier_host/src/icon.rs b/crates/notifier_host/src/icon.rs index c903a15..fab7efe 100644 --- a/crates/notifier_host/src/icon.rs +++ b/crates/notifier_host/src/icon.rs @@ -30,7 +30,8 @@ enum IconError { /// Get the fallback GTK icon, as a final fallback if the tray item has no icon. async fn fallback_icon(size: i32, scale: i32) -> Option { let theme = gtk::IconTheme::default().expect("Could not get default gtk theme"); - match theme.load_icon_for_scale("image-missing", size, scale, gtk::IconLookupFlags::FORCE_SIZE) { + match theme.load_icon_for_scale("image-missing", size, scale, gtk::IconLookupFlags::FORCE_SIZE) + { Ok(pb) => pb, Err(e) => { log::error!("failed to load \"image-missing\" from default theme: {}", e); @@ -70,7 +71,10 @@ fn icon_from_pixmap(width: i32, height: i32, mut data: Vec) -> gtk::gdk_pixb /// From a list of pixmaps, create an icon from the most appropriately sized one. /// /// This function returns None if and only if no pixmaps are provided. -fn icon_from_pixmaps(pixmaps: Vec<(i32, i32, Vec)>, size: i32) -> Option { +fn icon_from_pixmaps( + pixmaps: Vec<(i32, i32, Vec)>, + size: i32, +) -> Option { pixmaps .into_iter() .max_by(|(w1, h1, _), (w2, h2, _)| { @@ -190,7 +194,9 @@ pub async fn load_icon_from_sni( }, Err(zbus::Error::FDO(e)) => match *e { // property not existing is an expected error - zbus::fdo::Error::UnknownProperty(_) | zbus::fdo::Error::InvalidArgs(_) => Err(IconError::NotAvailable), + zbus::fdo::Error::UnknownProperty(_) | zbus::fdo::Error::InvalidArgs(_) => { + Err(IconError::NotAvailable) + } _ => Err(IconError::DBusPixmap(zbus::Error::FDO(e))), }, diff --git a/crates/notifier_host/src/item.rs b/crates/notifier_host/src/item.rs index 889937d..05ea598 100644 --- a/crates/notifier_host/src/item.rs +++ b/crates/notifier_host/src/item.rs @@ -65,16 +65,24 @@ impl Item { } else if service.starts_with(':') { ( service.to_owned(), - resolve_pathless_address(con, service, "/".to_owned()) - .await? - .ok_or_else(|| zbus::Error::Failure(format!("no StatusNotifierItem found for {service}")))?, + resolve_pathless_address(con, service, "/".to_owned()).await?.ok_or_else( + || { + zbus::Error::Failure(format!( + "no StatusNotifierItem found for {service}" + )) + }, + )?, ) } else { return Err(zbus::Error::Address(service.to_owned())); } }; - let sni = proxy::StatusNotifierItemProxy::builder(con).destination(addr)?.path(path)?.build().await?; + let sni = proxy::StatusNotifierItemProxy::builder(con) + .destination(addr)? + .path(path)? + .build() + .await?; Ok(Self { sni, gtk_menu: None }) } @@ -95,7 +103,12 @@ impl Item { Ok(()) } - pub async fn popup_menu(&self, event: >k::gdk::EventButton, x: i32, y: i32) -> zbus::Result<()> { + pub async fn popup_menu( + &self, + event: >k::gdk::EventButton, + x: i32, + y: i32, + ) -> zbus::Result<()> { if let Some(menu) = &self.gtk_menu { menu.popup_at_pointer(event.downcast_ref::()); Ok(()) @@ -131,12 +144,21 @@ struct DBusInterface { name: String, } -async fn resolve_pathless_address(con: &zbus::Connection, service: &str, path: String) -> zbus::Result> { - let introspection_xml = - IntrospectableProxy::builder(con).destination(service)?.path(path.as_str())?.build().await?.introspect().await?; +async fn resolve_pathless_address( + con: &zbus::Connection, + service: &str, + path: String, +) -> zbus::Result> { + let introspection_xml = IntrospectableProxy::builder(con) + .destination(service)? + .path(path.as_str())? + .build() + .await? + .introspect() + .await?; - let dbus_node = - quick_xml::de::from_str::(&introspection_xml).map_err(|err| zbus::Error::Failure(err.to_string()))?; + let dbus_node = quick_xml::de::from_str::(&introspection_xml) + .map_err(|err| zbus::Error::Failure(err.to_string()))?; if dbus_node.interface.iter().any(|interface| interface.name == "org.kde.StatusNotifierItem") { // This item implements the desired interface, so bubble it back up @@ -150,7 +172,9 @@ async fn resolve_pathless_address(con: &zbus::Connection, service: &str, path: S return Ok(Some(join_to_path(&path, name))); } - let path = Box::pin(resolve_pathless_address(con, service, join_to_path(&path, name))).await?; + let path = + Box::pin(resolve_pathless_address(con, service, join_to_path(&path, name))) + .await?; if path.is_some() { // Return the first item found from a child diff --git a/crates/notifier_host/src/watcher.rs b/crates/notifier_host/src/watcher.rs index a0e7c13..84dc299 100644 --- a/crates/notifier_host/src/watcher.rs +++ b/crates/notifier_host/src/watcher.rs @@ -75,7 +75,8 @@ impl Watcher { }; if removed_last { - if let Err(e) = Watcher::is_status_notifier_host_registered_refresh(&ctxt).await { + if let Err(e) = Watcher::is_status_notifier_host_registered_refresh(&ctxt).await + { log::error!("failed to signal Watcher: {}", e); } } @@ -149,7 +150,9 @@ impl Watcher { if let Err(e) = Watcher::registered_status_notifier_items_refresh(&ctxt).await { log::error!("failed to signal Watcher: {}", e); } - if let Err(e) = Watcher::status_notifier_item_unregistered(&ctxt, item.as_ref()).await { + if let Err(e) = + Watcher::status_notifier_item_unregistered(&ctxt, item.as_ref()).await + { log::error!("failed to signal Watcher: {}", e); } } @@ -160,11 +163,17 @@ impl Watcher { /// StatusNotifierItemRegistered signal #[dbus_interface(signal)] - async fn status_notifier_item_registered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>; + async fn status_notifier_item_registered( + ctxt: &zbus::SignalContext<'_>, + service: &str, + ) -> zbus::Result<()>; /// StatusNotifierItemUnregistered signal #[dbus_interface(signal)] - async fn status_notifier_item_unregistered(ctxt: &zbus::SignalContext<'_>, service: &str) -> zbus::Result<()>; + async fn status_notifier_item_unregistered( + ctxt: &zbus::SignalContext<'_>, + service: &str, + ) -> zbus::Result<()>; /// RegisteredStatusNotifierItems property #[dbus_interface(property)] @@ -208,7 +217,9 @@ impl Watcher { /// Equivalent to `is_status_notifier_host_registered_invalidate`, but without requiring /// `self`. - async fn is_status_notifier_host_registered_refresh(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()> { + async fn is_status_notifier_host_registered_refresh( + ctxt: &zbus::SignalContext<'_>, + ) -> zbus::Result<()> { zbus::fdo::Properties::properties_changed( ctxt, Self::name(), @@ -219,7 +230,9 @@ impl Watcher { } /// Equivalent to `registered_status_notifier_items_invalidate`, but without requiring `self`. - async fn registered_status_notifier_items_refresh(ctxt: &zbus::SignalContext<'_>) -> zbus::Result<()> { + async fn registered_status_notifier_items_refresh( + ctxt: &zbus::SignalContext<'_>, + ) -> zbus::Result<()> { zbus::fdo::Properties::properties_changed( ctxt, Self::name(), @@ -279,7 +292,10 @@ async fn parse_service<'a>( } /// Wait for a DBus service to disappear -async fn wait_for_service_exit(con: &zbus::Connection, service: zbus::names::BusName<'_>) -> zbus::fdo::Result<()> { +async fn wait_for_service_exit( + con: &zbus::Connection, + service: zbus::names::BusName<'_>, +) -> zbus::fdo::Result<()> { let dbus = zbus::fdo::DBusProxy::new(con).await?; let mut owner_changes = dbus.receive_name_owner_changed_with_args(&[(0, &service)]).await?; diff --git a/rustfmt.toml b/rustfmt.toml index b2b08e3..38dc120 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,5 +1,5 @@ use_small_heuristics = "Max" -max_width = 130 +max_width = 100 use_field_init_shorthand = true # these where set when we where still on nightly