Repository: espanso/espanso (language: rust)

Issue:
📝  improve contributing documentation
We have nowadays two documents to guide new and current contributors how to help the project, `Contributing.md` and `Compilation.md`.
This PR has the objective to merge those two in one single file


Discussion / hints:
341 files changed, and contributing.md and compilation.md don't appear to be among them?
Correct! This is a work in progress 😜 . Thanks for marking me, I converted it on a draft
...and a better justification on why the 341 files changed:
traditionally rust files are indented by 4 spaces. Not that you cannot develop rust with 2 indent spaces, but I think it's better to follow what most rust coders are used to read everywhere

Fix patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7774b2ccf..dba19d60e 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -5,6 +5,8 @@ name: CI
 
 on:
   push:
+    paths-ignore:
+      - 'docs/**'
     branches:
       - master
       - dev
diff --git a/.github/workflows/dev-release.yml b/.github/workflows/dev-release.yml
index 3ac4972bd..200cc0a57 100644
--- a/.github/workflows/dev-release.yml
+++ b/.github/workflows/dev-release.yml
@@ -5,6 +5,8 @@ name: Dev Release
 
 on:
   push:
+    paths-ignore:
+      - 'docs/**'
     branches:
       - dev
 
diff --git a/.gitignore b/.gitignore
index a4482b161..61e9f1df5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,5 +40,12 @@ venv/
 .vscode/
 *.profraw
 **/*.code-workspace
+
+# Binaries
+
+# Debian package builds
+*.deb
+
+# Windows
 Espanso-Win-Installer-x86_64*
 Espanso-Win-Portable-x86_64*
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
deleted file mode 100644
index 23d065fbe..000000000
--- a/CONTRIBUTING.md
+++ /dev/null
@@ -1,92 +0,0 @@
-# Contributing
-
-Welcome to Espanso!
-We are very happy to have you and we thank you for considering contributing!
-
-We would like to order the contributions like this:
-
-- Before you start hacking, it is important to **ask first** if your idea or bugfix is in order.
-  Create an issue or come and say hi in the `#dev` channel for fixing bugs and adding features involved with coding logic, and `#documentation` for updating primarly the website. Join us at [the discord][`espanso` discord].
-  We don't bite!.
-
-  It would be sad that you do the effort to clone the project, successfully make the PR, but it wasn't in our plans or there is another PR that is currently addressing that issue.
-
-- After the PR is submitted, the workflows will start to lint, check and test the changes. Please try to stay all green ✅.
-- Most of the time we take some time to respond. Sorry, we are few and there SO much to do here!
-
-## General guidelines and philosophy
-
-This is a list of things we would like to have and mantain across time. Please do your best to abide by.
-
-- We are geared towards a mostly-rust codebase, except on interactions with OS native modules (eg. C++ on Windows and Objective-C on macOS). We decided to stay on the native langauges on each platform, but if it's possible to make a change into rust, submit a PR and we'll see what can we do.
-- Everything should be explained on the documentation via drawings, markdown files, etc, but it is important to make it clear. There will always be some new guy or gal into the project we want to welcome 😄.
-- Use clear variable names and try to avoid confusing abbreviations. Think that your peers may not be fully fluent in english 💬.
-
-[`espanso` discord]: https://discord.gg/4QARseMS6k
-
-## Developing
-
-We would like the rust code:
-
-- to be formatted via `rustfmt`
-
-  ```console
-  cargo fmt --all
-  ```
-
-- to abide by the `clippy` ruleset we currently use
-
-  ```console
-  cargo clippy --workspace
-  ```
-
-- to approve the tests by running
-
-  ```console
-  cargo test --workspace
-  ```
-
-- to be compiled with `stable`, not `nightly`
-- prefer not to use macros, if possible. Try to use functions or generics.
-
-And C / C++ code:
-
-- we would like to use `clang-format`
-- and we would like to use `clang-tidy`
-
-but the code submitted is yet unformatted and untidy. Work in progress!
-
-### Tests
-
-It is good practice to cover your changes with a test. Also, try to think about corner cases and various ways how your changes could break. Cover those in the tests as well.
-
-Tests can be found in different places:
-
-- `/tests`
-- `src/tests`
-- command examples
-- crate-specific tests
-
-## `git`
-
-`git` is a powerful but a bit complex tool to use, and there are many criteria around the internet. We normally:
-
-- squash the commits when we merge a PR
-- TODO: setup git hooks with [`rusty-hook`](https://github.com/swellaby/rusty-hook)
-
----
-
-### A good PR makes a change!
-
-As a result of this PR-centric strategy and the general goal that the reviewers should easily understand your change, the **PR title and description matters** a great deal!
-
-> **Note**
-> Try to follow the suggestions in our PR message template to make sure we can quickly focus on the technical merits and impact on the users.
-
-#### A PR should limit itself to a single functional change or related set of same changes
-
-Mixing different changes in the same PR will make the review process much harder. A PR might get stuck on one aspect while we would actually like to land another change. Furthermore, if we are forced to revert a change, mixing and matching different aspects makes fixing bugs or regressions much harder.
-
-Thus, please try to **separate out unrelated changes**!
-**Don't** mix unrelated refactors with a potentially contested change.
-Stylistic fixes and housekeeping can be bundled up into singular PRs.
diff --git a/Compilation.md b/Compilation.md
index acb3b3653..b1c137238 100644
--- a/Compilation.md
+++ b/Compilation.md
@@ -1,143 +1,3 @@
-# Compilation
 
-This document tries to explain the various steps needed to build espanso. (Work in progress).
+# This guide has moved to [the `docs/` folder](https://github.com/AucaCoyan/espanso/tree/upgrade-contributing/docs)
 
-## Prerequisites
-
-These are the basic tools required to build espanso:
-
-* A recent Rust compiler. You can install it following [these instructions](https://www.rust-lang.org/tools/install)
-* A C/C++ compiler. There are multiple of them depending on the platform, but espanso officially supports the following:
-  * On Windows, you should use the MSVC compiler. The easiest way to install it is by downloading [Visual Studio](https://visualstudio.microsoft.com/) and checking "Desktop development with C++" in the installer.
-  Note that [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) alone doesn't fulfill all the requirements for espanso.
-  * On macOS, you should use the official build tools that come with Xcode. If you don't want to install Xcode, you should be able to download only the build tools by executing `xcode-select —install` and following the instructions.
-  * On Linux, you should use the default C/C++ compiler (it's usually GCC). On Ubuntu/Debian systems, you can install them with `sudo apt install build-essential`
-
-* Espanso heavily relies on [cargo make](https://github.com/sagiegurari/cargo-make) for the various packaging
-steps. You can install it by running:
-
-```bash
-cargo install rust-script
-cargo install --force cargo-make --version 0.37.5
-```
-
-## Windows
-
-After installing the prerequisites, you are ready to compile Espanso on Windows.
-
-Espanso supports multiple targets on Windows: plain executable, installer and portable mode. The following sections explain how to build Espanso for these configurations.
-
-### Plain executable
-
-If you only want to build the "plain" Espanso executable, you can do so by running:
-
-```bash
-cargo make --profile release -- build-binary
-```
-
-This will create an `espanso` executable in the `target/release` directory.
-
-### Installer
-
-If you want to build the Installer (the executable that installs Espanso on a machine), you can run:
-
-```bash
-cargo make --profile release -- build-windows-installer
-```
-
-This will generate the installer in the `target/windows/installer` directory.
-
-### Portable mode bundle
-
-You can also generate a portable-mode bundle (a self-contained ZIP archive that does not require installation) by running:
-
-```bash
-cargo make --profile release -- build-windows-portable
-```
-
-This will generate the executable in the `target/windows/portable` directory.
-There are README instructions inside!.
-
-## MacOS
-
-After installing the prerequisites, you are ready to build Espanso on macOS.
-
-Espanso supports two targets on macOS: plain executable and App Bundle. For most cases, the App Bundle format is preferrable.
-
-### App Bundle
-
-You can build the App Bundle by running:
-
-```bash
-cargo make --profile release -- create-bundle
-```
-
-This will create the `Espanso.app` bundle in the `target/mac` directory.
-
-## Linux
-
-Espanso on Linux comes in two different flavors: one for X11 and one for Wayland.
-If you don't know which one to choose, follow [these steps to determine which one you are running](https://unix.stackexchange.com/a/325972).
-
-### Necessary dependencies
-
-If compiling on a version of Ubuntu X11 before 22.04 (including 22.04):
-
-```bash
-sudo apt install libx11-dev libxtst-dev libxkbcommon-dev libdbus-1-dev libwxgtk3.0-gtk3-dev
-```
-
-If compiling on a version of Ubuntu X11 after 22.04:
-
-```bash
-sudo apt install libx11-dev libxtst-dev libxkbcommon-dev libdbus-1-dev libwxgtk3.*-dev
-```
-
-### Compiling for X11
-
-#### X11 AppImage
-
-The AppImage is a convenient format to distribute Linux applications, as besides the binary,
-it also bundles all the required libraries.
-
-You can create the AppImage by running (this will work on X11 systems):
-
-```bash
-cargo make --profile release -- create-app-image
-```
-
-You will find the resulting AppImage in the `target/linux/AppImage/out` folder.
-
-#### Binary
-
-You can build the Espanso binary on X11 by running the following command:
-
-```bash
-cargo make --profile release -- build-binary
-```
-
-You'll then find the `espanso` binary in the `target/release` directory.
-
-### Compiling on Wayland
-
-You can build Espanso on Wayland by running:
-
-```bash
-cargo make --env NO_X11=true --profile release -- build-binary
-```
-
-You'll then find the `espanso` binary in the `target/release` directory.
-
-## Advanced
-
-Espanso offers a few flags that might be necessary if you want to further tune the resulting binary.
-
-### Disabling modulo (GUI features)
-
-Espanso includes a component known as _modulo_, which handles most of the graphical-related parts of the tool.
-For example, the Search bar or Forms are handled by it.
-
-If you don't want them, you can pass the `--env NO_MODULO=true` flag to any of the previous `cargo make` commands
-to remove support for it.
-
-Keep in mind that espanso was designed with modulo as a first class citizen, so the experience might be far from perfect without it.
diff --git a/docs/.gitignore b/docs/.gitignore
new file mode 100644
index 000000000..7585238ef
--- /dev/null
+++ b/docs/.gitignore
@@ -0,0 +1,1 @@
+book
diff --git a/docs/README.md b/docs/README.md
new file mode 100644
index 000000000..fc66bc9d2
--- /dev/null
+++ b/docs/README.md
@@ -0,0 +1,65 @@
+# Espanso Developer docs
+
+This sub folder corresponds to the developer documentation. If you are looking
+to the user documentation it's [on the webpage](https://espanso.org/).
+
+![espanso docs picture](./assets/espanso-docs.png)
+
+## Description
+
+- `./docs` is the source directory of the book
+- `./docs/src/SUMMARY.md` configures the order of the menu on the left hand side
+  of the book (more info here). "Without this file, there is no book."
+- `./docs/assets` stores all the non-markdown content (screenshots, gifs) to be
+  used.
+- `./theme` stores general files to be used by mdbook to configure the look and
+  feel of the book (more info here).
+
+## Building instructions (Install mdBook)
+
+- from source
+
+```
+cargo install mdbook
+```
+
+- if you have `cargo-binstall`
+
+```
+cargo binstall mdbook
+```
+
+- or, you can also install it via `scoop` or `nix-packages`
+
+## run the book locally
+
+Run mdbook build in this directory.
+
+```
+mdbook build --open
+```
+
+And it's generated at `build/index.html`
+
+To see the website update in real-time while you edit the content, you can use
+`mdbook serve --open` instead of the build argument
+
+```
+mdbook serve --open
+```
+
+## `Couldn't open SUMMARY.md`
+
+If you see this error:
+
+```console
+2025-01-17 07:30:25 [ERROR] (mdbook::utils): Error: Couldn't open SUMMARY.md in "/home/acoyan/repos/espanso-upgrade-contributing/src" directory
+2025-01-17 07:30:25 [ERROR] (mdbook::utils): 	Caused By: No such file or directory (os error 2)
+```
+
+Make sure you are in the repo folder, inside `docs/` subfolder.
+
+```
+$ pwd
+/your/repo/location/espanso/docs
+```
diff --git a/docs/assets/espanso-docs.png b/docs/assets/espanso-docs.png
new file mode 100644
index 000000000..81d02f66e
Binary files /dev/null and b/docs/assets/espanso-docs.png differ
diff --git a/docs/book.toml b/docs/book.toml
new file mode 100644
index 000000000..787ef72b0
--- /dev/null
+++ b/docs/book.toml
@@ -0,0 +1,12 @@
+[book]
+authors = ["Auca Coyan"]
+language = "en"
+multilingual = false
+src = "src"
+title = "espanso-docs"
+
+[output.html]
+default-theme = "ayu"
+preferred-dark-theme = "ayu"
+git-repository-url = "https://github.com/espanso/espanso"
+git-repository-icon = "fa-github"
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
new file mode 100644
index 000000000..c765f4341
--- /dev/null
+++ b/docs/src/SUMMARY.md
@@ -0,0 +1,10 @@
+# Summary
+
+- [Introduction](./ch00-introduction.md)
+- [General guidelines](./ch01-general-guidelines.md)
+- [Building and compilation](./ch02-building-and-compilation.md)
+  - [Windows](./ch02-windows.md)
+  - [macOS](./ch02-macos.md)
+  - [linux](./ch02-linux.md)
+- [Creating a PR](./ch03-creating-a-pr.md)
+- [Dev recipes and cookbook](./ch04-recipes-and-cookbook.md)
diff --git a/docs/src/ch00-introduction.md b/docs/src/ch00-introduction.md
new file mode 100644
index 000000000..368543252
--- /dev/null
+++ b/docs/src/ch00-introduction.md
@@ -0,0 +1,18 @@
+# Introduction
+
+Welcome to Espanso!
+We are very happy to have you and we thank you for considering contributing!
+
+We would like to order the contributions like this:
+
+- Before you start hacking, it is important to **ask first** if your idea or bugfix is in order.
+  Create an issue or come and say hi in the `#dev` channel for fixing bugs and adding features involved with coding logic, and `#documentation` for updating primarly the website. Join us at [the discord][`espanso` discord].
+  We don't bite!.
+
+  It would be sad that you do the effort to clone the project, successfully make the PR, but it wasn't in our plans or there is another PR that is currently addressing that issue.
+
+- After the PR is submitted, the workflows will start to lint, check and test the changes. Please try to stay all green ✅.
+- Most of the time we take some time to respond. Sorry, we are few and there SO much to do here!
+
+
+[`espanso` discord]: https://discord.gg/4QARseMS6k
diff --git a/docs/src/ch01-general-guidelines.md b/docs/src/ch01-general-guidelines.md
new file mode 100644
index 000000000..a2a54c540
--- /dev/null
+++ b/docs/src/ch01-general-guidelines.md
@@ -0,0 +1,10 @@
+## General guidelines and philosophy
+
+This is a list of things we would like to have and maintain across time. Please do your best to abide by them.
+
+- We are geared towards a mostly-Rust codebase, except on interactions with OS native modules (eg. C++ on Windows and Objective-C on macOS). We decided to stay on the native langauges on each platform, but if it's possible to make a change into Rust, submit a PR and we'll see what can we do.
+- Everything should be explained on the documentation via drawings, markdown files, etc, but it is important to make it clear. There will always be some new guy or gal into the project we want to welcome 😄.
+- Use clear variable names and try to avoid confusing abbreviations. Think that your peers may not be fully fluent in English 💬.
+
+[`espanso` discord]: https://discord.gg/4QARseMS6k
+
diff --git a/docs/src/ch02-building-and-compilation.md b/docs/src/ch02-building-and-compilation.md
new file mode 100644
index 000000000..63d1a1598
--- /dev/null
+++ b/docs/src/ch02-building-and-compilation.md
@@ -0,0 +1,36 @@
+# Building and compilation
+
+This chapter explains the various steps needed to build espanso.
+
+### Prerequisites
+
+These are the basic tools required to build espanso:
+
+- A recent Rust compiler. You can install it following [these instructions](https://www.rust-lang.org/tools/install)
+- A C/C++ compiler. There are multiple of them depending on the platform, but espanso officially supports the following:
+  - On Windows, you should use the MSVC compiler. The easiest way to install it is by downloading [Visual Studio](https://visualstudio.microsoft.com/) and checking "Desktop development with C++" in the installer.
+  Note that [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) alone doesn't fulfill all the requirements for espanso.
+  - On macOS, you should use the official build tools that come with Xcode. If you don't want to install Xcode, you should be able to download only the build tools by executing `xcode-select —install` and following the instructions.
+  - On Linux, you should use the default C/C++ compiler (it's usually GCC). On Ubuntu/Debian systems, you can install them with `sudo apt install build-essential`
+
+- Espanso heavily relies on [cargo make](https://github.com/sagiegurari/cargo-make) for the various packaging
+steps. You can install it by running:
+
+```bash
+cargo install rust-script --version "0.7.0"
+cargo install --force cargo-make --version 0.37.5
+```
+### Advanced compilation
+
+Espanso offers a few flags that might be necessary if you want to further tune the resulting binary.
+
+#### Disabling modulo (GUI features)
+
+Espanso includes a component known as _modulo_, which handles most of the graphical-related parts of the tool.
+For example, the Search bar or Forms are handled by it.
+
+If you don't want them, you can pass the `--env NO_MODULO=true` flag to any of the previous `cargo make` commands
+to remove support for it.
+
+Keep in mind that espanso was designed with modulo as a first class citizen, so the experience might be far from perfect without it.
+
diff --git a/docs/src/ch02-linux.md b/docs/src/ch02-linux.md
new file mode 100644
index 000000000..ac26626fb
--- /dev/null
+++ b/docs/src/ch02-linux.md
@@ -0,0 +1,54 @@
+# linux
+
+Espanso on Linux comes in two different flavors: one for X11 and one for Wayland.
+If you don't know which one to choose, follow [these steps to determine which one you are running](https://unix.stackexchange.com/a/325972).
+
+#### Necessary dependencies
+
+If compiling on a version of Ubuntu X11 before 22.04 (including 22.04):
+
+```bash
+sudo apt install libx11-dev libxtst-dev libxkbcommon-dev libdbus-1-dev libwxgtk3.0-gtk3-dev
+```
+
+If compiling on a version of Ubuntu X11 after 22.04:
+
+```bash
+sudo apt install libx11-dev libxtst-dev libxkbcommon-dev libdbus-1-dev libwxgtk3.2-dev
+```
+
+#### Compiling for X11
+
+##### X11 AppImage
+
+The AppImage is a convenient format to distribute Linux applications, as besides the binary,
+it also bundles all the required libraries.
+
+You can create the AppImage by running (this will work on X11 systems):
+
+```bash
+cargo make --profile release -- create-app-image
+```
+
+You will find the resulting AppImage in the `target/linux/AppImage/out` folder.
+
+##### Binary
+
+You can build the Espanso binary on X11 by running the following command:
+
+```bash
+cargo make --profile release -- build-binary
+```
+
+You'll then find the `espanso` binary in the `target/release` directory.
+
+#### Compiling on Wayland
+
+You can build Espanso on Wayland by running:
+
+```bash
+cargo make --env NO_X11=true --profile release -- build-binary
+```
+
+You'll then find the `espanso` binary in the `target/release` directory.
+
diff --git a/docs/src/ch02-macos.md b/docs/src/ch02-macos.md
new file mode 100644
index 000000000..da1279726
--- /dev/null
+++ b/docs/src/ch02-macos.md
@@ -0,0 +1,17 @@
+# macOS
+
+After installing the prerequisites, you are ready to build Espanso on macOS.
+
+Espanso supports two targets on macOS: plain executable and App Bundle. For most cases, the App Bundle format is preferrable.
+
+#### App Bundle
+
+You can build the App Bundle by running:
+
+```bash
+cargo make --profile release -- create-bundle
+```
+
+This will create the `Espanso.app` bundle in the `target/mac` directory.
+
+
diff --git a/docs/src/ch02-windows.md b/docs/src/ch02-windows.md
new file mode 100644
index 000000000..24ffc9293
--- /dev/null
+++ b/docs/src/ch02-windows.md
@@ -0,0 +1,36 @@
+# Windows
+
+After installing the prerequisites, you are ready to compile Espanso on Windows.
+
+Espanso supports multiple targets on Windows: plain executable, installer and portable mode. The following sections explain how to build Espanso for these configurations.
+
+#### Plain executable
+
+If you only want to build the "plain" Espanso executable, you can do so by running:
+
+```bash
+cargo make --profile release -- build-binary
+```
+
+This will create an `espanso` executable in the `target/release` directory.
+
+##### Installer
+
+If you want to build the Installer (the executable that installs Espanso on a machine), you can run:
+
+```bash
+cargo make --profile release -- build-windows-installer
+```
+
+This will generate the installer in the `target/windows/installer` directory.
+
+##### Portable mode bundle
+
+You can also generate a portable-mode bundle (a self-contained ZIP archive that does not require installation) by running:
+
+```bash
+cargo make --profile release -- build-windows-portable
+```
+
+This will generate the executable in the `target/windows/portable` directory.
+There are README instructions inside!.
diff --git a/docs/src/ch03-creating-a-pr.md b/docs/src/ch03-creating-a-pr.md
new file mode 100644
index 000000000..a4eec6114
--- /dev/null
+++ b/docs/src/ch03-creating-a-pr.md
@@ -0,0 +1,69 @@
+# Creating a PR
+
+## Testing
+
+It is good practice to cover your changes with a test. Also, try to think about corner cases and various ways how your changes could break. Cover those in the tests as well.
+
+Tests can be found in 2 places:
+
+- `/test/` folder (we have this case only in `espanso-migrate`)
+- within the same file of the function, in a `tests` mod
+
+## Creating a PR
+
+Firt and foremost: **A good PR makes a change!**. Let's chat some basic theory before going to the practice
+
+Because of this PR-centric strategy and the goal that the reviewers should easily understand your change, the **PR title and description matters** a great deal!
+
+> **Note**
+> Try to follow the suggestions in our PR message template to make sure we can quickly focus on the technical merits and impact on the users.
+
+### A PR should limit itself to a single functional change or related set of same changes
+
+Mixing different changes in the same PR will make the review process much harder. A PR might get stuck on one aspect while we would actually like to land another change. Furthermore, if we are forced to revert a change, mixing and matching different aspects makes fixing bugs or regressions much harder.
+
+Thus, please try to **separate out unrelated changes**!
+**Don't** mix unrelated refactors with a potentially contested change.
+Stylistic fixes and housekeeping can be bundled up into singular PRs.
+
+### Going to the practice
+
+We would like the Rust code:
+
+- to be formatted via `rustfmt`
+
+  ```console
+  cargo fmt --all
+  ```
+
+- to abide by the `clippy` ruleset we currently use
+
+  ```console
+  cargo clippy --workspace
+  ```
+
+- to approve the tests by running
+
+  ```console
+  cargo test --workspace
+  ```
+
+- to be compiled with `stable`, not `nightly`
+- prefer not to use macros, if possible. Try to use functions or generics.
+
+And C / C++ code:
+
+- we would like to use a formatter, like `clang-format` (we can use [run-clang-format](https://github.com/lmapii/run-clang-format)
+to format folders recursively)
+- and we would like to use `clang-tidy`, but we need a Compilation database in order to use `clang-tidy`
+ (also, we can use [run-clang-tidy](https://github.com/lmapii/run-clang-tidy) to help too!)
+
+Today our submitted code is yet untidy. Work in progress!
+
+### `git`
+
+`git` is a powerful but a bit complex tool to use, and there are many criteria around the internet. We normally:
+
+- squash the commits when we merge a PR
+- TODO: setup git hooks with some tool
+
diff --git a/docs/src/ch04-recipes-and-cookbook.md b/docs/src/ch04-recipes-and-cookbook.md
new file mode 100644
index 000000000..053da1f06
--- /dev/null
+++ b/docs/src/ch04-recipes-and-cookbook.md
@@ -0,0 +1,63 @@
+# Dev recipes and cookbook
+
+Developing a project is sometimes complex, and we use these tools every now and then to check if we
+ are doing everything right. These aren't tools that we _need_ to run on CI, but
+ it's nice to have them and check if it's allright.
+
+## `cargo udeps` to find unused dependencies
+
+install it by
+
+```bash
+# traditional cargo install
+cargo install cargo-udeps --locked
+# or with cargo binstall
+cargo binstall cargo-udeps --locked
+```
+
+Nightly toolchain is needed, just for this tool only
+
+```bash
+rustup toolchain install nightly
+```
+
+and then run:
+
+```bash
+cargo +nightly udeps --all-targets
+```
+
+There is a [sample issue here](https://github.com/espanso/espanso/issues/1833),
+and [its PR there](https://github.com/espanso/espanso/pull/1856)
+We know some false positives, running on windows or linux gives:
+
+```bash
+unused dependencies:
+`espanso-mac-utils v0.1.0 (C:\Users\user\repos\espanso\espanso-mac-utils)`
+├─── dependencies
+│    ├─── "lazy_static"
+│    └─── "regex"
+└─── build-dependencies
+     └─── "cc"
+`espanso-modulo v0.1.0 (C:\Users\user\repos\espanso\espanso-modulo)`
+└─── build-dependencies
+     └─── "glob"
+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.
+```
+These are because the windows and linux can't see through the `target = macos`
+
+## check for outdated dependencies
+
+install it by
+```bash
+# traditional cargo install
+cargo install cargo-outdated --locked
+# or with cargo binstall
+cargo binstall cargo-outdated --locked
+```
+An run it with
+```bash
+cargo outdated
+```
diff --git a/espanso-modulo/src/search/algorithm.rs b/espanso-modulo/src/search/algorithm.rs
index 618cd7296..2cb8ee315 100644
--- a/espanso-modulo/src/search/algorithm.rs
+++ b/espanso-modulo/src/search/algorithm.rs
@@ -44,7 +44,7 @@ fn exact_match(query: &str, items: &[SearchItem]) -> Vec<usize> {
     .enumerate()
     .filter(|(_, item)| {
       item.label.contains(query)
-        || item.trigger.as_deref().map_or(false, |t| t.contains(query))
+        || item.trigger.as_deref().is_some_and(|t| t.contains(query))
         || item.search_terms.iter().any(|term| term.contains(query))
     })
     .map(|(i, _)| i)
@@ -61,7 +61,7 @@ fn case_insensitive_exact_match(query: &str, items: &[SearchItem]) -> Vec<usize>
         || item
           .trigger
           .as_deref()
-          .map_or(false, |t| t.to_lowercase().contains(query))
+          .is_some_and(|t| t.to_lowercase().contains(query))
         || item
           .search_terms
           .iter()
@@ -83,7 +83,7 @@ fn case_insensitive_keyword(query: &str, items: &[SearchItem]) -> Vec<usize> {
           && !item
             .trigger
             .as_deref()
-            .map_or(false, |t| t.to_lowercase().contains(keyword))
+            .is_some_and(|t| t.to_lowercase().contains(keyword))
           && !item
             .search_terms
             .iter()
diff --git a/espanso-render/src/extension/choice.rs b/espanso-render/src/extension/choice.rs
index d13219d92..72b574253 100644
--- a/espanso-render/src/extension/choice.rs
+++ b/espanso-render/src/extension/choice.rs
@@ -51,7 +51,7 @@ impl<'a> ChoiceExtension<'a> {
 }
 
 impl Extension for ChoiceExtension<'_> {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "choice"
   }
 
diff --git a/espanso-render/src/extension/clipboard.rs b/espanso-render/src/extension/clipboard.rs
index 3c94a2179..a902bdea7 100644
--- a/espanso-render/src/extension/clipboard.rs
+++ b/espanso-render/src/extension/clipboard.rs
@@ -36,7 +36,7 @@ impl<'a> ClipboardExtension<'a> {
 }
 
 impl Extension for ClipboardExtension<'_> {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "clipboard"
   }
 
diff --git a/espanso-render/src/extension/date.rs b/espanso-render/src/extension/date.rs
index 171da66ed..728a1da1d 100644
--- a/espanso-render/src/extension/date.rs
+++ b/espanso-render/src/extension/date.rs
@@ -41,7 +41,7 @@ impl<'a> DateExtension<'a> {
 }
 
 impl Extension for DateExtension<'_> {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "date"
   }
 
diff --git a/espanso-render/src/extension/form.rs b/espanso-render/src/extension/form.rs
index 418caad48..88f36f186 100644
--- a/espanso-render/src/extension/form.rs
+++ b/espanso-render/src/extension/form.rs
@@ -50,7 +50,7 @@ impl<'a> FormExtension<'a> {
 }
 
 impl Extension for FormExtension<'_> {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "form"
   }
 
diff --git a/espanso-render/src/extension/random.rs b/espanso-render/src/extension/random.rs
index 42b5e5eb7..70aaffa86 100644
--- a/espanso-render/src/extension/random.rs
+++ b/espanso-render/src/extension/random.rs
@@ -31,7 +31,7 @@ impl RandomExtension {
 }
 
 impl Extension for RandomExtension {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "random"
   }
 
diff --git a/espanso-render/src/extension/script.rs b/espanso-render/src/extension/script.rs
index 61a72f98a..c3a9e0c79 100644
--- a/espanso-render/src/extension/script.rs
+++ b/espanso-render/src/extension/script.rs
@@ -44,7 +44,7 @@ impl ScriptExtension {
 }
 
 impl Extension for ScriptExtension {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "script"
   }
 
diff --git a/espanso-render/src/extension/shell.rs b/espanso-render/src/extension/shell.rs
index 991a094a9..d1a1f8dcd 100644
--- a/espanso-render/src/extension/shell.rs
+++ b/espanso-render/src/extension/shell.rs
@@ -208,7 +208,7 @@ impl ShellExtension {
 }
 
 impl Extension for ShellExtension {
-  fn name(&self) -> &str {
+  fn name(&self) -> &'static str {
     "shell"
   }
 
diff --git a/espanso-render/src/renderer/mod.rs b/espanso-render/src/renderer/mod.rs
index cbd5c5e31..21abe458f 100644
--- a/espanso-render/src/renderer/mod.rs
+++ b/espanso-render/src/renderer/mod.rs
@@ -264,7 +264,7 @@ mod tests {
   struct MockExtension {}
 
   impl Extension for MockExtension {
-    fn name(&self) -> &str {
+    fn name(&self) -> &'static str {
       "mock"
     }
 
diff --git a/espanso/src/cli/edit.rs b/espanso/src/cli/edit.rs
index 33675b841..7da015387 100644
--- a/espanso/src/cli/edit.rs
+++ b/espanso/src/cli/edit.rs
@@ -143,10 +143,10 @@ fn determine_target_path(config_path: &Path, target_file: Option<&str>) -> PathB
       custom => {
         if !std::path::Path::new(custom)
           .extension()
-          .map_or(false, |ext| ext.eq_ignore_ascii_case("yml"))
+          .is_some_and(|ext| ext.eq_ignore_ascii_case("yml"))
           && !std::path::Path::new(custom)
             .extension()
-            .map_or(false, |ext| ext.eq_ignore_ascii_case("yaml"))
+            .is_some_and(|ext| ext.eq_ignore_ascii_case("yaml"))
         {
           config_path.join("match").join(format!("{custom}.yml"))
         } else {
diff --git a/espanso/src/lock.rs b/espanso/src/lock.rs
index 85b03d3e5..0a1d3445a 100644
--- a/espanso/src/lock.rs
+++ b/espanso/src/lock.rs
@@ -31,7 +31,7 @@ pub struct Lock {
 impl Lock {
   #[allow(dead_code)]
   pub fn release(self) -> Result<()> {
-    self.lock_file.unlock()?;
+    fs2::FileExt::unlock(&self.lock_file)?;
     Ok(())
   }
 
@@ -54,9 +54,7 @@ impl Lock {
 
 impl Drop for Lock {
   fn drop(&mut self) {
-    self
-      .lock_file
-      .unlock()
+    fs2::FileExt::unlock(&self.lock_file)
       .unwrap_or_else(|_| panic!("unable to unlock lock_file: {:?}", self.lock_file));
   }
 }


Test patch: