about summary refs log tree commit diff
diff options
context:
space:
mode:
authorgennyble <gen@nyble.dev>2024-04-13 05:40:17 -0500
committergennyble <gen@nyble.dev>2024-04-13 05:40:17 -0500
commitfafb3c3ceaa16e93f69b38e33e64e240573e4875 (patch)
treec49c9eb94e6c14c089847c02ba156d5566e5b118
parent1b93aecbdc261ca2f7932db2754c6e33487dd9c8 (diff)
downloadawake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.tar.gz
awake-fafb3c3ceaa16e93f69b38e33e64e240573e4875.zip
:)
-rw-r--r--Cargo.lock425
-rw-r--r--Cargo.toml5
-rw-r--r--readme.md38
-rw-r--r--src/fs.rs3
-rw-r--r--src/ifc.rs112
-rw-r--r--src/main.rs123
-rw-r--r--src/markup.rs15
7 files changed, 639 insertions, 82 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 0976342..1659482 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -18,6 +18,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
 
 [[package]]
+name = "aho-corasick"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab"
+dependencies = [
+ "memchr",
+]
+
+[[package]]
 name = "async-trait"
 version = "0.1.77"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -41,9 +50,14 @@ dependencies = [
  "axum",
  "bempline",
  "camino",
+ "confindent",
+ "cutie",
  "snafu",
+ "time",
  "tokio",
  "tokio-util",
+ "tracing",
+ "tracing-subscriber",
 ]
 
 [[package]]
@@ -141,9 +155,9 @@ checksum = "c59e92b5a388f549b863a7bea62612c09f24c8393560709a54558a9abdfb3b9c"
 
 [[package]]
 name = "cc"
-version = "1.0.86"
+version = "1.0.90"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f9fa1897e4325be0d68d48df6aa1a71ac2ed4d27723887e7754192705350730"
+checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5"
 
 [[package]]
 name = "cfg-if"
@@ -152,6 +166,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
 [[package]]
+name = "confindent"
+version = "3.0.0"
+source = "git+https://github.com/gennyble/confindent#e44cf398923fe90ec07f1ee0cdeae97c85a97d1a"
+
+[[package]]
+name = "cutie"
+version = "0.1.0"
+dependencies = [
+ "thiserror",
+]
+
+[[package]]
+name = "deranged"
+version = "0.3.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
+dependencies = [
+ "powerfmt",
+]
+
+[[package]]
 name = "equivalent"
 version = "1.0.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -250,15 +285,15 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
 
 [[package]]
 name = "hermit-abi"
-version = "0.3.3"
+version = "0.3.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7"
+checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
 
 [[package]]
 name = "http"
