File watching
This commit is contained in:
parent
640c0ab620
commit
2c1b9c620e
283
Cargo.lock
generated
283
Cargo.lock
generated
@ -170,6 +170,12 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitflags"
|
||||||
|
version = "1.3.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.6.0"
|
||||||
@ -283,6 +289,16 @@ version = "0.8.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "debounced"
|
||||||
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "107e5cd9b5163c19751e53eef634cae25cf5ed5f6d0c81125feaa92e43703cc7"
|
||||||
|
dependencies = [
|
||||||
|
"futures-timer",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "derive_test"
|
name = "derive_test"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
@ -330,6 +346,18 @@ version = "1.0.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "filetime"
|
||||||
|
version = "0.2.25"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"libc",
|
||||||
|
"libredox",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fixedbitset"
|
name = "fixedbitset"
|
||||||
version = "0.5.7"
|
version = "0.5.7"
|
||||||
@ -345,6 +373,15 @@ dependencies = [
|
|||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "fsevent-sys"
|
||||||
|
version = "4.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futf"
|
name = "futf"
|
||||||
version = "0.1.5"
|
version = "0.1.5"
|
||||||
@ -355,6 +392,101 @@ dependencies = [
|
|||||||
"new_debug_unreachable",
|
"new_debug_unreachable",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-executor",
|
||||||
|
"futures-io",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-channel"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-sink",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-core"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-executor"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"futures-task",
|
||||||
|
"futures-util",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-io"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-macro"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-sink"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-task"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-timer"
|
||||||
|
version = "3.0.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "futures-util"
|
||||||
|
version = "0.3.31"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
|
||||||
|
dependencies = [
|
||||||
|
"futures-channel",
|
||||||
|
"futures-core",
|
||||||
|
"futures-io",
|
||||||
|
"futures-macro",
|
||||||
|
"futures-sink",
|
||||||
|
"futures-task",
|
||||||
|
"memchr",
|
||||||
|
"pin-project-lite",
|
||||||
|
"pin-utils",
|
||||||
|
"slab",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "getopts"
|
name = "getopts"
|
||||||
version = "0.2.21"
|
version = "0.2.21"
|
||||||
@ -588,6 +720,35 @@ dependencies = [
|
|||||||
"hashbrown",
|
"hashbrown",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify"
|
||||||
|
version = "0.10.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fdd168d97690d0b8c412d6b6c10360277f4d7ee495c5d0d5d5fe0854923255cc"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"inotify-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "inotify-sys"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "instant"
|
||||||
|
version = "0.1.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "is_terminal_polyfill"
|
name = "is_terminal_polyfill"
|
||||||
version = "1.70.1"
|
version = "1.70.1"
|
||||||
@ -610,6 +771,26 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue"
|
||||||
|
version = "1.0.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c"
|
||||||
|
dependencies = [
|
||||||
|
"kqueue-sys",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "kqueue-sys"
|
||||||
|
version = "1.0.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 1.3.2",
|
||||||
|
"libc",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.169"
|
version = "0.2.169"
|
||||||
@ -622,6 +803,17 @@ version = "0.2.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libredox"
|
||||||
|
version = "0.1.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"libc",
|
||||||
|
"redox_syscall",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "litemap"
|
name = "litemap"
|
||||||
version = "0.7.4"
|
version = "0.7.4"
|
||||||
@ -720,6 +912,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
@ -740,6 +933,34 @@ dependencies = [
|
|||||||
"minimal-lexical",
|
"minimal-lexical",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify"
|
||||||
|
version = "7.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c533b4c39709f9ba5005d8002048266593c1cfaf3c5f0739d5b8ab0c6c504009"
|
||||||
|
dependencies = [
|
||||||
|
"bitflags 2.6.0",
|
||||||
|
"filetime",
|
||||||
|
"fsevent-sys",
|
||||||
|
"inotify",
|
||||||
|
"kqueue",
|
||||||
|
"libc",
|
||||||
|
"log",
|
||||||
|
"mio",
|
||||||
|
"notify-types",
|
||||||
|
"walkdir",
|
||||||
|
"windows-sys 0.52.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "notify-types"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "585d3cb5e12e01aed9e8a1f70d5c6b5e86fe2a6e48fc8cd0b3e0b8df6f6eb174"
|
||||||
|
dependencies = [
|
||||||
|
"instant",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "num-traits"
|
name = "num-traits"
|
||||||
version = "0.2.19"
|
version = "0.2.19"
|
||||||
@ -866,6 +1087,12 @@ version = "0.2.15"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
|
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "pin-utils"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ppv-lite86"
|
name = "ppv-lite86"
|
||||||
version = "0.2.20"
|
version = "0.2.20"
|
||||||
@ -896,7 +1123,7 @@ version = "0.12.2"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
|
checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.6.0",
|
||||||
"getopts",
|
"getopts",
|
||||||
"memchr",
|
"memchr",
|
||||||
"pulldown-cmark-escape",
|
"pulldown-cmark-escape",
|
||||||
@ -954,7 +1181,7 @@ version = "0.5.8"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags 2.6.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -998,6 +1225,15 @@ version = "1.0.18"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "same-file"
|
||||||
|
version = "1.0.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
|
||||||
|
dependencies = [
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "scopeguard"
|
name = "scopeguard"
|
||||||
version = "1.2.0"
|
version = "1.2.0"
|
||||||
@ -1066,6 +1302,15 @@ version = "0.3.11"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "slab"
|
||||||
|
version = "0.4.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||||
|
dependencies = [
|
||||||
|
"autocfg",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smallvec"
|
name = "smallvec"
|
||||||
version = "1.13.2"
|
version = "1.13.2"
|
||||||
@ -1207,6 +1452,17 @@ dependencies = [
|
|||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-stream"
|
||||||
|
version = "0.1.17"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
|
||||||
|
dependencies = [
|
||||||
|
"futures-core",
|
||||||
|
"pin-project-lite",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "toml"
|
name = "toml"
|
||||||
version = "0.8.19"
|
version = "0.8.19"
|
||||||
@ -1312,21 +1568,35 @@ dependencies = [
|
|||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"compute_graph",
|
"compute_graph",
|
||||||
|
"debounced",
|
||||||
"env_logger",
|
"env_logger",
|
||||||
|
"futures",
|
||||||
"html5ever",
|
"html5ever",
|
||||||
"log",
|
"log",
|
||||||
"markup5ever_rcdom",
|
"markup5ever_rcdom",
|
||||||
|
"notify",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
"pulldown-cmark",
|
"pulldown-cmark",
|
||||||
"regex",
|
"regex",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-stream",
|
||||||
"toml",
|
"toml",
|
||||||
"unicode-normalization",
|
"unicode-normalization",
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "walkdir"
|
||||||
|
version = "2.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
|
||||||
|
dependencies = [
|
||||||
|
"same-file",
|
||||||
|
"winapi-util",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@ -1387,6 +1657,15 @@ version = "0.2.99"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "winapi-util"
|
||||||
|
version = "0.1.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
|
||||||
|
dependencies = [
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
|
@ -21,15 +21,19 @@ askama = "0.12.1"
|
|||||||
chrono = { version = "0.4.39", features = ["serde"] }
|
chrono = { version = "0.4.39", features = ["serde"] }
|
||||||
clap = { version = "4.5.23", features = ["cargo"] }
|
clap = { version = "4.5.23", features = ["cargo"] }
|
||||||
compute_graph = { path = "crates/compute_graph" }
|
compute_graph = { path = "crates/compute_graph" }
|
||||||
|
debounced = "0.2.0"
|
||||||
env_logger = "0.11.6"
|
env_logger = "0.11.6"
|
||||||
|
futures = "0.3.31"
|
||||||
html5ever = "0.27.0"
|
html5ever = "0.27.0"
|
||||||
log = "0.4.22"
|
log = "0.4.22"
|
||||||
markup5ever_rcdom = "0.3.0"
|
markup5ever_rcdom = "0.3.0"
|
||||||
|
notify = "7.0.0"
|
||||||
once_cell = "1.20.2"
|
once_cell = "1.20.2"
|
||||||
pulldown-cmark = "0.12.2"
|
pulldown-cmark = "0.12.2"
|
||||||
regex = "1.11.1"
|
regex = "1.11.1"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
tokio = { version = "1.42.0", features = ["full"] }
|
tokio = { version = "1.42.0", features = ["full"] }
|
||||||
|
tokio-stream = "0.1.17"
|
||||||
toml = "0.8.19"
|
toml = "0.8.19"
|
||||||
unicode-normalization = "0.1.24"
|
unicode-normalization = "0.1.24"
|
||||||
url = "2.5.4"
|
url = "2.5.4"
|
||||||
|
@ -4,27 +4,31 @@ mod posts;
|
|||||||
mod tags;
|
mod tags;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use compute_graph::{AsyncGraph, builder::GraphBuilder};
|
use compute_graph::{AsyncGraph, builder::GraphBuilder};
|
||||||
use util::{Combine, MapToVoid};
|
use util::{Combine, MapToVoid};
|
||||||
|
|
||||||
pub async fn generate() -> anyhow::Result<()> {
|
pub use util::content_base_path;
|
||||||
|
pub use util::file_watcher::FileWatcher;
|
||||||
|
|
||||||
|
pub async fn generate(watcher: Rc<RefCell<FileWatcher>>) -> anyhow::Result<AsyncGraph<()>> {
|
||||||
std::fs::create_dir_all("out").expect("creating output dir");
|
std::fs::create_dir_all("out").expect("creating output dir");
|
||||||
|
|
||||||
// TODO: file watching
|
let mut graph = make_graph(watcher)?;
|
||||||
|
|
||||||
let mut graph = make_graph()?;
|
|
||||||
|
|
||||||
graph.evaluate_async().await;
|
graph.evaluate_async().await;
|
||||||
|
|
||||||
println!("{}", graph.as_dot_string());
|
println!("{}", graph.as_dot_string());
|
||||||
|
|
||||||
Ok(())
|
Ok(graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_graph() -> anyhow::Result<AsyncGraph<()>> {
|
fn make_graph(watcher: Rc<RefCell<FileWatcher>>) -> anyhow::Result<AsyncGraph<()>> {
|
||||||
let mut builder = GraphBuilder::new_async();
|
let mut builder = GraphBuilder::new_async();
|
||||||
|
|
||||||
let (void_outputs, posts, all_posts, post_metadatas) = posts::make_graph(&mut builder);
|
let (void_outputs, posts, all_posts, post_metadatas) = posts::make_graph(&mut builder, watcher);
|
||||||
|
|
||||||
let archive = archive::make_graph(&mut builder, all_posts);
|
let archive = archive::make_graph(&mut builder, all_posts);
|
||||||
|
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
pub mod content;
|
pub mod content;
|
||||||
pub mod metadata;
|
pub mod metadata;
|
||||||
|
|
||||||
|
use std::cell::RefCell;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use askama::Template;
|
use askama::Template;
|
||||||
use compute_graph::{
|
use compute_graph::{
|
||||||
@ -18,19 +20,26 @@ use metadata::PostMetadata;
|
|||||||
|
|
||||||
use crate::generator::util::output_rendered_template;
|
use crate::generator::util::output_rendered_template;
|
||||||
|
|
||||||
use super::util::{MapDynamicToVoid, content_path, templates::TemplateCommon};
|
use super::{
|
||||||
|
FileWatcher,
|
||||||
|
util::{MapDynamicToVoid, content_path, templates::TemplateCommon},
|
||||||
|
};
|
||||||
|
|
||||||
pub fn make_graph(
|
pub fn make_graph(
|
||||||
builder: &mut GraphBuilder<(), Asynchronous>,
|
builder: &mut GraphBuilder<(), Asynchronous>,
|
||||||
|
watcher: Rc<RefCell<FileWatcher>>,
|
||||||
) -> (
|
) -> (
|
||||||
Input<()>,
|
Input<()>,
|
||||||
DynamicInput<ReadPostOutput>,
|
DynamicInput<ReadPostOutput>,
|
||||||
Input<Vec<Post<HtmlContent>>>,
|
Input<Vec<Post<HtmlContent>>>,
|
||||||
Input<Vec<PostMetadata>>,
|
Input<Vec<PostMetadata>>,
|
||||||
) {
|
) {
|
||||||
// todo: make this invalidatable, watch files
|
let (post_files, invalidate_posts) = builder.add_invalidatable_rule(ListPostFiles);
|
||||||
let post_files = builder.add_rule(ListPostFiles);
|
watcher.borrow_mut().watch(content_path("posts/"), move || {
|
||||||
let posts = builder.add_dynamic_rule(MakeReadNodes::new(post_files));
|
invalidate_posts.invalidate();
|
||||||
|
});
|
||||||
|
|
||||||
|
let posts = builder.add_dynamic_rule(MakeReadNodes::new(post_files, watcher));
|
||||||
|
|
||||||
let extract_metadatas = builder.add_dynamic_rule(MakeExtractMetadatas::new(posts.clone()));
|
let extract_metadatas = builder.add_dynamic_rule(MakeExtractMetadatas::new(posts.clone()));
|
||||||
|
|
||||||
@ -80,12 +89,14 @@ fn find_index(path: PathBuf) -> Option<PathBuf> {
|
|||||||
#[derive(InputVisitable)]
|
#[derive(InputVisitable)]
|
||||||
struct MakeReadNodes {
|
struct MakeReadNodes {
|
||||||
files: Input<Vec<PathBuf>>,
|
files: Input<Vec<PathBuf>>,
|
||||||
|
watcher: Rc<RefCell<FileWatcher>>,
|
||||||
node_factory: DynamicNodeFactory<PathBuf, ReadPostOutput>,
|
node_factory: DynamicNodeFactory<PathBuf, ReadPostOutput>,
|
||||||
}
|
}
|
||||||
impl MakeReadNodes {
|
impl MakeReadNodes {
|
||||||
fn new(files: Input<Vec<PathBuf>>) -> Self {
|
fn new(files: Input<Vec<PathBuf>>, watcher: Rc<RefCell<FileWatcher>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
files,
|
files,
|
||||||
|
watcher,
|
||||||
node_factory: DynamicNodeFactory::new(),
|
node_factory: DynamicNodeFactory::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,7 +106,11 @@ impl DynamicRule for MakeReadNodes {
|
|||||||
fn evaluate(&mut self, ctx: &mut impl DynamicRuleContext) -> Vec<Input<Self::ChildOutput>> {
|
fn evaluate(&mut self, ctx: &mut impl DynamicRuleContext) -> Vec<Input<Self::ChildOutput>> {
|
||||||
for file in self.files.value().iter() {
|
for file in self.files.value().iter() {
|
||||||
self.node_factory.add_rule(ctx, file.clone(), |ctx| {
|
self.node_factory.add_rule(ctx, file.clone(), |ctx| {
|
||||||
ctx.add_rule(ReadPost { path: file.clone() })
|
let (input, signal) = ctx.add_invalidatable_rule(ReadPost { path: file.clone() });
|
||||||
|
self.watcher
|
||||||
|
.borrow_mut()
|
||||||
|
.watch(file.clone(), move || signal.invalidate());
|
||||||
|
input
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
self.node_factory.all_nodes(ctx)
|
self.node_factory.all_nodes(ctx)
|
||||||
|
80
src/generator/util/file_watcher.rs
Normal file
80
src/generator/util/file_watcher.rs
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
use std::{
|
||||||
|
collections::HashMap,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
};
|
||||||
|
|
||||||
|
use notify::{EventHandler, Watcher};
|
||||||
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
|
use crate::generator::util::content_base_path;
|
||||||
|
|
||||||
|
pub struct FileWatcher {
|
||||||
|
handlers: HashMap<PathBuf, Box<dyn Fn() -> ()>>,
|
||||||
|
watcher: Option<notify::RecommendedWatcher>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FileWatcher {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
handlers: HashMap::new(),
|
||||||
|
watcher: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn watch(&mut self, path: PathBuf, f: impl Fn() -> () + 'static) {
|
||||||
|
if let Some(existing) = self.handlers.remove(&path) {
|
||||||
|
self.handlers.insert(
|
||||||
|
path,
|
||||||
|
Box::new(move || {
|
||||||
|
existing();
|
||||||
|
f();
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.handlers.insert(path, Box::new(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn start(&mut self) -> anyhow::Result<()> {
|
||||||
|
assert!(self.watcher.is_none());
|
||||||
|
let (tx, mut rx) = tokio::sync::mpsc::unbounded_channel::<notify::Result<notify::Event>>();
|
||||||
|
|
||||||
|
let mut watcher = notify::recommended_watcher(AsyncEventHandler(tx))?;
|
||||||
|
watcher.watch(&content_base_path(), notify::RecursiveMode::Recursive)?;
|
||||||
|
self.watcher = Some(watcher);
|
||||||
|
|
||||||
|
let mut absolute_content_parent = content_base_path().canonicalize()?;
|
||||||
|
absolute_content_parent.pop();
|
||||||
|
|
||||||
|
while let Some(result) = rx.recv().await {
|
||||||
|
if let Ok(ev) = result {
|
||||||
|
self.handle_event(ev, &absolute_content_parent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_event(&self, event: notify::Event, base: &Path) {
|
||||||
|
for path in event.paths {
|
||||||
|
let relative = path
|
||||||
|
.strip_prefix(base)
|
||||||
|
.expect("should only receive events for paths in content path");
|
||||||
|
let mut path = PathBuf::new();
|
||||||
|
for component in relative {
|
||||||
|
path.push(component);
|
||||||
|
if let Some(handler) = self.handlers.get(&path) {
|
||||||
|
handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AsyncEventHandler(UnboundedSender<notify::Result<notify::Event>>);
|
||||||
|
|
||||||
|
impl EventHandler for AsyncEventHandler {
|
||||||
|
fn handle_event(&mut self, event: notify::Result<notify::Event>) {
|
||||||
|
self.0.send(event).expect("sending event");
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
pub mod file_watcher;
|
||||||
pub mod one_more;
|
pub mod one_more;
|
||||||
pub mod slugify;
|
pub mod slugify;
|
||||||
pub mod templates;
|
pub mod templates;
|
||||||
@ -80,8 +81,12 @@ pub fn from_frontmatter<D: DeserializeOwned>(contents: &str) -> anyhow::Result<(
|
|||||||
Ok((deserialized, chars.as_str()))
|
Ok((deserialized, chars.as_str()))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn content_base_path() -> PathBuf {
|
||||||
|
PathBuf::from("site_test/")
|
||||||
|
}
|
||||||
|
|
||||||
pub fn content_path(p: impl AsRef<Path>) -> PathBuf {
|
pub fn content_path(p: impl AsRef<Path>) -> PathBuf {
|
||||||
let mut buf = PathBuf::from("site_test/");
|
let mut buf = content_base_path();
|
||||||
join_abs(&mut buf, p.as_ref());
|
join_abs(&mut buf, p.as_ref());
|
||||||
buf
|
buf
|
||||||
}
|
}
|
||||||
|
57
src/main.rs
57
src/main.rs
@ -3,7 +3,16 @@
|
|||||||
mod generator;
|
mod generator;
|
||||||
|
|
||||||
use clap::{Command, arg, command};
|
use clap::{Command, arg, command};
|
||||||
|
use debounced::debounced;
|
||||||
|
use futures::FutureExt;
|
||||||
|
use generator::{FileWatcher, content_base_path};
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use std::cell::RefCell;
|
||||||
|
use std::rc::Rc;
|
||||||
|
use std::time::Duration;
|
||||||
|
use tokio::pin;
|
||||||
|
use tokio_stream::StreamExt;
|
||||||
|
use tokio_stream::wrappers::UnboundedReceiverStream;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
@ -12,7 +21,10 @@ async fn main() {
|
|||||||
let matches = command!()
|
let matches = command!()
|
||||||
.subcommand_required(true)
|
.subcommand_required(true)
|
||||||
.arg_required_else_help(true)
|
.arg_required_else_help(true)
|
||||||
.subcommand(Command::new("gen"))
|
.subcommand(
|
||||||
|
Command::new("gen")
|
||||||
|
.arg(arg!(--watch "Watch the site directory and regenerate on changes")),
|
||||||
|
)
|
||||||
.subcommand(
|
.subcommand(
|
||||||
Command::new("serve")
|
Command::new("serve")
|
||||||
.arg(arg!(--watch "Watch the site directory and regenerate on changes")),
|
.arg(arg!(--watch "Watch the site directory and regenerate on changes")),
|
||||||
@ -26,8 +38,47 @@ async fn main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
match matches.subcommand() {
|
match matches.subcommand() {
|
||||||
Some(("gen", _)) => {
|
Some(("gen", matches)) => {
|
||||||
generator::generate().await.expect("generating");
|
let watcher = Rc::new(RefCell::new(FileWatcher::new()));
|
||||||
|
|
||||||
|
let mut graph = generator::generate(Rc::clone(&watcher))
|
||||||
|
.await
|
||||||
|
.expect("generating");
|
||||||
|
|
||||||
|
if matches.contains_id("watch") {
|
||||||
|
let (tx, rx) = tokio::sync::mpsc::unbounded_channel::<()>();
|
||||||
|
|
||||||
|
let mut watcher = watcher.borrow_mut();
|
||||||
|
watcher.watch(content_base_path(), move || {
|
||||||
|
tx.send(()).expect("sending regenerate signal");
|
||||||
|
});
|
||||||
|
|
||||||
|
let mut debounced =
|
||||||
|
debounced(UnboundedReceiverStream::new(rx), Duration::from_millis(500));
|
||||||
|
|
||||||
|
let watch = watcher.start().fuse();
|
||||||
|
|
||||||
|
let regenerate = async move {
|
||||||
|
while let Some(_) = debounced.next().await {
|
||||||
|
info!("Regenerating");
|
||||||
|
graph.evaluate_async().await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.fuse();
|
||||||
|
|
||||||
|
pin!(regenerate, watch);
|
||||||
|
|
||||||
|
loop {
|
||||||
|
futures::select! {
|
||||||
|
watcher_res = watch => {
|
||||||
|
watcher_res.expect("watching files");
|
||||||
|
}
|
||||||
|
_ = regenerate => {
|
||||||
|
info!("regenerate channel closed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(("serve", _matches)) => {
|
Some(("serve", _matches)) => {
|
||||||
todo!()
|
todo!()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user