aboutsummaryrefslogtreecommitdiffstats
path: root/pkgs/by-name/lf
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--pkgs/by-name/lf/lf-make-map/.envrc11
-rw-r--r--pkgs/by-name/lf/lf-make-map/.gitignore10
-rw-r--r--pkgs/by-name/lf/lf-make-map/Cargo.lock527
-rw-r--r--pkgs/by-name/lf/lf-make-map/Cargo.toml20
-rw-r--r--pkgs/by-name/lf/lf-make-map/README.md12
-rw-r--r--pkgs/by-name/lf/lf-make-map/flake.lock139
-rw-r--r--pkgs/by-name/lf/lf-make-map/flake.nix137
-rw-r--r--pkgs/by-name/lf/lf-make-map/package.nix9
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/cli.rs16
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/main.rs157
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/interactive.rs172
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/lf_mapping.rs35
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/map_key.rs280
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/display.rs91
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/iterator.rs53
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/lf_mapping.rs24
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/mod.rs402
-rw-r--r--pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs318
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/tests/base.sh25
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/tests/cases/child_insert/test.sh27
-rw-r--r--pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/output.old13
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/test.sh49
-rw-r--r--pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/output.old17
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/test.sh53
-rw-r--r--pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old46
-rw-r--r--pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old.license9
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/tests/cases/simple/test.sh47
-rwxr-xr-xpkgs/by-name/lf/lf-make-map/update.sh14
28 files changed, 1489 insertions, 1224 deletions
diff --git a/pkgs/by-name/lf/lf-make-map/.envrc b/pkgs/by-name/lf/lf-make-map/.envrc
index 2b742cf6..880b1809 100644
--- a/pkgs/by-name/lf/lf-make-map/.envrc
+++ b/pkgs/by-name/lf/lf-make-map/.envrc
@@ -1,4 +1,15 @@
#!/usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
use flake || use nix
watch_file flake.nix
diff --git a/pkgs/by-name/lf/lf-make-map/.gitignore b/pkgs/by-name/lf/lf-make-map/.gitignore
index cb87f36f..8f29eabf 100644
--- a/pkgs/by-name/lf/lf-make-map/.gitignore
+++ b/pkgs/by-name/lf/lf-make-map/.gitignore
@@ -1,3 +1,13 @@
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
# build
/target
/result
diff --git a/pkgs/by-name/lf/lf-make-map/Cargo.lock b/pkgs/by-name/lf/lf-make-map/Cargo.lock
index d68f7492..c6a44974 100644
--- a/pkgs/by-name/lf/lf-make-map/Cargo.lock
+++ b/pkgs/by-name/lf/lf-make-map/Cargo.lock
@@ -1,14 +1,17 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
version = 4
[[package]]
-name = "android-tzdata"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
-
-[[package]]
name = "android_system_properties"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -19,9 +22,9 @@ dependencies = [
[[package]]
name = "anstream"
-version = "0.6.18"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
+checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d"
dependencies = [
"anstyle",
"anstyle-parse",
@@ -34,79 +37,85 @@ dependencies = [
[[package]]
name = "anstyle"
-version = "1.0.10"
+version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
+checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000"
[[package]]
name = "anstyle-parse"
-version = "0.2.6"
+version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
+checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e"
dependencies = [
"utf8parse",
]
[[package]]
name = "anstyle-query"
-version = "1.1.2"
+version = "1.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
+checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc"
dependencies = [
"windows-sys",
]
[[package]]
name = "anstyle-wincon"
-version = "3.0.7"
+version = "3.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
+checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d"
dependencies = [
"anstyle",
- "once_cell",
+ "once_cell_polyfill",
"windows-sys",
]
[[package]]
name = "anyhow"
-version = "1.0.97"
+version = "1.0.102"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
+checksum = "7f202df86484c868dbad7eaa557ef785d5c66295e41b460ef922eca0723b842c"
[[package]]
name = "autocfg"
-version = "1.4.0"
+version = "1.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
+
+[[package]]
+name = "bitflags"
+version = "2.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "84d7ced0ae9557296835c32bf1b1e02b44c746701f898460fb000d7eaa84f00a"
[[package]]
name = "bumpalo"
-version = "3.17.0"
+version = "3.20.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
+checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649"
[[package]]
name = "cc"
-version = "1.2.17"
+version = "1.2.63"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fcb57c740ae1daf453ae85f16e37396f672b039e00d9d866e07ddb24e328e3a"
+checksum = "556e016178bb5662a08681bbe0f00f8e17631781a4dfc8c45e466e4b185ec27f"
dependencies = [
+ "find-msvc-tools",
"shlex",
]
[[package]]
name = "cfg-if"
-version = "1.0.0"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
[[package]]
name = "chrono"
-version = "0.4.40"
+version = "0.4.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a7964611d71df112cb1730f2ee67324fcf4d0fc6606acbbe9bfe06df124637c"
+checksum = "c673075a2e0e5f4a1dde27ce9dee1ea4558c7ffe648f576438a20ca1d2acc4b0"
dependencies = [
- "android-tzdata",
"iana-time-zone",
"js-sys",
"num-traits",
@@ -116,9 +125,9 @@ dependencies = [
[[package]]
name = "clap"
-version = "4.5.34"
+version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e958897981290da2a852763fe9cdb89cd36977a5d729023127095fa94d95e2ff"
+checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51"
dependencies = [
"clap_builder",
"clap_derive",
@@ -126,9 +135,9 @@ dependencies = [
[[package]]
name = "clap_builder"
-version = "4.5.34"
+version = "4.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "83b0f35019843db2160b5bb19ae09b4e6411ac33fc6a712003c33e03090e2489"
+checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f"
dependencies = [
"anstream",
"anstyle",
@@ -138,9 +147,9 @@ dependencies = [
[[package]]
name = "clap_derive"
-version = "4.5.32"
+version = "4.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
+checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9"
dependencies = [
"heck",
"proc-macro2",
@@ -150,15 +159,15 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.4"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
+checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9"
[[package]]
name = "colorchoice"
-version = "1.0.3"
+version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
+checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570"
[[package]]
name = "core-foundation-sys"
@@ -167,6 +176,70 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
[[package]]
+name = "crossterm"
+version = "0.29.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b9f2e4c67f833b660cdb0a3523065869fb35570177239812ed4c905aeff87b"
+dependencies = [
+ "bitflags",
+ "document-features",
+ "mio",
+ "parking_lot",
+ "rustix",
+ "signal-hook",
+ "signal-hook-mio",
+]
+
+[[package]]
+name = "document-features"
+version = "0.2.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61"
+dependencies = [
+ "litrs",
+]
+
+[[package]]
+name = "errno"
+version = "0.3.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
+dependencies = [
+ "libc",
+ "windows-sys",
+]
+
+[[package]]
+name = "find-msvc-tools"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582"
+
+[[package]]
+name = "futures-core"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d"
+
+[[package]]
+name = "futures-task"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393"
+
+[[package]]
+name = "futures-util"
+version = "0.3.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6"
+dependencies = [
+ "futures-core",
+ "futures-task",
+ "pin-project-lite",
+ "slab",
+]
+
+[[package]]
name = "heck"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -174,15 +247,15 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
[[package]]
name = "hermit-abi"
-version = "0.5.0"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
+checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c"
[[package]]
name = "iana-time-zone"
-version = "0.1.62"
+version = "0.1.65"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b2fd658b06e56721792c5df4475705b6cda790e9298d19d2f8af083457bcd127"
+checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470"
dependencies = [
"android_system_properties",
"core-foundation-sys",
@@ -204,9 +277,9 @@ dependencies = [
[[package]]
name = "is-terminal"
-version = "0.4.16"
+version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e04d7f318608d35d4b61ddd75cbdaee86b023ebe2bd5a66ee0915f0bf93095a9"
+checksum = "3640c1c38b8e4e43584d8df18be5fc6b0aa314ce6ebf51b53313d4306cca8e46"
dependencies = [
"hermit-abi",
"libc",
@@ -215,26 +288,39 @@ dependencies = [
[[package]]
name = "is_terminal_polyfill"
-version = "1.70.1"
+version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695"
[[package]]
name = "js-sys"
-version = "0.3.77"
+version = "0.3.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
+checksum = "142bc4740e452c1e57ade0cbc129f139c9093e354346f0872ef985f4f5cf5f11"
dependencies = [
+ "cfg-if",
+ "futures-util",
"once_cell",
"wasm-bindgen",
]
[[package]]
+name = "keymaps"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea59e8e461942cf1d6a7ad938848d6fd2e40eb43799c21192c09226ecc86710f"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
name = "lf-make-map"
version = "0.1.0"
dependencies = [
"anyhow",
"clap",
+ "crossterm",
+ "keymaps",
"log",
"stderrlog",
"walkdir",
@@ -242,15 +328,48 @@ dependencies = [
[[package]]
name = "libc"
-version = "0.2.171"
+version = "0.2.186"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
+
+[[package]]
+name = "linux-raw-sys"
+version = "0.12.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53"
+
+[[package]]
+name = "litrs"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "11d3d7f243d5c5a8b9bb5d6dd2b1602c0cb0b9db1621bafc7ed66e35ff9fe092"
+
+[[package]]
+name = "lock_api"
+version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
+checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
+dependencies = [
+ "scopeguard",
+]
[[package]]
name = "log"
-version = "0.4.27"
+version = "0.4.31"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "113b30b4cd05f7c06868fdb2854f66a7b9fece9a48425351cd532e810d74024f"
+
+[[package]]
+name = "mio"
+version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
+checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda"
+dependencies = [
+ "libc",
+ "log",
+ "wasi",
+ "windows-sys",
+]
[[package]]
name = "num-traits"
@@ -263,33 +382,90 @@ dependencies = [
[[package]]
name = "once_cell"
-version = "1.21.3"
+version = "1.21.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
+
+[[package]]
+name = "once_cell_polyfill"
+version = "1.70.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
+checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
+
+[[package]]
+name = "parking_lot"
+version = "0.12.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a"
+dependencies = [
+ "lock_api",
+ "parking_lot_core",
+]
+
+[[package]]
+name = "parking_lot_core"
+version = "0.9.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "redox_syscall",
+ "smallvec",
+ "windows-link",
+]
+
+[[package]]
+name = "pin-project-lite"
+version = "0.2.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd"
[[package]]
name = "proc-macro2"
-version = "1.0.94"
+version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.40"
+version = "1.0.45"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
dependencies = [
"proc-macro2",
]
[[package]]
+name = "redox_syscall"
+version = "0.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "rustix"
+version = "1.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190"
+dependencies = [
+ "bitflags",
+ "errno",
+ "libc",
+ "linux-raw-sys",
+ "windows-sys",
+]
+
+[[package]]
name = "rustversion"
-version = "1.0.20"
+version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eded382c5f5f786b989652c49544c4877d9f015cc22e145a5ea8ea66c2921cd2"
+checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
[[package]]
name = "same-file"
@@ -301,10 +477,59 @@ dependencies = [
]
[[package]]
+name = "scopeguard"
+version = "1.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+
+[[package]]
name = "shlex"
-version = "1.3.0"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba"
+
+[[package]]
+name = "signal-hook"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2"
+dependencies = [
+ "libc",
+ "signal-hook-registry",
+]
+
+[[package]]
+name = "signal-hook-mio"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b75a19a7a740b25bc7944bdee6172368f988763b744e3d4dfe753f6b4ece40cc"
+dependencies = [
+ "libc",
+ "mio",
+ "signal-hook",
+]
+
+[[package]]
+name = "signal-hook-registry"
+version = "1.4.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b"
+dependencies = [
+ "errno",
+ "libc",
+]
+
+[[package]]
+name = "slab"
+version = "0.4.12"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5"
+
+[[package]]
+name = "smallvec"
+version = "1.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
+checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
[[package]]
name = "stderrlog"
@@ -327,9 +552,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]]
name = "syn"
-version = "2.0.100"
+version = "2.0.117"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
dependencies = [
"proc-macro2",
"quote",
@@ -346,20 +571,39 @@ dependencies = [
]
[[package]]
+name = "thiserror"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "2.0.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
name = "thread_local"
-version = "1.1.8"
+version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185"
dependencies = [
"cfg-if",
- "once_cell",
]
[[package]]
name = "unicode-ident"
-version = "1.0.18"
+version = "1.0.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
[[package]]
name = "utf8parse"
@@ -378,36 +622,29 @@ dependencies = [
]
[[package]]
+name = "wasi"
+version = "0.11.1+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
+
+[[package]]
name = "wasm-bindgen"
-version = "0.2.100"
+version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
+checksum = "3ed04576f974d2b2fba0f38c51dbc5518011e38c36bf1143164be765528fd409"
dependencies = [
"cfg-if",
"once_cell",
"rustversion",
"wasm-bindgen-macro",
-]
-
-[[package]]
-name = "wasm-bindgen-backend"
-version = "0.2.100"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
-dependencies = [
- "bumpalo",
- "log",
- "proc-macro2",
- "quote",
- "syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
-version = "0.2.100"
+version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
+checksum = "916151b09da36bd82f6615cbf3a419e2f0ba23a03c6160e8e92eb6bd4aa1dec6"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
@@ -415,119 +652,99 @@ dependencies = [
[[package]]
name = "wasm-bindgen-macro-support"
-version = "0.2.100"
+version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
+checksum = "299047362ccbfce148b67ab7e73349f77748e00c8296f9542adfad2ad82c5c5e"
dependencies = [
+ "bumpalo",
"proc-macro2",
"quote",
"syn",
- "wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
-version = "0.2.100"
+version = "0.2.122"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
+checksum = "9a929b2c61f11ba3e9bc35b50c1f25cb38e0e892c0c231ae2b8cf78d5dad4437"
dependencies = [
"unicode-ident",
]
[[package]]
name = "winapi-util"
-version = "0.1.9"
+version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
+checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
dependencies = [
"windows-sys",
]
[[package]]
name = "windows-core"
-version = "0.52.0"
+version = "0.62.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
+checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
dependencies = [
- "windows-targets",
+ "windows-implement",
+ "windows-interface",
+ "windows-link",
+ "windows-result",
+ "windows-strings",
]
[[package]]
-name = "windows-link"
-version = "0.1.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38"
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
+name = "windows-implement"
+version = "0.60.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
+checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf"
dependencies = [
- "windows-targets",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "windows-targets"
-version = "0.52.6"
+name = "windows-interface"
+version = "0.59.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
+checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358"
dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_gnullvm",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
-[[package]]
-name = "windows_aarch64_msvc"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
-
-[[package]]
-name = "windows_i686_gnu"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
-
-[[package]]
-name = "windows_i686_msvc"
-version = "0.52.6"
+name = "windows-link"
+version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
[[package]]
-name = "windows_x86_64_gnu"
-version = "0.52.6"
+name = "windows-result"
+version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
+checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
+dependencies = [
+ "windows-link",
+]
[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
+name = "windows-strings"
+version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
+dependencies = [
+ "windows-link",
+]
[[package]]
-name = "windows_x86_64_msvc"
-version = "0.52.6"
+name = "windows-sys"
+version = "0.61.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
+checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
+dependencies = [
+ "windows-link",
+]
diff --git a/pkgs/by-name/lf/lf-make-map/Cargo.toml b/pkgs/by-name/lf/lf-make-map/Cargo.toml
index d2427d73..272e62b9 100644
--- a/pkgs/by-name/lf/lf-make-map/Cargo.toml
+++ b/pkgs/by-name/lf/lf-make-map/Cargo.toml
@@ -1,14 +1,26 @@
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
[package]
name = "lf-make-map"
description = "An automatic lf cd mapping generator"
version = "0.1.0"
-edition = "2021"
+edition = "2024"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
-anyhow = "1.0.97"
-clap = { version = "4.5.34", features = ["derive", "env"] }
-log = "0.4.27"
+anyhow = "1.0.102"
+clap = { version = "4.6.1", features = ["derive", "env"] }
+crossterm = {version = "0.29.0", default-features = false, features = ["events"]}
+keymaps = "1.2.0"
+log = "0.4.31"
stderrlog = "0.6.0"
walkdir = "2.5.0"
diff --git a/pkgs/by-name/lf/lf-make-map/README.md b/pkgs/by-name/lf/lf-make-map/README.md
index 0c57cede..4d5dc95c 100644
--- a/pkgs/by-name/lf/lf-make-map/README.md
+++ b/pkgs/by-name/lf/lf-make-map/README.md
@@ -1,3 +1,15 @@
+<!--
+nixos-config - My current NixOS configuration
+
+Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+SPDX-License-Identifier: GPL-3.0-or-later
+
+This file is part of my nixos-config.
+
+You should have received a copy of the License along with this program.
+If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+-->
+
# Lf make map
> An automatic lf cd mapping generator
diff --git a/pkgs/by-name/lf/lf-make-map/flake.lock b/pkgs/by-name/lf/lf-make-map/flake.lock
deleted file mode 100644
index c9c523d9..00000000
--- a/pkgs/by-name/lf/lf-make-map/flake.lock
+++ /dev/null
@@ -1,139 +0,0 @@
-{
- "nodes": {
- "crane": {
- "locked": {
- "lastModified": 1742394900,
- "narHash": "sha256-vVOAp9ahvnU+fQoKd4SEXB2JG2wbENkpqcwlkIXgUC0=",
- "owner": "ipetkov",
- "repo": "crane",
- "rev": "70947c1908108c0c551ddfd73d4f750ff2ea67cd",
- "type": "github"
- },
- "original": {
- "owner": "ipetkov",
- "repo": "crane",
- "type": "github"
- }
- },
- "flake-compat": {
- "flake": false,
- "locked": {
- "lastModified": 1733328505,
- "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=",
- "owner": "edolstra",
- "repo": "flake-compat",
- "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec",
- "type": "github"
- },
- "original": {
- "owner": "edolstra",
- "repo": "flake-compat",
- "type": "github"
- }
- },
- "flake-utils": {
- "inputs": {
- "systems": [
- "systems"
- ]
- },
- "locked": {
- "lastModified": 1731533236,
- "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
- "owner": "numtide",
- "repo": "flake-utils",
- "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
- "type": "github"
- },
- "original": {
- "owner": "numtide",
- "repo": "flake-utils",
- "type": "github"
- }
- },
- "nixpkgs": {
- "locked": {
- "lastModified": 1743076231,
- "narHash": "sha256-yQugdVfi316qUfqzN8JMaA2vixl+45GxNm4oUfXlbgw=",
- "owner": "NixOS",
- "repo": "nixpkgs",
- "rev": "6c5963357f3c1c840201eda129a99d455074db04",
- "type": "github"
- },
- "original": {
- "owner": "NixOS",
- "ref": "nixpkgs-unstable",
- "repo": "nixpkgs",
- "type": "github"
- }
- },
- "root": {
- "inputs": {
- "crane": "crane",
- "flake-compat": "flake-compat",
- "flake-utils": "flake-utils",
- "nixpkgs": "nixpkgs",
- "rust-overlay": "rust-overlay",
- "systems": "systems",
- "treefmt-nix": "treefmt-nix"
- }
- },
- "rust-overlay": {
- "inputs": {
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1743215516,
- "narHash": "sha256-52qbrkG65U1hyrQWltgHTgH4nm0SJL+9TWv2UDCEPNI=",
- "owner": "oxalica",
- "repo": "rust-overlay",
- "rev": "524463199fdee49338006b049bc376b965a2cfed",
- "type": "github"
- },
- "original": {
- "owner": "oxalica",
- "repo": "rust-overlay",
- "type": "github"
- }
- },
- "systems": {
- "locked": {
- "lastModified": 1680978846,
- "narHash": "sha256-Gtqg8b/v49BFDpDetjclCYXm8mAnTrUzR0JnE2nv5aw=",
- "owner": "nix-systems",
- "repo": "x86_64-linux",
- "rev": "2ecfcac5e15790ba6ce360ceccddb15ad16d08a8",
- "type": "github"
- },
- "original": {
- "owner": "nix-systems",
- "repo": "x86_64-linux",
- "type": "github"
- }
- },
- "treefmt-nix": {
- "inputs": {
- "nixpkgs": [
- "nixpkgs"
- ]
- },
- "locked": {
- "lastModified": 1743081648,
- "narHash": "sha256-WRAylyYptt6OX5eCEBWyTwOEqEtD6zt33rlUkr6u3cE=",
- "owner": "numtide",
- "repo": "treefmt-nix",
- "rev": "29a3d7b768c70addce17af0869f6e2bd8f5be4b7",
- "type": "github"
- },
- "original": {
- "owner": "numtide",
- "repo": "treefmt-nix",
- "type": "github"
- }
- }
- },
- "root": "root",
- "version": 7
-}
diff --git a/pkgs/by-name/lf/lf-make-map/flake.nix b/pkgs/by-name/lf/lf-make-map/flake.nix
index dc8c24cc..2d1e93a2 100644
--- a/pkgs/by-name/lf/lf-make-map/flake.nix
+++ b/pkgs/by-name/lf/lf-make-map/flake.nix
@@ -1,125 +1,34 @@
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
{
description = "An automatic lf cd mapping generator";
- inputs = {
- nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
+ inputs = {};
- treefmt-nix = {
- url = "github:numtide/treefmt-nix";
- inputs = {
- nixpkgs.follows = "nixpkgs";
- };
- };
+ outputs = {...}: let
+ system = "x86_64-linux";
+ sources = import ../../../../npins/full.nix {};
- crane = {
- url = "github:ipetkov/crane";
- inputs = {
- nixpkgs.follows = "nixpkgs";
- };
- };
- rust-overlay = {
- url = "github:oxalica/rust-overlay";
- inputs = {
- nixpkgs.follows = "nixpkgs";
- flake-utils.follows = "flake-utils";
- };
- };
+ pkgs = (sources.loadFlake "nixpkgs").legacyPackages."${system}";
+ in {
+ devShells."${system}".default = pkgs.mkShell {
+ packages = [
+ pkgs.cargo
+ pkgs.clippy
+ pkgs.rustc
+ pkgs.rustfmt
- # inputs for following
- systems = {
- url = "github:nix-systems/x86_64-linux"; # only evaluate for this system
- };
- flake-compat = {
- url = "github:edolstra/flake-compat";
- flake = false;
- };
- flake-utils = {
- url = "github:numtide/flake-utils";
- inputs = {
- systems.follows = "systems";
- };
+ pkgs.cargo-edit
+ ];
};
};
-
- outputs = {
- self,
- nixpkgs,
- flake-utils,
- treefmt-nix,
- crane,
- rust-overlay,
- ...
- }:
- flake-utils.lib.eachDefaultSystem (system: let
- pkgs = import nixpkgs {
- inherit system;
- overlays = [(import rust-overlay)];
- };
-
- nightly = false;
- rust_minimal =
- if nightly
- then pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.minimal)
- else pkgs.rust-bin.stable.latest.minimal;
- rust_default =
- if nightly
- then pkgs.rust-bin.selectLatestNightlyWith (toolchain: toolchain.default)
- else pkgs.rust-bin.stable.latest.default;
-
- cargo_toml = craneLib.cleanCargoToml {cargoToml = ./Cargo.toml;};
- pname = cargo_toml.package.name;
-
- craneLib = (crane.mkLib pkgs).overrideToolchain rust_minimal;
- craneBuild = craneLib.buildPackage {
- src = craneLib.cleanCargoSource ./.;
-
- doCheck = true;
- };
-
- manual = pkgs.stdenv.mkDerivation {
- name = "${pname}-manual";
- inherit (cargo_toml.package) version;
-
- src = ./docs;
- nativeBuildInputs = with pkgs; [pandoc];
-
- buildPhase = ''
- mkdir --parents $out/docs;
-
- pandoc "./${pname}.1.md" -s -t man > $out/docs/${pname}.1
- '';
-
- installPhase = ''
- install -D $out/docs/${pname}.1 $out/share/man/man1/${pname};
- '';
- };
-
- treefmtEval = import ./treefmt.nix {inherit treefmt-nix pkgs;};
- in {
- packages.default = pkgs.symlinkJoin {
- inherit (cargo_toml.package) name;
-
- paths = [manual craneBuild];
- };
-
- checks = {
- inherit craneBuild;
- formatting = treefmtEval.config.build.check self;
- };
-
- formatter = treefmtEval.config.build.wrapper;
-
- devShells.default = pkgs.mkShell {
- packages = with pkgs; [
- cocogitto
-
- rust_default
- cargo-edit
-
- licensure
- ];
- };
- });
}
# vim: ts=2
diff --git a/pkgs/by-name/lf/lf-make-map/package.nix b/pkgs/by-name/lf/lf-make-map/package.nix
index 8404927f..8f77c843 100644
--- a/pkgs/by-name/lf/lf-make-map/package.nix
+++ b/pkgs/by-name/lf/lf-make-map/package.nix
@@ -1,3 +1,12 @@
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
{rustPlatform}:
rustPlatform.buildRustPackage {
pname = "lf-make-map";
diff --git a/pkgs/by-name/lf/lf-make-map/src/cli.rs b/pkgs/by-name/lf/lf-make-map/src/cli.rs
index a398e451..25a5a626 100644
--- a/pkgs/by-name/lf/lf-make-map/src/cli.rs
+++ b/pkgs/by-name/lf/lf-make-map/src/cli.rs
@@ -1,3 +1,13 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
use std::path::PathBuf;
use clap::{ArgAction, Parser, Subcommand};
@@ -40,6 +50,12 @@ pub enum Command {
#[command(flatten)]
options: CommandOptions,
},
+
+ /// Perform interactive selection, and then cd-there.
+ Interactive {
+ #[command(flatten)]
+ options: CommandOptions,
+ },
}
#[derive(Debug, Parser)]
diff --git a/pkgs/by-name/lf/lf-make-map/src/main.rs b/pkgs/by-name/lf/lf-make-map/src/main.rs
index aaf79b20..1576c1dd 100644
--- a/pkgs/by-name/lf/lf-make-map/src/main.rs
+++ b/pkgs/by-name/lf/lf-make-map/src/main.rs
@@ -1,13 +1,23 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
use std::path::{Path, PathBuf};
use anyhow::{Context, Result};
use clap::Parser;
use cli::{Args, Command};
use log::trace;
-use mapping::map_tree::MappingTree;
+use mapping::map_key::MapKey;
use walkdir::{DirEntry, WalkDir};
-use crate::mapping::MapKey;
+use crate::mapping::MappingsTrie;
mod cli;
mod mapping;
@@ -24,77 +34,73 @@ fn main() -> anyhow::Result<()> {
.timestamp(stderrlog::Timestamp::Off)
.init()?;
- let mut mappings = MappingTree::new();
+ let mut mappings = MappingsTrie::new();
let relevant_directories = match &args.command {
Command::Visualize { options } => &options.relevant_directories,
Command::Generate { options } => &options.relevant_directories,
+ Command::Interactive { options } => &options.relevant_directories,
};
for dir in relevant_directories {
- trace!("Processing '{}'..", dir.display());
- let path = strip_path(&dir, &args.home_name)?;
+ trace!("START Processing '{}'..", dir.display());
+ let path = strip_path(dir, &args.home_name)?;
mappings
.include(path_to_str(path)?)
.with_context(|| format!("Failed to include path: '{}'", path.display()))?;
+ trace!("END Finished processing {}.", dir.display());
+ }
+
+ trace!("Generated mappings for the relevant directories. Starting expanding to max depth.");
+ if log::log_enabled!(log::Level::Trace) {
+ eprintln!("{mappings}");
}
let home = path_to_str(&args.home_name)?.to_owned();
let mut current_depth = 1;
while current_depth != args.depth {
- for (key, value) in mappings.iter(false) {
- trace!(
- "Adding to child ('{}' -> '{}')",
- MapKey::display(&key),
- value
- );
+ for (keys, child) in mappings.0.iter().filter(|(_, child)| child.expendable) {
+ trace!("Adding to child '{}' ('{}')", MapKey::display(&keys), child);
- let mut local_mappings = MappingTree::new();
- for dir in WalkDir::new(extend(&home, &value)?)
+ let mut local_mappings = MappingsTrie::new();
+ for dir in WalkDir::new(extend(&home, &child.path)?)
.min_depth(1)
.max_depth(1)
.into_iter()
.filter_entry(|e| is_dir(e) && !is_hidden(e))
{
- let directory = dir
- .with_context(|| format!("Failed to read dir ('{}')", home.clone() + &value))?;
- let path_to_strip = &PathBuf::from(extend(&home, &value)?);
- let path = strip_path(&directory.path(), &path_to_strip)?;
+ let directory = dir.with_context(|| {
+ format!("Failed to read dir ('{}')", home.clone() + &child.path)
+ })?;
+ let path_to_strip = &PathBuf::from(extend(&home, &child.path)?);
+ let path = strip_path(directory.path(), path_to_strip)?;
trace!(
- "Including: '{}' (after stripping '{}' from '{}' -> '{}' + '/' + '{}')",
+ "Including: '{}' (after stripping '{}' from '{}')",
path.display(),
- directory.path().display(),
path_to_strip.display(),
- home,
- value
+ directory.path().display(),
);
let gen_key = MapKey::new_ones_from_path(path_to_str(path)?, 1);
local_mappings
.insert(
&gen_key,
- path_to_str(strip_path(&directory.path(), &PathBuf::from(&home))?)?,
+ path_to_str(strip_path(directory.path(), &PathBuf::from(&home))?)?,
)
.with_context(|| format!("Failed to include path: '{}'", path.display()))?;
}
- trace!("{}", local_mappings);
-
- trace!(
- "'{}' -> '{:#?}'",
- MapKey::display(&key),
- local_mappings.root_node()
- );
- mappings.interleave(&key, local_mappings.root_node().to_owned())?;
+ mappings.add_trie(&keys, local_mappings)?;
}
current_depth += 1;
}
match args.command {
- Command::Visualize { .. } => println!("{}", mappings),
+ Command::Visualize { .. } => println!("{}", mappings.0),
Command::Generate { .. } => println!("{}", mappings.to_lf_mappings(args.home_name)),
+ Command::Interactive { .. } => mappings.interactive_start(args.home_name)?,
}
Ok(())
@@ -120,7 +126,7 @@ fn is_dir(entry: &DirEntry) -> bool {
}
fn strip_path<'a>(path: &'a Path, to_strip: &Path) -> Result<&'a Path> {
- path.strip_prefix(&to_strip).with_context(|| {
+ path.strip_prefix(to_strip).with_context(|| {
format!(
"'{}' is not under the specified home path ('{}')!",
path.display(),
@@ -140,90 +146,3 @@ because it can't be turned to a string
)
})
}
-
-// fn gen_lf_mappings(home_name: PathBuf, char_num: usize, rel_dirs: Vec<PathBuf>) {
-// let mut mappings_vec = vec![];
-// let mut index_counter = 0;
-// rel_dirs.iter().for_each(|rel_dir| {
-// mappings_vec.push(vec![Mapping::new(
-// &gen_hot_key(rel_dir, rel_dir, char_num),
-// rel_dir,
-// rel_dir,
-// None,
-// )]);
-// get_dir(rel_dir.to_owned()).iter().for_each(|path| {
-// mappings_vec[index_counter].push(Mapping::new(
-// &gen_hot_key(
-// path,
-// path.parent().expect("All paths here should have parents"),
-// char_num,
-// ),
-// path,
-// &path
-// .parent()
-// .expect("All paths here should have parents")
-// .to_owned(),
-// None,
-// ));
-// });
-// index_counter += 1;
-// });
-// print_mappings(&mappings_vec, home_name);
-// mappings_vec
-// .into_iter()
-// .for_each(|rel_dir_mapping: Vec<Mapping>| {
-// let mut hash_map = sort_mapping_by_hot_key(rel_dir_mapping.clone());
-// //dbg!(hash_map);
-// hash_map.insert("gsi".to_owned(), vec![rel_dir_mapping[0].clone()]);
-// });
-// }
-//
-// fn sort_mapping_by_hot_key(mut mappings: Vec<Mapping>) -> HashMap<String, Vec<Mapping>> {
-// mappings.sort_by_key(|mapping| mapping.hot_key.clone());
-//
-// let mut filtered_mappings: HashMap<String, Vec<Mapping>> = HashMap::new();
-// mappings.iter().for_each(|mapping| {
-// filtered_mappings.insert(mapping.hot_key.clone(), vec![]);
-// });
-// //dbg!(&mappings);
-//
-// let mut index_counter = 1;
-// mappings.iter().for_each(|mapping| {
-// if mappings.len() > index_counter {
-// let next_mapping = &mappings[index_counter];
-// let vec = filtered_mappings
-// .get_mut(&mapping.hot_key)
-// .expect("This existst as it has been initialized");
-//
-// if &next_mapping.hot_key == &mapping.hot_key {
-// vec.push(mapping.clone());
-// vec.push(next_mapping.clone());
-// } else {
-// vec.push(mapping.clone());
-// }
-//
-// let new_vec = vec.to_owned();
-// filtered_mappings.insert(mapping.hot_key.to_owned(), new_vec);
-// }
-//
-// index_counter += 1;
-// });
-// filtered_mappings
-// }
-//
-// fn print_mappings(mappings: &Vec<Vec<Mapping>>, home_name: PathBuf) {
-// for mapping in mappings {
-// mapping.iter().for_each(|map| {
-// println!(
-// "{} = \"cd {}\";",
-// map.hot_key,
-// map.path
-// .display()
-// .to_string()
-// .replace(home_name.to_str().expect("This should be UTF-8"), "~")
-// );
-// });
-//
-// println!("# -------------");
-// }
-// }
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/interactive.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/interactive.rs
new file mode 100644
index 00000000..b8ac27d2
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/src/mapping/interactive.rs
@@ -0,0 +1,172 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::{io::stderr, path::PathBuf};
+
+use anyhow::Result;
+use crossterm::{
+ cursor::{MoveToRow, MoveUp},
+ event::{
+ Event, KeyEventKind, KeyModifiers, KeyboardEnhancementFlags, PopKeyboardEnhancementFlags,
+ PushKeyboardEnhancementFlags, read,
+ },
+ execute,
+ style::Print,
+ terminal::{self, Clear, ClearType, EnterAlternateScreen, LeaveAlternateScreen},
+};
+
+use crate::mapping::map_key::MapKey;
+
+use super::MappingsTrie;
+
+enum Status {
+ Done(PathBuf),
+ Stop,
+}
+
+impl MappingsTrie {
+ pub fn interactive_start(&self, home_path: PathBuf) -> Result<()> {
+ terminal::enable_raw_mode()?;
+ execute!(
+ stderr(),
+ EnterAlternateScreen,
+ PushKeyboardEnhancementFlags(KeyboardEnhancementFlags::DISAMBIGUATE_ESCAPE_CODES),
+ MoveToRow(0)
+ )?;
+
+ let output = self.interactive_start_inner(home_path);
+
+ execute!(stderr(), LeaveAlternateScreen, PopKeyboardEnhancementFlags)?;
+ terminal::disable_raw_mode()?;
+
+ match output? {
+ Status::Done(path_buf) => {
+ println!("{}", path_buf.display())
+ }
+ Status::Stop => (),
+ }
+
+ Ok(())
+ }
+
+ fn interactive_start_inner(&self, home_path: PathBuf) -> Result<Status> {
+ macro_rules! done {
+ ($state:ident, $last_length:ident) => {{
+ let value = match self.0.get(&$state).expect("Is some").value() {
+ Some(value) => value,
+ None => return Ok(Status::Stop),
+ };
+
+ let path = home_path.join(&value.path);
+
+ terminal::disable_raw_mode()?;
+ execute!(
+ stderr(),
+ MoveUp($last_length as u16),
+ Clear(ClearType::FromCursorDown),
+ Print(format!("{}\n", path.display()))
+ )?;
+ terminal::enable_raw_mode()?;
+
+ return Ok(Status::Done(path));
+ }};
+ }
+
+ let mut state: Vec<MapKey> = vec![];
+ let mut last_length: usize = 1;
+ while let (trie, matched) = self.0.try_get(&state)
+ && matched == state
+ {
+ if trie.value().is_some() {
+ done!(state, last_length);
+ } else {
+ if let Some(last) = state.last_mut()
+ && let Some(mlast) = matched.last()
+ {
+ last.resolution = mlast.resolution;
+ mlast.part_path.clone_into(&mut last.part_path);
+ }
+ }
+
+ {
+ terminal::disable_raw_mode()?;
+ let string = trie.to_string();
+ execute!(
+ stderr(),
+ MoveUp(last_length as u16),
+ Clear(ClearType::FromCursorDown),
+ Print(format!(
+ "Current state: {}\n",
+ self.current_progress(home_path.display().to_string(), &state)
+ )),
+ Print(&string)
+ )?;
+ last_length = string.lines().count() + 1;
+ terminal::enable_raw_mode()?;
+ }
+
+ if let Event::Key(event) = read()?
+ && event.kind == KeyEventKind::Press
+ {
+ match event.code {
+ crossterm::event::KeyCode::Backspace => {
+ state.pop();
+ }
+ crossterm::event::KeyCode::Enter => done!(state, last_length),
+ crossterm::event::KeyCode::Esc => break,
+ crossterm::event::KeyCode::Char(char) => {
+ if event.modifiers == KeyModifiers::CONTROL && char == 'c' {
+ break;
+ } else {
+ state.push(MapKey {
+ key: char,
+ resolution: 0,
+ part_path: String::new(),
+ });
+ }
+ }
+
+ crossterm::event::KeyCode::Left
+ | crossterm::event::KeyCode::Right
+ | crossterm::event::KeyCode::Up
+ | crossterm::event::KeyCode::Down
+ | crossterm::event::KeyCode::Home
+ | crossterm::event::KeyCode::End
+ | crossterm::event::KeyCode::PageUp
+ | crossterm::event::KeyCode::PageDown
+ | crossterm::event::KeyCode::Tab
+ | crossterm::event::KeyCode::BackTab
+ | crossterm::event::KeyCode::Delete
+ | crossterm::event::KeyCode::Insert
+ | crossterm::event::KeyCode::F(_)
+ | crossterm::event::KeyCode::Null
+ | crossterm::event::KeyCode::CapsLock
+ | crossterm::event::KeyCode::ScrollLock
+ | crossterm::event::KeyCode::NumLock
+ | crossterm::event::KeyCode::PrintScreen
+ | crossterm::event::KeyCode::Pause
+ | crossterm::event::KeyCode::Menu
+ | crossterm::event::KeyCode::KeypadBegin
+ | crossterm::event::KeyCode::Media(_)
+ | crossterm::event::KeyCode::Modifier(_) => (),
+ }
+ }
+ }
+
+ Ok(Status::Stop)
+ }
+
+ fn current_progress(&self, home_path: String, state: &[MapKey]) -> String {
+ state
+ .iter()
+ .map(|mk| &mk.part_path)
+ .fold(home_path, |acc, part| format!("{acc}/{part}"))
+ }
+}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/lf_mapping.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/lf_mapping.rs
new file mode 100644
index 00000000..f8a6182e
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/src/mapping/lf_mapping.rs
@@ -0,0 +1,35 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::path::PathBuf;
+
+use crate::mapping::MapKey;
+
+use super::MappingsTrie;
+
+impl MappingsTrie {
+ pub fn to_lf_mappings(&self, home_path: PathBuf) -> String {
+ let mut raw = self
+ .0
+ .iter()
+ .map(|(key, value)| {
+ format!(
+ "map g{} cd \"{}\"\n",
+ MapKey::display(&key),
+ home_path.join(&value.path).display()
+ )
+ })
+ .collect::<Vec<String>>();
+
+ raw.sort();
+
+ raw.into_iter().collect()
+ }
+}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/map_key.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/map_key.rs
new file mode 100644
index 00000000..d90eb963
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/src/mapping/map_key.rs
@@ -0,0 +1,280 @@
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+use std::fmt::Write;
+
+use anyhow::bail;
+use log::debug;
+
+#[derive(Clone, Debug)]
+pub struct MapKey {
+ pub key: char,
+
+ pub(crate) resolution: usize,
+
+ /// Part of the path, used to derive the key
+ pub(crate) part_path: String,
+}
+
+impl std::hash::Hash for MapKey {
+ fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
+ self.key.hash(state)
+ }
+}
+
+impl Eq for MapKey {}
+impl PartialEq for MapKey {
+ fn eq(&self, other: &Self) -> bool {
+ self.key == other.key
+ }
+}
+
+impl Ord for MapKey {
+ fn cmp(&self, other: &Self) -> std::cmp::Ordering {
+ self.key.cmp(&other.key)
+ }
+}
+impl PartialOrd for MapKey {
+ fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
+ Some(self.cmp(other))
+ }
+}
+
+impl MapKey {
+ pub fn new_from_part_path(part_path: &str, resolution: usize) -> Vec<Self> {
+ let key = Self::part_path_to_key(part_path, resolution);
+
+ key.chars()
+ .map(|ch| Self {
+ key: ch,
+ resolution,
+ part_path: part_path.to_owned(),
+ })
+ .collect()
+ }
+
+ pub fn new_ones_from_path(path: &str, number_of_chars: usize) -> Vec<Self> {
+ let key: Vec<MapKey> = path
+ .split('/')
+ .flat_map(|part| Self::new_from_part_path(part, number_of_chars))
+ .collect();
+
+ debug!(
+ "Generated full MapKeys: '{}' -> '{}'",
+ path,
+ MapKey::display(&key)
+ );
+ key
+ }
+
+ pub fn increment(&self, target_resolution: usize) -> Vec<Self> {
+ let new_resolution = target_resolution;
+
+ // debug!("Incrementing: '{}' ('{}')", &self, &self.part_path);
+
+ let added_chars = if new_resolution < self.part_path.len() {
+ MapKey::part_path_to_key(&self.part_path, new_resolution)
+ } else {
+ let mut generated_chars =
+ MapKey::part_path_to_key(&self.part_path, self.part_path.len());
+
+ generated_chars.extend(
+ (0..(new_resolution - self.part_path.len()))
+ .map(|_| self.part_path.chars().last().expect("This will exists")),
+ );
+
+ generated_chars
+ };
+
+ let part_path = self.part_path.clone();
+ let output: Vec<Self> = added_chars
+ .chars()
+ .enumerate()
+ .map(|(res, ch)| MapKey {
+ key: ch,
+ resolution: res + 1,
+ part_path: part_path.clone(),
+ })
+ .collect();
+
+ // debug!("Finished increment: '{}' ('{}')", MapKey::display(&output), output[0].part_path);
+ output
+ }
+
+ pub fn display(values: &[Self]) -> String {
+ values.iter().map(|value| value.key).collect()
+ }
+
+ fn part_path_to_key(part: &str, number_of_chars: usize) -> String {
+ fn make(pat: char, part: &str, number_of_chars: usize) -> String {
+ let mut acc = String::new();
+
+ if !part.split(pat).all(|part| !part.is_empty()) {
+ panic!(
+ "\
+Can't turn this path '{}' to a mapping.
+This should not happen, please report the bug!",
+ part
+ )
+ }
+
+ let mut last_working = None;
+ for i in 0..number_of_chars {
+ for str in part.split(pat) {
+ if acc.len() != number_of_chars {
+ acc.push(match str.chars().nth(i) {
+ Some(ch) => ch,
+ None => {
+ if let Some(last) = last_working {
+ str.chars().nth(last).expect("This should always exist")
+ } else {
+ last_working = Some(i - 1);
+ str.chars().nth(i - 1).expect("This should always exist")
+ }
+ }
+ })
+ }
+ }
+ }
+
+ acc
+ }
+
+ let value = if part.contains('_') && !part.starts_with('_') && !part.ends_with('_') {
+ make('_', part, number_of_chars)
+ } else if part.contains('-') && !part.starts_with('-') && !part.ends_with('-') {
+ make('-', part, number_of_chars)
+ } else if part.starts_with('.') {
+ // HACK: Special case for directories like ~/.config ~/.local and so on.
+ // We just drop the starting '.' and it's easier to type. <2026-06-02>
+ part.chars()
+ .skip(1)
+ .take(number_of_chars)
+ .collect::<String>()
+ } else {
+ part.chars().take(number_of_chars).collect::<String>()
+ };
+
+ assert_eq!(
+ value.chars().count(),
+ number_of_chars,
+ "'{}' does not have expected length of: {}",
+ value,
+ number_of_chars
+ );
+ value
+ }
+
+ /// Checks whether a tiebreak via the [`Self::increment`] function can result in unique keys.
+ pub fn can_tiebreak_with(&self, other: &Self) -> anyhow::Result<()> {
+ /// Check whether the `input` &str is composed of only one character.
+ /// If so, returns this character, otherwise returns None.
+ fn reduce_string(input: &str) -> Option<char> {
+ let first_char = input
+ .chars()
+ .take(1)
+ .last()
+ .expect("Should contain one char");
+
+ if input.chars().all(|ch| ch == first_char) {
+ Some(first_char)
+ } else {
+ None
+ }
+ }
+
+ /// Check whether `a` is a subset of `b` or `b` is a subset of `a`.
+ fn is_subset_either(a: &str, b: &str) -> bool {
+ /// Checks if `subset` is a subset of `set`.
+ ///
+ /// # Examples
+ /// ```
+ /// let a = "a";
+ /// let b = "aa";
+ /// assert!(is_subset(a, b))
+ /// ```
+ ///
+ /// ```
+ /// let a = "abc";
+ /// let b = "def";
+ /// assert!(!is_subset(a, b))
+ /// ```
+ fn is_subset(subset: &str, set: &str) -> bool {
+ let prefix: String = set.chars().take(subset.len()).collect();
+ let suffix: String = set.chars().skip(subset.len()).collect();
+
+ if prefix == subset {
+ let clean_suffix = reduce_string(&suffix);
+ if let Some(ch) = clean_suffix {
+ ch == subset.chars().last().expect("Will exists")
+ } else {
+ false
+ }
+ } else {
+ false
+ }
+ }
+
+ match a.len().cmp(&b.len()) {
+ std::cmp::Ordering::Less => {
+ // `b` is the longer string. As such we need to check if `a` is a subset of `b`.
+ is_subset(a, b)
+ }
+ std::cmp::Ordering::Greater => {
+ // `a` is the longer string. As such we need to check if `b` is a subset of `a`.
+ is_subset(b, a)
+ }
+ std::cmp::Ordering::Equal => a == b,
+ }
+ }
+
+ if reduce_string(&other.part_path)
+ .is_some_and(|a| Some(a) == reduce_string(&self.part_path))
+ {
+ bail!(
+ "\
+The foreign_key ('{}', path_part: '{}' -> '{}') and our_key ('{}', path_part: '{}' -> '{}') \
+have an identical path_part (when duplicated chars are removed)!
+I cannot extended them via incrementation.
+Please rename the paths to fix this.
+ ",
+ other,
+ &other.part_path,
+ reduce_string(&other.part_path).expect("Is some here"),
+ self,
+ &self.part_path,
+ reduce_string(&self.part_path).expect("Is some here"),
+ );
+ }
+
+ if is_subset_either(&other.part_path, &self.part_path) {
+ bail!(
+ "\
+The foreign_key ('{}', path_part: '{}') and our_key ('{}', path_part: '{}') \
+are subsets of one another!
+A discrimination through incrementation will not work!
+Please rename the paths to fix this.
+ ",
+ other,
+ &other.part_path,
+ self,
+ &self.part_path,
+ );
+ }
+
+ Ok(())
+ }
+}
+
+impl std::fmt::Display for MapKey {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_char(self.key)
+ }
+}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/display.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/display.rs
deleted file mode 100644
index 65302e1e..00000000
--- a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/display.rs
+++ /dev/null
@@ -1,91 +0,0 @@
-use std::fmt::Display;
-
-use crate::mapping::{
- map_tree::{Node, NodeValue},
- MapKey,
-};
-
-use super::MappingTree;
-
-impl Display for MappingTree {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- fn write_node(
- f: &mut std::fmt::Formatter<'_>,
- node: &Node,
- indention: String,
- location: Vec<MapKey>,
- is_last: bool,
- is_root: bool,
- ) -> std::fmt::Result {
- let node_value = match &node.value {
- NodeValue::Parent { children: _ } => "<Parent>".to_owned(),
- NodeValue::Child { path, extandable } => {
- path.to_owned() + if *extandable { " [exten.]" } else { " [stop]" }
- }
- };
-
- let new_idention = indention.clone()
- + if is_root {
- ""
- } else {
- match is_last {
- true => " ",
- false => "│ ",
- }
- };
-
- let bullet = match is_last {
- true => String::from("└── "),
- false => String::from("├── "),
- };
-
- if is_root {
- write!(f, ": {}\n", node_value)?;
- } else {
- write!(
- f,
- "{}{}\x1b[1;33m{}\x1b[0m: {}\n",
- indention,
- bullet,
- MapKey::display(&location),
- node_value,
- )?;
- };
-
- match &node.value {
- NodeValue::Parent { children } => {
- let mut children_vec: Vec<(&MapKey, &Node)> = children.iter().collect();
- children_vec.sort_by(|(a, _), (b, _)| a.key.cmp(&b.key));
-
- let mut counter = 1;
- for (key, child) in &children_vec {
- let mut new_location = location.clone();
- new_location.push((*key).to_owned());
-
- write_node(
- f,
- child,
- new_idention.clone(),
- new_location.clone(),
- counter == children_vec.len(),
- false,
- )?;
- counter += 1;
- }
- }
- NodeValue::Child {
- path: _,
- extandable: _,
- } => {
- // Do nothing and stop the recursion
- }
- }
-
- Ok(())
- }
-
- write_node(f, &self.root, String::new(), vec![], false, true)?;
-
- Ok(())
- }
-}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/iterator.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/iterator.rs
deleted file mode 100644
index 4364bb2b..00000000
--- a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/iterator.rs
+++ /dev/null
@@ -1,53 +0,0 @@
-use crate::mapping::MapKey;
-
-use super::{MappingTree, Node, NodeValue};
-
-pub struct MappingTreeIterator {
- children: Vec<(Vec<MapKey>, String)>,
-}
-
-impl MappingTreeIterator {
- pub fn new(tree: &MappingTree, ignore_extendable: bool) -> Self {
- let children = extract_child(vec![], &tree.root, ignore_extendable);
-
- Self { children }
- }
-}
-
-fn extract_child(
- current_key: Vec<MapKey>,
- node: &Node,
- ignore_extendable: bool,
-) -> Vec<(Vec<MapKey>, String)> {
- match &node.value {
- NodeValue::Parent { children } => children
- .iter()
- .map(|(key, value)| {
- let mut new_key = current_key.clone();
- new_key.push(key.to_owned());
-
- extract_child(new_key, value, ignore_extendable)
- })
- .flatten()
- .collect(),
- NodeValue::Child { path, extandable } => {
- if ignore_extendable {
- vec![(current_key, path.to_string())]
- } else {
- if *extandable {
- vec![(current_key, path.to_string())]
- } else {
- vec![]
- }
- }
- }
- }
-}
-
-impl Iterator for MappingTreeIterator {
- type Item = (Vec<MapKey>, String);
-
- fn next(&mut self) -> Option<Self::Item> {
- self.children.pop()
- }
-}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/lf_mapping.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/lf_mapping.rs
deleted file mode 100644
index ba485dc2..00000000
--- a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/lf_mapping.rs
+++ /dev/null
@@ -1,24 +0,0 @@
-use std::path::PathBuf;
-
-use crate::mapping::MapKey;
-
-use super::MappingTree;
-
-impl MappingTree {
- pub fn to_lf_mappings(self, home_path: PathBuf) -> String {
- let mut raw = self
- .iter(true)
- .map(|(key, value)| {
- format!(
- "map g{} cd \"{}\"\n",
- MapKey::display(&key),
- home_path.join(&value).display()
- )
- })
- .collect::<Vec<String>>();
-
- raw.sort();
-
- raw.into_iter().collect()
- }
-}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/mod.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/mod.rs
deleted file mode 100644
index 35e6d91d..00000000
--- a/pkgs/by-name/lf/lf-make-map/src/mapping/map_tree/mod.rs
+++ /dev/null
@@ -1,402 +0,0 @@
-use std::{collections::HashMap, mem};
-
-use anyhow::{bail, Result};
-use log::debug;
-
-use self::iterator::MappingTreeIterator;
-
-use super::MapKey;
-
-pub mod display;
-pub mod iterator;
-pub mod lf_mapping;
-
-/// A prefix tree
-#[derive(Debug)]
-pub struct MappingTree {
- root: Node,
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum NodeValue {
- Parent { children: HashMap<MapKey, Node> },
- Child { path: String, extandable: bool },
-}
-
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub struct Node {
- value: NodeValue,
-}
-
-impl MappingTree {
- pub fn new() -> Self {
- Self {
- root: Node::new_parent(),
- }
- }
-
- pub fn root_node(&self) -> &Node {
- &self.root
- }
-
- pub fn iter(&self, ignore_extendable: bool) -> MappingTreeIterator {
- MappingTreeIterator::new(&self, ignore_extendable)
- }
-
- /// Returns the node at the key, otherwise None. The node can be changed
- pub fn get_mut(&mut self, key: &[MapKey]) -> Option<&mut Node> {
- let mut current_node = &mut self.root;
- for ch in key.iter() {
- if let NodeValue::Parent { children } = &mut current_node.value {
- current_node = children.get_mut(&ch)?
- } else {
- return None;
- }
- }
-
- Some(current_node)
- }
-
- /// Returns the node at the key, otherwise the last node that matched.
- pub fn try_get(&self, key: &[MapKey]) -> (&Node, Vec<MapKey>) {
- let mut current_node = &self.root;
- let mut current_key = vec![];
-
- for ch in key.iter() {
- if let NodeValue::Parent { children } = &current_node.value {
- current_node = if let Some(node) = children.get(&ch) {
- let (key, _value) = children
- .get_key_value(&ch)
- .expect("This exists, we checked");
- current_key.push(key.clone());
-
- node
- } else {
- return (current_node, current_key);
- };
- } else {
- return (current_node, current_key);
- }
- }
-
- (current_node, current_key)
- }
-
- pub fn include(&mut self, path: &str) -> Result<()> {
- let associated_key = MapKey::new_ones_from_path(path, 1);
- self.insert(&associated_key, path)
- }
-
- pub fn insert(&mut self, key: &[MapKey], path: &str) -> Result<()> {
- self.insert_node(key, Node::new_child(path.to_owned()))
- }
-
- pub fn interleave(&mut self, key: &[MapKey], node: Node) -> Result<()> {
- let want_to_be_parent = self.get_mut(&key).expect("This value exists");
- let (parent_value, _parent_children) = if let NodeValue::Parent { children } = node.value {
- (
- NodeValue::Parent {
- children: children.clone(),
- },
- children,
- )
- } else {
- unreachable!("This value will be a parent")
- };
-
- let child_value = mem::replace(&mut want_to_be_parent.value, parent_value);
- assert!(matches!(
- child_value,
- NodeValue::Child {
- path: _,
- extandable: _
- }
- ));
-
- let child_value = if let NodeValue::Child {
- path,
- extandable: _,
- } = child_value
- {
- NodeValue::Child {
- path,
- extandable: false,
- }
- } else {
- unreachable!("This is only a child value")
- };
-
- let child = Node { value: child_value };
-
- let mut new_key = key.to_vec();
- new_key.push(MapKey {
- key: '.',
- part_path: ".".to_owned(),
- resolution: 1,
- });
- self.insert_node(&new_key, child)?;
- Ok(())
- }
-
- pub fn insert_node(&mut self, key: &[MapKey], node: Node) -> Result<()> {
- let (_node, found_key) = self.try_get(key).clone();
-
- if found_key != key {
- let needed_nodes_key = key
- .strip_prefix(&found_key[..])
- .expect("The node's location is a prefix");
-
- let needed_nodes_length = needed_nodes_key.iter().count();
-
- let mut current_node = self
- .get_mut(&found_key[..])
- .expect("This should always exists");
- let mut current_location = found_key.clone();
- let mut counter = 1;
-
- for ch in needed_nodes_key.iter() {
- current_location.push(ch.to_owned());
-
- let next_node = if counter == needed_nodes_length {
- node.clone()
- } else {
- Node::new_parent()
- };
-
- current_node = match &current_node.value {
- NodeValue::Parent { children } => {
- assert_eq!(children.get(&ch), None);
-
- let children =
- if let NodeValue::Parent { children } = &mut current_node.value {
- children
- } else {
- unreachable!("This is a parent, we cheched")
- };
-
- children.insert(ch.to_owned(), next_node);
- children.get_mut(&ch).expect("Was just inserted")
- }
- NodeValue::Child {
- path,
- extandable: _,
- } => {
- // A node that should be a parent was classified
- // as child before:
- //
- // 1. Remove the child node and replace it with a parent one.
- // 2. Add the child node to the parent node as child, but with a '.' as MapKey.
- // 3. Add the original node also as child to the parent node.
-
- let mut children = HashMap::new();
- let move_child_node = Node::new_child(path.to_owned());
-
- children.insert(
- MapKey {
- key: '.',
- part_path: ".".to_owned(),
- resolution: 1,
- },
- move_child_node,
- );
- children.insert(ch.to_owned(), next_node);
-
- current_node.value = NodeValue::Parent { children };
-
- let children =
- if let NodeValue::Parent { children } = &mut current_node.value {
- children
- } else {
- unreachable!("We just inserted the parent value.")
- };
-
- children.get_mut(&ch).expect("Was just inserted")
- }
- };
-
- counter += 1;
- }
- } else {
- fn reduce_string(a: &str) -> Option<char> {
- let first_char = a.chars().take(1).last().expect("Should contain one char");
-
- if a.chars().all(|ch| ch == first_char) {
- return Some(first_char);
- } else {
- return None;
- }
- }
- fn check_subset(a: &str, b: &str) -> bool {
- if a.len() > b.len() {
- let a_prefix: String = a.chars().take(b.len()).collect();
- let a_suffix: String = a.chars().skip(b.len()).collect();
-
- if a_prefix == b {
- let clean_suffix = reduce_string(&a_suffix);
- if let Some(ch) = clean_suffix {
- ch == b.chars().last().expect("Will match")
- } else {
- false
- }
- } else {
- false
- }
- } else if b.len() > a.len() {
- let b_prefix: String = b.chars().take(a.len()).collect();
- let b_suffix: String = b.chars().skip(a.len()).collect();
-
- if b_prefix == a {
- let clean_suffix = reduce_string(&b_suffix);
- if let Some(ch) = clean_suffix {
- ch == a.chars().last().expect("Will match")
- } else {
- false
- }
- } else {
- false
- }
- } else {
- a == b
- }
- }
-
- // Another node was already inserted with the same key!
- // So we simple increase the resolution of the other node and this node, until their
- // keys are not the same anymore.
- // This only includes the last segment of the `MapKey`
- //
- // 1. Change both keys, until they are not equal any more
- // 2. Move the wrongly placed node to the new place.
- // 3. Insert our node.
- let mut foreign_key = vec![found_key.last().expect("This will exist").clone()];
- let mut our_key = vec![key.last().expect("This will exist").clone()];
-
- debug!(
- "'{}' ('{}') and '{}' ('{}') are the same, try to find a better combination!",
- MapKey::display(&our_key),
- our_key[0].part_path,
- MapKey::display(&foreign_key),
- foreign_key[0].part_path,
- );
-
- // The 'a' and 'b' stuff is here, to ensure that both returning None will not match
- // this condition.
- if reduce_string(&foreign_key[0].part_path).unwrap_or('a')
- == reduce_string(&our_key[0].part_path).unwrap_or('b')
- {
- bail!(
- "\
-The foreign_key ('{}', path_part: '{}' -> '{}') and our_key ('{}', path_part: '{}' -> '{}') \
-have an identical path_part (when duplicated chars are removed)!
-I cannot extended them via incrementation.
-Please rename the paths to fix this.
- ",
- MapKey::display(&foreign_key),
- &foreign_key[0].part_path,
- reduce_string(&foreign_key[0].part_path).expect("Is some here"),
- MapKey::display(&our_key),
- &our_key[0].part_path,
- reduce_string(&our_key[0].part_path).expect("Is some here"),
- );
- }
-
- if check_subset(&foreign_key[0].part_path, &our_key[0].part_path) {
- bail!(
- "\
-The foreign_key ('{}', path_part: '{}') and our_key ('{}', path_part: '{}') \
-are subsets of one another!
-A discrimination through incrementation will not work!
-Please rename the paths to fix this.
- ",
- MapKey::display(&foreign_key),
- &foreign_key[0].part_path,
- MapKey::display(&our_key),
- &our_key[0].part_path,
- );
- }
-
- while our_key == foreign_key {
- our_key = our_key[0].increment(our_key[our_key.len() - 1].resolution + 1);
- foreign_key =
- foreign_key[0].increment(foreign_key[foreign_key.len() - 1].resolution + 1);
- debug!(
- "Now its: '{}' ('{}') and '{}' ('{}')",
- MapKey::display(&our_key),
- our_key[0].part_path,
- MapKey::display(&foreign_key),
- foreign_key[0].part_path,
- );
- }
-
- debug!(
- "Found a better one: '{}' ('{}') and '{}' ('{}')",
- MapKey::display(&our_key),
- our_key[0].part_path,
- MapKey::display(&foreign_key),
- foreign_key[0].part_path,
- );
-
- let parent = self
- .get_mut(&found_key[..&found_key.len() - 1])
- .expect("This will exist");
-
- if let NodeValue::Parent { children } = &mut parent.value {
- if let NodeValue::Child {
- path: _,
- extandable: _,
- } = children
- .get(found_key.last().expect("Exists"))
- .expect("This node also exists")
- .value
- {
- let old = children
- .remove(found_key.last().expect("This will exist"))
- .expect("This will be there");
-
- let full_foreign_key: Vec<_> = found_key
- .clone()
- .into_iter()
- .rev()
- .skip(1)
- .rev()
- .chain(foreign_key.clone().into_iter())
- .collect();
- self.insert_node(&full_foreign_key, old.clone())?;
- }
-
- let full_our_key: Vec<_> = key
- .to_vec()
- .into_iter()
- .rev()
- .skip(1)
- .rev()
- .chain(our_key.clone().into_iter())
- .collect();
-
- self.insert_node(&full_our_key, node.clone())?;
- } else {
- unreachable!("This node will be a parent");
- }
- }
-
- Ok(())
- }
-}
-
-impl Node {
- pub fn new_child(path: String) -> Self {
- Self {
- value: NodeValue::Child {
- path,
- extandable: true,
- },
- }
- }
- pub fn new_parent() -> Self {
- Self {
- value: NodeValue::Parent {
- children: HashMap::new(),
- },
- }
- }
-}
diff --git a/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs b/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs
index 114fdca0..b733990e 100644
--- a/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs
+++ b/pkgs/by-name/lf/lf-make-map/src/mapping/mod.rs
@@ -1,156 +1,232 @@
-use std::{
- fmt::{Display, Write},
- hash::Hash,
-};
+// nixos-config - My current NixOS configuration
+//
+// Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+// This file is part of my nixos-config.
+//
+// You should have received a copy of the License along with this program.
+// If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
-use log::debug;
+use anyhow::Result;
+use keymaps::map_tree::{Node, Trie};
+use log::{Level, debug, log_enabled, trace};
+use map_key::MapKey;
-pub mod map_tree;
+pub mod lf_mapping;
+pub mod interactive;
+pub mod map_key;
-#[derive(Clone, Debug, Eq)]
-pub struct MapKey {
- pub key: char,
+#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
+pub struct MapChild {
+ pub path: String,
+ pub expendable: bool,
+}
- resolution: usize,
+impl std::fmt::Display for MapChild {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ f.write_str(&self.path)?;
+ if !self.expendable {
+ f.write_str(" [stop]")?;
+ }
- /// Part of the path, used to derive the key
- part_path: String,
+ Ok(())
+ }
}
-impl Hash for MapKey {
- fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
- self.key.hash(state)
+pub struct MappingsTrie(pub Trie<MapKey, MapChild>);
+impl std::fmt::Display for MappingsTrie {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ self.0.fmt(f)
}
}
-impl PartialEq for MapKey {
- fn eq(&self, other: &Self) -> bool {
- self.key == other.key
+impl MappingsTrie {
+ pub fn new() -> Self {
+ Self(Trie::new())
}
-}
-impl MapKey {
- pub fn new_from_part_path(part_path: &str, resolution: usize) -> Vec<Self> {
- let key = Self::part_path_to_key(&part_path, resolution);
+ pub(crate) fn include(&mut self, path: &str) -> Result<()> {
+ let associated_key = MapKey::new_ones_from_path(path, 1);
+ self.insert(&associated_key, path)
+ }
- key.chars()
- .map(|ch| Self {
- key: ch,
- resolution,
- part_path: part_path.to_owned(),
- })
- .collect()
+ pub(crate) fn insert(&mut self, keys: &[MapKey], path: &str) -> Result<()> {
+ let value = Node::new_child(MapChild {
+ path: path.to_owned(),
+ expendable: true,
+ });
+ self.insert_node(keys, value)
}
- pub fn new_ones_from_path(path: &str, number_of_chars: usize) -> Vec<Self> {
- let key: Vec<MapKey> = path
- .split('/')
- .map(|part| Self::new_from_part_path(part, number_of_chars))
- .flatten()
- .collect();
+ pub(crate) fn insert_node(
+ &mut self,
+ keys: &[MapKey],
+ node: Node<MapKey, MapChild>,
+ ) -> Result<()> {
+ if let Err(err) = self.0.insert_node(keys, &node) {
+ match err {
+ keymaps::error::TrieInsert::KeyAlreadySet(found_keys) => {
+ // Another node was already inserted with the same key!
+ // So we simple increase the resolution of the other node and this node, until their
+ // keys are no longer equal.
+ // This only includes the last segment of the `MapKey`
+ //
+ // 1. Change both keys, until they are not equal any more
+ // 2. Move the wrongly placed node to the new place.
+ // 3. Insert our node.
+ assert_eq!(keys, found_keys);
- debug!(
- "Generated full MapKeys: '{}' -> '{}'",
- path,
- MapKey::display(&key)
- );
- key
- }
+ let mut foreign_keys =
+ vec![found_keys.last().expect("This will exist").clone()];
+ let mut our_keys = vec![keys.last().expect("This will exist").clone()];
- pub fn increment(&self, target_resolution: usize) -> Vec<Self> {
- let new_resolution = target_resolution;
+ debug!(
+ "'{}' ('{}') and '{}' ('{}') are the same, trying to find a better combination!",
+ MapKey::display(&our_keys),
+ our_keys[0].part_path,
+ MapKey::display(&foreign_keys),
+ foreign_keys[0].part_path,
+ );
- // debug!("Incrementing: '{}' ('{}')", &self, &self.part_path);
+ our_keys[0].can_tiebreak_with(&foreign_keys[0])?;
- let added_chars = if new_resolution < self.part_path.len() {
- MapKey::part_path_to_key(&self.part_path, new_resolution)
- } else {
- let mut generated_chars =
- MapKey::part_path_to_key(&self.part_path, self.part_path.len());
+ while our_keys == foreign_keys {
+ our_keys =
+ our_keys[0].increment(our_keys[our_keys.len() - 1].resolution + 1);
+ foreign_keys = foreign_keys[0]
+ .increment(foreign_keys[foreign_keys.len() - 1].resolution + 1);
+ debug!(
+ "Now its: '{}' ('{}') and '{}' ('{}')",
+ MapKey::display(&our_keys),
+ our_keys[0].part_path,
+ MapKey::display(&foreign_keys),
+ foreign_keys[0].part_path,
+ );
+ }
+ debug!(
+ "Found a better one: '{}' ('{}') and '{}' ('{}')",
+ MapKey::display(&our_keys),
+ our_keys[0].part_path,
+ MapKey::display(&foreign_keys),
+ foreign_keys[0].part_path,
+ );
- generated_chars.extend(
- (0..(new_resolution - self.part_path.len()))
- .into_iter()
- .map(|_| self.part_path.chars().last().expect("This will exists")),
- );
+ let parent_keys = &found_keys[..&found_keys.len() - 1];
- generated_chars
- };
+ {
+ if self
+ .0
+ .get(&found_keys)
+ .expect("This will exist")
+ .value()
+ .is_some()
+ {
+ // This is a child, we must replace it with a parent.
+ let other_node = self
+ .0
+ .replace_node(&found_keys, Node::new_parent())
+ .expect("This node exists");
- let part_path = self.part_path.clone();
- let output: Vec<Self> = added_chars
- .chars()
- .enumerate()
- .map(|(res, ch)| MapKey {
- key: ch,
- resolution: res + 1,
- part_path: part_path.clone(),
- })
- .collect();
+ {
+ let mut full_foreign_keys = parent_keys.to_vec();
+ full_foreign_keys.append(&mut foreign_keys);
+ self.insert_node(&full_foreign_keys, other_node)?;
+ }
+ }
+ }
- // debug!("Finished increment: '{}' ('{}')", MapKey::display(&output), output[0].part_path);
- output
- }
+ {
+ let mut full_our_keys = parent_keys.to_vec();
+ full_our_keys.append(&mut our_keys);
+ self.insert_node(&full_our_keys, node)?;
+ }
- pub fn display(values: &[Self]) -> String {
- values.iter().map(|value| value.key.clone()).collect()
- }
- fn part_path_to_key(part: &str, number_of_chars: usize) -> String {
- fn make(pat: char, part: &str, number_of_chars: usize) -> String {
- let mut acc = String::new();
+ Ok(())
+ }
+ keymaps::error::TrieInsert::KeyIncludesChild {
+ child_key: key,
+ child_value,
+ } => {
+ // A node that should be a parent was classified
+ // as child before:
+ //
+ // 1. Remove the child node and replace it with a parent one.
+ // 2. Add the child node to the parent node as child, but with a '.' as MapKey.
+ // 3. Add the original node also as child to the parent node.
- if !part.split(pat).all(|part| part.len() > 0) {
- panic!(
- "\
-Can't turn this path '{}' to a mapping.
-This should not happen, please report the bug!",
- part
- )
- }
+ assert_eq!(key, keys);
- let mut last_working = None;
- for i in 0..number_of_chars {
- for str in part.split(pat) {
- if acc.len() != number_of_chars {
- acc.push(match str.chars().nth(i) {
- Some(ch) => ch,
- None => {
- if let Some(last) = last_working {
- str.chars().nth(last).expect("This should always exist")
- } else {
- last_working = Some(i - 1);
- str.chars().nth(i - 1).expect("This should always exist")
- }
- }
- })
- }
+ let (fetched_child_value, mut child_key) = self.0.try_get(keys);
+ assert_eq!(fetched_child_value.value(), Some(&child_value));
+
+ trace!(
+ "Replacing child ('{}') with a parent, so that we can continue from this point.",
+ MapKey::display(&child_key)
+ );
+
+ let child = self
+ .0
+ .replace_node(&child_key, Node::new_parent())
+ .expect("Node exists");
+ assert_eq!(child.value(), Some(&child_value));
+
+ child_key.push(MapKey {
+ key: '.',
+ part_path: ".".to_owned(),
+ resolution: 1,
+ });
+ self.0
+ .insert_node(&child_key, &child)
+ .expect("We just created a parent here");
+
+ // Recursive call, because this key could have hit the previous child directly
+ // (thus it will now trigger the `KeyAlreadySet` error.)
+ self.insert_node(keys, node)
}
}
+ } else {
+ Ok(())
+ }
+ }
+
+ /// Add a new [`MappingsTrie`] at the position `keys` into this Trie.
+ pub(crate) fn add_trie(&mut self, keys: &[MapKey], trie: Self) -> Result<()> {
+ if log_enabled!(Level::Trace) {
+ trace!("Adding mappings under '{}':", MapKey::display(keys));
+ eprintln!("{trie}");
- acc
+ trace!("Self is:");
+ eprintln!("{self}");
}
- let value = if part.contains('_') && !part.starts_with('_') && !part.ends_with('_') {
- make('_', part, number_of_chars)
- } else if part.contains('-') && !part.starts_with('-') && !part.ends_with('-') {
- make('-', part, number_of_chars)
- } else {
- part.chars().take(number_of_chars).collect::<String>()
- };
+ let replaced = self
+ .0
+ .replace_node(keys, trie.0.root_node().to_owned())
+ .expect("This value exists");
- assert_eq!(
- value.len(),
- number_of_chars,
- "'{}' does not have expected length of: {}",
- value,
- number_of_chars
- );
- value
- }
-}
+ if log_enabled!(Level::Trace) {
+ trace!("After replace adding the new trie");
+ eprintln!("{self}");
+ }
-impl Display for MapKey {
- fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
- f.write_char(self.key)
+ {
+ let mut new_keys = keys.to_vec();
+ new_keys.push(MapKey {
+ key: '.',
+ part_path: ".".to_owned(),
+ resolution: 1,
+ });
+
+ let mut value = replaced.value().expect("Is a child").clone();
+ value.expendable = false;
+
+ trace!("Re-inserting '{}' into self.", MapKey::display(keys));
+ self.0
+ .insert_node(&new_keys, &Node::new_child(value))
+ .expect("This key is not used.");
+ }
+
+ Ok(())
}
}
diff --git a/pkgs/by-name/lf/lf-make-map/tests/base.sh b/pkgs/by-name/lf/lf-make-map/tests/base.sh
new file mode 100755
index 00000000..d860cf84
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/base.sh
@@ -0,0 +1,25 @@
+#! /usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+cd "$(dirname "$0")" || exit 2
+
+cargo build
+execute_make_maps() {
+ ../target/debug/lf-make-map "$@"
+}
+
+fd . cases --max-depth 1 --type directory | while read -r case; do
+ echo "Executing '${case}test.sh'"
+
+ # shellcheck source=/dev/null
+ LOCATION="$case/test.sh" . "$case/test.sh"
+done
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/child_insert/test.sh b/pkgs/by-name/lf/lf-make-map/tests/cases/child_insert/test.sh
new file mode 100755
index 00000000..af6a1391
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/child_insert/test.sh
@@ -0,0 +1,27 @@
+#! /usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+test="$(mktemp --directory -t lf_make_map_test_XXXX)"
+
+cleanup() {
+ rm --recursive "$test"
+}
+trap cleanup EXIT
+
+cat <<EOF | while read -r name; do mkdir --parents "$test/media/books/${name}"; done
+Andre A
+Anton B
+Andon C
+Anton D
+EOF
+
+execute_make_maps --home-name "$test" --depth 100 generate "$test"/* >/dev/null
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/output.old b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/output.old
new file mode 100644
index 00000000..49307bc6
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/output.old
@@ -0,0 +1,13 @@
+map gc. cd "/tmp/tmp.DfcgjemfCG/.config"
+map gca. cd "/tmp/tmp.DfcgjemfCG/.config/apzu"
+map gcl. cd "/tmp/tmp.DfcgjemfCG/.config/lahmu"
+map gct. cd "/tmp/tmp.DfcgjemfCG/.config/tiamat"
+map gd. cd "/tmp/tmp.DfcgjemfCG/documents"
+map gda. cd "/tmp/tmp.DfcgjemfCG/documents/apzu"
+map gdl. cd "/tmp/tmp.DfcgjemfCG/documents/lahmu"
+map gdt. cd "/tmp/tmp.DfcgjemfCG/documents/tiamat"
+map gl. cd "/tmp/tmp.DfcgjemfCG/.local"
+map gln. cd "/tmp/tmp.DfcgjemfCG/.local/nvim"
+map glsh. cd "/tmp/tmp.DfcgjemfCG/.local/share"
+map glst. cd "/tmp/tmp.DfcgjemfCG/.local/state"
+
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/test.sh b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/test.sh
new file mode 100755
index 00000000..d3df848c
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs/test.sh
@@ -0,0 +1,49 @@
+#! /usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+mkFile() {
+ t="$1"
+
+ mkdir --parents "$(dirname "$t")"
+ echo "TEST_FILE" >"$t"
+}
+
+# We need to hard code this, so that our output matches the golden sample.
+base="/tmp/tmp.DfcgjemfCG"
+test="$(mktemp --directory -t lf_make_temp_test_XXXXX)"
+
+if [ -d "$base" ]; then
+ rm --recursive "$base"
+fi
+mkdir "$base"
+
+cleanup() {
+ rm --recursive "$base" "$test"
+}
+trap cleanup EXIT
+
+mkFile "$base/.local/share/file1.txt"
+mkFile "$base/.local/state/file1.txt"
+mkFile "$base/.local/nvim/log.LOG"
+mkFile "$base/.local/.tog/TOG.LOG"
+
+mkFile "$base/.config/apzu/file2.txt"
+mkFile "$base/.config/tiamat/file2.txt"
+mkFile "$base/.config/lahmu/file2.txt"
+
+mkFile "$base/documents/apzu/file2.txt"
+mkFile "$base/documents/tiamat/file2.txt"
+mkFile "$base/documents/lahmu/file2.txt"
+
+execute_make_maps --home-name "$base" --depth 100 generate "$base/.local" "$base/.config" "$base/documents" >"$test/output.new"
+
+diff "$test/output.new" "$(dirname "$LOCATION")/output.old"
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/output.old b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/output.old
new file mode 100644
index 00000000..f7523ba3
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/output.old
@@ -0,0 +1,17 @@
+map gca. cd "/tmp/tmp.DfcgjemfCG/cats"
+map gcaa. cd "/tmp/tmp.DfcgjemfCG/cats/apzu"
+map gcal. cd "/tmp/tmp.DfcgjemfCG/cats/lahmu"
+map gcat. cd "/tmp/tmp.DfcgjemfCG/cats/tiamat"
+map gco. cd "/tmp/tmp.DfcgjemfCG/.config"
+map gcoa. cd "/tmp/tmp.DfcgjemfCG/.config/apzu"
+map gcol. cd "/tmp/tmp.DfcgjemfCG/.config/lahmu"
+map gcot. cd "/tmp/tmp.DfcgjemfCG/.config/tiamat"
+map gd. cd "/tmp/tmp.DfcgjemfCG/documents"
+map gda. cd "/tmp/tmp.DfcgjemfCG/documents/apzu"
+map gdl. cd "/tmp/tmp.DfcgjemfCG/documents/lahmu"
+map gdt. cd "/tmp/tmp.DfcgjemfCG/documents/tiamat"
+map gl. cd "/tmp/tmp.DfcgjemfCG/.local"
+map gln. cd "/tmp/tmp.DfcgjemfCG/.local/nvim"
+map glsh. cd "/tmp/tmp.DfcgjemfCG/.local/share"
+map glst. cd "/tmp/tmp.DfcgjemfCG/.local/state"
+
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/test.sh b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/test.sh
new file mode 100755
index 00000000..33447e54
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/dot_dirs_duplicates/test.sh
@@ -0,0 +1,53 @@
+#! /usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+mkFile() {
+ t="$1"
+
+ mkdir --parents "$(dirname "$t")"
+ echo "TEST_FILE" >"$t"
+}
+
+# We need to hard code this, so that our output matches the golden sample.
+base="/tmp/tmp.DfcgjemfCG"
+test="$(mktemp --directory -t lf_make_temp_test_XXXXX)"
+
+if [ -d "$base" ]; then
+ rm --recursive "$base"
+fi
+mkdir "$base"
+
+cleanup() {
+ rm --recursive "$base" "$test"
+}
+trap cleanup EXIT
+
+mkFile "$base/.local/share/file1.txt"
+mkFile "$base/.local/state/file1.txt"
+mkFile "$base/.local/nvim/log.LOG"
+mkFile "$base/.local/.tog/TOG.LOG"
+
+mkFile "$base/.config/apzu/file2.txt"
+mkFile "$base/.config/tiamat/file2.txt"
+mkFile "$base/.config/lahmu/file2.txt"
+
+mkFile "$base/documents/apzu/file2.txt"
+mkFile "$base/documents/tiamat/file2.txt"
+mkFile "$base/documents/lahmu/file2.txt"
+
+mkFile "$base/cats/apzu/file2.txt"
+mkFile "$base/cats/tiamat/file2.txt"
+mkFile "$base/cats/lahmu/file2.txt"
+
+execute_make_maps --home-name "$base" --depth 100 generate "$base/.local" "$base/.config" "$base/documents" "$base/cats" >"$test/output.new"
+
+diff "$test/output.new" "$(dirname "$LOCATION")/output.old"
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old
new file mode 100644
index 00000000..90591f16
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old
@@ -0,0 +1,46 @@
+map gdd. cd "/tmp/tmp.DfcgjemfCG/d"
+map gddcc. cd "/tmp/tmp.DfcgjemfCG/d/c"
+map gddccb. cd "/tmp/tmp.DfcgjemfCG/d/c/b"
+map gddccbc. cd "/tmp/tmp.DfcgjemfCG/d/c/b/c"
+map gddccbcf. cd "/tmp/tmp.DfcgjemfCG/d/c/b/c/file.test"
+map gddccd. cd "/tmp/tmp.DfcgjemfCG/d/c/d"
+map gddccdf. cd "/tmp/tmp.DfcgjemfCG/d/c/d/f"
+map gddccdff. cd "/tmp/tmp.DfcgjemfCG/d/c/d/f/file.test2"
+map gddcco. cd "/tmp/tmp.DfcgjemfCG/d/c/other"
+map gddccof. cd "/tmp/tmp.DfcgjemfCG/d/c/other/file.test3"
+map gddct. cd "/tmp/tmp.DfcgjemfCG/d/cll_the-things"
+map gddcto. cd "/tmp/tmp.DfcgjemfCG/d/cll_the-things/other"
+map gddctof. cd "/tmp/tmp.DfcgjemfCG/d/cll_the-things/other/file.test4"
+map gddm. cd "/tmp/tmp.DfcgjemfCG/d/mcybe some whitespcce"
+map gddmt. cd "/tmp/tmp.DfcgjemfCG/d/mcybe some whitespcce/test.file5"
+map gdi. cd "/tmp/tmp.DfcgjemfCG/dir"
+map gdicc. cd "/tmp/tmp.DfcgjemfCG/dir/c"
+map gdiccb. cd "/tmp/tmp.DfcgjemfCG/dir/c/b"
+map gdiccbc. cd "/tmp/tmp.DfcgjemfCG/dir/c/b/c"
+map gdiccbcf. cd "/tmp/tmp.DfcgjemfCG/dir/c/b/c/file.test"
+map gdiccd. cd "/tmp/tmp.DfcgjemfCG/dir/c/d"
+map gdiccdf. cd "/tmp/tmp.DfcgjemfCG/dir/c/d/f"
+map gdiccdff. cd "/tmp/tmp.DfcgjemfCG/dir/c/d/f/file.test2"
+map gdicco. cd "/tmp/tmp.DfcgjemfCG/dir/c/other"
+map gdiccof. cd "/tmp/tmp.DfcgjemfCG/dir/c/other/file.test3"
+map gdict. cd "/tmp/tmp.DfcgjemfCG/dir/cll_the-things"
+map gdicto. cd "/tmp/tmp.DfcgjemfCG/dir/cll_the-things/other"
+map gdictof. cd "/tmp/tmp.DfcgjemfCG/dir/cll_the-things/other/file.test4"
+map gdim. cd "/tmp/tmp.DfcgjemfCG/dir/mcybe some whitespcce"
+map gdimt. cd "/tmp/tmp.DfcgjemfCG/dir/mcybe some whitespcce/test.file5"
+map gdo. cd "/tmp/tmp.DfcgjemfCG/dor"
+map gdocc. cd "/tmp/tmp.DfcgjemfCG/dor/c"
+map gdoccb. cd "/tmp/tmp.DfcgjemfCG/dor/c/b"
+map gdoccbc. cd "/tmp/tmp.DfcgjemfCG/dor/c/b/c"
+map gdoccbcf. cd "/tmp/tmp.DfcgjemfCG/dor/c/b/c/file.test"
+map gdoccd. cd "/tmp/tmp.DfcgjemfCG/dor/c/d"
+map gdoccdf. cd "/tmp/tmp.DfcgjemfCG/dor/c/d/f"
+map gdoccdff. cd "/tmp/tmp.DfcgjemfCG/dor/c/d/f/file.test2"
+map gdocco. cd "/tmp/tmp.DfcgjemfCG/dor/c/other"
+map gdoccof. cd "/tmp/tmp.DfcgjemfCG/dor/c/other/file.test3"
+map gdoct. cd "/tmp/tmp.DfcgjemfCG/dor/cll_the-things"
+map gdocto. cd "/tmp/tmp.DfcgjemfCG/dor/cll_the-things/other"
+map gdoctof. cd "/tmp/tmp.DfcgjemfCG/dor/cll_the-things/other/file.test4"
+map gdom. cd "/tmp/tmp.DfcgjemfCG/dor/mcybe some whitespcce"
+map gdomt. cd "/tmp/tmp.DfcgjemfCG/dor/mcybe some whitespcce/test.file5"
+
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old.license b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old.license
new file mode 100644
index 00000000..eae6a84c
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/output.old.license
@@ -0,0 +1,9 @@
+nixos-config - My current NixOS configuration
+
+Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+SPDX-License-Identifier: GPL-3.0-or-later
+
+This file is part of my nixos-config.
+
+You should have received a copy of the License along with this program.
+If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
diff --git a/pkgs/by-name/lf/lf-make-map/tests/cases/simple/test.sh b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/test.sh
new file mode 100755
index 00000000..97ee0cb9
--- /dev/null
+++ b/pkgs/by-name/lf/lf-make-map/tests/cases/simple/test.sh
@@ -0,0 +1,47 @@
+#! /usr/bin/env sh
+
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+# We need to hard code this, so that our output matches the golden sample.
+base="/tmp/tmp.DfcgjemfCG"
+test="$(mktemp --directory -t lf_make_temp_test_XXXXX)"
+
+if [ -d "$base" ]; then
+ rm --recursive "$base"
+fi
+mkdir "$base"
+
+cleanup() {
+ rm --recursive "$base" "$test"
+}
+trap cleanup EXIT
+
+mkdir --parents "$base/dir/c/b/c/file.test"
+mkdir --parents "$base/dir/c/d/f/file.test2"
+mkdir --parents "$base/dir/c/other/file.test3"
+mkdir --parents "$base/dir/cll_the-things/other/file.test4"
+mkdir --parents "$base/dir/mcybe some whitespcce/test.file5"
+
+mkdir --parents "$base/dor/c/b/c/file.test"
+mkdir --parents "$base/dor/c/d/f/file.test2"
+mkdir --parents "$base/dor/c/other/file.test3"
+mkdir --parents "$base/dor/cll_the-things/other/file.test4"
+mkdir --parents "$base/dor/mcybe some whitespcce/test.file5"
+
+mkdir --parents "$base/d/c/b/c/file.test"
+mkdir --parents "$base/d/c/d/f/file.test2"
+mkdir --parents "$base/d/c/other/file.test3"
+mkdir --parents "$base/d/cll_the-things/other/file.test4"
+mkdir --parents "$base/d/mcybe some whitespcce/test.file5"
+
+execute_make_maps --home-name "$base" --depth 100 generate "$base"/* >"$test/output.new"
+
+diff "$test/output.new" "$(dirname "$LOCATION")/output.old"
diff --git a/pkgs/by-name/lf/lf-make-map/update.sh b/pkgs/by-name/lf/lf-make-map/update.sh
index 7d517e8b..188771c4 100755
--- a/pkgs/by-name/lf/lf-make-map/update.sh
+++ b/pkgs/by-name/lf/lf-make-map/update.sh
@@ -1,4 +1,14 @@
#!/usr/bin/env sh
-[ "$1" = "upgrade" ] && cargo upgrade
-cargo update
+# nixos-config - My current NixOS configuration
+#
+# Copyright (C) 2025 Benedikt Peetz <benedikt.peetz@b-peetz.de>
+# SPDX-License-Identifier: GPL-3.0-or-later
+#
+# This file is part of my nixos-config.
+#
+# You should have received a copy of the License along with this program.
+# If not, see <https://www.gnu.org/licenses/gpl-3.0.txt>.
+
+[ "$1" = "upgrade" ] && cargo upgrade --incompatible allow --pinned allow --recursive true
+cargo update --recursive