-version = "1.0.0"
+version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b32afd38673a8016f7c9ae69e5af41a58f81b1d31689040f2f1959594ce194ea"
+checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258"
 dependencies = [
  "bytes",
  "fnv",
@@ -302,9 +337,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
 
 [[package]]
 name = "hyper"
-version = "1.1.0"
+version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fb5aa53871fc917b1a9ed87b683a5d86db645e23acb32c2e0785a353e522fb75"
+checksum = "186548d73ac615b32a73aafe38fb4f56c0d340e110e5a200bcadbaf2e199263a"
 dependencies = [
  "bytes",
  "futures-channel",
@@ -316,6 +351,7 @@ dependencies = [
  "httpdate",
  "itoa",
  "pin-project-lite",
+ "smallvec",
  "tokio",
 ]
 
@@ -337,9 +373,9 @@ dependencies = [
 
 [[package]]
 name = "indexmap"
-version = "2.2.3"
+version = "2.2.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
+checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4"
 dependencies = [
  "equivalent",
  "hashbrown",
@@ -352,6 +388,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
 
 [[package]]
+name = "lazy_static"
+version = "1.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
+
+[[package]]
 name = "libc"
 version = "0.2.153"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -359,9 +401,9 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
 
 [[package]]
 name = "lock_api"
-version = "0.4.10"
+version = "0.4.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16"
+checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45"
 dependencies = [
  "autocfg",
  "scopeguard",
@@ -369,9 +411,18 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.20"
+version = "0.4.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
+
+[[package]]
+name = "matchers"
+version = "0.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
+checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
+dependencies = [
+ "regex-automata 0.1.10",
+]
 
 [[package]]
 name = "matchit"
@@ -402,16 +453,32 @@ dependencies = [
 
 [[package]]
 name = "mio"
-version = "0.8.10"
+version = "0.8.11"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09"
+checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c"
 dependencies = [
  "libc",
  "wasi",
- "windows-sys",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
+name = "nu-ansi-term"
+version = "0.46.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84"
+dependencies = [
+ "overload",
+ "winapi",
 ]
 
 [[package]]
+name = "num-conv"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
+
+[[package]]
 name = "num_cpus"
 version = "1.16.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -437,6 +504,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
 
 [[package]]
+name = "overload"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39"
+
+[[package]]
 name = "parking_lot"
 version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -448,15 +521,15 @@ dependencies = [
 
 [[package]]
 name = "parking_lot_core"
-version = "0.9.8"
+version = "0.9.9"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447"
+checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e"
 dependencies = [
  "cfg-if",
  "libc",
  "redox_syscall",
  "smallvec",
- "windows-targets",
+ "windows-targets 0.48.5",
 ]
 
 [[package]]
@@ -467,18 +540,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
 
 [[package]]
 name = "pin-project"
-version = "1.1.4"
+version = "1.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0302c4a0442c456bd56f841aee5c3bfd17967563f6fadc9ceb9f9c23cf3807e0"
+checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3"
 dependencies = [
  "pin-project-internal",
 ]
 
 [[package]]
 name = "pin-project-internal"
-version = "1.1.4"
+version = "1.1.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "266c042b60c9c76b8d53061e52b2e0d1116abc57cefc8c5cd671619a56ac3690"
+checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -498,6 +571,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
 
 [[package]]
+name = "powerfmt"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.78"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -517,14 +596,58 @@ dependencies = [
 
 [[package]]
 name = "redox_syscall"
-version = "0.3.5"
+version = "0.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29"
+checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa"
 dependencies = [
  "bitflags",
 ]
 
 [[package]]
+name = "regex"
+version = "1.9.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-automata 0.3.8",
+ "regex-syntax 0.7.5",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.1.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
+dependencies = [
+ "regex-syntax 0.6.29",
+]
+
+[[package]]
+name = "regex-automata"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.7.5",
+]
+
+[[package]]
+name = "regex-syntax"
+version = "0.6.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+
+[[package]]
+name = "regex-syntax"
+version = "0.7.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
+
+[[package]]
 name = "rustc-demangle"
 version = "0.1.23"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -581,9 +704,9 @@ dependencies = [
 
 [[package]]
 name = "serde_path_to_error"
-version = "0.1.15"
+version = "0.1.16"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ebd154a240de39fdebcf5775d2675c204d7c13cf39a4c697be6493c8e734337c"
+checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6"
 dependencies = [
  "itoa",
  "serde",
@@ -602,6 +725,15 @@ dependencies = [
 ]
 
 [[package]]
+name = "sharded-slab"
+version = "0.1.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6"
+dependencies = [
+ "lazy_static",
+]
+
+[[package]]
 name = "signal-hook-registry"
 version = "1.4.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -621,24 +753,24 @@ dependencies = [
 
 [[package]]
 name = "smallvec"
-version = "1.11.0"
+version = "1.13.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9"
+checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7"
 
 [[package]]
 name = "snafu"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d342c51730e54029130d7dc9fd735d28c4cd360f1368c01981d4f03ff207f096"
+checksum = "5ed22871b3fe6eff9f1b48f6cbd54149ff8e9acd740dea9146092435f9c43bd3"
 dependencies = [
  "snafu-derive",
 ]
 
 [[package]]
 name = "snafu-derive"
-version = "0.8.0"
+version = "0.8.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "080c44971436b1af15d6f61ddd8b543995cf63ab8e677d46b00cc06f4ef267a0"
+checksum = "4651148226ec36010993fcba6c3381552e8463e9f3e337b75af202b0688b5274"
 dependencies = [
  "heck",
  "proc-macro2",
@@ -648,19 +780,19 @@ dependencies = [
 
 [[package]]
 name = "socket2"
-version = "0.5.5"
+version = "0.5.6"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9"
+checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871"
 dependencies = [
  "libc",
- "windows-sys",
+ "windows-sys 0.52.0",
 ]
 
 [[package]]
 name = "syn"
-version = "2.0.50"
+version = "2.0.52"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "74f1bdc9872430ce9b75da68329d1c1746faf50ffac5f19e02b71e37ff881ffb"
+checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -674,6 +806,67 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
 
 [[package]]
+name = "thiserror"
+version = "1.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.57"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "thread_local"
+version = "1.1.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c"
+dependencies = [
+ "cfg-if",
+ "once_cell",
+]
+
+[[package]]
+name = "time"
+version = "0.3.36"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
+dependencies = [
+ "deranged",
+ "itoa",
+ "num-conv",
+ "powerfmt",
+ "serde",
+ "time-core",
+ "time-macros",
+]
+
+[[package]]
+name = "time-core"
+version = "0.1.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
+
+[[package]]
+name = "time-macros"
+version = "0.2.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
+dependencies = [
+ "num-conv",
+ "time-core",
+]
+
+[[package]]
 name = "tokio"
 version = "1.36.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -689,7 +882,7 @@ dependencies = [
  "signal-hook-registry",
  "socket2",
  "tokio-macros",
- "windows-sys",
+ "windows-sys 0.48.0",
 ]
 
 [[package]]
@@ -753,16 +946,58 @@ checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef"
 dependencies = [
  "log",
  "pin-project-lite",
+ "tracing-attributes",
  "tracing-core",
 ]
 
 [[package]]
+name = "tracing-attributes"
+version = "0.1.27"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
 name = "tracing-core"
 version = "0.1.32"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54"
 dependencies = [
  "once_cell",
+ "valuable",
+]
+
+[[package]]
+name = "tracing-log"
+version = "0.2.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3"
+dependencies = [
+ "log",
+ "once_cell",
+ "tracing-core",
+]
+
+[[package]]
+name = "tracing-subscriber"
+version = "0.3.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b"
+dependencies = [
+ "matchers",
+ "nu-ansi-term",
+ "once_cell",
+ "regex",
+ "sharded-slab",
+ "smallvec",
+ "thread_local",
+ "tracing",
+ "tracing-core",
+ "tracing-log",
 ]
 
 [[package]]
@@ -772,18 +1007,55 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
 
 [[package]]
+name = "valuable"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
+
+[[package]]
 name = "wasi"
 version = "0.11.0+wasi-snapshot-preview1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
 
 [[package]]
+name = "winapi"
+version = "0.3.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
+dependencies = [
+ "winapi-i686-pc-windows-gnu",
+ "winapi-x86_64-pc-windows-gnu",
+]
+
+[[package]]
+name = "winapi-i686-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+
+[[package]]
+name = "winapi-x86_64-pc-windows-gnu"
+version = "0.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
+
+[[package]]
 name = "windows-sys"
 version = "0.48.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
 dependencies = [
- "windows-targets",
+ "windows-targets 0.48.5",
+]
+
+[[package]]
+name = "windows-sys"
+version = "0.52.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+dependencies = [
+ "windows-targets 0.52.4",
 ]
 
 [[package]]
@@ -792,13 +1064,28 @@ version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
 dependencies = [
- "windows_aarch64_gnullvm",
- "windows_aarch64_msvc",
- "windows_i686_gnu",
- "windows_i686_msvc",
- "windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
- "windows_x86_64_msvc",
+ "windows_aarch64_gnullvm 0.48.5",
+ "windows_aarch64_msvc 0.48.5",
+ "windows_i686_gnu 0.48.5",
+ "windows_i686_msvc 0.48.5",
+ "windows_x86_64_gnu 0.48.5",
+ "windows_x86_64_gnullvm 0.48.5",
+ "windows_x86_64_msvc 0.48.5",
+]
+
+[[package]]
+name = "windows-targets"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
+dependencies = [
+ "windows_aarch64_gnullvm 0.52.4",
+ "windows_aarch64_msvc 0.52.4",
+ "windows_i686_gnu 0.52.4",
+ "windows_i686_msvc 0.52.4",
+ "windows_x86_64_gnu 0.52.4",
+ "windows_x86_64_gnullvm 0.52.4",
+ "windows_x86_64_msvc 0.52.4",
 ]
 
 [[package]]
@@ -808,37 +1095,79 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
 
 [[package]]
+name = "windows_aarch64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
+
+[[package]]
 name = "windows_aarch64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
 
 [[package]]
+name = "windows_aarch64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
+
+[[package]]
 name = "windows_i686_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
 
 [[package]]
+name = "windows_i686_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3"
+
+[[package]]
 name = "windows_i686_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
 
 [[package]]
+name = "windows_i686_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02"
+
+[[package]]
 name = "windows_x86_64_gnu"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
 
 [[package]]
+name = "windows_x86_64_gnu"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03"
+
+[[package]]
 name = "windows_x86_64_gnullvm"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
 
 [[package]]
+name = "windows_x86_64_gnullvm"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177"
+
+[[package]]
 name = "windows_x86_64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "windows_x86_64_msvc"
+version = "0.52.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8"
diff --git a/Cargo.toml b/Cargo.toml
index 220d7e3..c13ed5b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -12,3 +12,8 @@ snafu = "0.8.0"
 bempline = { git = "https://github.com/gennyble/bempline" }
 tokio = { version = "1.36.0", features = ["full"] }
 tokio-util = { version = "0.7.10", features = ["io"] }
+confindent = { git = "https://github.com/gennyble/confindent" }
+cutie = { path = "../cutie" }
+tracing = "0.1.40"
+tracing-subscriber = { version = "0.3.18", features = ["env-filter"] }
+time = { version = "0.3.36", features = ["macros", "parsing", "formatting"] }
diff --git a/readme.md b/readme.md
index e870276..11fb06d 100644
--- a/readme.md
+++ b/readme.md
@@ -6,6 +6,10 @@ map tile. Make a gif with a few frames of radar so we can embed it on the site.
 Zoomed out far enough that I'm not worried about opsec and with no marker for
 where I am in the tile.
 
+**Bring back file-times**
+Times are stored by whenwasit in a CSV files. I want to add the times to the
+bottom of the page again. I miss them.
+
 ## Dirfiles
 These are files that match the name of the directory.
 
@@ -20,11 +24,6 @@ What do you name the root file, then? You shouldn't have to match the webroot's
 directory name. Perhaps it should be configurable. I think for now we'll
 hard-code in `home.html`, though.
 
-**TODO:**  
-we need to redirect directories to themselves with slashes. The browser thinks
-that anything not ending in a slash is a file. It couldvery well be right, but
-this causes chaos when we try to relative link to a directories resources.
-
 ## Page-content uses templates
 Because writing the same outer-html for everything poses a few problems. I'll
 enumerate them for fun!
@@ -71,6 +70,15 @@ a one or two sentence description of the page.
 <meta property="og:description" content="gone for now. stepped out for a bit." />
 ```
 
+**path-offset** (default: none)  
+remove a path component from the end of tree when displaying with the
+**path** pattern
+
+### patterns
+**path**  
+use this pattern with `path_link` and `path_name` to insert links to the
+directories below a page.
+
 ## Page content uses a weird kind of markup language
 It's mostly just HTML, but I'm tired of writing `<p>` so damn much.
 
@@ -92,4 +100,22 @@ the next line.
 
 ### annotations
 
-**[#element-id]** - give the paragraph for this text block an ID of `element-id`
\ No newline at end of file
+**[#element-id]** - give the paragraph for this text block an ID of `element-id`
+
+## Atomizer!!!
+launch with the arguments `atomizer <awake.conf> <atom.conf>`
+
+known issues:
+- [ ] Relative links are not absoluteified
+- [ ] we should remove `<script>`. *(rather, we shouldn't put any in)*
+
+## Date/Time Parsing
+Acceptable formats:
+- Date only: `2024-04-13`
+- Date/Time: `2024-04-13 02:56`
+- Date/Time/Offset: `2024-04-13 02:56 CDT`
+
+If no time is provided, noon is assumed.  
+If no offset is provided, Central Time with the correct DST is assumed.
+
+Known timezones: `CST`, `CDT`
\ No newline at end of file
diff --git a/src/fs.rs b/src/fs.rs
index b44e4c4..7dc94d3 100644
--- a/src/fs.rs
+++ b/src/fs.rs
@@ -8,7 +8,7 @@ use crate::RuntimeError;
 /// below the webroot and will never start or end with a slash.
 #[derive(Clone, Debug, PartialEq)]
 pub struct Webpath {
-	webcanon: Utf8PathBuf,
+	pub webcanon: Utf8PathBuf,
 	is_dir: bool,
 }
 
@@ -106,7 +106,6 @@ impl Filesystem {
 	}
 
 	pub fn resolve(&self, webpath: &Webpath) -> Result<PathResolution, RuntimeError> {
-		println!("resolve = {webpath}");
 		if webpath.is_index() || webpath == ROOT_INDEX {
 			return Ok(PathResolution {
 				filepath: self.webroot.join(ROOT_INDEX),
diff --git a/src/ifc.rs b/src/ifc.rs
new file mode 100644
index 0000000..d0a9f5f
--- /dev/null
+++ b/src/ifc.rs
@@ -0,0 +1,112 @@
+//! The international fixed calendar is a 13-month calendar with each month
+//! containing exactly 28 days. There is an extra day at the end of the year
+//! called the year day.
+//!
+//! In leap-years there is an extra day inserted at the end of June called the
+//! leap day. It is directly after the fourth week of june and is given to june,
+//! so it becomes June 29th. The day after June 29th starts the new month, Sol,
+//! with Sol 1.
+//!
+//! [Wikipedia: International Fixed Calendar][wp-ifc]
+//! [wp-ifc]: https://en.wikipedia.org/wiki/International_Fixed_Calendar
+
+use time::Date as TimeDate;
+
+const MONTHS: [[&str; 2]; 13] = [
+	["January", "Jan"],
+	["February", "Feb"],
+	["March", "Mar"],
+	["April", "Apr"],
+	["May", "May"],
+	["June", "Jun"],
+	["Sol", "Sol"],
+	["July", "Jul"],
+	["August", "Aug"],
+	["September", "Sep"],
+	["October", "Oct"],
+	["November", "Nov"],
+	["December", "Dec"],
+];
+
+pub struct Calendar {
+	pub year: usize,
+	pub ordinal: usize,
+}
+
+impl Calendar {
+	pub fn from_year(year: usize) -> Self {
+		Self { year, ordinal: 0 }
+	}
+
+	pub fn from_time_date(date: TimeDate) -> Self {
+		let year = date.year() as usize;
+		let ord = date.ordinal() as usize;
+
+		Self { year, ordinal: ord }
+	}
+}
+
+pub struct Date {
+	pub year: u32,
+	pub month: u8,
+	pub day: u8,
+}
+
+impl Date {
+	pub fn from_time_date(date: TimeDate) -> Self {
+		let year = date.year() as u32;
+		let ord = date.ordinal();
+
+		if !year_leaps(year) || ord <= 168 {
+			// not a leap year path
+			// also the "leap year but before the leap-day" path
+			Self {
+				year,
+				month: (ord / 28) as u8,
+				day: (ord % 28) as u8,
+			}
+		} else if ord == 169 {
+			Self {
+				year,
+				month: 6,
+				day: 29,
+			}
+		} else {
+			todo!()
+		}
+	}
+
+	pub fn is_leap(&self) -> bool {
+		year_leaps(self.year)
+	}
+}
+
+/// Whether or not a year is a leap year
+fn year_leaps(year: u32) -> bool {
+	let four = year % 4 == 0;
+	let hundreds = year % 100 == 0;
+	let fourhund = year % 400 == 0;
+
+	// leap if:
+	// - four AND NOT hundred
+	// - four AND hundred AND fourhund
+
+	// `fourhund` here checks `hundreds` by virtue of 100 being a multiple of 400
+	four && (!hundreds || fourhund)
+}
+
+mod test {
+	use crate::ifc::year_leaps;
+
+	#[test]
+	fn leap_years() {
+		// the examples given by wikipedia
+		assert!(year_leaps(2000));
+		assert!(!year_leaps(1700));
+		assert!(!year_leaps(1800));
+		assert!(!year_leaps(1900));
+
+		// testing the four rule
+		assert!(year_leaps(2024));
+	}
+}
diff --git a/src/main.rs b/src/main.rs
index 29716e8..b43e463 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,8 +1,11 @@
+mod atomizer;
 mod error;
 mod fs;
+mod ifc;
 mod markup;
 mod settings;
 mod templated;
+mod timeparse;
 
 use std::{os::unix::fs::MetadataExt, str::FromStr};
 
@@ -16,10 +19,12 @@ use axum::{
 };
 use bempline::{Document, Options};
 use camino::Utf8PathBuf;
+use confindent::Confindent;
 pub use error::RuntimeError;
 use fs::Filesystem;
 use settings::Settings;
 use tokio_util::io::ReaderStream;
+use tracing_subscriber::{prelude::*, EnvFilter};
 
 use crate::{
 	fs::{PathResolution, Webpath},
@@ -28,10 +33,35 @@ use crate::{
 
 #[tokio::main]
 async fn main() {
-	let fs = Filesystem::new("../inf/served");
+	match std::env::args().nth(1).as_deref() {
+		Some("atomizer") => atomizer::main(),
+		Some("serve") =>
+		/* fallthrough*/
+		{
+			()
+		}
+		_ => (),
+	}
+
+	tracing_subscriber::registry()
+		.with(tracing_subscriber::fmt::layer())
+		.with(
+			EnvFilter::try_from_default_env()
+				.or_else(|_| EnvFilter::try_new("info"))
+				.unwrap(),
+		)
+		.init();
+
+	let conf = Confindent::from_file(std::env::args().nth(2).unwrap()).unwrap();
+	let webroot: Utf8PathBuf = conf.child_parse("Webroot").unwrap();
+	let templates = conf.child_value("Templates").unwrap();
+
+	let fs = Filesystem::new(&webroot);
 
 	let settings = Settings {
-		template_dir: Utf8PathBuf::from("../inf/templates"),
+		template_dir: Utf8PathBuf::from(webroot.join(templates))
+			.canonicalize_utf8()
+			.unwrap(),
 	};
 
 	let app = Router::new()
@@ -66,30 +96,25 @@ async fn falible_handler(
 	settings: Settings,
 	path: String,
 ) -> Result<Response, RuntimeError> {
-	println!("raw = {path}");
+	tracing::debug!("webpath = {path}");
 
 	let webpath: Webpath = path.parse()?;
+	let resolve = fs.resolve(&webpath)?;
 
-	println!("path = {path}");
-
-	let PathResolution {
-		filepath,
-		is_dirfile,
-	} = fs.resolve(&webpath)?;
-
-	if !webpath.is_dir() && is_dirfile {
-		println!("as_dir = {}", webpath.as_dir());
+	if !webpath.is_dir() && resolve.is_dirfile {
 		return Ok(redirect(webpath.as_dir()));
 	}
 
-	let ext = filepath.extension().unwrap_or_default();
+	tracing::info!("serving {webpath}");
+
+	let ext = resolve.filepath.extension().unwrap_or_default();
 
 	if ext != "html" {
-		send_file(filepath).await
+		send_file(resolve.filepath).await
 	} else {
-		let content = Filesystem::read_to_string(&filepath).await?;
+		let content = Filesystem::read_to_string(&resolve.filepath).await?;
 		match Templated::from_str(&content) {
-			Ok(templated) => send_template(templated, filepath, settings).await,
+			Ok(templated) => send_template(templated, resolve, webpath, settings).await,
 			Err(_) => Ok(Response::builder()
 				.header(header::CONTENT_TYPE, "text/html")
 				.body(Body::from(content))
@@ -100,7 +125,7 @@ async fn falible_handler(
 
 fn redirect<S: Into<String>>(redirection: S) -> Response {
 	let location = redirection.into();
-	println!("redirecting to {location}");
+	tracing::info!("redirect to {location}");
 	Response::builder()
 		.status(StatusCode::TEMPORARY_REDIRECT)
 		.header(header::LOCATION, &location)
@@ -113,13 +138,16 @@ const STREAM_AFTER: u64 = 20 * 1024 * 1024;
 
 async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 	let ext = filepath.extension().unwrap_or_default();
+	let stem = filepath.file_stem().unwrap_or_default();
 
 	let mime = match ext {
 		// Text
 		"css" => "text/css",
 		"html" => "text/html",
 		"js" => "text/javascript",
-		"txt" => "txt/plain",
+		"txt" => "text/plain",
+		"xml" if stem.ends_with("atom") => "application/atom+xml",
+		"xml" => "application/xml",
 
 		// Multimedia
 		"gif" => "image/gif",
@@ -136,6 +164,8 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 
 	let metadata = Filesystem::metadata(&filepath)?;
 	if metadata.size() > STREAM_AFTER {
+		tracing::debug!("large file, streaming to client");
+
 		let file = Filesystem::open(filepath).await?;
 		let stream = ReaderStream::new(file);
 		Ok(response.body(Body::from_stream(stream)).unwrap())
@@ -147,14 +177,18 @@ async fn send_file(filepath: Utf8PathBuf) -> Result<Response, RuntimeError> {
 
 async fn send_template(
 	templated: Templated,
-	path: Utf8PathBuf,
+	resolve: PathResolution,
+	webpath: Webpath,
 	settings: Settings,
 ) -> Result<Response, RuntimeError> {
 	let template_stem = templated.frontmatter.get("template").expect("no template");
 	let template_name = Utf8PathBuf::from(format!("{template_stem}.html"));
 	let template_path = settings.template_dir.join(template_name);
 
-	let filename = path.file_name().expect("template has no filename");
+	let filename = resolve
+		.filepath
+		.file_name()
+		.expect("template has no filename");
 
 	let mut template = Document::from_file(
 		template_path,
@@ -169,6 +203,7 @@ async fn send_template(
 		templated.frontmatter.get("title").unwrap_or(filename),
 	);
 
+	// styles the templated stuff wants
 	let style_pattern = template.get_pattern("styles").unwrap();
 	for style in templated.frontmatter.get_many("style") {
 		let mut pat = style_pattern.clone();
@@ -176,7 +211,53 @@ async fn send_template(
 		template.set_pattern("styles", pat);
 	}
 
-	template.set("main", templated.content);
+	// path to the file for navigation
+	let mut path: Vec<&str> = webpath.webcanon.iter().collect();
+	// we don't want the directory/filename itself
+	path.pop();
+
+	if let Some(path_pattern) = template.get_pattern("path") {
+		let offset = match templated
+			.frontmatter
+			.get("path-offset")
+			.map(|raw| raw.parse::<usize>())
+		{
+			Some(Ok(offset)) => offset,
+			None => 0,
+			Some(Err(_)) => {
+				tracing::error!(
+					"path-offset in template {} is not an integer",
+					resolve.filepath
+				);
+
+				0
+			}
+		};
+
+		for _ in 0..offset {
+			path.pop();
+		}
+
+		let mut link = Utf8PathBuf::from("/");
+
+		let mut pat = path_pattern.clone();
+		pat.set("path_link", "/");
+		pat.set("path_name", "home");
+		template.set_pattern("path", pat);
+
+		for part in path {
+			link.push(part);
+
+			let mut pat = path_pattern.clone();
+			pat.set("path_link", &link);
+			pat.set("path_name", part);
+			template.set_pattern("path", pat);
+		}
+	}
+
+	// insert the page content itself
+	let markedup = markup::process(&templated.content);
+	template.set("main", markedup);
 
 	Ok(Response::builder()
 		.header(header::CONTENT_TYPE, "text/html")
diff --git a/src/markup.rs b/src/markup.rs
index 4e0d66e..a1516f4 100644
--- a/src/markup.rs
+++ b/src/markup.rs
@@ -47,12 +47,12 @@ impl State {
 
 			let escaped = self.escape_line(line);
 			self.current.push_str(escaped);
+			
+			self.last_blank = false;
 		} else {
 			// line is empty.
 			self.push_current();
 		}
-
-		self.last_blank = false;
 	}
 
 	pub fn done(mut self) -> String {
@@ -62,7 +62,7 @@ impl State {
 
 	fn escape_line<'a>(&mut self, line: &'a str) -> &'a str {
 		if let Some(strip) = line.strip_prefix('\\') {
-			match line.chars().next() {
+			match strip.chars().next() {
 				Some('[') => strip,
 				Some('<') => {
 					if self.last_blank {
@@ -157,8 +157,6 @@ pub fn process(raw: &str) -> String {
 
 #[cfg(test)]
 mod test {
-	use camino::Utf8PathBuf;
-
 	use crate::markup::process;
 
 	#[test]
@@ -200,6 +198,13 @@ mod test {
 		assert_eq!(process(str), correct)
 	}
 
+	#[test]
+	fn wraps_escaped_html() {
+		let str = "\\<i>test</i>";
+		let correct = "<p>\n<i>test</i>\n</p>";
+		assert_eq!(process(str), correct)
+	}
+
 	const BASE: &str = "test/markup";
 	fn test_files(test: &str) {
 		let input_path = format!("{BASE}/{test}/input.html");