diff --git a/Cargo.lock b/Cargo.lock index d6edef15..2872d3d9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -30,9 +30,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] @@ -127,6 +127,12 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +[[package]] +name = "arrayvec" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" + [[package]] name = "arrayvec" version = "0.7.4" @@ -135,20 +141,20 @@ checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "async-trait" -version = "0.1.77" +version = "0.1.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c980ee35e870bd1a4d2c8294d4c04d0499e67bca1e4b5cefcc693c2fa00caea9" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] name = "autocfg" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" [[package]] name = "await-tree" @@ -176,9 +182,9 @@ checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "26b05800d2e817c8b3b4b54abd461726265fa9789ae34330622f2db9ee696f9d" dependencies = [ "addr2line", "cc", @@ -256,9 +262,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -336,9 +342,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" [[package]] name = "camino" @@ -351,9 +357,9 @@ dependencies = [ [[package]] name = "cargo-platform" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "694c8807f2ae16faecc43dc17d74b3eb042482789fd0eb64b39a2e04e087053f" +checksum = "24b1f0365a6c6bb4020cd05806fd0d33c44d38046b8bd7f0e40814b9763cabfc" dependencies = [ "serde", ] @@ -408,9 +414,9 @@ checksum = "7588475145507237ded760e52bf2f1085495245502033756d28ea72ade0e498b" [[package]] name = "chrono" -version = "0.4.35" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eaf5903dcbc0a39312feb77df2ff4c76387d591b9fc7b04a238dcf8bb62639a" +checksum = "8a0d04d43504c61aa6c7531f1871dd0d418d91130162063b789da00fd7057a5e" dependencies = [ "android-tzdata", "iana-time-zone", @@ -460,9 +466,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "949626d00e063efc93b6dca932419ceb5432f99769911c0b995f7e884c778813" +checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0" dependencies = [ "clap_builder", "clap_derive", @@ -504,14 +510,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.3" +version = "4.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90239a040c80f5e14809ca132ddc4176ab33d5e17e49691793296e3fcb34d72f" +checksum = "528131438037fd55894f62d6e9f068b8f45ac57ffa77517819645d10aed04f64" dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -569,16 +575,37 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "comemo" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf5705468fa80602ee6a5f9318306e6c428bffd53e43209a78bc05e6e667c6f4" +dependencies = [ + "comemo-macros 0.3.1", + "siphasher 1.0.1", +] + [[package]] name = "comemo" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df6916408a724339aa77b18214233355f3eb04c42eb895e5f8909215bd8a7a91" dependencies = [ - "comemo-macros", + "comemo-macros 0.4.0", "once_cell", "parking_lot", - "siphasher 1.0.0", + "siphasher 1.0.1", +] + +[[package]] +name = "comemo-macros" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54af6ac68ada2d161fa9cc1ab52676228e340866d094d6542107e74b82acc095" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", ] [[package]] @@ -589,7 +616,7 @@ checksum = "c8936e42f9b4f5bdfaf23700609ac1f11cb03ad4c1ec128a4ee4fd0903e228db" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -772,7 +799,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -794,7 +821,7 @@ checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f" dependencies = [ "darling_core 0.20.8", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -918,7 +945,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -935,9 +962,18 @@ checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" [[package]] name = "ecow" -version = "0.2.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dba31a30727c42ff5e60468d695c7f21e43a6db2808b7195adcab908fbd9f794" +checksum = "1d1990d053cf6edf3f030682dba3b0eb65ef01fabb2686072765d8a17d6728e8" +dependencies = [ + "serde", +] + +[[package]] +name = "ecow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54bfbb1708988623190a6c4dbedaeaf0f53c20c6395abd6a01feb327b3146f4b" dependencies = [ "serde", ] @@ -1004,7 +1040,7 @@ checksum = "0d28318a75d4aead5c4db25382e8ef717932d0346600cacae6357eb5941bc5ff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1064,9 +1100,9 @@ checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "658bd65b1cf4c852a3cc96f18a8ce7b5640f6b703f905c7d74532294c2a63984" [[package]] name = "fdeflate" @@ -1244,7 +1280,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1335,17 +1371,28 @@ checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "git2" -version = "0.18.2" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b3ba52851e73b46a4c3df1d89343741112003f0f6f13beb0dfac9e457c3fdcd" +checksum = "232e6a7bfe35766bf715e55a88b39a700596c0ccfd88cd3680b4cdb40d66ef70" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "libgit2-sys", "log", "url", ] +[[package]] +name = "globmatch" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3755076379cc2b2bbf53855fe718e1eed3093cfb769ebf5d290f617fa9cc09a0" +dependencies = [ + "globset", + "log", + "walkdir", +] + [[package]] name = "globset" version = "0.4.14" @@ -1371,7 +1418,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.5", + "indexmap 2.2.6", "slab", "tokio", "tokio-util", @@ -1412,7 +1459,7 @@ dependencies = [ "biblatex", "ciborium", "citationberg", - "indexmap 2.2.5", + "indexmap 2.2.6", "numerals", "paste", "serde", @@ -1701,7 +1748,7 @@ checksum = "d2abdd3a62551e8337af119c5899e600ca0c88ec8f23a46c60ba216c803dcf1a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -1783,9 +1830,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.5" +version = "2.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown 0.14.3", @@ -1826,9 +1873,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.36.1" +version = "1.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" +checksum = "1718b3f2b85bb5054baf8ce406e36401f27c3169205f4175504c4b1d98252d3f" dependencies = [ "console", "globset", @@ -1836,7 +1883,6 @@ dependencies = [ "linked-hash-map", "similar", "walkdir", - "yaml-rust", ] [[package]] @@ -1873,6 +1919,15 @@ dependencies = [ "once_cell", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + [[package]] name = "itertools" version = "0.11.0" @@ -1893,9 +1948,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jobserver" @@ -1956,7 +2011,7 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd85a5776cd9500c2e2059c8c76c3b01528566b7fcbaf8098b55a33fc298849b" dependencies = [ - "arrayvec", + "arrayvec 0.7.4", ] [[package]] @@ -1995,16 +2050,16 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall", ] [[package]] name = "libz-sys" -version = "1.1.15" +version = "1.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037731f5d3aaa87a5675e895b63ddff1a87624bc29f77004ea829809654e48f6" +checksum = "5e143b5e666b2695d28f6bca6497720813f699c9602dd7f5cac91008b8ada7f9" dependencies = [ "cc", "libc", @@ -2014,12 +2069,9 @@ dependencies = [ [[package]] name = "line-wrap" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30344350a2a51da54c1d53be93fade8a237e545dbcc4bdbe635413f2117cab9" -dependencies = [ - "safemem", -] +checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" [[package]] name = "linked-hash-map" @@ -2188,7 +2240,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -2293,7 +2345,7 @@ version = "0.10.64" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg-if", "foreign-types", "libc", @@ -2310,7 +2362,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2357,7 +2409,7 @@ checksum = "e8890702dbec0bad9116041ae586f84805b13eecd1d8b1df27c29998a9969d6d" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2449,7 +2501,7 @@ dependencies = [ "phf_shared", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2484,7 +2536,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -2516,12 +2568,12 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5699cc8a63d1aa2b1ee8e12b9ad70ac790d65788cd36101fa37f87ea46c4cef" +checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" dependencies = [ "base64 0.21.7", - "indexmap 2.2.5", + "indexmap 2.2.6", "line-wrap", "quick-xml", "serde", @@ -2570,6 +2622,17 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "pretty" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55c4d17d994b637e2f4daf6e5dc5d660d209d5642377d675d7a1c3ab69fa579" +dependencies = [ + "arrayvec 0.5.2", + "typed-arena", + "unicode-width", +] + [[package]] name = "proc-macro2" version = "1.0.79" @@ -2671,9 +2734,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" +checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" dependencies = [ "either", "rayon-core", @@ -2717,9 +2780,9 @@ checksum = "247ea8050cb5c88b41a68b3269f5a2eb7ebff55851a564d96b035643418346e6" dependencies = [ "base64 0.22.0", "bitvec", - "comemo", + "comemo 0.4.0", "dashmap", - "ecow", + "ecow 0.2.2", "fxhash", "once_cell", "parking_lot", @@ -2729,15 +2792,15 @@ dependencies = [ "serde_json", "serde_repr", "serde_with", - "siphasher 1.0.0", + "siphasher 1.0.1", "tiny-skia-path", ] [[package]] name = "regex" -version = "1.10.3" +version = "1.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" +checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c" dependencies = [ "aho-corasick", "memchr", @@ -2758,9 +2821,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" [[package]] name = "rend" @@ -2773,9 +2836,9 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.26" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78bf93c4af7a8bb7d879d51cebe797356ff10ae8516ace542b5182d9dcac10b2" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ "base64 0.21.7", "bytes", @@ -2921,11 +2984,11 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.31" +version = "0.38.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" +checksum = "65e04861e65f21776e67888bfbea442b3642beaa0138fdb1dd7a84a52dffdb89" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "libc", "linux-raw-sys", @@ -2975,7 +3038,7 @@ version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0ae5692c5beaad6a9e22830deeed7874eae8a4e3ba4076fb48e12c56856222c" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "bytemuck", "smallvec", "ttf-parser", @@ -2991,12 +3054,6 @@ version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" -[[package]] -name = "safemem" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" - [[package]] name = "same-file" version = "1.0.6" @@ -3086,14 +3143,14 @@ checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.115" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd" dependencies = [ "itoa", "ryu", @@ -3108,7 +3165,7 @@ checksum = "0b2e6b945e9d3df726b65d6ee24060aff8e3533d431f677a9695db04eff9dfdb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3142,7 +3199,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_derive", "serde_json", @@ -3159,16 +3216,16 @@ dependencies = [ "darling 0.20.8", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] name = "serde_yaml" -version = "0.9.32" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd075d994154d4a774f95b51fb96bdc2832b0ea48425c92546073816cda1f2f" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "itoa", "ryu", "serde", @@ -3241,9 +3298,9 @@ checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" [[package]] name = "siphasher" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54ac45299ccbd390721be55b412d41931911f654fa99e2cb8bfb57184b2061fe" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" [[package]] name = "slab" @@ -3265,9 +3322,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "socket2" @@ -3359,7 +3416,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3372,7 +3429,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3419,9 +3476,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.52" +version = "2.0.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" +checksum = "002a1b3dbf967edfafc32655d0f377ab0bb7b994aa1d32c8cc7e9b8bf3ebb8f0" dependencies = [ "proc-macro2", "quote", @@ -3442,7 +3499,7 @@ checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3553,7 +3610,7 @@ checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3602,7 +3659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", - "arrayvec", + "arrayvec 0.7.4", "bytemuck", "cfg-if", "log", @@ -3635,7 +3692,7 @@ dependencies = [ "clap_complete_fig", "clap_mangen", "codespan-reporting", - "comemo", + "comemo 0.4.0", "crossbeam-channel", "dhat", "env_logger", @@ -3652,7 +3709,7 @@ dependencies = [ "tinymist-query", "tokio", "tokio-util", - "toml", + "toml 0.8.12", "typst", "typst-assets", "typst-pdf", @@ -3662,6 +3719,8 @@ dependencies = [ "typst-timing", "typst-ts-compiler", "typst-ts-core", + "typstfmt_lib", + "typstyle", "vergen", "walkdir", ] @@ -3671,13 +3730,13 @@ name = "tinymist-query" version = "0.11.1" dependencies = [ "anyhow", - "comemo", - "ecow", + "comemo 0.4.0", + "ecow 0.2.2", "ena", "fxhash", "hex", "if_chain", - "indexmap 2.2.5", + "indexmap 2.2.6", "insta", "itertools 0.12.1", "lazy_static", @@ -3691,7 +3750,7 @@ dependencies = [ "serde_json", "sha2", "strum 0.26.2", - "toml", + "toml 0.8.12", "typst", "typst-ide", "typst-ts-compiler", @@ -3752,7 +3811,7 @@ checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3803,14 +3862,26 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9dd1545e8208b4a5af1aa9bbd0b4cf7e9ea08fabc5d0a5c67fcaafa17433aa3" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.22.9", ] [[package]] @@ -3824,15 +3895,28 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.5", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.22.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" +dependencies = [ + "indexmap 2.2.6", + "serde", + "serde_spanned", + "toml_datetime", + "winnow 0.6.5", ] [[package]] @@ -3860,7 +3944,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -3932,12 +4016,12 @@ version = "0.11.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#88608109579929b0c1fbab12d7a2afaea0baaf74" dependencies = [ "az", - "bitflags 2.4.2", + "bitflags 2.5.0", "chinese-number", "ciborium", - "comemo", + "comemo 0.4.0", "csv", - "ecow", + "ecow 0.2.2", "fontdb", "hayagriva", "hypher", @@ -3948,7 +4032,7 @@ dependencies = [ "icu_segmenter", "if_chain", "image", - "indexmap 2.2.5", + "indexmap 2.2.6", "kamadak-exif", "kurbo", "lipsum", @@ -3966,18 +4050,18 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "siphasher 1.0.0", + "siphasher 1.0.1", "smallvec", "stacker", "syntect", "time", - "toml", + "toml 0.8.12", "ttf-parser", "two-face", "typed-arena", "typst-assets", "typst-macros", - "typst-syntax", + "typst-syntax 0.11.0 (git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0)", "typst-timing", "unicode-bidi", "unicode-math-class", @@ -3998,8 +4082,8 @@ name = "typst-ide" version = "0.11.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#88608109579929b0c1fbab12d7a2afaea0baaf74" dependencies = [ - "comemo", - "ecow", + "comemo 0.4.0", + "ecow 0.2.2", "if_chain", "log", "serde", @@ -4015,7 +4099,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] [[package]] @@ -4025,8 +4109,8 @@ source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11. dependencies = [ "base64 0.22.0", "bytemuck", - "comemo", - "ecow", + "comemo 0.4.0", + "ecow 0.2.2", "image", "miniz_oxide", "once_cell", @@ -4054,12 +4138,12 @@ dependencies = [ "clap", "clap_complete", "clap_mangen", - "comemo", + "comemo 0.4.0", "elsa", "env_logger", "futures", "hyper", - "indexmap 2.2.5", + "indexmap 2.2.6", "log", "memmap2", "notify", @@ -4084,7 +4168,7 @@ version = "0.11.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#88608109579929b0c1fbab12d7a2afaea0baaf74" dependencies = [ "bytemuck", - "comemo", + "comemo 0.4.0", "flate2", "image", "pixglyph", @@ -4104,8 +4188,8 @@ version = "0.11.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#88608109579929b0c1fbab12d7a2afaea0baaf74" dependencies = [ "base64 0.22.0", - "comemo", - "ecow", + "comemo 0.4.0", + "ecow 0.2.2", "flate2", "ttf-parser", "typst", @@ -4115,13 +4199,46 @@ dependencies = [ "xmlwriter", ] +[[package]] +name = "typst-syntax" +version = "0.7.0" +source = "git+https://github.com/typst/typst.git?tag=v0.7.0#da8367e189b02918a8fe1a98fd3059fd11a82cd9" +dependencies = [ + "comemo 0.3.1", + "ecow 0.1.2", + "once_cell", + "serde", + "tracing", + "unicode-ident", + "unicode-math-class", + "unicode-segmentation", + "unscanny", +] + +[[package]] +name = "typst-syntax" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "367d86bf18f0363146bea1ea76fad19b54458695fdfad5e74ead3ede574b75fe" +dependencies = [ + "comemo 0.4.0", + "ecow 0.2.2", + "once_cell", + "serde", + "unicode-ident", + "unicode-math-class", + "unicode-script", + "unicode-segmentation", + "unscanny", +] + [[package]] name = "typst-syntax" version = "0.11.0" source = "git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0#88608109579929b0c1fbab12d7a2afaea0baaf74" dependencies = [ - "comemo", - "ecow", + "comemo 0.4.0", + "ecow 0.2.2", "once_cell", "serde", "unicode-ident", @@ -4139,7 +4256,7 @@ dependencies = [ "parking_lot", "serde", "serde_json", - "typst-syntax", + "typst-syntax 0.11.0 (git+https://github.com/Myriad-Dreamin/typst.git?branch=tinymist-v0.11.0)", ] [[package]] @@ -4152,14 +4269,14 @@ dependencies = [ "base64 0.22.0", "chrono", "codespan-reporting", - "comemo", + "comemo 0.4.0", "dirs", "dissimilar", "flate2", "fontdb", "fst", "hex", - "indexmap 2.2.5", + "indexmap 2.2.6", "instant", "log", "nohash-hasher", @@ -4191,10 +4308,10 @@ dependencies = [ "base64-serde", "bitvec", "byteorder", - "comemo", + "comemo 0.4.0", "crossbeam-queue", "dashmap", - "ecow", + "ecow 0.2.2", "elsa", "flate2", "fxhash", @@ -4211,7 +4328,7 @@ dependencies = [ "serde_repr", "serde_with", "sha2", - "siphasher 1.0.0", + "siphasher 1.0.1", "tiny-skia", "tiny-skia-path", "ttf-parser", @@ -4226,17 +4343,48 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6063f63c8e3ba3d4d7f4cb1a8fd96b096e8e713f24783278fea98dac0746966" dependencies = [ "base64 0.22.0", - "comemo", + "comemo 0.4.0", "log", "once_cell", "rayon", "reflexo", - "siphasher 1.0.0", + "siphasher 1.0.1", "tiny-skia", "typst", "typst-ts-core", ] +[[package]] +name = "typstfmt_lib" +version = "0.2.7" +source = "git+https://github.com/astrale-sharp/typstfmt?tag=0.2.7#46b4ec34b4726c3c6541012f433c68c22d9e509c" +dependencies = [ + "globmatch", + "itertools 0.10.5", + "regex", + "serde", + "toml 0.7.8", + "tracing", + "typst-syntax 0.7.0", + "unicode-segmentation", +] + +[[package]] +name = "typstyle" +version = "0.11.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffc3c575170689efd2c1c3362f051dadd80782f96f5f06ccda2a754b706d5cba" +dependencies = [ + "anyhow", + "clap", + "itertools 0.12.1", + "once_cell", + "pretty", + "typst-syntax 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "vergen", + "wasm-bindgen", +] + [[package]] name = "unic-langid" version = "0.9.4" @@ -4336,9 +4484,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "unscanny" @@ -4444,9 +4592,9 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" [[package]] name = "uuid" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" +checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" [[package]] name = "vcpkg" @@ -4531,7 +4679,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "wasm-bindgen-shared", ] @@ -4565,7 +4713,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -4816,6 +4964,15 @@ version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + [[package]] name = "winnow" version = "0.6.5" @@ -4908,7 +5065,7 @@ checksum = "9e6936f0cce458098a201c245a11bef556c6a0181129c7034d10d76d1ec3a2b8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "synstructure", ] @@ -4929,7 +5086,7 @@ checksum = "e6a647510471d372f2e6c2e6b7219e44d8c574d24fdc11c610a61455782f18c3" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", "synstructure", ] @@ -4965,5 +5122,5 @@ checksum = "7b4e5997cbf58990550ef1f0e5124a05e47e1ebd33a84af25739be6031a62c20" dependencies = [ "proc-macro2", "quote", - "syn 2.0.52", + "syn 2.0.55", ] diff --git a/Cargo.toml b/Cargo.toml index f0b42dc2..9ef2ec8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -53,15 +53,17 @@ reflexo = { version = "0.5.0-rc2", default-features = false, features = [ typst-ts-core = { version = "0.5.0-rc2", default-features = false } typst-ts-compiler = { version = "0.5.0-rc2" } typst-preview = { version = "0.11.3" } +typstyle = "0.11.4" +typstfmt_lib = { git = "https://github.com/astrale-sharp/typstfmt", tag = "0.2.7" } lsp-server = "0.7.6" lsp-types = { version = "=0.95.0", features = ["proposed"] } crossbeam-channel = "0.5.12" -clap = { version = "4.4", features = ["derive", "env", "unicode", "wrap_help"] } +clap = { version = "4.5", features = ["derive", "env", "unicode", "wrap_help"] } clap_builder = { version = "4", features = ["string"] } -clap_complete = "4.4" -clap_complete_fig = "4.4" +clap_complete = "4.5" +clap_complete_fig = "4.5" clap_mangen = { version = "0.2.15" } vergen = { version = "8.2.5", features = [ "build", diff --git a/crates/tinymist-query/src/lib.rs b/crates/tinymist-query/src/lib.rs index 1fed457a..18d4b0ac 100644 --- a/crates/tinymist-query/src/lib.rs +++ b/crates/tinymist-query/src/lib.rs @@ -109,6 +109,7 @@ pub trait StatefulRequest { #[allow(missing_docs)] mod polymorphic { + use lsp_types::TextEdit; use serde::{Deserialize, Serialize}; use super::prelude::*; @@ -150,6 +151,12 @@ mod polymorphic { pub path: PathBuf, } + #[derive(Debug, Clone)] + pub struct FormattingRequest { + /// The path of the document to get semantic tokens for. + pub path: PathBuf, + } + #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub enum FoldRequestFeature { PinnedFirst, @@ -176,6 +183,7 @@ mod polymorphic { Symbol(SymbolRequest), SemanticTokensFull(SemanticTokensFullRequest), SemanticTokensDelta(SemanticTokensDeltaRequest), + Formatting(FormattingRequest), FoldingRange(FoldingRangeRequest), SelectionRange(SelectionRangeRequest), } @@ -200,6 +208,7 @@ mod polymorphic { CompilerQueryRequest::Symbol(..) => Mergable, CompilerQueryRequest::SemanticTokensFull(..) => ContextFreeUnique, CompilerQueryRequest::SemanticTokensDelta(..) => ContextFreeUnique, + CompilerQueryRequest::Formatting(..) => ContextFreeUnique, CompilerQueryRequest::FoldingRange(..) => ContextFreeUnique, CompilerQueryRequest::SelectionRange(..) => ContextFreeUnique, } @@ -223,6 +232,7 @@ mod polymorphic { CompilerQueryRequest::Symbol(..) => return None, CompilerQueryRequest::SemanticTokensFull(req) => &req.path, CompilerQueryRequest::SemanticTokensDelta(req) => &req.path, + CompilerQueryRequest::Formatting(req) => &req.path, CompilerQueryRequest::FoldingRange(req) => &req.path, CompilerQueryRequest::SelectionRange(req) => &req.path, }) @@ -247,6 +257,7 @@ mod polymorphic { Symbol(Option>), SemanticTokensFull(Option), SemanticTokensDelta(Option), + Formatting(Option>), FoldingRange(Option>), SelectionRange(Option>), } diff --git a/crates/tinymist/Cargo.toml b/crates/tinymist/Cargo.toml index c5da76b8..6e7ba047 100644 --- a/crates/tinymist/Cargo.toml +++ b/crates/tinymist/Cargo.toml @@ -42,6 +42,9 @@ typst-render.workspace = true typst-timing.workspace = true typst-assets = { workspace = true, features = ["fonts"] } +typstyle.workspace = true +typstfmt_lib.workspace = true + typst-ts-core = { workspace = true, default-features = false, features = [ "flat-vector", "vector-bbox", diff --git a/crates/tinymist/src/actor.rs b/crates/tinymist/src/actor.rs index 918598ca..9b02852a 100644 --- a/crates/tinymist/src/actor.rs +++ b/crates/tinymist/src/actor.rs @@ -1,6 +1,7 @@ //! Bootstrap actors for Tinymist. pub mod cluster; +mod formatting; pub mod render; pub mod typ_client; pub mod typ_server; @@ -14,6 +15,7 @@ use typst_ts_compiler::{ use typst_ts_core::config::compiler::EntryState; use self::{ + formatting::run_format_thread, render::{ExportActor, ExportConfig}, typ_client::{CompileClientActor, CompileDriver, CompileHandler}, typ_server::CompileServerActor, @@ -24,6 +26,8 @@ use crate::{ TypstLanguageServer, }; +pub use formatting::{FormattingConfig, FormattingRequest}; + type CompileDriverInner = CompileDriverImpl; impl CompileServer { @@ -113,4 +117,20 @@ impl TypstLanguageServer { ) -> CompileClientActor { self.primary.server(diag_group, entry, inputs) } + + pub fn run_format_thread(&mut self) { + if self.format_thread.is_some() { + log::error!("formatting thread already started"); + return; + } + + let (tx_req, rx_req) = crossbeam_channel::unbounded(); + self.format_thread = Some(tx_req.clone()); + + let client = self.client.clone(); + let mode = self.config.formatter; + std::thread::spawn(move || { + run_format_thread(FormattingConfig { mode, width: 120 }, rx_req, client) + }); + } } diff --git a/crates/tinymist/src/actor/formatting.rs b/crates/tinymist/src/actor/formatting.rs new file mode 100644 index 00000000..c12fd374 --- /dev/null +++ b/crates/tinymist/src/actor/formatting.rs @@ -0,0 +1,91 @@ +use lsp_server::RequestId; +use lsp_types::{Position, Range, TextEdit}; +use typst::syntax::Source; + +use crate::{result_to_response_, FormatterMode, LspHost, LspResult, TypstLanguageServer}; + +#[derive(Debug, Clone)] +pub struct FormattingConfig { + pub mode: FormatterMode, + pub width: u32, +} + +pub enum FormattingRequest { + ChangeConfig(FormattingConfig), + Formatting((RequestId, Source)), +} + +pub fn run_format_thread( + init_c: FormattingConfig, + rx_req: crossbeam_channel::Receiver, + client: LspHost, +) { + type FmtFn = Box LspResult>>>; + let compile = |c: FormattingConfig| -> FmtFn { + log::info!("formatting thread with config: {c:#?}"); + match c.mode { + FormatterMode::Typstyle => { + let cw = c.width as usize; + let f: FmtFn = Box::new(move |e: Source| { + let res = typstyle_core::pretty_print(e.text(), cw); + Ok(Some(vec![TextEdit { + new_text: res, + range: Range::new( + Position { + line: 0, + character: 0, + }, + Position { + line: u32::MAX, + character: u32::MAX, + }, + ), + }])) + }); + f + } + FormatterMode::Typstfmt => { + let config = typstfmt_lib::Config { + max_line_length: 120, + ..typstfmt_lib::Config::default() + }; + let f: FmtFn = Box::new(move |e: Source| { + let res = typstfmt_lib::format(e.text(), config); + Ok(Some(vec![TextEdit { + new_text: res, + range: Range::new( + Position { + line: 0, + character: 0, + }, + Position { + line: u32::MAX, + character: u32::MAX, + }, + ), + }])) + }); + f + } + FormatterMode::Disable => { + let f: FmtFn = Box::new(|_| Ok(None)); + f + } + } + }; + + let mut f: FmtFn = compile(init_c); + while let Ok(req) = rx_req.recv() { + match req { + FormattingRequest::ChangeConfig(c) => f = compile(c), + FormattingRequest::Formatting((id, source)) => { + let res = f(source); + if let Ok(response) = result_to_response_(id, res) { + client.respond(response); + } + } + } + } + + log::info!("formatting thread did shut down"); +} diff --git a/crates/tinymist/src/server/lsp.rs b/crates/tinymist/src/server/lsp.rs index 8605a515..c70acd1e 100644 --- a/crates/tinymist/src/server/lsp.rs +++ b/crates/tinymist/src/server/lsp.rs @@ -37,7 +37,7 @@ use crossbeam_channel::select; use crossbeam_channel::Receiver; use futures::future::BoxFuture; use log::{error, info, trace, warn}; -use lsp_server::{ErrorCode, Message, Notification, Request, ResponseError}; +use lsp_server::{ErrorCode, Message, Notification, Request, RequestId, ResponseError}; use lsp_types::notification::Notification as NotificationTrait; use lsp_types::request::{GotoDeclarationParams, GotoDeclarationResponse, WorkspaceConfiguration}; use lsp_types::*; @@ -60,6 +60,7 @@ use typst_ts_core::{error::prelude::*, ImmutPath}; use super::lsp_init::*; use crate::actor::render::ExportConfig; use crate::actor::typ_client::CompileClientActor; +use crate::actor::{FormattingConfig, FormattingRequest}; use crate::compiler::{CompileServer, CompileServerArgs}; use crate::compiler_init::CompilerConstConfig; use crate::harness::{InitializedLspDriver, LspHost}; @@ -83,14 +84,20 @@ impl fmt::Display for Event { } } -struct Cancelled; +pub(crate) struct Cancelled; type LspMethod = fn(srv: &mut TypstLanguageServer, args: JsonValue) -> LspResult; type LspHandler = fn(srv: &mut TypstLanguageServer, args: Req) -> LspResult; +/// Returns Ok(Some()) -> Already responded +/// Returns Ok(None) -> Need to respond none +/// Returns Err(..) -> Need t o respond error +type LspRawHandler = + fn(srv: &mut TypstLanguageServer, args: (RequestId, JsonValue)) -> LspResult>; + type ExecuteCmdMap = HashMap<&'static str, LspHandler, JsonValue>>; type NotifyCmdMap = HashMap<&'static str, LspMethod<()>>; -type RegularCmdMap = HashMap<&'static str, LspMethod>; +type RegularCmdMap = HashMap<&'static str, LspRawHandler>; macro_rules! exec_fn { ($ty: ty, Self::$method: ident, $($arg_key:ident),+ $(,)?) => {{ @@ -99,15 +106,44 @@ macro_rules! exec_fn { }}; } +macro_rules! request_fn_ { + ($desc: ty, Self::$method: ident) => { + (<$desc>::METHOD, { + const E: LspRawHandler = |this, (req_id, req)| { + let req: <$desc as lsp_types::request::Request>::Params = + serde_json::from_value(req).unwrap(); // todo: soft unwrap + this.$method(req_id, req) + }; + E + }) + }; +} + macro_rules! request_fn { ($desc: ty, Self::$method: ident) => { (<$desc>::METHOD, { - const E: LspMethod = |this, req| { + const E: LspRawHandler = |this, (req_id, req)| { let req: <$desc as lsp_types::request::Request>::Params = serde_json::from_value(req).unwrap(); // todo: soft unwrap - let res = this.$method(req)?; - let res = serde_json::to_value(res).unwrap(); // todo: soft unwrap - Ok(res) + let res = this + .$method(req) + .map(|res| serde_json::to_value(res).unwrap()); // todo: soft unwrap + + if let Ok(response) = result_to_response(req_id, res) { + this.client.respond(response); + } + + // todo: cancellation + // Err(e) => match e.downcast::() { + // Ok(cancelled) => return Err(cancelled), + // Err(e) => lsp_server::Response::new_err( + // id, + // lsp_server::ErrorCode::InternalError as i32, + // e.to_string(), + // ), + // }, + + Ok(Some(())) }; E }) @@ -152,6 +188,7 @@ pub struct TypstLanguageServer { /// Whether the server is shutting down. pub shutdown_requested: bool, pub sema_tokens_registered: Option, + pub formatter_registered: Option, // Configurations /// User configuration from the editor. @@ -175,6 +212,7 @@ pub struct TypstLanguageServer { pub primary: CompileServer, pub main: Option, pub tokens_ctx: SemanticTokenContext, + pub format_thread: Option>, } /// Getters and the main loop. @@ -200,6 +238,7 @@ impl TypstLanguageServer { }), shutdown_requested: false, sema_tokens_registered: None, + formatter_registered: None, config: Default::default(), const_config: args.const_config, compile_opts: args.compile_opts, @@ -212,6 +251,7 @@ impl TypstLanguageServer { pinning: false, main: None, tokens_ctx, + format_thread: None, } } @@ -238,6 +278,7 @@ impl TypstLanguageServer { request_fn!(SemanticTokensFullDeltaRequest, Self::semantic_tokens_full_delta), request_fn!(DocumentSymbolRequest, Self::document_symbol), // Sync for low latency + request_fn_!(Formatting, Self::formatting), request_fn!(SelectionRangeRequest, Self::selection_range), // latency insensitive request_fn!(InlayHintRequest, Self::inlay_hint), @@ -287,6 +328,15 @@ impl InitializedLspDriver for TypstLanguageServer { } } + if self.const_config().doc_fmt_dynamic_registration + && self.config.formatter != FormatterMode::Disable + { + let err = self.react_formatter_changes(true); + if let Err(err) = err { + error!("could not register formatter for initialization: {err}"); + } + } + if self.const_config().cfg_change_registration { trace!("setting up to request config change notifications"); @@ -394,30 +444,13 @@ impl TypstLanguageServer { return; }; - let result = handler(self, req.params); - - if let Ok(response) = result_to_response(req.id, result) { - self.client.respond(response); + let res = handler(self, (req.id.clone(), req.params)); + if matches!(res, Ok(Some(()))) { + return; } - // todo: cancellation - // Err(e) => match e.downcast::() { - // Ok(cancelled) => return Err(cancelled), - // Err(e) => lsp_server::Response::new_err( - // id, - // lsp_server::ErrorCode::InternalError as i32, - // e.to_string(), - // ), - // }, - fn result_to_response( - id: lsp_server::RequestId, - result: Result, - ) -> Result { - let res = match result { - Ok(resp) => lsp_server::Response::new_ok(id, resp), - Err(e) => lsp_server::Response::new_err(id, e.code, e.message), - }; - Ok(res) + if let Ok(response) = result_to_response_(req.id, res) { + self.client.respond(response); } } @@ -481,6 +514,53 @@ impl TypstLanguageServer { res } + + fn react_formatter_changes(&mut self, enable: bool) -> anyhow::Result<()> { + if !self.const_config().doc_fmt_dynamic_registration { + trace!("skip dynamic register formatter by config"); + return Ok(()); + } + + const FORMATTING_REGISTRATION_ID: &str = "formatting"; + const DOCUMENT_FORMATTING_METHOD_ID: &str = "textDocument/formatting"; + + pub fn get_formatting_registration() -> Registration { + Registration { + id: FORMATTING_REGISTRATION_ID.to_owned(), + method: DOCUMENT_FORMATTING_METHOD_ID.to_owned(), + register_options: None, + } + } + + pub fn get_formatting_unregistration() -> Unregistration { + Unregistration { + id: FORMATTING_REGISTRATION_ID.to_owned(), + method: DOCUMENT_FORMATTING_METHOD_ID.to_owned(), + } + } + + let res = match (enable, self.formatter_registered) { + (true, None | Some(false)) => { + trace!("registering formatter"); + self.client + .register_capability(vec![get_formatting_registration()]) + .context("could not register formatter") + } + (false, Some(true)) => { + trace!("unregistering formatter"); + self.client + .unregister_capability(vec![get_formatting_unregistration()]) + .context("could not unregister formatter") + } + (true, Some(true)) | (false, None | Some(false)) => Ok(()), + }; + + if res.is_ok() { + self.formatter_registered = Some(enable); + } + + res + } } /// Trait implemented by language server backends. @@ -823,6 +903,22 @@ impl TypstLanguageServer { } } + if config.formatter != self.config.formatter { + let err = self.react_formatter_changes(self.config.formatter != FormatterMode::Disable); + if let Err(err) = err { + error!("could not change formatter config: {err}"); + } + if let Some(f) = &self.format_thread { + let err = f.send(FormattingRequest::ChangeConfig(FormattingConfig { + mode: self.config.formatter, + width: 120, + })); + if let Err(err) = err { + error!("could not change formatter config: {err}"); + } + } + } + // todo: watch changes of the root path Ok(()) @@ -929,6 +1025,26 @@ impl TypstLanguageServer { run_query!(self.SemanticTokensDelta(path, previous_result_id)) } + fn formatting( + &self, + req_id: RequestId, + params: DocumentFormattingParams, + ) -> LspResult> { + if matches!(self.config.formatter, FormatterMode::Disable) { + return Ok(None); + } + + let path = as_path(params.text_document); + self.query_source(&path, |source| { + if let Some(f) = &self.format_thread { + f.send(FormattingRequest::Formatting((req_id, source.clone())))?; + } + + Ok(Some(())) + }) + .map_err(|e| internal_error(format!("could not format document: {e}"))) + } + fn inlay_hint(&self, params: InlayHintParams) -> LspResult>> { let path = as_path(params.text_document); let range = params.range; @@ -998,3 +1114,31 @@ pub fn method_not_found() -> ResponseError { data: None, } } + +pub(crate) fn result_to_response_( + id: lsp_server::RequestId, + result: Result, +) -> Result { + let res = match result { + Ok(resp) => { + let resp = serde_json::to_value(resp); + match resp { + Ok(resp) => lsp_server::Response::new_ok(id, resp), + Err(e) => return result_to_response(id, Err(internal_error(e.to_string()))), + } + } + Err(e) => lsp_server::Response::new_err(id, e.code, e.message), + }; + Ok(res) +} + +fn result_to_response( + id: lsp_server::RequestId, + result: Result, +) -> Result { + let res = match result { + Ok(resp) => lsp_server::Response::new_ok(id, resp), + Err(e) => lsp_server::Response::new_err(id, e.code, e.message), + }; + Ok(res) +} diff --git a/crates/tinymist/src/server/lsp_init.rs b/crates/tinymist/src/server/lsp_init.rs index 1a99c929..070bcc0c 100644 --- a/crates/tinymist/src/server/lsp_init.rs +++ b/crates/tinymist/src/server/lsp_init.rs @@ -24,15 +24,17 @@ use crate::{ // LocationLink[] even if the client does not report the // textDocument.definition.linkSupport capability. -/// The mode of the experimental formatter. +/// The mode of the formatter. #[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Deserialize)] #[serde(rename_all = "camelCase")] -pub enum ExperimentalFormatterMode { - /// Disable the experimental formatter. +pub enum FormatterMode { + /// Disable the formatter. #[default] Disable, - /// Enable the experimental formatter. - Enable, + /// Use `typstyle` formatter. + Typstyle, + /// Use `typstfmt` formatter. + Typstfmt, } /// The mode of PDF/SVG/PNG export. @@ -83,7 +85,7 @@ const CONFIG_ITEMS: &[&str] = &[ "exportPdf", "rootPath", "semanticTokens", - "experimentalFormatterMode", + "formatterMode", "typstExtraArgs", ]; @@ -95,7 +97,7 @@ pub struct Config { /// Dynamic configuration for semantic tokens. pub semantic_tokens: SemanticTokensMode, /// Dynamic configuration for the experimental formatter. - pub formatter: ExperimentalFormatterMode, + pub formatter: FormatterMode, } impl Config { @@ -153,8 +155,8 @@ impl Config { } let formatter = update - .get("experimentalFormatterMode") - .map(ExperimentalFormatterMode::deserialize) + .get("formatterMode") + .map(FormatterMode::deserialize) .and_then(Result::ok); if let Some(formatter) = formatter { self.formatter = formatter; @@ -354,6 +356,8 @@ impl Init { service.primary.config = config.compile.clone(); service.config = config; + service.run_format_thread(); + let cluster_actor = CompileClusterActor { host: self.host.clone(), diag_rx, @@ -383,8 +387,11 @@ impl Init { _ => None, }; + // if !cc.doc_fmt_dynamic_registration let document_formatting_provider = match service.config.formatter { - ExperimentalFormatterMode::Enable if !cc.doc_fmt_dynamic_registration => { + FormatterMode::Typstyle | FormatterMode::Typstfmt + if !cc.doc_fmt_dynamic_registration => + { Some(OneOf::Left(true)) } _ => None, @@ -480,7 +487,7 @@ mod tests { "exportPdf": "onSave", "rootPath": root_path, "semanticTokens": "enable", - "experimentalFormatterMode": "enable", + "formatterMode": "typstyle", "typstExtraArgs": ["--root", root_path] }); @@ -490,7 +497,7 @@ mod tests { assert_eq!(config.compile.export_pdf, ExportMode::OnSave); assert_eq!(config.compile.root_path, Some(PathBuf::from(root_path))); assert_eq!(config.semantic_tokens, SemanticTokensMode::Enable); - assert_eq!(config.formatter, ExperimentalFormatterMode::Enable); + assert_eq!(config.formatter, FormatterMode::Typstyle); assert_eq!( config.compile.typst_extra_args, Some(CompileExtraOpts { diff --git a/crates/tinymist/src/state.rs b/crates/tinymist/src/state.rs index 42057c0a..f5e20852 100644 --- a/crates/tinymist/src/state.rs +++ b/crates/tinymist/src/state.rs @@ -1,6 +1,6 @@ //! Bootstrap actors for Tinymist. -use std::path::PathBuf; +use std::path::{Path, PathBuf}; use ::typst::{diag::FileResult, syntax::Source}; use anyhow::anyhow; @@ -162,16 +162,13 @@ macro_rules! run_query { } macro_rules! query_source { - ($self:ident, $method:ident, $req:expr) => {{ - let path: ImmutPath = $req.path.clone().into(); - let snapshot = $self.memory_changes.get(&path); - let snapshot = snapshot.ok_or_else(|| anyhow!("file missing {:?}", path))?; - let source = snapshot.content.clone(); - - let enc = $self.const_config.position_encoding; - let res = $req.request(&source, enc); - Ok(CompilerQueryResponse::$method(res)) - }}; + ($self:ident, $method:ident, $req:expr) => { + $self.query_source(&$req.path.clone(), |source| { + let enc = $self.const_config.position_encoding; + let res = $req.request(&source, enc); + Ok(CompilerQueryResponse::$method(res)) + }) + }; } macro_rules! query_tokens_cache { @@ -201,6 +198,18 @@ macro_rules! query_world { } impl TypstLanguageServer { + pub fn query_source( + &self, + p: &Path, + f: impl FnOnce(Source) -> anyhow::Result, + ) -> anyhow::Result { + let path: ImmutPath = p.into(); + let snapshot = self.memory_changes.get(&path); + let snapshot = snapshot.ok_or_else(|| anyhow!("file missing {:?}", path))?; + let source = snapshot.content.clone(); + f(source) + } + pub fn query(&self, query: CompilerQueryRequest) -> anyhow::Result { use CompilerQueryRequest::*; @@ -254,6 +263,7 @@ impl TypstLanguageServer { FoldingRange(..) | SelectionRange(..) | SemanticTokensDelta(..) + | Formatting(..) | DocumentSymbol(..) | SemanticTokensFull(..) => unreachable!(), } diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 3b0264a3..4167264f 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -121,18 +121,20 @@ "default": "off", "description": "Traces the communication between VS Code and the language server." }, - "tinymist.experimentalFormatterMode": { + "tinymist.formatterMode": { "title": "Enable Experimental Formatter", - "description": "The extension can format Typst files using typstfmt (experimental).", + "description": "The extension can format Typst files using typstfmt or typstyle.", "type": "string", "default": "disable", "enum": [ "disable", - "enable" + "typstyle", + "typstfmt" ], "enumDescriptions": [ "Formatter is not activated.", - "Experimental formatter is activated." + "Use typstyle formatter.", + "Use typstfmt formatter." ] } }