Repository: espanso/espanso (language: rust)

Issue:
unused crates
I ran [cargo-udeps](https://github.com/est31/cargo-udeps) to know if we are having unused dependencies and gave a few we can clean. (or at least move them into dev dependencies

```
cargo +nightly udeps --all-targets
```

<details>

```
unused dependencies:
`espanso v2.2.1 (C:\Users\aucac\other-repos\espanso\espanso\espanso)`
└─── dependencies
     └─── "maplit"
`espanso-clipboard v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-clipboard)`
└─── dependencies
     ├─── "lazy_static"
     └─── "lazycell"
`espanso-engine v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-engine)`
└─── dev-dependencies
     └─── "tempdir"
`espanso-info v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-info)`
└─── dependencies
     ├─── "lazy_static"
     ├─── "lazycell"
     └─── "thiserror"
`espanso-inject v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-inject)`
├─── dependencies
│    └─── "lazycell"
└─── dev-dependencies
     └─── "enum-as-inner"
`espanso-ipc v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-ipc)`
└─── dependencies
     └─── "crossbeam"
`espanso-kvs v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-kvs)`
└─── dependencies
     └─── "log"
`espanso-mac-utils v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-mac-utils)`
├─── dependencies
│    ├─── "anyhow"
│    ├─── "lazy_static"
│    ├─── "lazycell"
│    ├─── "log"
│    ├─── "regex"
│    └─── "thiserror"
└─── build-dependencies
     └─── "cc"
`espanso-match v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-match)`
└─── dependencies
     ├─── "anyhow"
     └─── "thiserror"
`espanso-migrate v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-migrate)`
├─── dependencies
│    ├─── "dunce"
│    └─── "log"
└─── dev-dependencies
     └─── "tempfile"
`espanso-modulo v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-modulo)`
├─── dependencies
│    ├─── "log"
│    └─── "serde_json"
└─── build-dependencies
     └─── "glob"
`espanso-path v0.1.0 (C:\Users\aucac\other-repos\espanso\espanso\espanso-path)`
└─── dependencies
     ├─── "anyhow"
     └─── "thiserror"
Note: They might be false-positive.
      For example, `cargo-udeps` cannot detect usage of crates that are only used in doc-tests.
      To ignore some dependencies, write `package.metadata.cargo-udeps.ignore` in Cargo.toml.
```

</details>

