From 9a9b2110629b05e2056dde404a9f6432a8973de4 Mon Sep 17 00:00:00 2001 From: SandroPacella Date: Mon, 23 Feb 2026 18:47:39 +0100 Subject: [PATCH 1/2] feat: add customizable keyboard shortcuts via textpod.toml Reads an optional textpod.toml config file from the working directory on startup. Shortcuts are defined under a [shortcuts] section (e.g. save = "Cmd+Enter") and injected into the frontend via template variables, reusing the existing {{FAVICON}} replacement pattern. Defaults to Ctrl+Enter when no config file is present, keeping full backwards compatibility. Resolves #46. --- Cargo.lock | 95 ++++++++++++++++++++++++++++++++++++++++++++------ Cargo.toml | 2 ++ README.md | 11 ++++++ src/index.html | 19 ++++++++-- src/main.rs | 48 ++++++++++++++++++++++--- 5 files changed, 158 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 80026af..dca2da0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -548,9 +548,9 @@ checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "hashbrown" -version = "0.15.1" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a9bfc1af68b1726ea47d3d5109de126281def866b33970e10fbab11b5dafab3" +checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" [[package]] name = "heck" @@ -682,9 +682,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "indexmap" -version = "2.6.0" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" dependencies = [ "equivalent", "hashbrown", @@ -1064,18 +1064,28 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.215" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.215" +version = "1.0.228" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" dependencies = [ "proc-macro2", "quote", @@ -1084,14 +1094,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.149" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" dependencies = [ "itoa", "memchr", - "ryu", "serde", + "serde_core", + "zmij", ] [[package]] @@ -1104,6 +1115,15 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +dependencies = [ + "serde_core", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -1250,7 +1270,9 @@ dependencies = [ "clap", "comrak", "serde", + "serde_json", "tokio", + "toml", "tower-http", "tracing", "tracing-subscriber", @@ -1374,6 +1396,45 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "1.0.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7614eaf19ad818347db24addfa201729cf2a9b6fdfd9eb0ab870fcacc606c0c" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.0.0+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32c2555c699578a4f59f0cc68e5116c8d7cabbd45e1409b989d4be085b53f13e" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.0.9+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "702d4415e08923e7e1ef96cd5727c0dfed80b4d2fa25db9647fe5eb6f7c5a4c4" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.0.6+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" + [[package]] name = "tower" version = "0.5.1" @@ -1729,6 +1790,12 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "winnow" +version = "0.7.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" + [[package]] name = "xdg" version = "2.5.2" @@ -1743,3 +1810,9 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/Cargo.toml b/Cargo.toml index ba20382..bf7e7fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,3 +19,5 @@ clap = { version = "4.4", features = ["derive"] } tracing = "0.1" tracing-subscriber = "0.3.18" base64 = "0.22.1" +toml = "1.0.3" +serde_json = "1.0.149" diff --git a/README.md b/README.md index 092ea08..761e29c 100644 --- a/README.md +++ b/README.md @@ -36,6 +36,17 @@ In order to download webpages, you need to have `monolith` installed. `cargo ins Run `textpod` in any directory. It will create a `notes.md` file if it doesn't exist. It will create `attachments` directory for file and image attachments. Webpages are saved in `attachments/webpages`. You can specify the port with `-p` flag, e.g. `textpod -p 8080` and/or the address with `-l` flag, e.g. `textpod -l 0.0.0.0`. +## Configuration + +You can customize keyboard shortcuts by placing a `textpod.toml` file in the working directory (alongside `notes.md`). The file is optional — if absent, defaults apply. + +```toml +[shortcuts] +save = "Cmd+Enter" +``` + +Supported modifiers: `Ctrl`, `Cmd`, `Alt`, `Shift`. Combine them with `+` and a key name (e.g. `Enter`, `s`). The default save shortcut is `Ctrl+Enter`. + ## Docker Docker image is available at [Docker Hub](https://hub.docker.com/r/freetonik/textpod). diff --git a/src/index.html b/src/index.html index b70b8c3..7c39c90 100644 --- a/src/index.html +++ b/src/index.html @@ -113,11 +113,26 @@ + placeholder="{{SAVE_SHORTCUT_DISPLAY}} to save. Type / to search. Drag & drop files to attach. Start links with + to save local copies.">