diff --git a/rustfmt.toml b/rustfmt.toml index c4a051a..edce9c8 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -11,3 +11,4 @@ condense_wildcard_suffixes = true format_code_in_doc_comments = true format_macro_matchers = true format_strings = true +use_small_heuristics = "Max" diff --git a/src/app.rs b/src/app.rs index 4c4f714..af729ec 100644 --- a/src/app.rs +++ b/src/app.rs @@ -149,20 +149,10 @@ impl App { } } DaemonCommand::OpenMany { windows, sender } => { - let result = windows - .iter() - .map(|w| self.open_window(w, None, None, None, None)) - .collect::>(); + let result = windows.iter().map(|w| self.open_window(w, None, None, None, None)).collect::>(); respond_with_error(sender, result)?; } - DaemonCommand::OpenWindow { - window_name, - pos, - size, - anchor, - monitor, - sender, - } => { + DaemonCommand::OpenWindow { window_name, pos, size, anchor, monitor, sender } => { let result = self.open_window(&window_name, pos, size, monitor, anchor); respond_with_error(sender, result)?; } @@ -171,15 +161,9 @@ impl App { respond_with_error(sender, result)?; } DaemonCommand::PrintState(sender) => { - let output = self - .eww_state - .get_variables() - .iter() - .map(|(key, value)| format!("{}: {}", key, value)) - .join("\n"); - sender - .send(DaemonResponse::Success(output)) - .context("sending response from main thread")? + let output = + self.eww_state.get_variables().iter().map(|(key, value)| format!("{}: {}", key, value)).join("\n"); + sender.send(DaemonResponse::Success(output)).context("sending response from main thread")? } DaemonCommand::PrintWindows(sender) => { let output = self @@ -191,15 +175,11 @@ impl App { format!("{}{}", if is_open { "*" } else { "" }, window_name) }) .join("\n"); - sender - .send(DaemonResponse::Success(output)) - .context("sending response from main thread")? + sender.send(DaemonResponse::Success(output)).context("sending response from main thread")? } DaemonCommand::PrintDebug(sender) => { let output = format!("state: {:#?}\n\nconfig: {:#?}", &self.eww_state, &self.eww_config); - sender - .send(DaemonResponse::Success(output)) - .context("sending response from main thread")? + sender.send(DaemonResponse::Success(output)).context("sending response from main thread")? } } }; @@ -223,10 +203,8 @@ impl App { self.script_var_handler.stop_for_variable(unused_var.clone()); } - let window = self - .open_windows - .remove(window_name) - .context(format!("No window with name '{}' is running.", window_name))?; + let window = + self.open_windows.remove(window_name).context(format!("No window with name '{}' is running.", window_name))?; window.close(); self.eww_state.clear_window_state(window_name); @@ -251,9 +229,7 @@ impl App { window_def.geometry = window_def.geometry.override_if_given(anchor, pos, size); let root_widget = - window_def - .widget - .render(&mut self.eww_state, window_name, &self.eww_config.get_widget_definitions())?; + window_def.widget.render(&mut self.eww_state, window_name, &self.eww_config.get_widget_definitions())?; root_widget.get_style_context().add_class(&window_name.to_string()); let monitor_geometry = @@ -264,9 +240,8 @@ impl App { // initialize script var handlers for variables that where not used before opening this window. // TODO somehow make this less shit - for newly_used_var in self - .variables_only_used_in(&window_name) - .filter_map(|var| self.eww_config.get_script_var(&var).ok()) + for newly_used_var in + self.variables_only_used_in(&window_name).filter_map(|var| self.eww_config.get_script_var(&var).ok()) { self.script_var_handler.add(newly_used_var.clone()); } @@ -298,9 +273,7 @@ impl App { /// Get all variable names that are currently referenced in any of the open windows. pub fn get_currently_used_variables(&self) -> impl Iterator { - self.open_windows - .keys() - .flat_map(move |window_name| self.eww_state.vars_referenced_in(window_name)) + self.open_windows.keys().flat_map(move |window_name| self.eww_state.vars_referenced_in(window_name)) } /// Get all variables mapped to a list of windows they are being used in. @@ -308,9 +281,7 @@ impl App { let mut vars: HashMap<&'a VarName, Vec<_>> = HashMap::new(); for window_name in self.open_windows.keys() { for var in self.eww_state.vars_referenced_in(window_name) { - vars.entry(var) - .and_modify(|l| l.push(window_name)) - .or_insert_with(|| vec![window_name]); + vars.entry(var).and_modify(|l| l.push(window_name)).or_insert_with(|| vec![window_name]); } } vars @@ -332,11 +303,8 @@ fn initialize_window( ) -> Result { let actual_window_rect = window_def.geometry.get_window_rectangle(monitor_geometry); - let window = if window_def.focusable { - gtk::Window::new(gtk::WindowType::Toplevel) - } else { - gtk::Window::new(gtk::WindowType::Popup) - }; + let window = + if window_def.focusable { gtk::Window::new(gtk::WindowType::Toplevel) } else { gtk::Window::new(gtk::WindowType::Popup) }; window.set_title(&format!("Eww - {}", window_def.name)); let wm_class_name = format!("eww-{}", window_def.name); @@ -360,10 +328,7 @@ fn initialize_window( // as it is sized according to how much space it's contents require. // This is necessary to handle different anchors correctly in case the size was wrong. let (gtk_window_width, gtk_window_height) = window.get_size(); - window_def.geometry.size = Coords { - x: NumWithUnit::Pixels(gtk_window_width), - y: NumWithUnit::Pixels(gtk_window_height), - }; + window_def.geometry.size = Coords { x: NumWithUnit::Pixels(gtk_window_width), y: NumWithUnit::Pixels(gtk_window_height) }; let actual_window_rect = window_def.geometry.get_window_rectangle(monitor_geometry); window.show_all(); @@ -382,37 +347,24 @@ fn initialize_window( display_backend::reserve_space_for(&window, monitor_geometry, window_def.struts)?; - Ok(EwwWindow { - name: window_def.name.clone(), - definition: window_def, - gtk_window: window, - }) + Ok(EwwWindow { name: window_def.name.clone(), definition: window_def, gtk_window: window }) } fn on_screen_changed(window: >k::Window, _old_screen: Option<&gdk::Screen>) { - let visual = window.get_screen().and_then(|screen| { - screen - .get_rgba_visual() - .filter(|_| screen.is_composited()) - .or_else(|| screen.get_system_visual()) - }); + let visual = window + .get_screen() + .and_then(|screen| screen.get_rgba_visual().filter(|_| screen.is_composited()).or_else(|| screen.get_system_visual())); window.set_visual(visual.as_ref()); } /// get the index of the default monitor fn get_default_monitor_index() -> i32 { - gdk::Display::get_default() - .expect("could not get default display") - .get_default_screen() - .get_primary_monitor() + gdk::Display::get_default().expect("could not get default display").get_default_screen().get_primary_monitor() } /// Get the monitor geometry of a given monitor number fn get_monitor_geometry(n: i32) -> gdk::Rectangle { - gdk::Display::get_default() - .expect("could not get default display") - .get_default_screen() - .get_monitor_geometry(n) + gdk::Display::get_default().expect("could not get default display").get_default_screen().get_monitor_geometry(n) } /// In case of an Err, send the error message to a sender. diff --git a/src/application_lifecycle.rs b/src/application_lifecycle.rs index e012206..6a85902 100644 --- a/src/application_lifecycle.rs +++ b/src/application_lifecycle.rs @@ -11,20 +11,14 @@ lazy_static::lazy_static! { /// Notify all listening tasks of the termination of the eww application process. pub fn send_exit() -> Result<()> { - (&*APPLICATION_EXIT_SENDER) - .send(()) - .context("Failed to send exit lifecycle event")?; + (&*APPLICATION_EXIT_SENDER).send(()).context("Failed to send exit lifecycle event")?; Ok(()) } /// Yields Ok(()) on application termination. Await on this in all long-running tasks /// and perform any cleanup if necessary. pub async fn recv_exit() -> Result<()> { - (&*APPLICATION_EXIT_SENDER) - .subscribe() - .recv() - .await - .context("Failed to receive lifecycle event") + (&*APPLICATION_EXIT_SENDER).subscribe().recv().await.context("Failed to receive lifecycle event") } /// Select in a loop, breaking once a application termination event (see `crate::application_lifecycle`) is received. diff --git a/src/client.rs b/src/client.rs index 7ccd245..3001357 100644 --- a/src/client.rs +++ b/src/client.rs @@ -26,24 +26,16 @@ pub fn handle_client_only_action(paths: &EwwPaths, action: ActionClientOnly) -> pub fn do_server_call(mut stream: UnixStream, action: opts::ActionWithServer) -> Result> { log::info!("Forwarding options to server"); - stream - .set_nonblocking(false) - .context("Failed to set stream to non-blocking")?; + 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")?; + 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/src/config/element.rs b/src/config/element.rs index a3ea17a..ba18cc0 100644 --- a/src/config/element.rs +++ b/src/config/element.rs @@ -58,12 +58,7 @@ impl PartialEq for WidgetUse { impl WidgetUse { pub fn new(name: String, children: Vec) -> Self { - WidgetUse { - name, - children, - attrs: HashMap::new(), - ..WidgetUse::default() - } + WidgetUse { name, children, attrs: HashMap::new(), ..WidgetUse::default() } } pub fn from_xml_node(xml: XmlNode) -> Result { @@ -171,9 +166,6 @@ mod test { }, }; - assert_eq!( - expected, - WidgetDefinition::from_xml_element(xml.as_element().unwrap()).unwrap() - ); + assert_eq!(expected, WidgetDefinition::from_xml_element(xml.as_element().unwrap()).unwrap()); } } diff --git a/src/config/eww_config.rs b/src/config/eww_config.rs index 7b11bf5..0b9a0f5 100644 --- a/src/config/eww_config.rs +++ b/src/config/eww_config.rs @@ -28,21 +28,12 @@ impl EwwConfig { } pub fn generate(conf: RawEwwConfig) -> Result { - let RawEwwConfig { - windows, - initial_variables, - script_vars, - filepath, - widgets, - } = conf; + let RawEwwConfig { windows, initial_variables, script_vars, filepath, widgets } = conf; Ok(EwwConfig { windows: windows .into_iter() .map(|(name, window)| { - Ok(( - name, - EwwWindowDefinition::generate(&widgets, window).context("Failed expand window definition")?, - )) + Ok((name, EwwWindowDefinition::generate(&widgets, window).context("Failed expand window definition")?)) }) .collect::>>()?, widgets, @@ -54,11 +45,8 @@ impl EwwConfig { // TODO this is kinda ugly pub fn generate_initial_state(&self) -> Result> { - let mut vars = self - .script_vars - .iter() - .map(|var| Ok((var.0.clone(), var.1.initial_value()?))) - .collect::>>()?; + let mut vars = + self.script_vars.iter().map(|var| Ok((var.0.clone(), var.1.initial_value()?))).collect::>>()?; vars.extend(self.initial_variables.clone()); Ok(vars) } @@ -68,15 +56,11 @@ impl EwwConfig { } pub fn get_window(&self, name: &WindowName) -> Result<&EwwWindowDefinition> { - self.windows - .get(name) - .with_context(|| format!("No window named '{}' exists", name)) + self.windows.get(name).with_context(|| format!("No window named '{}' exists", name)) } pub fn get_script_var(&self, name: &VarName) -> Result<&ScriptVar> { - self.script_vars - .get(name) - .with_context(|| format!("No script var named '{}' exists", name)) + self.script_vars.get(name).with_context(|| format!("No script var named '{}' exists", name)) } pub fn get_widget_definitions(&self) -> &HashMap { @@ -192,13 +176,7 @@ impl RawEwwConfig { None => Default::default(), }; - let config = RawEwwConfig { - widgets: definitions, - windows, - initial_variables, - script_vars, - filepath: path.to_path_buf(), - }; + let config = RawEwwConfig { widgets: definitions, windows, initial_variables, script_vars, filepath: path.to_path_buf() }; Ok((config, included_paths)) } } @@ -209,10 +187,7 @@ fn parse_variables_block(xml: XmlElement) -> Result<(HashMap { - let value = node - .only_child() - .map(|c| c.as_text_or_sourcecode()) - .unwrap_or_else(|_| String::new()); + let value = node.only_child().map(|c| c.as_text_or_sourcecode()).unwrap_or_else(|_| String::new()); normal_vars.insert(VarName(node.attr("name")?.to_owned()), PrimitiveValue::from_string(value)); } "script-var" => { @@ -282,12 +257,10 @@ mod test { let document1 = roxmltree::Document::parse(&input1).unwrap(); let document2 = roxmltree::Document::parse(input2).unwrap(); - let config1 = RawEwwConfig::from_xml_element(XmlNode::from(document1.root_element()).as_element().unwrap().clone(), "") - .unwrap() - .0; - let config2 = RawEwwConfig::from_xml_element(XmlNode::from(document2.root_element()).as_element().unwrap().clone(), "") - .unwrap() - .0; + let config1 = + RawEwwConfig::from_xml_element(XmlNode::from(document1.root_element()).as_element().unwrap().clone(), "").unwrap().0; + let config2 = + RawEwwConfig::from_xml_element(XmlNode::from(document2.root_element()).as_element().unwrap().clone(), "").unwrap().0; let base_config = RawEwwConfig { widgets: HashMap::new(), windows: HashMap::new(), diff --git a/src/config/mod.rs b/src/config/mod.rs index 7654c48..6ef5988 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -24,12 +24,7 @@ macro_rules! ensure_xml_tag_is { ($element:ident, $name:literal) => { ensure!( $element.tag_name() == $name, - anyhow!( - "{} | Tag needed to be of type '{}', but was: {}", - $element.text_pos(), - $name, - $element.as_tag_string() - ) + anyhow!("{} | Tag needed to be of type '{}', but was: {}", $element.text_pos(), $name, $element.as_tag_string()) ) }; } diff --git a/src/config/window_definition.rs b/src/config/window_definition.rs index 6527079..f084226 100644 --- a/src/config/window_definition.rs +++ b/src/config/window_definition.rs @@ -55,12 +55,8 @@ impl RawEwwWindowDefinition { let focusable = xml.parse_optional_attr("focusable")?; let screen_number = xml.parse_optional_attr("screen")?; - let struts: Option = xml - .child("reserve") - .ok() - .map(StrutDefinition::from_xml_element) - .transpose() - .context("Failed to parse ")?; + let struts: Option = + xml.child("reserve").ok().map(StrutDefinition::from_xml_element).transpose().context("Failed to parse ")?; Ok(RawEwwWindowDefinition { name: WindowName(xml.attr("name")?.to_owned()), @@ -94,10 +90,7 @@ impl std::str::FromStr for Side { "r" | "right" => Ok(Side::Right), "t" | "top" => Ok(Side::Top), "b" | "bottom" => Ok(Side::Bottom), - _ => Err(anyhow!( - "Failed to parse {} as valid side. Must be one of \"left\", \"right\", \"top\", \"bottom\"", - s - )), + _ => Err(anyhow!("Failed to parse {} as valid side. Must be one of \"left\", \"right\", \"top\", \"bottom\"", s)), } } } @@ -110,10 +103,7 @@ pub struct StrutDefinition { impl StrutDefinition { pub fn from_xml_element(xml: XmlElement) -> Result { - Ok(StrutDefinition { - side: xml.attr("side")?.parse()?, - dist: xml.attr("distance")?.parse()?, - }) + Ok(StrutDefinition { side: xml.attr("side")?.parse()?, dist: xml.attr("distance")?.parse()? }) } } @@ -132,10 +122,7 @@ impl std::str::FromStr for WindowStacking { match s.as_str() { "foreground" | "fg" | "f" => Ok(WindowStacking::Foreground), "background" | "bg" | "b" => Ok(WindowStacking::Background), - _ => Err(anyhow!( - "Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg", - s - )), + _ => Err(anyhow!("Couldn't parse '{}' as window stacking, must be either foreground, fg, background or bg", s)), } } } diff --git a/src/config/window_geometry.rs b/src/config/window_geometry.rs index baad2c1..0caa0be 100644 --- a/src/config/window_geometry.rs +++ b/src/config/window_geometry.rs @@ -24,10 +24,7 @@ impl AnchorAlignment { "l" | "left" => Ok(AnchorAlignment::START), "c" | "center" => Ok(AnchorAlignment::CENTER), "r" | "right" => Ok(AnchorAlignment::END), - _ => bail!( - r#"couldn't parse '{}' as x-alignment. Must be one of "left", "center", "right""#, - s - ), + _ => bail!(r#"couldn't parse '{}' as x-alignment. Must be one of "left", "center", "right""#, s), } } @@ -36,10 +33,7 @@ impl AnchorAlignment { "t" | "top" => Ok(AnchorAlignment::START), "c" | "center" => Ok(AnchorAlignment::CENTER), "b" | "bottom" => Ok(AnchorAlignment::END), - _ => bail!( - r#"couldn't parse '{}' as y-alignment. Must be one of "top", "center", "bottom""#, - s - ), + _ => bail!(r#"couldn't parse '{}' as y-alignment. Must be one of "top", "center", "bottom""#, s), } } @@ -86,25 +80,16 @@ impl std::str::FromStr for AnchorPoint { fn from_str(s: &str) -> Result { if s == "center" { - Ok(AnchorPoint { - x: AnchorAlignment::CENTER, - y: AnchorAlignment::CENTER, - }) + Ok(AnchorPoint { x: AnchorAlignment::CENTER, y: AnchorAlignment::CENTER }) } else { let (first, second) = s .split_once(' ') .context("Failed to parse anchor: Must either be \"center\" or be formatted like \"top left\"")?; let x_y_result: Result<_> = try { - AnchorPoint { - x: AnchorAlignment::from_x_alignment(first)?, - y: AnchorAlignment::from_y_alignment(second)?, - } + AnchorPoint { x: AnchorAlignment::from_x_alignment(first)?, y: AnchorAlignment::from_y_alignment(second)? } }; x_y_result.or_else(|_| { - Ok(AnchorPoint { - x: AnchorAlignment::from_x_alignment(second)?, - y: AnchorAlignment::from_y_alignment(first)?, - }) + Ok(AnchorPoint { x: AnchorAlignment::from_x_alignment(second)?, y: AnchorAlignment::from_y_alignment(first)? }) }) } } diff --git a/src/config/xml_ext.rs b/src/config/xml_ext.rs index a2e2d84..710e733 100644 --- a/src/config/xml_ext.rs +++ b/src/config/xml_ext.rs @@ -31,11 +31,8 @@ impl<'a, 'b> fmt::Display for XmlNode<'a, 'b> { /// Get the part of a string that is selected by the start and end TextPos. /// Will panic if the range is out of bounds in any way. fn get_text_from_text_range(s: &str, (start_pos, end_pos): (roxmltree::TextPos, roxmltree::TextPos)) -> String { - let mut code_text = s - .lines() - .dropping(start_pos.row as usize - 1) - .take(end_pos.row as usize - (start_pos.row as usize - 1)) - .collect_vec(); + let mut code_text = + s.lines().dropping(start_pos.row as usize - 1).take(end_pos.row as usize - (start_pos.row as usize - 1)).collect_vec(); if let Some(first_line) = code_text.first_mut() { *first_line = first_line.split_at(start_pos.col as usize - 1).1; } @@ -133,11 +130,7 @@ impl<'a, 'b> fmt::Display for XmlElement<'a, 'b> { impl<'a, 'b> XmlElement<'a, 'b> { pub fn as_tag_string(&self) -> String { - let attrs = self - .attributes() - .iter() - .map(|attr| format!("{}=\"{}\"", attr.name(), attr.value())) - .join(" "); + let attrs = self.attributes().iter().map(|attr| format!("{}=\"{}\"", attr.name(), attr.value())).join(" "); format!("<{} {}>", self.tag_name(), attrs) } @@ -255,10 +248,7 @@ mod test { let input = "whatever"; let document = roxmltree::Document::parse(&input).unwrap(); let root_node = XmlNode::from(document.root_element()); - assert_eq!( - root_node.as_element().unwrap().only_child().unwrap().as_text_or_sourcecode(), - "whatever".to_string() - ); + assert_eq!(root_node.as_element().unwrap().only_child().unwrap().as_text_or_sourcecode(), "whatever".to_string()); } #[test] diff --git a/src/display_backend.rs b/src/display_backend.rs index 49e10bd..b55d97b 100644 --- a/src/display_backend.rs +++ b/src/display_backend.rs @@ -41,11 +41,7 @@ mod platform { let (conn, screen_num) = RustConnection::connect(None)?; let screen = conn.setup().roots[screen_num].clone(); let atoms = AtomCollection::new(&conn)?.reply()?; - Ok(X11Backend { - conn, - root_window: screen.root, - atoms, - }) + Ok(X11Backend { conn, root_window: screen.root, atoms }) } fn reserve_space_for( diff --git a/src/eww_state.rs b/src/eww_state.rs index 29f3db5..f32659f 100644 --- a/src/eww_state.rs +++ b/src/eww_state.rs @@ -51,10 +51,7 @@ impl EwwWindowState { fn put_handler(&mut self, handler: StateChangeHandler) { let handler = Arc::new(handler); for var_name in handler.used_variables() { - self.state_change_handlers - .entry(var_name.clone()) - .or_insert_with(Vec::new) - .push(handler.clone()); + self.state_change_handlers.entry(var_name.clone()).or_insert_with(Vec::new).push(handler.clone()); } } } @@ -75,10 +72,7 @@ impl std::fmt::Debug for EwwState { impl EwwState { pub fn from_default_vars(defaults: HashMap) -> Self { - EwwState { - variables_state: defaults, - ..EwwState::default() - } + EwwState { variables_state: defaults, ..EwwState::default() } } pub fn get_variables(&self) -> &HashMap { @@ -110,9 +104,7 @@ impl EwwState { /// Look up a single variable in the eww state, returning an `Err` when the value is not found. pub fn lookup(&self, var_name: &VarName) -> Result<&PrimitiveValue> { - self.variables_state - .get(var_name) - .with_context(|| format!("Unknown variable '{}' referenced", var_name)) + self.variables_state.get(var_name).with_context(|| format!("Unknown variable '{}' referenced", var_name)) } /// resolves a value if possible, using the current eww_state. @@ -134,19 +126,13 @@ impl EwwState { required_attributes: HashMap, set_value: F, ) { - let handler = StateChangeHandler { - func: Box::new(set_value), - unresolved_values: required_attributes, - }; + let handler = StateChangeHandler { func: Box::new(set_value), unresolved_values: required_attributes }; handler.run_with_state(&self.variables_state); // only store the handler if at least one variable is being used if handler.used_variables().next().is_some() { - self.windows - .entry(window_name.clone()) - .or_insert_with(EwwWindowState::default) - .put_handler(handler); + self.windows.entry(window_name.clone()).or_insert_with(EwwWindowState::default).put_handler(handler); } } @@ -155,9 +141,6 @@ impl EwwState { } pub fn vars_referenced_in(&self, window_name: &WindowName) -> std::collections::HashSet<&VarName> { - self.windows - .get(window_name) - .map(|window| window.state_change_handlers.keys().collect()) - .unwrap_or_default() + self.windows.get(window_name).map(|window| window.state_change_handlers.keys().collect()).unwrap_or_default() } } diff --git a/src/geometry.rs b/src/geometry.rs index d114234..7073cfb 100644 --- a/src/geometry.rs +++ b/src/geometry.rs @@ -26,11 +26,6 @@ impl Rectangular for Rect { impl Rectangular for gdk::Rectangle { fn get_rect(&self) -> Rect { - Rect { - x: self.x, - y: self.y, - width: self.width, - height: self.height, - } + Rect { x: self.x, y: self.y, width: self.width, height: self.height } } } diff --git a/src/ipc_server.rs b/src/ipc_server.rs index 493d10a..ac1e116 100644 --- a/src/ipc_server.rs +++ b/src/ipc_server.rs @@ -53,17 +53,11 @@ async fn handle_connection(mut stream: tokio::net::UnixStream, evt_send: Unbound /// 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_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/src/main.rs b/src/main.rs index e727b37..a96ce7b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,32 +35,20 @@ pub mod widgets; fn main() { let opts: opts::Opt = opts::Opt::from_env(); - let log_level_filter = if opts.log_debug { - log::LevelFilter::Debug - } else { - log::LevelFilter::Off - }; + let log_level_filter = if opts.log_debug { log::LevelFilter::Debug } else { log::LevelFilter::Off }; - pretty_env_logger::formatted_builder() - .filter(Some("eww"), log_level_filter) - .init(); + pretty_env_logger::formatted_builder().filter(Some("eww"), log_level_filter).init(); let result: Result<_> = try { - let paths = opts - .config_path - .map(EwwPaths::from_config_dir) - .unwrap_or_else(EwwPaths::default) - .context("Failed set paths")?; + let paths = + opts.config_path.map(EwwPaths::from_config_dir).unwrap_or_else(EwwPaths::default).context("Failed set paths")?; match opts.action { opts::Action::ClientOnly(action) => { client::handle_client_only_action(&paths, action)?; } opts::Action::WithServer(action) => { - log::info!( - "Trying to find server process at socket {}", - paths.get_ipc_socket_file().display() - ); + log::info!("Trying to find server process at socket {}", paths.get_ipc_socket_file().display()); match net::UnixStream::connect(&paths.get_ipc_socket_file()) { Ok(stream) => { log::info!("Connected to Eww server ({}).", &paths.get_ipc_socket_file().display()); @@ -122,9 +110,7 @@ impl EwwPaths { pub fn from_config_dir>(config_dir: P) -> Result { let config_dir = config_dir.as_ref(); let config_dir = if config_dir.is_file() { - config_dir - .parent() - .context("Given config file did not have a parent directory")? + config_dir.parent().context("Given config file did not have a parent directory")? } else { config_dir }; diff --git a/src/opts.rs b/src/opts.rs index f7a5f03..10d648c 100644 --- a/src/opts.rs +++ b/src/opts.rs @@ -133,16 +133,8 @@ impl Opt { impl From for Opt { fn from(other: RawOpt) -> Self { - let RawOpt { - action, - log_debug, - config, - } = other; - Opt { - action, - log_debug, - config_path: config, - } + let RawOpt { action, log_debug, config } = other; + Opt { action, log_debug, config_path: config } } } @@ -168,13 +160,7 @@ impl ActionWithServer { ActionWithServer::OpenMany { windows } => { return with_response_channel(|sender| app::DaemonCommand::OpenMany { windows, sender }); } - ActionWithServer::OpenWindow { - window_name, - pos, - size, - monitor, - anchor, - } => { + ActionWithServer::OpenWindow { window_name, pos, size, monitor, anchor } => { return with_response_channel(|sender| app::DaemonCommand::OpenWindow { window_name, pos, diff --git a/src/script_var_handler.rs b/src/script_var_handler.rs index 949b580..abaf547 100644 --- a/src/script_var_handler.rs +++ b/src/script_var_handler.rs @@ -122,10 +122,7 @@ struct PollVarHandler { impl PollVarHandler { fn new(evt_send: UnboundedSender) -> Result { - let handler = PollVarHandler { - evt_send, - poll_handles: HashMap::new(), - }; + let handler = PollVarHandler { evt_send, poll_handles: HashMap::new() }; Ok(handler) } @@ -177,10 +174,7 @@ struct TailVarHandler { impl TailVarHandler { fn new(evt_send: UnboundedSender) -> Result { - let handler = TailVarHandler { - evt_send, - tail_process_handles: HashMap::new(), - }; + let handler = TailVarHandler { evt_send, tail_process_handles: HashMap::new() }; Ok(handler) } diff --git a/src/server.rs b/src/server.rs index ed1f760..75470ce 100644 --- a/src/server.rs +++ b/src/server.rs @@ -70,10 +70,7 @@ pub fn initialize_server(paths: EwwPaths) -> Result<()> { fn init_async_part(paths: EwwPaths, ui_send: UnboundedSender) { std::thread::spawn(move || { - let rt = tokio::runtime::Builder::new_multi_thread() - .enable_all() - .build() - .expect("Failed to initialize tokio runtime"); + let rt = tokio::runtime::Builder::new_multi_thread().enable_all().build().expect("Failed to initialize tokio runtime"); rt.block_on(async { let filewatch_join_handle = { let ui_send = ui_send.clone(); @@ -168,10 +165,7 @@ fn do_detach(log_file_path: impl AsRef) -> Result<()> { .create(true) .append(true) .open(&log_file_path) - .expect(&format!( - "Error opening log file ({}), for writing", - log_file_path.as_ref().to_string_lossy() - )); + .expect(&format!("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)? { diff --git a/src/util.rs b/src/util.rs index a254017..8026c98 100644 --- a/src/util.rs +++ b/src/util.rs @@ -69,9 +69,7 @@ pub fn extend_safe, b: T, ) -> Vec { - b.into_iter() - .filter_map(|(k, v)| a.insert(k.clone(), v).map(|_| k.clone())) - .collect() + b.into_iter().filter_map(|(k, v)| a.insert(k.clone(), v).map(|_| k.clone())).collect() } /// read an scss file, replace all environment variable references within it and @@ -122,9 +120,7 @@ pub fn replace_env_var_references(input: String) -> String { static ref ENV_VAR_PATTERN: regex::Regex = regex::Regex::new(r"\$\{([^\s]*)\}").unwrap(); } ENV_VAR_PATTERN - .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/src/value/attr_value/attr_value_expr.rs b/src/value/attr_value/attr_value_expr.rs index cb0f9cb..888a32d 100644 --- a/src/value/attr_value/attr_value_expr.rs +++ b/src/value/attr_value/attr_value_expr.rs @@ -94,18 +94,13 @@ impl AttrValueExpr { match self { Literal(x) => Ok(AttrValueExpr::Literal(x)), VarRef(ref name) => Ok(Literal(AttrValue::from_primitive( - variables - .get(name) - .with_context(|| format!("Unknown variable {} referenced in {:?}", &name, &self))? - .clone(), + variables.get(name).with_context(|| format!("Unknown variable {} referenced in {:?}", &name, &self))?.clone(), ))), BinOp(box a, op, box b) => Ok(BinOp(box a.resolve_refs(variables)?, op, box b.resolve_refs(variables)?)), UnaryOp(op, box x) => Ok(UnaryOp(op, box x.resolve_refs(variables)?)), - IfElse(box a, box b, box c) => Ok(IfElse( - box a.resolve_refs(variables)?, - box b.resolve_refs(variables)?, - box c.resolve_refs(variables)?, - )), + IfElse(box a, box b, box c) => { + Ok(IfElse(box a.resolve_refs(variables)?, box b.resolve_refs(variables)?, box c.resolve_refs(variables)?)) + } } } @@ -132,10 +127,10 @@ impl AttrValueExpr { pub fn eval(self, values: &HashMap) -> Result { match self { AttrValueExpr::Literal(x) => x.resolve_fully(&values), - AttrValueExpr::VarRef(ref name) => values.get(name).cloned().context(format!( - "Got unresolved variable {} while trying to evaluate expression {:?}", - &name, &self - )), + AttrValueExpr::VarRef(ref name) => values + .get(name) + .cloned() + .context(format!("Got unresolved variable {} while trying to evaluate expression {:?}", &name, &self)), AttrValueExpr::BinOp(a, op, b) => { let a = a.eval(values)?; let b = b.eval(values)?; diff --git a/src/value/attr_value/parser.rs b/src/value/attr_value/parser.rs index ce63fd9..475e1aa 100644 --- a/src/value/attr_value/parser.rs +++ b/src/value/attr_value/parser.rs @@ -28,10 +28,7 @@ fn parse_num(i: &str) -> IResult<&str, i32, VerboseError<&str>> { } fn parse_stringlit(i: &str) -> IResult<&str, &str, VerboseError<&str>> { - alt(( - delimited(tag("'"), take_while(|c| c != '\''), tag("'")), - delimited(tag("\""), take_while(|c| c != '"'), tag("\"")), - ))(i) + alt((delimited(tag("'"), take_while(|c| c != '\''), tag("'")), delimited(tag("\""), take_while(|c| c != '"'), tag("\""))))(i) } fn parse_bool(i: &str) -> IResult<&str, &str, VerboseError<&str>> { @@ -43,13 +40,9 @@ fn parse_literal(i: &str) -> IResult<&str, &str, VerboseError<&str>> { } fn parse_identifier(i: &str) -> IResult<&str, &str, VerboseError<&str>> { - verify( - recognize(pair( - alt((alpha1, tag("_"), tag("-"))), - many0(alt((alphanumeric1, tag("_"), tag("-")))), - )), - |x| !["if", "then", "else"].contains(x), - )(i) + verify(recognize(pair(alt((alpha1, tag("_"), tag("-"))), many0(alt((alphanumeric1, tag("_"), tag("-")))))), |x| { + !["if", "then", "else"].contains(x) + })(i) } fn parse_unary_op(i: &str) -> IResult<&str, UnaryOp, VerboseError<&str>> { @@ -65,14 +58,8 @@ fn parse_factor(i: &str) -> IResult<&str, AttrValueExpr, VerboseError<&str>> { let (i, factor) = alt(( context("expression", ws(delimited(tag("("), parse_expr, tag(")")))), context("if-expression", ws(parse_ifelse)), - context( - "literal", - map(ws(parse_literal), |x| AttrValueExpr::Literal(AttrValue::parse_string(x))), - ), - context( - "identifier", - map(ws(parse_identifier), |x| AttrValueExpr::VarRef(VarName(x.to_string()))), - ), + context("literal", map(ws(parse_literal), |x| AttrValueExpr::Literal(AttrValue::parse_string(x)))), + context("identifier", map(ws(parse_identifier), |x| AttrValueExpr::VarRef(VarName(x.to_string())))), ))(i)?; Ok(( i, @@ -91,9 +78,7 @@ fn parse_term3(i: &str) -> IResult<&str, AttrValueExpr, VerboseError<&str>> { map(preceded(tag("%"), parse_factor), |x| (BinOp::Mod, x)), )))(i)?; - let exprs = remainder - .into_iter() - .fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); + let exprs = remainder.into_iter().fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); Ok((i, exprs)) } @@ -104,9 +89,7 @@ fn parse_term2(i: &str) -> IResult<&str, AttrValueExpr, VerboseError<&str>> { map(preceded(tag("-"), parse_term3), |x| (BinOp::Minus, x)), )))(i)?; - let exprs = remainder - .into_iter() - .fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); + let exprs = remainder.into_iter().fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); Ok((i, exprs)) } @@ -120,9 +103,7 @@ fn parse_term1(i: &str) -> IResult<&str, AttrValueExpr, VerboseError<&str>> { map(preceded(tag("<"), parse_term2), |x| (BinOp::LT, x)), )))(i)?; - let exprs = remainder - .into_iter() - .fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); + let exprs = remainder.into_iter().fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); Ok((i, exprs)) } @@ -134,9 +115,7 @@ pub fn parse_expr(i: &str) -> IResult<&str, AttrValueExpr, VerboseError<&str>> { map(preceded(tag("?:"), parse_term1), |x| (BinOp::Elvis, x)), )))(i)?; - let exprs = remainder - .into_iter() - .fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); + let exprs = remainder.into_iter().fold(initial, |acc, (op, expr)| AttrValueExpr::BinOp(box acc, op, box expr)); Ok((i, exprs)) } @@ -161,10 +140,7 @@ mod test { use pretty_assertions::assert_eq; #[test] fn test_parser() { - assert_eq!( - AttrValueExpr::Literal(AttrValue::from_primitive("12")), - AttrValueExpr::parse("12").unwrap() - ); + assert_eq!(AttrValueExpr::Literal(AttrValue::from_primitive("12")), AttrValueExpr::parse("12").unwrap()); assert_eq!( AttrValueExpr::UnaryOp(UnaryOp::Not, box AttrValueExpr::Literal(AttrValue::from_primitive("false"))), AttrValueExpr::parse("!false").unwrap() diff --git a/src/value/coords.rs b/src/value/coords.rs index e017ace..cb50699 100644 --- a/src/value/coords.rs +++ b/src/value/coords.rs @@ -69,10 +69,7 @@ impl fmt::Debug for Coords { impl Coords { pub fn from_pixels(x: i32, y: i32) -> Self { - Coords { - x: NumWithUnit::Pixels(x), - y: NumWithUnit::Pixels(y), - } + Coords { x: NumWithUnit::Pixels(x), y: NumWithUnit::Pixels(y) } } /// parse a string for x and a string for y into a [`Coords`] object. @@ -104,13 +101,7 @@ 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/src/value/primitive.rs b/src/value/primitive.rs index d869d00..fe51a4c 100644 --- a/src/value/primitive.rs +++ b/src/value/primitive.rs @@ -92,21 +92,15 @@ impl PrimitiveValue { } pub fn as_f64(&self) -> Result { - self.0 - .parse() - .map_err(|e| anyhow!("couldn't convert {:?} to f64: {}", &self, e)) + self.0.parse().map_err(|e| anyhow!("couldn't convert {:?} to f64: {}", &self, e)) } pub fn as_i32(&self) -> Result { - self.0 - .parse() - .map_err(|e| anyhow!("couldn't convert {:?} to i32: {}", &self, e)) + self.0.parse().map_err(|e| anyhow!("couldn't convert {:?} to i32: {}", &self, e)) } pub fn as_bool(&self) -> Result { - self.0 - .parse() - .map_err(|e| anyhow!("couldn't convert {:?} to bool: {}", &self, e)) + self.0.parse().map_err(|e| anyhow!("couldn't convert {:?} to bool: {}", &self, e)) } pub fn as_vec(&self) -> Result> { @@ -141,36 +135,21 @@ mod test { use pretty_assertions::assert_eq; #[test] fn test_parse_vec() { - assert_eq!( - vec![""], - parse_vec("[]".to_string()).unwrap(), - "should be able to parse empty lists" - ); - assert_eq!( - vec!["hi"], - parse_vec("[hi]".to_string()).unwrap(), - "should be able to parse single element list" - ); + assert_eq!(vec![""], parse_vec("[]".to_string()).unwrap(), "should be able to parse empty lists"); + assert_eq!(vec!["hi"], parse_vec("[hi]".to_string()).unwrap(), "should be able to parse single element list"); assert_eq!( vec!["hi", "ho", "hu"], parse_vec("[hi,ho,hu]".to_string()).unwrap(), "should be able to parse three element list" ); - assert_eq!( - vec!["hi,ho"], - parse_vec("[hi\\,ho]".to_string()).unwrap(), - "should be able to parse list with escaped comma" - ); + assert_eq!(vec!["hi,ho"], parse_vec("[hi\\,ho]".to_string()).unwrap(), "should be able to parse list with escaped comma"); assert_eq!( vec!["hi,ho", "hu"], parse_vec("[hi\\,ho,hu]".to_string()).unwrap(), "should be able to parse two element list with escaped comma" ); assert!(parse_vec("".to_string()).is_err(), "Should fail when parsing empty string"); - assert!( - parse_vec("[a,b".to_string()).is_err(), - "Should fail when parsing unclosed list" - ); + assert!(parse_vec("[a,b".to_string()).is_err(), "Should fail when parsing unclosed list"); assert!(parse_vec("a]".to_string()).is_err(), "Should fail when parsing unopened list"); } } diff --git a/src/widgets/mod.rs b/src/widgets/mod.rs index 15e6c04..dc4fc9a 100644 --- a/src/widgets/mod.rs +++ b/src/widgets/mod.rs @@ -64,18 +64,13 @@ fn build_builtin_gtk_widget( widget_definitions: &HashMap, widget: &widget_node::Generic, ) -> Result> { - let mut bargs = BuilderArgs { - eww_state, - widget, - window_name, - unhandled_attrs: widget.attrs.keys().collect(), - widget_definitions, - }; + let mut bargs = + BuilderArgs { eww_state, widget, window_name, unhandled_attrs: widget.attrs.keys().collect(), widget_definitions }; let gtk_widget = match widget_to_gtk_widget(&mut bargs) { Ok(Some(gtk_widget)) => gtk_widget, result => { return result.with_context(|| { - anyhow!( + format!( "{}Error building widget {}", bargs.widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(), bargs.widget.name, @@ -89,16 +84,14 @@ fn build_builtin_gtk_widget( if let Some(gtk_widget) = gtk_widget.dynamic_cast_ref::() { resolve_container_attrs(&mut bargs, >k_widget); for child in &widget.children { - let child_widget = child - .render(bargs.eww_state, window_name, widget_definitions) - .with_context(|| { - format!( - "{}error while building child '{:#?}' of '{}'", - widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(), - &child, - >k_widget.get_widget_name() - ) - })?; + let child_widget = child.render(bargs.eww_state, window_name, widget_definitions).with_context(|| { + format!( + "{}error while building child '{:#?}' of '{}'", + widget.text_pos.map(|x| format!("{} |", x)).unwrap_or_default(), + &child, + >k_widget.get_widget_name() + ) + })?; gtk_widget.add(&child_widget); child_widget.show(); } diff --git a/src/widgets/widget_definitions.rs b/src/widgets/widget_definitions.rs index 2be85bc..a424825 100644 --- a/src/widgets/widget_definitions.rs +++ b/src/widgets/widget_definitions.rs @@ -25,7 +25,7 @@ pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result build_gtk_color_chooser(bargs)?.upcast(), "combo-box-text" => build_gtk_combo_box_text(bargs)?.upcast(), "checkbox" => build_gtk_checkbox(bargs)?.upcast(), - + "if-else" => build_if_else(bargs)?.upcast(), _ => return Ok(None), }; Ok(Some(gtk_widget)) @@ -37,11 +37,7 @@ pub(super) fn widget_to_gtk_widget(bargs: &mut BuilderArgs) -> Result Result { + if bargs.widget.children.len() != 2 { + bail!("if-widget needs to have exactly two children, but had {}", bargs.widget.children.len()); + } + let gtk_widget = gtk::Box::new(gtk::Orientation::Vertical, 0); + let (yes_widget, no_widget) = (bargs.widget.children[0].clone(), bargs.widget.children[1].clone()); + + let yes_widget = yes_widget.render(bargs.eww_state, bargs.window_name, bargs.widget_definitions)?; + let no_widget = no_widget.render(bargs.eww_state, bargs.window_name, bargs.widget_definitions)?; + + resolve_block!(bargs, gtk_widget, { + prop(cond: as_bool) { + gtk_widget.get_children().iter().for_each(|w| gtk_widget.remove(w)); + if cond { + gtk_widget.add(&yes_widget) + } else { + gtk_widget.add(&no_widget) + } + } + }); + Ok(gtk_widget) +} + /// @widget combo-box-text /// @desc A combo box allowing the user to choose between several items. fn build_gtk_combo_box_text(bargs: &mut BuilderArgs) -> Result { @@ -272,10 +291,7 @@ fn build_gtk_color_chooser(bargs: &mut BuilderArgs) -> Result 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)), - ); + 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))); resolve_block!(bargs, gtk_widget, { // @prop flipped - flip the direction prop(flipped: as_bool) { gtk_widget.set_inverted(flipped) }, @@ -472,10 +488,7 @@ fn parse_orientation(o: &str) -> Result { Ok(match o { "vertical" | "v" => gtk::Orientation::Vertical, "horizontal" | "h" => gtk::Orientation::Horizontal, - _ => bail!( - r#"Couldn't parse orientation: '{}'. Possible values are "vertical", "v", "horizontal", "h""#, - o - ), + _ => bail!(r#"Couldn't parse orientation: '{}'. Possible values are "vertical", "v", "horizontal", "h""#, o), }) } @@ -487,10 +500,7 @@ fn parse_align(o: &str) -> Result { "center" => gtk::Align::Center, "start" => gtk::Align::Start, "end" => gtk::Align::End, - _ => bail!( - r#"Couldn't parse alignment: '{}'. Possible values are "fill", "baseline", "center", "start", "end""#, - o - ), + _ => bail!(r#"Couldn't parse alignment: '{}'. Possible values are "fill", "baseline", "center", "start", "end""#, o), }) } diff --git a/src/widgets/widget_node.rs b/src/widgets/widget_node.rs index e305e0f..d428228 100644 --- a/src/widgets/widget_node.rs +++ b/src/widgets/widget_node.rs @@ -66,9 +66,7 @@ pub struct Generic { impl Generic { pub fn get_attr(&self, key: &str) -> Result<&AttrValue> { - self.attrs - .get(key) - .context(format!("attribute '{}' missing from use of '{}'", key, &self.name)) + self.attrs.get(key).context(format!("attribute '{}' missing from use of '{}'", key, &self.name)) } /// returns all the variables that are referenced in this widget @@ -92,10 +90,8 @@ impl WidgetNode for Generic { window_name: &WindowName, widget_definitions: &HashMap, ) -> Result { - Ok( - crate::widgets::build_builtin_gtk_widget(eww_state, window_name, widget_definitions, &self)? - .with_context(|| format!("Unknown widget '{}'", self.get_name()))?, - ) + Ok(crate::widgets::build_builtin_gtk_widget(eww_state, window_name, widget_definitions, &self)? + .with_context(|| format!("Unknown widget '{}'", self.get_name()))?) } } @@ -114,20 +110,12 @@ pub fn generate_generic_widget_node( .collect::>(); let content = generate_generic_widget_node(defs, &new_local_env, def.structure.clone())?; - Ok(Box::new(UserDefined { - name: w.name, - text_pos: w.text_pos, - content, - })) + Ok(Box::new(UserDefined { name: w.name, text_pos: w.text_pos, content })) } else { Ok(Box::new(Generic { name: w.name, text_pos: w.text_pos, - attrs: w - .attrs - .into_iter() - .map(|(name, value)| (name, value.resolve_one_level(local_env))) - .collect(), + attrs: w.attrs.into_iter().map(|(name, value)| (name, value.resolve_one_level(local_env))).collect(), children: w .children .into_iter()