I can submit a PR after the other pending are merged or rejected ( #1831 , #1830 , #1829 and #1797). Otherwise it would be merge conflicts galore!



Discussion / hints:

Fix patch:
diff --git a/Cargo.lock b/Cargo.lock
index 082f34a8..f62be84f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -157,9 +157,9 @@ checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
 
 [[package]]
 name = "bzip2"
-version = "0.4.3"
+version = "0.4.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6afcd980b5f3a45017c57e57a2fcccbb351cc43a356ce117ef760ef8052b89b0"
+checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
 dependencies = [
  "bzip2-sys",
  "libc",
@@ -655,7 +655,6 @@ dependencies = [
  "libc",
  "log",
  "log-panics",
- "maplit",
  "named_pipe",
  "notify",
  "opener",
@@ -678,8 +677,6 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "cc",
- "lazy_static",
- "lazycell",
  "log",
  "thiserror",
  "wait-timeout",
@@ -735,7 +732,6 @@ dependencies = [
  "html2text",
  "log",
  "markdown",
- "tempdir",
  "thiserror",
 ]
 
@@ -745,10 +741,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "cc",
- "lazy_static",
- "lazycell",
  "log",
- "thiserror",
  "widestring",
 ]
 
@@ -758,10 +751,8 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "cc",
- "enum-as-inner 0.6.0",
  "itertools",
  "lazy_static",
- "lazycell",
  "libc",
  "log",
  "regex",
@@ -775,7 +766,6 @@ name = "espanso-ipc"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "crossbeam",
  "log",
  "named_pipe",
  "serde",
@@ -788,7 +778,6 @@ name = "espanso-kvs"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "log",
  "serde",
  "serde_json",
  "tempdir",
@@ -799,23 +788,17 @@ dependencies = [
 name = "espanso-mac-utils"
 version = "0.1.0"
 dependencies = [
- "anyhow",
  "cc",
  "lazy_static",
- "lazycell",
- "log",
  "regex",
- "thiserror",
 ]
 
 [[package]]
 name = "espanso-match"
 version = "0.1.0"
 dependencies = [
- "anyhow",
  "log",
  "regex",
- "thiserror",
  "unicase",
 ]
 
@@ -824,17 +807,14 @@ name = "espanso-migrate"
 version = "0.1.0"
 dependencies = [
  "anyhow",
- "dunce",
  "fs_extra",
  "glob",
  "include_dir",
  "lazy_static",
- "log",
  "path-slash",
  "pretty_assertions",
  "regex",
  "tempdir",
- "tempfile",
  "test-case",
  "thiserror",
  "walkdir",
@@ -849,10 +829,8 @@ dependencies = [
  "cc",
  "glob",
  "lazy_static",
- "log",
  "regex",
  "serde",
- "serde_json",
  "thiserror",
  "winres",
  "zip",
@@ -885,10 +863,8 @@ dependencies = [
 name = "espanso-path"
 version = "0.1.0"
 dependencies = [
- "anyhow",
  "dirs 3.0.1",
  "log",
- "thiserror",
 ]
 
 [[package]]
@@ -1555,12 +1531,6 @@ dependencies = [
  "libc",
 ]
 
-[[package]]
-name = "maplit"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d"
-
 [[package]]
 name = "markdown"
 version = "0.3.0"
diff --git a/Cargo.toml b/Cargo.toml
index 2245c83d..e6dd0f65 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -20,3 +20,29 @@ members = [
   "espanso-engine",
   "espanso-package",
 ]
+
+[workspace.lints.clippy]
+too_many_lines = "allow"
+needless_pass_by_value = "allow"
+missing_errors_doc = "allow"
+missing_panics_doc = "allow"
+cast_possible_wrap = "allow"
+module_name_repetitions = "allow"
+match_same_arms = "allow"
+unnecessary_wraps = "allow"
+cast_possible_truncation = "allow"
+cast_sign_loss = "allow"
+cast_lossless = "allow"
+ptr_as_ptr = "allow"
+as_conversions = "allow"
+used_underscore_binding = "allow"
+no_effect_underscore_binding = "allow"
+borrow_as_ptr = "allow"
+must_use_candidate = "allow"
+similar_names = "allow"
+struct_excessive_bools = "allow"
+wildcard_imports = "allow"
+items_after_statements = "allow"
+struct_field_names = "allow"
+unused_self = "allow"
+pedantic = { level = "warn", priority = -2 }
diff --git a/espanso-clipboard/Cargo.toml b/espanso-clipboard/Cargo.toml
index be7e7998..9e096d9d 100644
--- a/espanso-clipboard/Cargo.toml
+++ b/espanso-clipboard/Cargo.toml
@@ -16,10 +16,11 @@ avoid-gdi = []
 
 [dependencies]
 log = "0.4.14"
-lazycell = "1.3.0"
 anyhow = "1.0.38"
 thiserror = "1.0.23"
-lazy_static = "1.4.0"
+
+[lints]
+workspace = true
 
 [target.'cfg(windows)'.dependencies]
 widestring = "0.4.3"
diff --git a/espanso-config/Cargo.toml b/espanso-config/Cargo.toml
index 530c2407..71eca641 100644
--- a/espanso-config/Cargo.toml
+++ b/espanso-config/Cargo.toml
@@ -23,3 +23,6 @@ indoc = "1.0.3"
 tempdir = "0.3.7"
 tempfile = "3.2.0"
 mockall = "0.9.1"
+
+[lints]
+workspace = true
diff --git a/espanso-config/src/config/mod.rs b/espanso-config/src/config/mod.rs
index 23ef0d8b..0b4890b4 100644
--- a/espanso-config/src/config/mod.rs
+++ b/espanso-config/src/config/mod.rs
@@ -147,7 +147,7 @@ pub trait Config: Send + Sync {
   // Note: currently not working on Linux
   fn show_icon(&self) -> bool;
 
-  // If false, avoid showing the SecureInput notification on macOS
+  // If false, avoid showing the `SecureInput`` notification on macOS
   fn secure_input_notification(&self) -> bool;
 
   // The number of milliseconds to wait after a form has been closed.
diff --git a/espanso-config/src/config/path.rs b/espanso-config/src/config/path.rs
index b55c5b06..bf93184c 100644
--- a/espanso-config/src/config/path.rs
+++ b/espanso-config/src/config/path.rs
@@ -20,6 +20,7 @@
 use std::{collections::HashSet, path::Path};
 
 use glob::glob;
+use lazy_static::lazy_static;
 use log::error;
 use regex::Regex;
 
diff --git a/espanso-config/src/config/store.rs b/espanso-config/src/config/store.rs
index 15767261..a2c37d66 100644
--- a/espanso-config/src/config/store.rs
+++ b/espanso-config/src/config/store.rs
@@ -127,8 +127,11 @@ impl DefaultConfigStore {
     ))
   }
 
-  pub fn from_configs(default: Arc<dyn Config>, customs: Vec<Arc<dyn Config>>) -> Result<Self> {
-    Ok(Self { default, customs })
+  pub fn from_configs(
+    default: Arc<dyn Config>,
+    customs: Vec<Arc<dyn Config>>,
+  ) -> DefaultConfigStore {
+    Self { default, customs }
   }
 }
 
diff --git a/espanso-config/src/legacy/mod.rs b/espanso-config/src/legacy/mod.rs
index 83a3d0e8..e1156c9d 100644
--- a/espanso-config/src/legacy/mod.rs
+++ b/espanso-config/src/legacy/mod.rs
@@ -77,7 +77,7 @@ pub fn load(
     custom_configs.push(Arc::new(custom_config));
   }
 
-  let config_store = DefaultConfigStore::from_configs(Arc::new(default_config), custom_configs)?;
+  let config_store = DefaultConfigStore::from_configs(Arc::new(default_config), custom_configs);
   let match_store = LegacyMatchStore::new(match_groups);
 
   Ok((Box::new(config_store), Box::new(match_store)))
diff --git a/espanso-config/src/lib.rs b/espanso-config/src/lib.rs
index adbbc879..510c9f8b 100644
--- a/espanso-config/src/lib.rs
+++ b/espanso-config/src/lib.rs
@@ -23,9 +23,6 @@ use matches::store::MatchStore;
 use std::path::Path;
 use thiserror::Error;
 
-#[macro_use]
-extern crate lazy_static;
-
 pub mod config;
 mod counter;
 pub mod error;
diff --git a/espanso-config/src/matches/group/loader/mod.rs b/espanso-config/src/matches/group/loader/mod.rs
index ed32c667..8253083f 100644
--- a/espanso-config/src/matches/group/loader/mod.rs
+++ b/espanso-config/src/matches/group/loader/mod.rs
@@ -18,6 +18,7 @@
  */
 
 use anyhow::Result;
+use lazy_static::lazy_static;
 use std::path::Path;
 use thiserror::Error;
 
diff --git a/espanso-config/src/matches/group/loader/yaml/mod.rs b/espanso-config/src/matches/group/loader/yaml/mod.rs
index 3cda3f4a..887c00f3 100644
--- a/espanso-config/src/matches/group/loader/yaml/mod.rs
+++ b/espanso-config/src/matches/group/loader/yaml/mod.rs
@@ -27,6 +27,7 @@ use crate::{
   },
 };
 use anyhow::{anyhow, bail, Context, Result};
+use lazy_static::lazy_static;
 use parse::YAMLMatchGroup;
 use regex::{Captures, Regex};
 
@@ -352,8 +353,7 @@ mod tests {
     let (m, warnings) = create_match_with_warnings(yaml, false)?;
     assert!(
       warnings.is_empty(),
-      "warnings were detected but not handled: {:?}",
-      warnings
+      "warnings were detected but not handled: {warnings:?}"
     );
     Ok(m)
   }
diff --git a/espanso-detect/Cargo.toml b/espanso-detect/Cargo.toml
index de50b5fe..a933282f 100644
--- a/espanso-detect/Cargo.toml
+++ b/espanso-detect/Cargo.toml
@@ -18,6 +18,12 @@ thiserror = "1.0.23"
 regex = "1.5.5"
 lazy_static = "1.4.0"
 
+[dev-dependencies]
+enum-as-inner = "0.6.0"
+
+[lints]
+workspace = true
+
 [target.'cfg(windows)'.dependencies]
 widestring = "0.4.3"
 
@@ -28,6 +34,3 @@ sctk = { package = "smithay-client-toolkit", version = "0.16.1", optional = true
 
 [build-dependencies]
 cc = "1.0.73"
-
-[dev-dependencies]
-enum-as-inner = "0.6.0"
diff --git a/espanso-detect/src/evdev/device.rs b/espanso-detect/src/evdev/device.rs
index ab2173f5..bf4ea5b1 100644
--- a/espanso-detect/src/evdev/device.rs
+++ b/espanso-detect/src/evdev/device.rs
@@ -206,7 +206,7 @@ impl Device {
 
   pub fn update_modifier_state(
     &mut self,
-    modifiers_state: &ModifiersState,
+    modifiers_state: ModifiersState,
     modifiers_map: &HashMap<String, u32>,
   ) {
     if modifiers_state.alt {
diff --git a/espanso-detect/src/evdev/hotkey.rs b/espanso-detect/src/evdev/hotkey.rs
index bb768c3b..4fd88ef0 100644
--- a/espanso-detect/src/evdev/hotkey.rs
+++ b/espanso-detect/src/evdev/hotkey.rs
@@ -88,7 +88,7 @@ impl HotKeyFilter {
         }
       }));
     } else {
-      key_code = Some(event.code)
+      key_code = Some(event.code);
     }
 
     // Remove the old entries
@@ -112,15 +112,15 @@ impl HotKeyFilter {
       to_be_removed.sort();
       to_be_removed.dedup();
       to_be_removed.reverse();
-      to_be_removed.into_iter().for_each(|index| {
+      for index in to_be_removed {
         self.memory.remove(index);
-      })
+      }
     }
 
     if let Some(code) = key_code {
       self.memory.push((code, Instant::now()));
 
-      for (id, codes) in self.hotkey_raw_map.iter() {
+      for (id, codes) in &self.hotkey_raw_map {
         if codes
           .iter()
           .all(|hk_code| self.memory.iter().any(|(m_code, _)| m_code == hk_code))
@@ -139,7 +139,7 @@ impl HotKeyFilter {
     let key_code = self.map.get(&hk.key.to_code()?)?;
     codes.push(*key_code);
 
-    for modifier in hk.modifiers.iter() {
+    for modifier in &hk.modifiers {
       let code = self.map.get(&modifier.to_code()?)?;
       codes.push(*code);
     }
diff --git a/espanso-detect/src/evdev/mod.rs b/espanso-detect/src/evdev/mod.rs
index 9c90ca35..075fcd94 100644
--- a/espanso-detect/src/evdev/mod.rs
+++ b/espanso-detect/src/evdev/mod.rs
@@ -44,9 +44,24 @@ use log::{debug, error, info, trace, warn};
 use thiserror::Error;
 
 use crate::event::{InputEvent, Key, KeyboardEvent, Variant};
-use crate::event::{Key::*, MouseButton, MouseEvent};
-use crate::{event::HotKeyEvent, event::Variant::*, hotkey::HotKey};
-use crate::{event::Status::*, KeyboardConfig, Source, SourceCallback, SourceCreationOptions};
+use crate::event::{
+  Key::{
+    Alt, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Backspace, CapsLock, Control, End, Enter,
+    Escape, Home, Meta, NumLock, Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6,
+    Numpad7, Numpad8, Numpad9, Other, PageDown, PageUp, Shift, Space, Tab, F1, F10, F11, F12, F13,
+    F14, F15, F16, F17, F18, F19, F2, F20, F3, F4, F5, F6, F7, F8, F9,
+  },
+  MouseButton, MouseEvent,
+};
+use crate::{
+  event::HotKeyEvent,
+  event::Variant::{Left, Right},
+  hotkey::HotKey,
+};
+use crate::{
+  event::Status::{Pressed, Released},
+  KeyboardConfig, Source, SourceCallback, SourceCreationOptions,
+};
 
 use self::{
   device::{DeviceError, RawInputEvent, KEY_STATE_PRESS, KEY_STATE_RELEASE},
@@ -138,7 +153,7 @@ impl Source for EVDEVSource {
       debug!("Updating device modifier state: {:?}", modifiers_state);
 
       for device in &mut self.devices {
-        device.update_modifier_state(&modifiers_state, &self._modifiers_map);
+        device.update_modifier_state(modifiers_state, &self._modifiers_map);
       }
     }
 
@@ -199,10 +214,9 @@ impl Source for EVDEVSource {
       if ret < 0 {
         if unsafe { *errno_ptr } == EINTR {
           continue;
-        } else {
-          error!("Could not poll for events, {}", unsafe { *errno_ptr });
-          return Err(EVDEVSourceError::Internal().into());
         }
+        error!("Could not poll for events, {}", unsafe { *errno_ptr });
+        return Err(EVDEVSourceError::Internal().into());
       }
 
       #[allow(clippy::needless_range_loop)]
@@ -212,13 +226,13 @@ impl Source for EVDEVSource {
         match device.read() {
           Ok(events) if !events.is_empty() => {
             // Convert raw events to the common format and invoke the callback
-            events.into_iter().for_each(|raw_event| {
+            for raw_event in events {
               let event: Option<InputEvent> = raw_event.into();
               if let Some(event) = event {
                 // On Wayland we need to detect the global shortcuts manually
                 if let InputEvent::Keyboard(key_event) = &event {
                   if let Some(hotkey) = (*hotkey_filter).process_event(key_event) {
-                    event_callback(InputEvent::HotKey(HotKeyEvent { hotkey_id: hotkey }))
+                    event_callback(InputEvent::HotKey(HotKeyEvent { hotkey_id: hotkey }));
                   }
                 }
 
@@ -226,7 +240,7 @@ impl Source for EVDEVSource {
               } else {
                 trace!("unable to convert raw event to input event");
               }
-            });
+            }
           }
           Ok(_) => { /* SKIP EMPTY */ }
           Err(err) => {
@@ -250,7 +264,7 @@ impl Source for EVDEVSource {
                 return Err(EVDEVSourceError::Internal().into());
               }
             } else {
-              error!("Can't read from device {}: {}", device.get_path(), err)
+              error!("Can't read from device {}: {}", device.get_path(), err);
             }
           }
         }
diff --git a/espanso-detect/src/evdev/sync/wayland.rs b/espanso-detect/src/evdev/sync/wayland.rs
index c8f33892..f48af4e8 100644
--- a/espanso-detect/src/evdev/sync/wayland.rs
+++ b/espanso-detect/src/evdev/sync/wayland.rs
@@ -46,8 +46,7 @@ pub fn get_modifiers_state() -> Result<Option<super::ModifiersState>> {
       // Keep last event in priority order : Close > Configure > Refresh
       let replace = matches!(
         (&evt, &*next_action),
-        (_, &None)
-          | (_, &Some(WEvent::Refresh))
+        (_, &None | &Some(WEvent::Refresh))
           | (&WEvent::Configure { .. }, &Some(WEvent::Configure { .. }))
           | (&WEvent::Close, _)
       );
@@ -131,7 +130,7 @@ pub fn get_modifiers_state() -> Result<Option<super::ModifiersState>> {
             eprintln!(
               "Failed to map keyboard on seat {} : {:?}.",
               seat_data.name, e
-            )
+            );
           }
         }
       }
@@ -166,7 +165,7 @@ pub fn get_modifiers_state() -> Result<Option<super::ModifiersState>> {
       }) => {
         if let Some((w, h)) = new_size {
           window.resize(w, h);
-          dimensions = (w, h)
+          dimensions = (w, h);
         }
         window.refresh();
         redraw(&mut pool, window.surface(), dimensions).expect("Failed to draw");
@@ -205,7 +204,7 @@ fn keyboard_event_handler(
       caps_lock: modifiers.caps_lock,
       meta: modifiers.logo,
       num_lock: modifiers.num_lock,
-    })
+    });
   }
 }
 
diff --git a/espanso-detect/src/hotkey/keys.rs b/espanso-detect/src/hotkey/keys.rs
index 8e25a114..d4bc22a9 100644
--- a/espanso-detect/src/hotkey/keys.rs
+++ b/espanso-detect/src/hotkey/keys.rs
@@ -19,6 +19,7 @@
 
 use std::fmt::Display;
 
+use lazy_static::lazy_static;
 use regex::Regex;
 
 lazy_static! {
diff --git a/espanso-detect/src/layout/gnome.rs b/espanso-detect/src/layout/gnome.rs
index 24252581..f0e85e03 100644
--- a/espanso-detect/src/layout/gnome.rs
+++ b/espanso-detect/src/layout/gnome.rs
@@ -17,11 +17,11 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-use std::process::Command;
-
+use lazy_static::lazy_static;
 use log::error;
 use regex::Regex;
 use std::path::PathBuf;
+use std::process::Command;
 
 lazy_static! {
   static ref LAYOUT_EXTRACT_REGEX: Regex = Regex::new(r"^\[\('.*?', '(.*?)'\)").unwrap();
diff --git a/espanso-detect/src/lib.rs b/espanso-detect/src/lib.rs
index 4df5cb9a..26ed5c9a 100644
--- a/espanso-detect/src/lib.rs
+++ b/espanso-detect/src/lib.rs
@@ -38,9 +38,6 @@ pub mod evdev;
 #[cfg(target_os = "macos")]
 pub mod mac;
 
-#[macro_use]
-extern crate lazy_static;
-
 pub type SourceCallback = Box<dyn Fn(event::InputEvent)>;
 
 pub trait Source {
diff --git a/espanso-detect/src/mac/mod.rs b/espanso-detect/src/mac/mod.rs
index 18e39ea2..f12dddb6 100644
--- a/espanso-detect/src/mac/mod.rs
+++ b/espanso-detect/src/mac/mod.rs
@@ -17,6 +17,10 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use anyhow::Result;
+use lazy_static::lazy_static;
+use lazycell::LazyCell;
+use log::{error, trace, warn};
 use std::{
   convert::TryInto,
   ffi::CStr,
@@ -25,17 +29,26 @@ use std::{
     Arc, Mutex,
   },
 };
-
-use lazycell::LazyCell;
-use log::{error, trace, warn};
-
-use anyhow::Result;
 use thiserror::Error;
 
 use crate::event::{HotKeyEvent, InputEvent, Key, KeyboardEvent, Status, Variant};
-use crate::event::{Key::*, MouseButton, MouseEvent};
-use crate::{event::Status::*, Source, SourceCallback};
-use crate::{event::Variant::*, hotkey::HotKey};
+use crate::event::{
+  Key::{
+    Alt, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Backspace, CapsLock, Control, End, Enter,
+    Escape, Home, Meta, Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6, Numpad7,
+    Numpad8, Numpad9, Other, PageDown, PageUp, Shift, Space, Tab, F1, F10, F11, F12, F13, F14, F15,
+    F16, F17, F18, F19, F2, F20, F3, F4, F5, F6, F7, F8, F9,
+  },
+  MouseButton, MouseEvent,
+};
+use crate::{
+  event::Status::{Pressed, Released},
+  Source, SourceCallback,
+};
+use crate::{
+  event::Variant::{Left, Right},
+  hotkey::HotKey,
+};
 
 const INPUT_EVENT_TYPE_KEYBOARD: i32 = 1;
 const INPUT_EVENT_TYPE_MOUSE: i32 = 2;
diff --git a/espanso-detect/src/x11/mod.rs b/espanso-detect/src/x11/mod.rs
index 98f1d6df..5c09b83a 100644
--- a/espanso-detect/src/x11/mod.rs
+++ b/espanso-detect/src/x11/mod.rs
@@ -29,10 +29,25 @@ use log::{debug, error, trace, warn};
 use anyhow::Result;
 use thiserror::Error;
 
-use crate::event::{HotKeyEvent, Key::*, MouseButton, MouseEvent};
+use crate::event::{
+  HotKeyEvent,
+  Key::{
+    Alt, ArrowDown, ArrowLeft, ArrowRight, ArrowUp, Backspace, CapsLock, Control, End, Enter,
+    Escape, Home, Meta, NumLock, Numpad0, Numpad1, Numpad2, Numpad3, Numpad4, Numpad5, Numpad6,
+    Numpad7, Numpad8, Numpad9, Other, PageDown, PageUp, Shift, Space, Tab, F1, F10, F11, F12, F13,
+    F14, F15, F16, F17, F18, F19, F2, F20, F3, F4, F5, F6, F7, F8, F9,
+  },
+  MouseButton, MouseEvent,
+};
 use crate::event::{InputEvent, Key, KeyboardEvent, Variant};
-use crate::{event::Status::*, Source, SourceCallback};
-use crate::{event::Variant::*, hotkey::HotKey};
+use crate::{
+  event::Status::{Pressed, Released},
+  Source, SourceCallback,
+};
+use crate::{
+  event::Variant::{Left, Right},
+  hotkey::HotKey,
+};
 
 const INPUT_EVENT_TYPE_KEYBOARD: i32 = 1;
 const INPUT_EVENT_TYPE_MOUSE: i32 = 2;
@@ -202,7 +217,7 @@ impl Source for X11Source {
       );
       if let Some(callback) = source_self.callback.borrow() {
         if let Some(event) = event {
-          callback(event)
+          callback(event);
         } else {
           trace!("Unable to convert raw event to input event");
         }
@@ -491,7 +506,7 @@ mod tests {
   fn raw_to_input_event_hotkey_works_correctly() {
     let mut raw = default_raw_input_event();
     raw.event_type = INPUT_EVENT_TYPE_HOTKEY;
-    raw.state = 0b00000011;
+    raw.state = 0b0000_0011;
     raw.key_code = 10;
 
     let mut raw_hotkey_mapping = HashMap::new();
diff --git a/espanso-engine/Cargo.toml b/espanso-engine/Cargo.toml
index 483d5335..74340a88 100644
--- a/espanso-engine/Cargo.toml
+++ b/espanso-engine/Cargo.toml
@@ -12,6 +12,5 @@ crossbeam = "0.8.0"
 markdown = "0.3.0"
 html2text = "0.12.0"
 
-
-[dev-dependencies]
-tempdir = "0.3.7"
+[lints]
+workspace = true
diff --git a/espanso-info/Cargo.toml b/espanso-info/Cargo.toml
index 3eddf060..c0590800 100644
--- a/espanso-info/Cargo.toml
+++ b/espanso-info/Cargo.toml
@@ -11,10 +11,10 @@ wayland = []
 
 [dependencies]
 log = "0.4.14"
-lazycell = "1.3.0"
 anyhow = "1.0.38"
-thiserror = "1.0.23"
-lazy_static = "1.4.0"
+
+[lints]
+workspace = true
 
 [target.'cfg(windows)'.dependencies]
 widestring = "0.4.3"
diff --git a/espanso-info/src/cocoa/mod.rs b/espanso-info/src/cocoa/mod.rs
index 16f40c9f..67384458 100644
--- a/espanso-info/src/cocoa/mod.rs
+++ b/espanso-info/src/cocoa/mod.rs
@@ -49,10 +49,10 @@ impl CocoaAppInfoProvider {
     if unsafe { info_get_exec(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
@@ -64,10 +64,10 @@ impl CocoaAppInfoProvider {
     if unsafe { info_get_class(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
@@ -79,10 +79,10 @@ impl CocoaAppInfoProvider {
     if unsafe { info_get_title(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
@@ -95,10 +95,10 @@ impl CocoaAppInfoProvider {
     if unsafe { info_get_title_fallback(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
diff --git a/espanso-info/src/x11/mod.rs b/espanso-info/src/x11/mod.rs
index 54a64c7c..d40deab6 100644
--- a/espanso-info/src/x11/mod.rs
+++ b/espanso-info/src/x11/mod.rs
@@ -49,10 +49,10 @@ impl X11AppInfoProvider {
     if unsafe { info_get_exec(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
@@ -64,10 +64,10 @@ impl X11AppInfoProvider {
     if unsafe { info_get_class(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
@@ -79,10 +79,10 @@ impl X11AppInfoProvider {
     if unsafe { info_get_title(buffer.as_mut_ptr(), (buffer.len() - 1) as i32) } > 0 {
       let string = unsafe { CStr::from_ptr(buffer.as_ptr()) };
       let string = string.to_string_lossy();
-      if !string.is_empty() {
-        Some(string.to_string())
-      } else {
+      if string.is_empty() {
         None
+      } else {
+        Some(string.to_string())
       }
     } else {
       None
diff --git a/espanso-inject/Cargo.toml b/espanso-inject/Cargo.toml
index 7e3b6cad..b0550f76 100644
--- a/espanso-inject/Cargo.toml
+++ b/espanso-inject/Cargo.toml
@@ -12,12 +12,17 @@ wayland = []
 
 [dependencies]
 log = "0.4.14"
-lazycell = "1.3.0"
 anyhow = "1.0.38"
 thiserror = "1.0.23"
 lazy_static = "1.4.0"
 regex = "1.5.5"
 
+[dev-dependencies]
+enum-as-inner = "0.6.0"
+
+[lints]
+workspace = true
+
 [target.'cfg(windows)'.dependencies]
 widestring = "0.4.3"
 
@@ -28,6 +33,3 @@ itertools = "0.10.0"
 
 [build-dependencies]
 cc = "1.0.73"
-
-[dev-dependencies]
-enum-as-inner = "0.6.0"
diff --git a/espanso-inject/src/evdev/mod.rs b/espanso-inject/src/evdev/mod.rs
index 5e0d3cb3..62adec42 100644
--- a/espanso-inject/src/evdev/mod.rs
+++ b/espanso-inject/src/evdev/mod.rs
@@ -160,11 +160,11 @@ impl EVDEVInjector {
 
     // Cycle through all code/modifiers combinations to populate the reverse lookup tables
     for key_code in 8..256u32 {
-      for modifier_combination in modifier_combinations.iter() {
+      for modifier_combination in &modifier_combinations {
         let state = State::new(keymap)?;
 
         // Apply the modifiers
-        for modifier in modifier_combination.iter() {
+        for modifier in modifier_combination {
           // We need to add the EVDEV offset for xkbcommon to recognize it correctly
           state.update_key(*modifier + EVDEV_OFFSET, true);
         }
@@ -195,7 +195,7 @@ impl EVDEVInjector {
     for sequence_len in 1..=max_modifier_sequence_len {
       let current_combinations = modifiers
         .iter()
-        .cloned()
+        .copied()
         .combinations(sequence_len as usize);
       combinations.extend(current_combinations);
     }
@@ -244,10 +244,9 @@ impl EVDEVInjector {
       }
 
       bail!("timed-out while waiting for key release: {}", code);
-    } else {
-      // Keyboard provider not available,
-      Ok(())
     }
+    // else Keyboard provider not available,
+    Ok(())
   }
 
   fn wait_delay(&self, delay_ms: u32) {
@@ -280,7 +279,7 @@ impl Injector for EVDEVInjector {
     let mut current_modifiers: HashSet<u32> = HashSet::new();
 
     for record in records? {
-      let record_modifiers = record.modifiers.iter().cloned().collect::<HashSet<_>>();
+      let record_modifiers = record.modifiers.iter().copied().collect::<HashSet<_>>();
 
       // Release all the modifiers that are not needed anymore
       for expired_modifier in current_modifiers.difference(&record_modifiers) {
@@ -326,7 +325,7 @@ impl Injector for EVDEVInjector {
 
     for record in records {
       // Press the modifiers
-      for modifier in record.modifiers.iter() {
+      for modifier in &record.modifiers {
         self.send_key(*modifier, true, delay_us);
       }
 
@@ -335,7 +334,7 @@ impl Injector for EVDEVInjector {
       self.send_key(record.code, false, delay_us);
 
       // Release the modifiers
-      for modifier in record.modifiers.iter() {
+      for modifier in &record.modifiers {
         self.send_key(*modifier, false, delay_us);
       }
     }
@@ -351,9 +350,9 @@ impl Injector for EVDEVInjector {
     let delay_us = options.delay as u32 * 1000; // Convert to micro seconds
 
     // First press the keys
-    for record in records.iter() {
+    for record in &records {
       // Press the modifiers
-      for modifier in record.modifiers.iter() {
+      for modifier in &record.modifiers {
         self.send_key(*modifier, true, delay_us);
       }
 
@@ -366,7 +365,7 @@ impl Injector for EVDEVInjector {
       self.send_key(record.code, false, delay_us);
 
       // Release the modifiers
-      for modifier in record.modifiers.iter() {
+      for modifier in &record.modifiers {
         self.send_key(*modifier, false, delay_us);
       }
     }
diff --git a/espanso-inject/src/keys.rs b/espanso-inject/src/keys.rs
index fccdf607..56284e6e 100644
--- a/espanso-inject/src/keys.rs
+++ b/espanso-inject/src/keys.rs
@@ -19,6 +19,7 @@
 
 use std::fmt::Display;
 
+use lazy_static::lazy_static;
 use regex::Regex;
 
 lazy_static! {
diff --git a/espanso-inject/src/lib.rs b/espanso-inject/src/lib.rs
index 9e02dcc8..552b26c6 100644
--- a/espanso-inject/src/lib.rs
+++ b/espanso-inject/src/lib.rs
@@ -38,9 +38,6 @@ mod linux;
 #[cfg(target_os = "macos")]
 mod mac;
 
-#[macro_use]
-extern crate lazy_static;
-
 pub trait Injector {
   fn send_string(&self, string: &str, options: InjectionOptions) -> Result<()>;
   fn send_keys(&self, keys: &[keys::Key], options: InjectionOptions) -> Result<()>;
diff --git a/espanso-inject/src/linux/raw_keys.rs b/espanso-inject/src/linux/raw_keys.rs
index e586527c..0b916fa0 100644
--- a/espanso-inject/src/linux/raw_keys.rs
+++ b/espanso-inject/src/linux/raw_keys.rs
@@ -128,10 +128,10 @@ pub fn convert_key_to_sym(key: &Key) -> Option<u32> {
 
 pub fn convert_to_sym_array(keys: &[Key]) -> Result<Vec<u64>> {
   let mut virtual_keys: Vec<u64> = Vec::new();
-  for key in keys.iter() {
+  for key in keys {
     let vk = convert_key_to_sym(key);
     if let Some(vk) = vk {
-      virtual_keys.push(vk as u64)
+      virtual_keys.push(vk as u64);
     } else {
       return Err(LinuxRawKeyError::MappingFailure(key.clone()).into());
     }
diff --git a/espanso-inject/src/mac/mod.rs b/espanso-inject/src/mac/mod.rs
index fc8a2ee5..0b908f6f 100644
--- a/espanso-inject/src/mac/mod.rs
+++ b/espanso-inject/src/mac/mod.rs
@@ -47,10 +47,10 @@ impl MacInjector {
 
   pub fn convert_to_vk_array(keys: &[keys::Key]) -> Result<Vec<i32>> {
     let mut virtual_keys: Vec<i32> = Vec::new();
-    for key in keys.iter() {
+    for key in keys {
       let vk = convert_key_to_vkey(key);
       if let Some(vk) = vk {
-        virtual_keys.push(vk)
+        virtual_keys.push(vk);
       } else {
         return Err(MacInjectorError::MappingFailure(key.clone()).into());
       }
diff --git a/espanso-inject/src/x11/default/mod.rs b/espanso-inject/src/x11/default/mod.rs
index b90a1cdc..df5bde4e 100644
--- a/espanso-inject/src/x11/default/mod.rs
+++ b/espanso-inject/src/x11/default/mod.rs
@@ -115,7 +115,7 @@ impl X11DefaultInjector {
     if input_method.is_null() {
       bail!("could not open input method");
     }
-    let _im_guard = scopeguard::guard((), |_| {
+    let _im_guard = scopeguard::guard((), |()| {
       unsafe { XCloseIM(input_method) };
     });
 
@@ -132,7 +132,7 @@ impl X11DefaultInjector {
     if input_context.is_null() {
       bail!("could not open input context");
     }
-    let _ic_guard = scopeguard::guard((), |_| {
+    let _ic_guard = scopeguard::guard((), |()| {
       unsafe { XDestroyIC(input_context) };
     });
 
@@ -141,7 +141,7 @@ impl X11DefaultInjector {
     // Cycle through all state/code combinations to populate the reverse lookup tables
     for key_code in 0..256u32 {
       for modifier_state in 0..256u32 {
-        for dead_key in deadkeys.iter() {
+        for dead_key in &deadkeys {
           let code_with_offset = key_code + EVDEV_OFFSET;
 
           let preceding_dead_key = if let Some(dead_key) = dead_key {
@@ -311,7 +311,7 @@ impl X11DefaultInjector {
         self
           .sym_map
           .get(sym)
-          .cloned()
+          .copied()
           .ok_or_else(|| X11InjectorError::SymMapping(*sym).into())
       })
       .collect()
@@ -491,7 +491,7 @@ impl Injector for X11DefaultInjector {
         self
           .char_map
           .get(&char)
-          .cloned()
+          .copied()
           .ok_or_else(|| X11InjectorError::CharMapping(char).into())
       })
       .collect();
@@ -564,7 +564,7 @@ impl Injector for X11DefaultInjector {
     let delay_us = options.delay as u32 * 1000; // Convert to micro seconds
 
     // First press the keys
-    for record in records.iter() {
+    for record in &records {
       if options.disable_fast_inject {
         self.xtest_send_key(&record.main, true, delay_us);
       } else {
diff --git a/espanso-ipc/Cargo.toml b/espanso-ipc/Cargo.toml
index 60932bdd..469f21a9 100644
--- a/espanso-ipc/Cargo.toml
+++ b/espanso-ipc/Cargo.toml
@@ -10,7 +10,9 @@ anyhow = "1.0.38"
 thiserror = "1.0.23"
 serde = { version = "1.0.123", features = ["derive"] }
 serde_json = "1.0.62"
-crossbeam = "0.8.0"
+
+[lints]
+workspace = true
 
 [target.'cfg(windows)'.dependencies]
 named_pipe = "0.4.1"
diff --git a/espanso-ipc/src/unix.rs b/espanso-ipc/src/unix.rs
index d18dcc4c..7f4fdf5e 100644
--- a/espanso-ipc/src/unix.rs
+++ b/espanso-ipc/src/unix.rs
@@ -35,7 +35,7 @@ pub struct UnixIPCServer {
 
 impl UnixIPCServer {
   pub fn new(id: &str, parent_dir: &Path) -> Result<Self> {
-    let socket_path = parent_dir.join(format!("{}.sock", id));
+    let socket_path = parent_dir.join(format!("{id}.sock"));
 
     // Remove previous Unix socket
     if socket_path.exists() {
@@ -107,7 +107,7 @@ pub struct UnixIPCClient {
 
 impl UnixIPCClient {
   pub fn new(id: &str, parent_dir: &Path) -> Result<Self> {
-    let socket_path = parent_dir.join(format!("{}.sock", id));
+    let socket_path = parent_dir.join(format!("{id}.sock"));
     let stream = UnixStream::connect(socket_path)?;
 
     Ok(Self { stream })
diff --git a/espanso-kvs/Cargo.toml b/espanso-kvs/Cargo.toml
index e1631ee1..aa985517 100644
--- a/espanso-kvs/Cargo.toml
+++ b/espanso-kvs/Cargo.toml
@@ -5,12 +5,13 @@ authors = ["Federico Terzi <federico-terzi@users.noreply.github.com>"]
 edition = "2021"
 
 [dependencies]
-log = "0.4.14"
 anyhow = "1.0.38"
 thiserror = "1.0.23"
 serde = { version = "1.0.123", features = ["derive"] }
 serde_json = "1.0.62"
 
-
 [dev-dependencies]
 tempdir = "0.3.7"
+
+[lints]
+workspace = true
diff --git a/espanso-mac-utils/Cargo.toml b/espanso-mac-utils/Cargo.toml
index f0ae995b..ad58d361 100644
--- a/espanso-mac-utils/Cargo.toml
+++ b/espanso-mac-utils/Cargo.toml
@@ -6,12 +6,11 @@ edition = "2021"
 build = "build.rs"
 
 [dependencies]
-log = "0.4.14"
-lazycell = "1.3.0"
-anyhow = "1.0.38"
-thiserror = "1.0.23"
 lazy_static = "1.4.0"
 regex = "1.5.5"
 
 [build-dependencies]
 cc = "1.0.73"
+
+[lints]
+workspace = true
diff --git a/espanso-mac-utils/src/lib.rs b/espanso-mac-utils/src/lib.rs
index a338ae31..1224dfa0 100644
--- a/espanso-mac-utils/src/lib.rs
+++ b/espanso-mac-utils/src/lib.rs
@@ -18,16 +18,14 @@
  */
 
 #[cfg(target_os = "macos")]
-use std::{ffi::CStr, os::raw::c_char};
-
-#[macro_use]
+use lazy_static::lazy_static;
 #[cfg(target_os = "macos")]
-extern crate lazy_static;
+use std::{ffi::CStr, os::raw::c_char};
 
 mod ffi;
 
 /// Check whether an application is currently holding the Secure Input.
-/// Return None if no application has claimed SecureInput, its PID otherwise.
+/// Return None if no application has claimed `SecureInput`, its PID otherwise.
 #[cfg(target_os = "macos")]
 pub fn get_secure_input_pid() -> Option<i64> {
   unsafe {
@@ -43,7 +41,7 @@ pub fn get_secure_input_pid() -> Option<i64> {
 }
 
 /// Check whether an application is currently holding the Secure Input.
-/// Return None if no application has claimed SecureInput, Some((AppName, AppPath)) otherwise.
+/// Return None if no application has claimed `SecureInput`, `Some((AppName, AppPath))` otherwise.
 #[cfg(target_os = "macos")]
 pub fn get_secure_input_application() -> Option<(String, String)> {
   unsafe {
@@ -64,7 +62,7 @@ pub fn get_secure_input_application() -> Option<(String, String)> {
             let app_name = if let Some(name) = get_app_name_from_path(&process) {
               name
             } else {
-              process.to_owned()
+              process.clone()
             };
 
             return Some((app_name, process));
diff --git a/espanso-mac-utils/src/native.h b/espanso-mac-utils/src/native.h
index b44ee48a..0c964130 100644
--- a/espanso-mac-utils/src/native.h
+++ b/espanso-mac-utils/src/native.h
@@ -22,7 +22,7 @@
 
 #include <stdint.h>
 
-// If a process is currently holding SecureInput, then return 1 and set the pid pointer to the corresponding PID.
+// If a process is currently holding `SecureInput`, then return 1 and set the pid pointer to the corresponding PID.
 extern "C" int32_t mac_utils_get_secure_input_process(int64_t *pid);
 
 // Find the executable path corresponding to the given PID, return 0 if no process was found.
diff --git a/espanso-match/Cargo.toml b/espanso-match/Cargo.toml
index 25b6db3f..317cf950 100644
--- a/espanso-match/Cargo.toml
+++ b/espanso-match/Cargo.toml
@@ -6,7 +6,8 @@ edition = "2021"
 
 [dependencies]
 log = "0.4.14"
-anyhow = "1.0.38"
-thiserror = "1.0.23"
 regex = "1.5.5"
 unicase = "2.6.0"
+
+[lints]
+workspace = true
diff --git a/espanso-migrate/Cargo.toml b/espanso-migrate/Cargo.toml
index 148d0e15..25d972dd 100644
--- a/espanso-migrate/Cargo.toml
+++ b/espanso-migrate/Cargo.toml
@@ -5,13 +5,11 @@ authors = ["Federico Terzi <federico-terzi@users.noreply.github.com>"]
 edition = "2021"
 
 [dependencies]
-log = "0.4.14"
 anyhow = "1.0.38"
 thiserror = "1.0.23"
 glob = "0.3.0"
 regex = "1.5.5"
 lazy_static = "1.4.0"
-dunce = "1.0.1"
 walkdir = "2.3.1"
 yaml-rust = { version = "0.4.6", git = "https://github.com/federico-terzi/yaml-rust" }
 path-slash = "0.1.4"
@@ -19,7 +17,9 @@ tempdir = "0.3.7"
 fs_extra = "1.3.0"
 
 [dev-dependencies]
-tempfile = "3.2.0"
 include_dir = { version = "0.6.0", features = ["search"] }
 test-case = "1.1.0"
 pretty_assertions = "0.7.2"
+
+[lints]
+workspace = true
diff --git a/espanso-migrate/src/convert.rs b/espanso-migrate/src/convert.rs
index 6a9e99e9..a598bc52 100644
--- a/espanso-migrate/src/convert.rs
+++ b/espanso-migrate/src/convert.rs
@@ -17,6 +17,7 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use lazy_static::lazy_static;
 use regex::{Captures, Regex};
 use std::{cmp::Ordering, collections::HashMap, path::PathBuf};
 use yaml_rust::{yaml::Hash, Yaml};
diff --git a/espanso-migrate/src/lib.rs b/espanso-migrate/src/lib.rs
index e0c93968..045f414e 100644
--- a/espanso-migrate/src/lib.rs
+++ b/espanso-migrate/src/lib.rs
@@ -17,10 +17,6 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-#[allow(unused_imports)]
-#[macro_use]
-extern crate lazy_static;
-
 #[allow(unused_imports)]
 #[macro_use]
 #[cfg(test)]
@@ -172,7 +168,7 @@ mod tests {
   }
 
   fn to_sorted_list<T>(hash: HashMap<String, T>) -> Vec<(String, T)> {
-    let mut tuples: Vec<(String, T)> = hash.into_iter().map(|(k, v)| (k, v)).collect();
+    let mut tuples: Vec<(String, T)> = hash.into_iter().collect();
     tuples.sort_by_key(|(k, _)| k.clone());
     tuples
   }
diff --git a/espanso-modulo/Cargo.toml b/espanso-modulo/Cargo.toml
index 97269c17..3aeb034f 100644
--- a/espanso-modulo/Cargo.toml
+++ b/espanso-modulo/Cargo.toml
@@ -6,8 +6,6 @@ edition = "2021"
 build = "build.rs"
 
 [dependencies]
-log = "0.4.14"
-serde_json = "1.0.61"
 serde = { version = "1.0.123", features = ["derive"] }
 anyhow = "1.0.38"
 thiserror = "1.0.23"
@@ -20,3 +18,6 @@ regex = "1.5.5"
 zip = "0.5.12"
 winres = "0.1.11"
 glob = "0.3.0"
+
+[lints]
+workspace = true
diff --git a/espanso-modulo/build.rs b/espanso-modulo/build.rs
index 19d7139b..820af4d7 100644
--- a/espanso-modulo/build.rs
+++ b/espanso-modulo/build.rs
@@ -158,15 +158,10 @@ fn build_native() {
   let project_dir =
     PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").expect("missing CARGO_MANIFEST_DIR"));
   let wx_archive = project_dir.join("vendor").join(WX_WIDGETS_ARCHIVE_NAME);
-  if !wx_archive.is_file() {
-    panic!("could not find wxWidgets archive!");
-  }
+  assert!(wx_archive.is_file(), "could not find wxWidgets archive!");
 
   let out_dir = if let Ok(out_path) = std::env::var(WX_WIDGETS_BUILD_OUT_DIR_ENV_NAME) {
-    println!(
-      "detected wxWidgets build output directory override: {}",
-      out_path
-    );
+    println!("detected wxWidgets build output directory override: {out_path}");
     let path = PathBuf::from(out_path);
     std::fs::create_dir_all(&path).expect("unable to create wxWidgets out dir");
     path
@@ -182,7 +177,7 @@ fn build_native() {
   {
     "x86_64" => "x86_64",
     "aarch64" => "arm64",
-    arch => panic!("unsupported arch {}", arch),
+    arch => panic!("unsupported arch {arch}"),
   };
 
   let should_use_ci_m1_workaround =
@@ -226,7 +221,7 @@ fn build_native() {
           "--without-liblzma",
           "--with-libjpeg=builtin",
           "--with-libpng=builtin",
-          &format!("--enable-macosx_arch={}", target_arch),
+          &format!("--enable-macosx_arch={target_arch}"),
         ])
         .spawn()
         .expect("failed to execute configure")
@@ -255,9 +250,10 @@ fn build_native() {
   }
 
   // Make sure wxWidgets is compiled
-  if !out_wx_dir.join("build-cocoa").is_dir() {
-    panic!("wxWidgets is not compiled correctly, missing 'build-cocoa/' directory")
-  }
+  assert!(
+    out_wx_dir.join("build-cocoa").is_dir(),
+    "wxWidgets is not compiled correctly, missing 'build-cocoa/' directory"
+  );
 
   // If using the M1 CI workaround, convert all the universal libraries to arm64 ones
   // This is needed until https://github.com/rust-lang/rust/issues/55235 is fixed
@@ -302,7 +298,7 @@ fn build_native() {
   // More details at https://github.com/alexcrichton/curl-rust/issues/279.
   if let Some(path) = macos_link_search_path() {
     println!("cargo:rustc-link-lib=clang_rt.osx");
-    println!("cargo:rustc-link-search={}", path);
+    println!("cargo:rustc-link-search={path}");
   }
 }
 
@@ -341,9 +337,10 @@ fn convert_fat_libraries_to_arm(lib_dir: &Path) {
       .output()
       .expect("unable to extract arm64 slice from library");
 
-    if !result.status.success() {
-      panic!("unable to convert fat library to arm64 version");
-    }
+    assert!(
+      result.status.success(),
+      "unable to convert fat library to arm64 version"
+    );
   }
 }
 
@@ -358,10 +355,10 @@ fn get_cpp_flags(wx_config_path: &Path) -> Vec<String> {
   let cpp_flags: Vec<String> = config_libs
     .split(' ')
     .filter_map(|s| {
-      if !s.trim().is_empty() {
-        Some(s.trim().to_owned())
-      } else {
+      if s.trim().is_empty() {
         None
+      } else {
+        Some(s.trim().to_owned())
       }
     })
     .collect();
@@ -380,10 +377,10 @@ fn generate_linker_flags(wx_config_path: &Path) {
   let linker_flags: Vec<String> = config_libs
     .split(' ')
     .filter_map(|s| {
-      if !s.trim().is_empty() {
-        Some(s.trim().to_owned())
-      } else {
+      if s.trim().is_empty() {
         None
+      } else {
+        Some(s.trim().to_owned())
       }
     })
     .collect();
@@ -395,7 +392,7 @@ fn generate_linker_flags(wx_config_path: &Path) {
   for (i, flag) in linker_flags.iter().enumerate() {
     if flag.starts_with("-L") {
       let path = flag.trim_start_matches("-L");
-      println!("cargo:rustc-link-search=native={}", path);
+      println!("cargo:rustc-link-search=native={path}");
     } else if flag.starts_with("-framework") {
       println!("cargo:rustc-link-lib=framework={}", linker_flags[i + 1]);
     } else if flag.starts_with('/') {
@@ -406,7 +403,7 @@ fn generate_linker_flags(wx_config_path: &Path) {
       println!("cargo:rustc-link-lib=static={}", libname.as_str());
     } else if flag.starts_with("-l") {
       let libname = flag.trim_start_matches("-l");
-      println!("cargo:rustc-link-lib=dylib={}", libname);
+      println!("cargo:rustc-link-lib=dylib={libname}");
     }
   }
 }
@@ -427,7 +424,7 @@ fn macos_link_search_path() -> Option<String> {
   for line in stdout.lines() {
     if line.contains("libraries: =") {
       let path = line.split('=').nth(1)?;
-      return Some(format!("{}/lib/darwin", path));
+      return Some(format!("{path}/lib/darwin"));
     }
   }
 
diff --git a/espanso-modulo/src/form/parser/layout.rs b/espanso-modulo/src/form/parser/layout.rs
index ec6bda99..4ea21d12 100644
--- a/espanso-modulo/src/form/parser/layout.rs
+++ b/espanso-modulo/src/form/parser/layout.rs
@@ -18,6 +18,7 @@
  */
 
 use super::split::*;
+use lazy_static::lazy_static;
 use regex::Regex;
 
 lazy_static! {
diff --git a/espanso-modulo/src/lib.rs b/espanso-modulo/src/lib.rs
index 59ce4950..8749b1a9 100644
--- a/espanso-modulo/src/lib.rs
+++ b/espanso-modulo/src/lib.rs
@@ -17,9 +17,6 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-#[macro_use]
-extern crate lazy_static;
-
 pub mod form;
 pub mod search;
 mod sys;
diff --git a/espanso-modulo/src/search/algorithm.rs b/espanso-modulo/src/search/algorithm.rs
index 9a7a377c..618cd729 100644
--- a/espanso-modulo/src/search/algorithm.rs
+++ b/espanso-modulo/src/search/algorithm.rs
@@ -28,7 +28,7 @@ pub fn get_algorithm(name: &str, use_command_filter: bool) -> Box<FilterCallback
     "exact" => Box::new(exact_match),
     "iexact" => Box::new(case_insensitive_exact_match),
     "ikey" => Box::new(case_insensitive_keyword),
-    _ => panic!("unknown search algorithm: {}", name),
+    _ => panic!("unknown search algorithm: {name}"),
   };
 
   if use_command_filter {
diff --git a/espanso-modulo/src/sys/troubleshooting/mod.rs b/espanso-modulo/src/sys/troubleshooting/mod.rs
index 4133dc57..c33bdbea 100644
--- a/espanso-modulo/src/sys/troubleshooting/mod.rs
+++ b/espanso-modulo/src/sys/troubleshooting/mod.rs
@@ -28,6 +28,7 @@ use crate::sys::troubleshooting::interop::OwnedErrorSet;
 use crate::sys::util::convert_to_cstring_or_null;
 use crate::troubleshooting::{TroubleshootingHandlers, TroubleshootingOptions};
 use anyhow::Result;
+use lazy_static::lazy_static;
 
 lazy_static! {
   static ref HANDLERS: Mutex<Option<TroubleshootingHandlers>> = Mutex::new(None);
diff --git a/espanso-modulo/src/sys/welcome/mod.rs b/espanso-modulo/src/sys/welcome/mod.rs
index 7e838ae0..6615ccb6 100644
--- a/espanso-modulo/src/sys/welcome/mod.rs
+++ b/espanso-modulo/src/sys/welcome/mod.rs
@@ -25,6 +25,7 @@ use crate::{
   sys::interop::WelcomeMetadata,
   welcome::{WelcomeHandlers, WelcomeOptions},
 };
+use lazy_static::lazy_static;
 
 lazy_static! {
   static ref HANDLERS: Mutex<Option<WelcomeHandlers>> = Mutex::new(None);
diff --git a/espanso-modulo/src/sys/wizard/mod.rs b/espanso-modulo/src/sys/wizard/mod.rs
index 6c73cca6..3c092196 100644
--- a/espanso-modulo/src/sys/wizard/mod.rs
+++ b/espanso-modulo/src/sys/wizard/mod.rs
@@ -31,6 +31,7 @@ use crate::{
   },
   wizard::{WizardHandlers, WizardOptions},
 };
+use lazy_static::lazy_static;
 
 lazy_static! {
   static ref HANDLERS: Mutex<Option<WizardHandlers>> = Mutex::new(None);
diff --git a/espanso-package/Cargo.toml b/espanso-package/Cargo.toml
index a0aec21b..3a3726b9 100644
--- a/espanso-package/Cargo.toml
+++ b/espanso-package/Cargo.toml
@@ -32,3 +32,6 @@ reqwest = { version = "0.11.16", features = [
 [features]
 default-tls = ["reqwest/default-tls"]
 rustls-tls = ["reqwest/rustls-tls"]
+
+[lints]
+workspace = true
diff --git a/espanso-path/Cargo.toml b/espanso-path/Cargo.toml
index 154644de..054362c8 100644
--- a/espanso-path/Cargo.toml
+++ b/espanso-path/Cargo.toml
@@ -6,6 +6,7 @@ edition = "2021"
 
 [dependencies]
 log = "0.4.14"
-anyhow = "1.0.38"
-thiserror = "1.0.23"
 dirs = "3.0.1"
+
+[lints]
+workspace = true
diff --git a/espanso-render/Cargo.toml b/espanso-render/Cargo.toml
index 62c0448b..865fad9f 100644
--- a/espanso-render/Cargo.toml
+++ b/espanso-render/Cargo.toml
@@ -14,3 +14,6 @@ chrono = { version = "0.4.19", features = ["unstable-locales"] }
 enum-as-inner = "0.6.0"
 rand = "0.8.3"
 sys-locale = "0.1.0"
+
+[lints]
+workspace = true
diff --git a/espanso-render/src/extension/exec_util.rs b/espanso-render/src/extension/exec_util.rs
index 6c4a5f52..74fd89f6 100644
--- a/espanso-render/src/extension/exec_util.rs
+++ b/espanso-render/src/extension/exec_util.rs
@@ -55,6 +55,7 @@ pub fn determine_path_env_variable_override(_: Option<MacShell>) -> Option<Strin
 
 #[cfg(target_os = "macos")]
 pub fn determine_default_macos_shell() -> Option<MacShell> {
+  use lazy_static::lazy_static;
   use regex::Regex;
   use std::process::Command;
 
diff --git a/espanso-render/src/extension/form.rs b/espanso-render/src/extension/form.rs
index 47d99502..cd2cfc6c 100644
--- a/espanso-render/src/extension/form.rs
+++ b/espanso-render/src/extension/form.rs
@@ -17,6 +17,7 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use lazy_static::lazy_static;
 use log::error;
 use std::collections::HashMap;
 use thiserror::Error;
diff --git a/espanso-render/src/extension/script.rs b/espanso-render/src/extension/script.rs
index 4ab982eb..61a72f98 100644
--- a/espanso-render/src/extension/script.rs
+++ b/espanso-render/src/extension/script.rs
@@ -201,7 +201,7 @@ mod tests {
     .collect::<Params>();
     assert_eq!(
       extension
-        .calculate(&Default::default(), &Default::default(), &param)
+        .calculate(&crate::Context::default(), &HashMap::default(), &param)
         .into_success()
         .unwrap(),
       ExtensionOutput::Single("hello world".to_string())
@@ -228,7 +228,7 @@ mod tests {
     if cfg!(target_os = "windows") {
       assert_eq!(
         extension
-          .calculate(&Default::default(), &Default::default(), &param)
+          .calculate(&crate::Context::default(), &HashMap::default(), &param)
           .into_success()
           .unwrap(),
         ExtensionOutput::Single("hello world\r\n".to_string())
@@ -236,7 +236,7 @@ mod tests {
     } else {
       assert_eq!(
         extension
-          .calculate(&Default::default(), &Default::default(), &param)
+          .calculate(&crate::Context::default(), &HashMap::default(), &param)
           .into_success()
           .unwrap(),
         ExtensionOutput::Single("hello world\n".to_string())
@@ -263,7 +263,7 @@ mod tests {
     scope.insert("var1", ExtensionOutput::Single("hello world".to_string()));
     assert_eq!(
       extension
-        .calculate(&Default::default(), &scope, &param)
+        .calculate(&crate::Context::default(), &scope, &param)
         .into_success()
         .unwrap(),
       ExtensionOutput::Single("hello world".to_string())
@@ -302,7 +302,7 @@ mod tests {
     .into_iter()
     .collect::<Params>();
     assert!(matches!(
-      extension.calculate(&Default::default(), &Default::default(), &param),
+      extension.calculate(&crate::Context::default(), &HashMap::default(), &param),
       ExtensionResult::Error(_)
     ));
   }
@@ -327,7 +327,7 @@ mod tests {
     .collect::<Params>();
     assert_eq!(
       extension
-        .calculate(&Default::default(), &Default::default(), &param)
+        .calculate(&crate::Context::default(), &HashMap::default(), &param)
         .into_success()
         .unwrap(),
       ExtensionOutput::Single(String::new())
diff --git a/espanso-render/src/extension/shell.rs b/espanso-render/src/extension/shell.rs
index ba349b38..e530b06a 100644
--- a/espanso-render/src/extension/shell.rs
+++ b/espanso-render/src/extension/shell.rs
@@ -17,6 +17,7 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
+use lazy_static::lazy_static;
 use std::{
   collections::HashMap,
   path::{Path, PathBuf},
@@ -369,7 +370,7 @@ mod tests {
     .collect::<Params>();
     assert_eq!(
       extension
-        .calculate(&Default::default(), &Default::default(), &param)
+        .calculate(&crate::Context::default(), &HashMap::default(), &param)
         .into_success()
         .unwrap(),
       ExtensionOutput::Single("hello world".to_string())
@@ -434,7 +435,7 @@ mod tests {
       .into_iter()
       .collect::<Params>();
     assert!(matches!(
-      extension.calculate(&Default::default(), &Default::default(), &param),
+      extension.calculate(&crate::Context::default(), &HashMap::default(), &param),
       ExtensionResult::Error(_)
     ));
   }
diff --git a/espanso-render/src/lib.rs b/espanso-render/src/lib.rs
index da444b8f..324ba6ab 100644
--- a/espanso-render/src/lib.rs
+++ b/espanso-render/src/lib.rs
@@ -17,9 +17,6 @@
  * along with espanso.  If not, see <https://www.gnu.org/licenses/>.
  */
 
-#[macro_use]
-extern crate lazy_static;
-
 use enum_as_inner::EnumAsInner;
 use std::collections::HashMap;
 
diff --git a/espanso-render/src/renderer/mod.rs b/espanso-render/src/renderer/mod.rs
index fd79bce5..59b283b1 100644
--- a/espanso-render/src/renderer/mod.rs
+++ b/espanso-render/src/renderer/mod.rs
@@ -23,6 +23,7 @@ use crate::{
   CasingStyle, Context, Extension, ExtensionOutput, ExtensionResult, RenderOptions, RenderResult,
   Renderer, Scope, Template, Value, Variable,
 };
+use lazy_static::lazy_static;
 use log::{error, warn};
 use regex::{Captures, Regex};
 use thiserror::Error;
diff --git a/espanso-ui/Cargo.toml b/espanso-ui/Cargo.toml
index a0e26e31..1c636eb2 100644
--- a/espanso-ui/Cargo.toml
+++ b/espanso-ui/Cargo.toml
@@ -32,3 +32,6 @@ crossbeam = "0.8.0"
 
 [build-dependencies]
 cc = "1.0.73"
+
+[lints]
+workspace = true
diff --git a/espanso-ui/src/icons.rs b/espanso-ui/src/icons.rs
index b1adca07..d3228cc0 100644
--- a/espanso-ui/src/icons.rs
+++ b/espanso-ui/src/icons.rs
@@ -22,6 +22,6 @@ pub enum TrayIcon {
   Normal,
   Disabled,
 
-  // For example, when macOS activates SecureInput
+  // For example, when macOS activates `SecureInput`
   SystemDisabled,
 }
diff --git a/espanso-ui/src/linux/mod.rs b/espanso-ui/src/linux/mod.rs
index f51d3195..f654fbe9 100644
--- a/espanso-ui/src/linux/mod.rs
+++ b/espanso-ui/src/linux/mod.rs
@@ -108,7 +108,7 @@ impl UIEventLoop for LinuxEventLoop {
           // We don't run an event loop on Linux as there is no tray icon or application window needed.
           // Thad said, we still need a way to block this method, and thus we use a channel
           match result {
-            Ok(_) => {
+            Ok(()) => {
               // remote.exit() called
               return Ok(());
             }
diff --git a/espanso-ui/src/mac/mod.rs b/espanso-ui/src/mac/mod.rs
index 2e28d869..1364954a 100644
--- a/espanso-ui/src/mac/mod.rs
+++ b/espanso-ui/src/mac/mod.rs
@@ -69,10 +69,7 @@ pub struct MacUIOptions<'a> {
 
 pub fn create(options: MacUIOptions) -> Result<(MacRemote, MacEventLoop)> {
   // Validate icons
-  if options.icon_paths.len() > MAX_ICON_COUNT {
-    panic!("MacOS UI received too many icon paths, please increase the MAX_ICON_COUNT constant to support more");
-  }
-
+  assert!(options.icon_paths.len() <= MAX_ICON_COUNT, "MacOS UI received too many icon paths, please increase the MAX_ICON_COUNT constant to support more");
   // Convert the icon paths to the internal representation
   let mut icon_indexes: HashMap<TrayIcon, usize> = HashMap::new();
   let mut icons = Vec::new();
@@ -140,9 +137,10 @@ impl UIEventLoop for MacEventLoop {
   fn run(&self, event_callback: MacUIEventCallback) -> Result<()> {
     // Make sure the run() method is called in the same thread as initialize()
     if let Some(init_id) = self._init_thread_id.borrow() {
-      if init_id != &std::thread::current().id() {
-        panic!("MacEventLoop run() and initialize() methods should be called in the same thread");
-      }
+      assert!(
+        !(init_id != &std::thread::current().id()),
+        "MacEventLoop run() and initialize() methods should be called in the same thread"
+      );
     }
 
     if self._event_callback.fill(event_callback).is_err() {
@@ -154,7 +152,7 @@ impl UIEventLoop for MacEventLoop {
       if let Some(callback) = unsafe { (*_self)._event_callback.borrow() } {
         let event: Option<UIEvent> = event.into();
         if let Some(event) = event {
-          callback(event)
+          callback(event);
         } else {
           trace!("Unable to convert raw event to input event");
         }
diff --git a/espanso/Cargo.toml b/espanso/Cargo.toml
index 6796b15d..df7c0f8d 100644
--- a/espanso/Cargo.toml
+++ b/espanso/Cargo.toml
@@ -51,7 +51,6 @@ espanso-migrate = { path = "../espanso-migrate" }
 espanso-kvs = { path = "../espanso-kvs" }
 espanso-engine = { path = "../espanso-engine" }
 espanso-package = { path = "../espanso-package" }
-maplit = "1.0.2"
 simplelog = "0.9.0"
 log = "0.4.14"
 anyhow = "1.0.38"
diff --git a/espanso/src/cli/edit.rs b/espanso/src/cli/edit.rs
index a065071f..f1ec014f 100644
--- a/espanso/src/cli/edit.rs
+++ b/espanso/src/cli/edit.rs
@@ -153,7 +153,13 @@ fn determine_target_path(config_path: &Path, target_file: Option<&str>) -> PathB
         }
       }
       custom => {
-        if !custom.ends_with(".yml") && !custom.ends_with(".yaml") {
+        if !std::path::Path::new(custom)
+          .extension()
+          .map_or(false, |ext| ext.eq_ignore_ascii_case("yml"))
+          && !std::path::Path::new(custom)
+            .extension()
+            .map_or(false, |ext| ext.eq_ignore_ascii_case("yaml"))
+        {
           if espanso_config::is_legacy_config(config_path) {
             config_path.join("user").join(format!("{custom}.yml"))
           } else {
diff --git a/espanso/src/cli/log.rs b/espanso/src/cli/log.rs
index 6cca6e81..7b049e52 100644
--- a/espanso/src/cli/log.rs
+++ b/espanso/src/cli/log.rs
@@ -43,7 +43,7 @@ fn log_main(args: CliModuleArgs) -> i32 {
   let log_file = File::open(log_file);
   if let Ok(log_file) = log_file {
     let reader = BufReader::new(log_file);
-    for line in reader.lines().flatten() {
+    for line in reader.lines().map_while(Result::ok) {
       println!("{line}");
     }
   } else {
diff --git a/espanso/src/cli/match_cli/list.rs b/espanso/src/cli/match_cli/list.rs
index 9b1f9735..be2be8b1 100644
--- a/espanso/src/cli/match_cli/list.rs
+++ b/espanso/src/cli/match_cli/list.rs
@@ -75,12 +75,12 @@ pub fn print_matches_as_plain(
               trigger,
               description.replace('\n', " "),
               label
-            )
+            );
           }
         } else if preserve_newlines {
           println!("{trigger} - {description}");
         } else {
-          println!("{} - {}", trigger, description.replace('\n', " "))
+          println!("{} - {}", trigger, description.replace('\n', " "));
         }
       }
     }
@@ -109,7 +109,7 @@ pub fn print_matches_as_json(match_list: &[&Match]) -> Result<()> {
       triggers,
       replace: m.description().to_string(),
       label: m.label.clone(),
-    })
+    });
   }
 
   let json = serde_json::to_string_pretty(&entries)?;
diff --git a/espanso/src/cli/service/linux.rs b/espanso/src/cli/service/linux.rs
index 8f7ab21e..f86ffc93 100644
--- a/espanso/src/cli/service/linux.rs
+++ b/espanso/src/cli/service/linux.rs
@@ -19,6 +19,7 @@
 
 use anyhow::Result;
 use const_format::formatcp;
+use lazy_static::lazy_static;
 use regex::Regex;
 use std::fs::create_dir_all;
 use std::path::PathBuf;
@@ -144,7 +145,9 @@ pub fn is_registered() -> bool {
           let path = caps.get(1).map_or("", |m| m.as_str());
           let espanso_path = get_binary_path().expect("unable to get espanso executable path");
 
-          if espanso_path.to_string_lossy() != path {
+          if espanso_path.to_string_lossy() == path {
+            true
+          } else {
             error_eprintln!("Espanso is registered as a systemd service, but it points to another binary location:");
             error_eprintln!("");
             error_eprintln!("  {}", path);
@@ -156,8 +159,6 @@ pub fn is_registered() -> bool {
             error_eprintln!("");
 
             false
-          } else {
-            true
           }
         } else {
           error_eprintln!("systemctl command returned non-zero exit code");
@@ -176,32 +177,29 @@ pub fn is_registered() -> bool {
 
 pub fn start_service() -> Result<()> {
   // Check if systemd is available in the system
-  match Command::new("systemctl")
+  if let Ok(status) = Command::new("systemctl")
     .args(["--version"])
     .stdin(Stdio::null())
     .stdout(Stdio::null())
     .status()
   {
-    Ok(status) => {
-      if !status.success() {
-        return Err(StartError::SystemctlNonZeroExitCode.into());
-      }
-    }
-    Err(_) => {
-      error_eprintln!(
-        "Systemd was not found in this system, which means espanso can't run in managed mode"
-      );
-      error_eprintln!("You can run it in unmanaged mode with `espanso service start --unmanaged`");
-      error_eprintln!("");
-      error_eprintln!(
-        "NOTE: unmanaged mode means espanso does not rely on the system service manager"
-      );
-      error_eprintln!(
-        "      to run, but as a result, you are in charge of starting/stopping espanso"
-      );
-      error_eprintln!("      when needed.");
-      return Err(StartError::SystemdNotFound.into());
+    if !status.success() {
+      return Err(StartError::SystemctlNonZeroExitCode.into());
     }
+  } else {
+    error_eprintln!(
+      "Systemd was not found in this system, which means espanso can't run in managed mode"
+    );
+    error_eprintln!("You can run it in unmanaged mode with `espanso service start --unmanaged`");
+    error_eprintln!("");
+    error_eprintln!(
+      "NOTE: unmanaged mode means espanso does not rely on the system service manager"
+    );
+    error_eprintln!(
+      "      to run, but as a result, you are in charge of starting/stopping espanso"
+    );
+    error_eprintln!("      when needed.");
+    return Err(StartError::SystemdNotFound.into());
   }
 
   if !is_registered() {
diff --git a/espanso/src/cli/worker/secure_input.rs b/espanso/src/cli/worker/secure_input.rs
index 417582ff..8b6e172b 100644
--- a/espanso/src/cli/worker/secure_input.rs
+++ b/espanso/src/cli/worker/secure_input.rs
@@ -63,9 +63,9 @@ fn secure_input_main(
     let pid = espanso_mac_utils::get_secure_input_pid();
 
     if let Some(pid) = pid {
-      // Some application is currently on SecureInput
+      // Some application is currently on `SecureInput`
       let should_notify = if let Some(old_pid) = last_secure_input_pid {
-        // We already detected a SecureInput app
+        // We already detected a `SecureInput` app
         #[allow(clippy::needless_bool)]
         if old_pid != pid {
           // The old app is different from the current one, we should take action
@@ -75,7 +75,7 @@ fn secure_input_main(
           false
         }
       } else {
-        // First time we see this SecureInput app, we should take action
+        // First time we see this `SecureInput` app, we should take action
         true
       };
 
@@ -97,9 +97,9 @@ fn secure_input_main(
 
       last_secure_input_pid = Some(pid);
     } else {
-      // No app is currently keeping SecureInput
+      // No app is currently keeping `SecureInput`
 
-      // If there was an app with SecureInput, notify that is now free
+      // If there was an app with `SecureInput`, notify that is now free
       if last_secure_input_pid.is_some() {
         info!("secure input has been disabled");
 
diff --git a/espanso/src/exit_code.rs b/espanso/src/exit_code.rs
index 7c5ca02b..6500c539 100644
--- a/espanso/src/exit_code.rs
+++ b/espanso/src/exit_code.rs
@@ -72,6 +72,7 @@ pub const PACKAGE_UPDATE_PARTIAL_FAILURE: i32 = 6;
 #[allow(dead_code)]
 pub const UNEXPECTED_RUN_AS_ROOT: i32 = 42;
 
+use lazy_static::lazy_static;
 use std::sync::Mutex;
 
 use crate::error_eprintln;
diff --git a/espanso/src/lock.rs b/espanso/src/lock.rs
index 906f8ba7..accba9d3 100644
--- a/espanso/src/lock.rs
+++ b/espanso/src/lock.rs
@@ -42,13 +42,7 @@ impl Lock {
       .write(true)
       .create(true)
       .open(&lock_file_path)
-      .unwrap_or_else(|_| {
-        panic!(
-          "unable to create reference to lock file: {:?}",
-          lock_file_path
-        )
-      });
-
+      .unwrap_or_else(|_| panic!("unable to create reference to lock file: {lock_file_path:?}"));
     if lock_file.try_lock_exclusive().is_ok() {
       Some(Lock { lock_file })
     } else {
diff --git a/espanso/src/main.rs b/espanso/src/main.rs
index 7db6bf20..e4b9ac9e 100644
--- a/espanso/src/main.rs
+++ b/espanso/src/main.rs
@@ -20,9 +20,6 @@
 // This is needed to avoid showing a console window when starting espanso on Windows
 #![windows_subsystem = "windows"]
 
-#[macro_use]
-extern crate lazy_static;
-
 use std::path::PathBuf;
 
 use clap::{App, AppSettings, Arg, ArgMatches, SubCommand};
@@ -58,6 +55,8 @@ mod util;
 const VERSION: &str = env!("CARGO_PKG_VERSION");
 const LOG_FILE_NAME: &str = "espanso.log";
 
+use lazy_static::lazy_static;
+
 lazy_static! {
   static ref CLI_HANDLERS: Vec<CliModule> = vec![
     cli::path::new(),
diff --git a/espanso/src/preferences/default.rs b/espanso/src/preferences/default.rs
index 250cd72b..5bb5f8da 100644
--- a/espanso/src/preferences/default.rs
+++ b/espanso/src/preferences/default.rs
@@ -44,14 +44,14 @@ impl<KVSType: KVS> DefaultPreferences<KVSType> {
     self
       .kvs
       .get(key)
-      .unwrap_or_else(|_| panic!("unable to read preference for key {}", key))
+      .unwrap_or_else(|_| panic!("unable to read preference for key {key}"))
   }
 
   fn set<T: Serialize>(&self, key: &str, value: T) {
     self
       .kvs
       .set(key, value)
-      .unwrap_or_else(|_| panic!("unable to write preference for key {}", key));
+      .unwrap_or_else(|_| panic!("unable to write preference for key {key}"));
   }
 }
 


Test patch: