diff --git a/Cargo.lock b/Cargo.lock index bd068f8..14d8452 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,18 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "adler2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" + [[package]] name = "aho-corasick" version = "1.1.4" @@ -11,6 +23,30 @@ dependencies = [ "memchr", ] +[[package]] +name = "aligned" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" +dependencies = [ + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", +] + +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "0.6.21" @@ -67,6 +103,23 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" + +[[package]] +name = "arg_enum_proc_macro" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "arrayvec" version = "0.7.6" @@ -74,12 +127,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] -name = "atomic" -version = "0.6.1" +name = "as-slice" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" dependencies = [ - "bytemuck", + "stable_deref_trait", ] [[package]] @@ -88,6 +141,49 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "av-scenechange" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" +dependencies = [ + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.17", + "v_frame", + "y4m", +] + +[[package]] +name = "av1-grain" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" +dependencies = [ + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", +] + +[[package]] +name = "avif-serialize" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "375082f007bd67184fb9c0374614b29f9aaa604ec301635f72338bb65386a53d" +dependencies = [ + "arrayvec", +] + [[package]] name = "base64" version = "0.22.1" @@ -96,18 +192,24 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bit-set" -version = "0.5.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" +checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3" dependencies = [ "bit-vec", ] [[package]] name = "bit-vec" -version = "0.6.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" +checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7" + +[[package]] +name = "bit_field" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" [[package]] name = "bitflags" @@ -121,6 +223,15 @@ version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" +[[package]] +name = "bitstream-io" +version = "4.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" +dependencies = [ + "no_std_io2", +] + [[package]] name = "block-buffer" version = "0.10.4" @@ -130,6 +241,12 @@ dependencies = [ "generic-array", ] +[[package]] +name = "built" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4ad8f11f288f48ca24471bbd51ac257aaeaaa07adae295591266b792902ae64" + [[package]] name = "bumpalo" version = "3.19.1" @@ -142,6 +259,24 @@ version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fbdf580320f38b612e485521afda1ee26d10cc9884efaaa750d383e13e3c5f4" +[[package]] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" + +[[package]] +name = "cc" +version = "1.2.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d16d90359e986641506914ba71350897565610e87ce0ad9e6f28569db3dd5c6d" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + [[package]] name = "cfg-if" version = "1.0.4" @@ -209,9 +344,15 @@ dependencies = [ "serde", "termwiz", "toml", - "vt100", + "wezterm-term", ] +[[package]] +name = "color_quant" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" + [[package]] name = "colorchoice" version = "1.0.4" @@ -227,6 +368,46 @@ dependencies = [ "libc", ] +[[package]] +name = "crc32fast" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + +[[package]] +name = "crunchy" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" + [[package]] name = "crypto-common" version = "0.1.7" @@ -284,6 +465,29 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "downcast-rs" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "either" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" + [[package]] name = "env_filter" version = "0.1.4" @@ -307,6 +511,26 @@ dependencies = [ "log", ] +[[package]] +name = "equator" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" +dependencies = [ + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "equivalent" version = "1.0.2" @@ -333,20 +557,50 @@ dependencies = [ ] [[package]] -name = "fancy-regex" -version = "0.11.0" +name = "exr" +version = "1.74.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b95f7c0680e4142284cf8b22c14a476e87d61b004a3a0861872b32ef7ead40a2" +checksum = "4300e043a56aa2cb633c01af81ca8f699a321879a7854d3896a0ba89056363be" +dependencies = [ + "bit_field", + "half", + "lebe", + "miniz_oxide 0.8.9", + "rayon-core", + "smallvec", + "zune-inflate", +] + +[[package]] +name = "fancy-regex" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" dependencies = [ "bit-set", - "regex", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + +[[package]] +name = "fdeflate" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" +dependencies = [ + "simd-adler32", ] [[package]] name = "filedescriptor" version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e40758ed24c9b2eeb76c35fb0aebc66c626084edd827e07e1552279814c6682d" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "libc", "thiserror 1.0.69", @@ -354,10 +608,15 @@ dependencies = [ ] [[package]] -name = "finl_unicode" -version = "1.4.0" +name = "find-msvc-tools" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9844ddc3a6e533d62bba727eb6c28b5d360921d5175e9ff0f1e621a5c590a4d5" +checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" + +[[package]] +name = "finl_unicode" +version = "1.3.0" +source = "git+https://github.com/wez/finl_unicode.git?branch=no_std#a1892f26245529f2ef3877a9ebd610c96cec07a6" [[package]] name = "fixedbitset" @@ -365,12 +624,37 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "flate2" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c" +dependencies = [ + "crc32fast", + "miniz_oxide 0.8.9", +] + [[package]] name = "fnv" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + +[[package]] +name = "form_urlencoded" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf" +dependencies = [ + "percent-encoding", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -404,11 +688,37 @@ dependencies = [ "wasip2", ] +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "half" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" +dependencies = [ + "cfg-if", + "crunchy", + "zerocopy", +] + [[package]] name = "hashbrown" version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "heck" @@ -422,6 +732,157 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "humansize" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb51c9a029ddc91b07a787f1d86b53ccfa49b0e86688c946ebe8d3555685dd7" +dependencies = [ + "libm", +] + +[[package]] +name = "icu_collections" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c6b649701667bbe825c3b7e6388cb521c23d88644678e83c0c4d0a621a34b43" +dependencies = [ + "displaydoc", + "potential_utf", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locale_core" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edba7861004dd3714265b4db54a3c390e880ab658fec5f7db895fae2046b5bb6" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_normalizer" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f6c8828b67bf8908d82127b2054ea1b4427ff0230ee9141c54251934ab1b599" +dependencies = [ + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7aedcccd01fc5fe81e6b489c15b247b8b0690feb23304303a9e560f37efc560a" + +[[package]] +name = "icu_properties" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "020bfc02fe870ec3a66d93e677ccca0562506e5872c650f893269e08615d74ec" +dependencies = [ + "icu_collections", + "icu_locale_core", + "icu_properties_data", + "icu_provider", + "zerotrie", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "616c294cf8d725c6afcd8f55abc17c56464ef6211f9ed59cccffe534129c77af" + +[[package]] +name = "icu_provider" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85962cf0ce02e1e0a629cc34e7ca3e373ce20dda4c4d7294bbd0bf1fdb59e614" +dependencies = [ + "displaydoc", + "icu_locale_core", + "writeable", + "yoke", + "zerofrom", + "zerotrie", + "zerovec", +] + +[[package]] +name = "idna" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +dependencies = [ + "icu_normalizer", + "icu_properties", +] + +[[package]] +name = "image" +version = "0.25.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" +dependencies = [ + "bytemuck", + "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", + "moxcms", + "num-traits", + "png", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", +] + +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40fac9d56ed6437b198fddba683305e8e2d651aa42647f00f5ae542e7f5c94a2" + [[package]] name = "indexmap" version = "2.13.0" @@ -432,6 +893,17 @@ dependencies = [ "hashbrown", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -439,10 +911,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" [[package]] -name = "itoa" -version = "1.0.17" +name = "itertools" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +dependencies = [ + "either", +] [[package]] name = "jiff" @@ -468,6 +943,16 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.85" @@ -490,12 +975,34 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +[[package]] +name = "lebe" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" + [[package]] name = "libc" version = "0.2.177" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976" +[[package]] +name = "libfuzzer-sys" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f12a681b7dd8ce12bff52488013ba614b869148d54dd79836ab85aafdd53f08d" +dependencies = [ + "arbitrary", + "cc", +] + +[[package]] +name = "libm" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d2cec3eae94f9f509c767b45932f1ada8350c4bdb85af2fcab4a3c14807981" + [[package]] name = "libredox" version = "0.1.12" @@ -506,6 +1013,12 @@ dependencies = [ "libc", ] +[[package]] +name = "litemap" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" + [[package]] name = "log" version = "0.4.29" @@ -513,13 +1026,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" [[package]] -name = "mac_address" -version = "1.1.8" +name = "loop9" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0aeb26bf5e836cc1c341c8106051b573f1766dfa05aa87f0b98be5e51b02303" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "nix 0.29.0", - "winapi", + "imgref", +] + +[[package]] +name = "lru" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f66e8d5d03f609abc3a39e6f08e4164ebf1447a732906d39eb9b99b7919ef39" +dependencies = [ + "hashbrown", +] + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", ] [[package]] @@ -534,21 +1065,47 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a64a92489e2744ce060c349162be1c5f33c6969234104dbd99ddb5feb08b8c15" -[[package]] -name = "memoffset" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] - [[package]] name = "minimal-lexical" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" +[[package]] +name = "miniz_oxide" +version = "0.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +dependencies = [ + "adler", +] + +[[package]] +name = "miniz_oxide" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +dependencies = [ + "adler2", + "simd-adler32", +] + +[[package]] +name = "moxcms" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb85c154ba489f01b25c0d36ae69a87e4a1c73a72631fc6c0eb6dde34a73e44b" +dependencies = [ + "num-traits", + "pxfm", +] + +[[package]] +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + [[package]] name = "nix" version = "0.29.0" @@ -559,7 +1116,6 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", - "memoffset", ] [[package]] @@ -574,6 +1130,15 @@ dependencies = [ "libc", ] +[[package]] +name = "no_std_io2" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b51ed7824b6e07d354605f4abb3d9d300350701299da96642ee084f5ce631550" +dependencies = [ + "memchr", +] + [[package]] name = "nom" version = "7.1.3" @@ -584,6 +1149,31 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "nom" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df9761775871bdef83bee530e60050f7e54b1105350d6884eb0fb4f46c2f9405" +dependencies = [ + "memchr", +] + +[[package]] +name = "noop_proc_macro" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" + +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + [[package]] name = "num-derive" version = "0.4.2" @@ -595,6 +1185,26 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -602,6 +1212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -631,6 +1242,24 @@ dependencies = [ "num-traits", ] +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" + +[[package]] +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + [[package]] name = "pest" version = "2.8.5" @@ -701,7 +1330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" dependencies = [ "phf_shared", - "rand", + "rand 0.8.5", ] [[package]] @@ -726,6 +1355,19 @@ dependencies = [ "siphasher", ] +[[package]] +name = "png" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60769b8b31b2a9f263dae2776c37b1b28ae246943cf719eb6946a1db05128a61" +dependencies = [ + "bitflags 2.10.0", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] + [[package]] name = "portable-atomic" version = "1.13.0" @@ -741,6 +1383,24 @@ dependencies = [ "portable-atomic", ] +[[package]] +name = "potential_utf" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b73949432f5e2a09657003c25bca5e19a0e9c84f8058ca374f49e0ebe605af77" +dependencies = [ + "zerovec", +] + +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro2" version = "1.0.105" @@ -750,6 +1410,25 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3eb8486b569e12e2c32ad3e204dbaba5e4b5b216e9367044f25f1dba42341773" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52717f9a02b6965224f95ca2a81e2e0c5c43baacd28ca057577988930b6c3d5b" +dependencies = [ + "quote", + "syn 2.0.114", +] + [[package]] name = "pty-mock" version = "0.1.4" @@ -757,6 +1436,27 @@ dependencies = [ "clap", ] +[[package]] +name = "pxfm" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c5ccf5294c6ccd63a74f1565028353830a9c2f5eb0c682c355c471726a6e3f" + +[[package]] +name = "qoi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" +dependencies = [ + "bytemuck", +] + +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quote" version = "1.0.43" @@ -778,7 +1478,27 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "rand_core", + "rand_core 0.6.4", +] + +[[package]] +name = "rand" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c5af06bb1b7d3216d91932aed5265164bf384dc89cd6ba05cf59a35f5f76ea" +dependencies = [ + "rand_chacha", + "rand_core 0.9.5", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core 0.9.5", ] [[package]] @@ -787,6 +1507,85 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "rand_core" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.4", + "rand_chacha", + "simd_helpers", + "thiserror 2.0.17", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "rayon" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" +dependencies = [ + "either", + "rayon-core", +] + +[[package]] +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + [[package]] name = "redox_users" version = "0.5.2" @@ -827,6 +1626,12 @@ version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "rustversion" version = "1.0.22" @@ -883,6 +1688,12 @@ dependencies = [ "digest", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.18" @@ -903,12 +1714,39 @@ dependencies = [ "libc", ] +[[package]] +name = "simd-adler32" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "703d5c7ef118737c72f1af64ad2f6f8c5e1921f818cdcb97b8fe6fc69bf66214" + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + [[package]] name = "siphasher" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" +[[package]] +name = "smallvec" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" + +[[package]] +name = "stable_deref_trait" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" + [[package]] name = "strsim" version = "0.11.1" @@ -937,6 +1775,17 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "synstructure" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + [[package]] name = "terminfo" version = "0.9.0" @@ -944,7 +1793,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4ea810f0692f9f51b382fff5893887bb4580f5fa246fde546e0b13e7fcee662" dependencies = [ "fnv", - "nom", + "nom 7.1.3", "phf", "phf_codegen", ] @@ -960,19 +1809,16 @@ dependencies = [ [[package]] name = "termwiz" -version = "0.23.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4676b37242ccbd1aabf56edb093a4827dc49086c0ffd764a5705899e0f35f8f7" +version = "0.24.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "anyhow", - "base64", "bitflags 2.10.0", "fancy-regex", "filedescriptor", "finl_unicode", "fixedbitset", - "hex", - "lazy_static", + "image", "libc", "log", "memmem", @@ -994,9 +1840,13 @@ dependencies = [ "vtparse", "wezterm-bidi", "wezterm-blob-leases", + "wezterm-cell", + "wezterm-char-props", "wezterm-color-types", "wezterm-dynamic", + "wezterm-escape-parser", "wezterm-input-types", + "wezterm-surface", "winapi", ] @@ -1040,6 +1890,45 @@ dependencies = [ "syn 2.0.114", ] +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + +[[package]] +name = "tinystr" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42d3e9c45c09de15d06dd8acf5f4e0e399e85927b7f00711024eb7ae10fa4869" +dependencies = [ + "displaydoc", + "zerovec", +] + +[[package]] +name = "tinyvec" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e61e67053d25a4e82c844e8424039d9745781b3fc4f32b8d55ed50f5f667ef3" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "toml" version = "0.8.23" @@ -1099,6 +1988,15 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" +[[package]] +name = "unicode-normalization" +version = "0.1.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5fd4f6878c9cb28d874b009da9e8d183b5abc80117c40bbd187a1fde336be6e8" +dependencies = [ + "tinyvec", +] + [[package]] name = "unicode-segmentation" version = "1.12.0" @@ -1106,10 +2004,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] -name = "unicode-width" -version = "0.2.2" +name = "url" +version = "2.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" +checksum = "ff67a8a4397373c3ef660812acab3268222035010ab8680ec4215f38ba3d0eed" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", + "serde", +] + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "utf8parse" @@ -1123,44 +2033,32 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee48d38b119b0cd71fe4141b30f5ba9c7c5d9f4e7a3a8b4a674e4b6ef789976f" dependencies = [ - "atomic", "getrandom 0.3.4", "js-sys", "wasm-bindgen", ] +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", + "wasm-bindgen", +] + [[package]] name = "version_check" version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" -[[package]] -name = "vt100" -version = "0.16.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054ff75fb8fa83e609e685106df4faeffdf3a735d3c74ebce97ec557d5d36fd9" -dependencies = [ - "itoa", - "unicode-width", - "vte", -] - -[[package]] -name = "vte" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd" -dependencies = [ - "arrayvec", - "memchr", -] - [[package]] name = "vtparse" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9b2acfb050df409c972a37d3b8e08cdea3bddb0c09db9d53137e504cfabed0" +version = "0.7.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "utf8parse", ] @@ -1225,11 +2123,16 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + [[package]] name = "wezterm-bidi" version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c0a6e355560527dd2d1cf7890652f4f09bb3433b6aadade4c9b5ed76de5f3ec" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "log", "wezterm-dynamic", @@ -1238,65 +2141,166 @@ dependencies = [ [[package]] name = "wezterm-blob-leases" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692daff6d93d94e29e4114544ef6d5c942a7ed998b37abdc19b17136ea428eb7" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "getrandom 0.3.4", - "mac_address", "sha2", "thiserror 1.0.69", "uuid", ] +[[package]] +name = "wezterm-cell" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" +dependencies = [ + "finl_unicode", + "image", + "log", + "ordered-float", + "serde", + "sha2", + "thiserror 1.0.69", + "wezterm-blob-leases", + "wezterm-char-props", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-escape-parser", +] + +[[package]] +name = "wezterm-char-props" +version = "0.1.3" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" +dependencies = [ + "phf", + "serde", + "ucd-trie", +] + [[package]] name = "wezterm-color-types" version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de81ef35c9010270d63772bebef2f2d6d1f2d20a983d27505ac850b8c4b4296" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "csscolorparser", "deltae", - "lazy_static", + "num-traits", + "serde", "wezterm-dynamic", ] [[package]] name = "wezterm-dynamic" version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f2ab60e120fd6eaa68d9567f3226e876684639d22a4219b313ff69ec0ccd5ac" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "log", "ordered-float", "strsim", - "thiserror 1.0.69", + "thiserror 2.0.17", "wezterm-dynamic-derive", ] [[package]] name = "wezterm-dynamic-derive" version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c0cf2d539c645b448eaffec9ec494b8b19bd5077d9e58cb1ae7efece8d575b" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "proc-macro2", "quote", "syn 1.0.109", ] +[[package]] +name = "wezterm-escape-parser" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" +dependencies = [ + "base64", + "bitflags 2.10.0", + "hex", + "image", + "log", + "nix 0.29.0", + "num-derive", + "num-traits", + "ordered-float", + "pest", + "pest_derive", + "sha2", + "thiserror 2.0.17", + "vtparse", + "wezterm-blob-leases", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-input-types", + "winapi", +] + [[package]] name = "wezterm-input-types" version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7012add459f951456ec9d6c7e6fc340b1ce15d6fc9629f8c42853412c029e57e" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" dependencies = [ "bitflags 1.3.2", "euclid", - "lazy_static", "serde", "wezterm-dynamic", ] +[[package]] +name = "wezterm-surface" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" +dependencies = [ + "bitflags 2.10.0", + "fancy-regex", + "finl_unicode", + "fixedbitset", + "ordered-float", + "siphasher", + "unicode-segmentation", + "wezterm-bidi", + "wezterm-cell", + "wezterm-char-props", + "wezterm-color-types", + "wezterm-dynamic", + "wezterm-escape-parser", + "wezterm-input-types", +] + +[[package]] +name = "wezterm-term" +version = "0.1.0" +source = "git+https://github.com/wezterm/wezterm?rev=577474d89ee61aef4a48145cdec82a638d874751#577474d89ee61aef4a48145cdec82a638d874751" +dependencies = [ + "anyhow", + "bitflags 1.3.2", + "csscolorparser", + "downcast-rs", + "finl_unicode", + "hex", + "humansize", + "image", + "lazy_static", + "log", + "lru", + "miniz_oxide 0.7.4", + "num-traits", + "ordered-float", + "serde", + "terminfo", + "termwiz", + "unicode-normalization", + "url", + "wezterm-bidi", + "wezterm-cell", + "wezterm-dynamic", + "wezterm-escape-parser", + "wezterm-surface", +] + [[package]] name = "winapi" version = "0.3.9" @@ -1348,3 +2352,136 @@ name = "wit-bindgen" version = "0.51.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7249219f66ced02969388cf2bb044a09756a083d0fab1e566056b04d9fbcaa5" + +[[package]] +name = "writeable" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" + +[[package]] +name = "y4m" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" + +[[package]] +name = "yoke" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72d6e5c6afb84d73944e5cedb052c4680d5657337201555f9f2a16b7406d4954" +dependencies = [ + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b659052874eb698efe5b9e8cf382204678a0086ebf46982b79d6ca3182927e5d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", + "synstructure", +] + +[[package]] +name = "zerocopy" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eed437bf9d6692032087e337407a86f04cd8d6a16a37199ed57949d415bd68e9" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70e3cd084b1788766f53af483dd21f93881ff30d7320490ec3ef7526d203bad4" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "zerofrom" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69faa1f2a1ea75661980b013019ed6687ed0e83d069bc1114e2cc74c6c04c4df" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", + "synstructure", +] + +[[package]] +name = "zerotrie" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a59c17a5562d507e4b54960e8569ebee33bee890c70aa3fe7b97e85a9fd7851" +dependencies = [ + "displaydoc", + "yoke", + "zerofrom", +] + +[[package]] +name = "zerovec" +version = "0.11.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c28719294829477f525be0186d13efa9a3c602f7ec202ca9e353d310fb9a002" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eadce39539ca5cb3985590102671f2567e659fca9666581ad3411d59207951f3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.114", +] + +[[package]] +name = "zune-core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb8a0807f7c01457d0379ba880ba6322660448ddebc890ce29bb64da71fb40f9" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/crates/claude-chill/Cargo.toml b/crates/claude-chill/Cargo.toml index 376cf37..ac147d7 100644 --- a/crates/claude-chill/Cargo.toml +++ b/crates/claude-chill/Cargo.toml @@ -25,7 +25,7 @@ nix = { version = "0.30", features = ["term", "signal", "poll", "process", "fs"] libc = "0.2" serde = { version = "1", features = ["derive"] } toml = "0.8" -vt100 = "0.16" -termwiz = "0.23" +termwiz = { git = "https://github.com/wezterm/wezterm", rev = "577474d89ee61aef4a48145cdec82a638d874751" } +wezterm-term = { git = "https://github.com/wezterm/wezterm", rev = "577474d89ee61aef4a48145cdec82a638d874751" } log = "0.4" env_logger = "0.11" diff --git a/crates/claude-chill/src/color_preservation_tests.rs b/crates/claude-chill/src/color_preservation_tests.rs index 6fed42a..260c8c8 100644 --- a/crates/claude-chill/src/color_preservation_tests.rs +++ b/crates/claude-chill/src/color_preservation_tests.rs @@ -4,17 +4,20 @@ //! force a render, capture what the proxy emits to its stdout side, and //! assert that the styling survives the round-trip. //! -//! They currently FAIL on master because the underlying `vt100 0.16` -//! emulator only models a handful of attributes (fg/bg color, bold, dim, -//! italic, underline, inverse). Anything else — OSC 8 hyperlinks, -//! strikethrough, fancy underline styles, underline color — is silently -//! dropped on render. +//! After the swap from `vt100 0.16` to `wezterm-term` + `termwiz` Surface +//! diffing, most of the modern attribute set is preserved end-to-end: +//! OSC 8 hyperlinks, strikethrough, double underline, and truecolor all +//! round-trip. Two known gaps remain — both are limitations of termwiz's +//! `TerminfoRenderer`, not of the cell model: //! -//! They are gated behind `#[ignore]` so CI stays green. Run them with: -//! cargo test -p claude-chill --lib color_preservation -- --ignored +//! * Curly / dotted / dashed underline styles (`SGR 4:3`, `4:4`, `4:5`): +//! stored on the cell, never emitted on render. +//! * Underline color (`SGR 58`): stored on the cell, never emitted on +//! render. //! -//! The expectation is that they pass once the emulator is swapped to -//! termwiz's `Surface`. Remove the `#[ignore]` attributes at that point. +//! Tests for those two are kept `#[ignore]` so CI stays green. They will +//! pass if/when termwiz's renderer learns to emit them (or we replace +//! the emit step with a custom serializer). #[cfg(test)] mod tests { @@ -119,7 +122,6 @@ mod tests { } #[test] - #[ignore] // FIXME: passes once VT emulator swap to termwiz lands fn osc8_hyperlink_survives_render() { // OSC 8 hyperlinks — used for clickable file paths / URLs. // Format: ESC ] 8 ; ; URL ESC \ ... ESC ] 8 ; ; ESC \ @@ -142,7 +144,6 @@ mod tests { } #[test] - #[ignore] // FIXME: passes once VT emulator swap to termwiz lands fn strikethrough_survives_render() { // SGR 9 = strikethrough. vt100 0.16 has no field for it. let input = b"\x1b[9mstruck through text\x1b[0m"; @@ -155,7 +156,7 @@ mod tests { } #[test] - #[ignore] // FIXME: passes once VT emulator swap to termwiz lands + #[ignore] // termwiz TerminfoRenderer only emits Single/Double underline. fn curly_underline_survives_render() { // SGR 4:3 = curly underline (kitty/wezterm/ghostty all support). let input = b"\x1b[4:3mcurly underline\x1b[0m"; @@ -168,7 +169,7 @@ mod tests { } #[test] - #[ignore] // FIXME: passes once VT emulator swap to termwiz lands + #[ignore] // termwiz TerminfoRenderer doesn't emit SGR 58 underline color. fn underline_color_survives_render() { // SGR 58:2::R:G:B = truecolor underline color. let input = b"\x1b[4m\x1b[58:2::255:0:0mcolored underline\x1b[0m"; @@ -181,7 +182,6 @@ mod tests { } #[test] - #[ignore] // FIXME: passes once VT emulator swap to termwiz lands fn double_underline_survives_render() { // SGR 21 = doubly underlined. let input = b"\x1b[21mdouble underlined\x1b[0m"; diff --git a/crates/claude-chill/src/lib.rs b/crates/claude-chill/src/lib.rs index 3fc02d7..9e9d64e 100644 --- a/crates/claude-chill/src/lib.rs +++ b/crates/claude-chill/src/lib.rs @@ -10,3 +10,4 @@ pub mod key_parser; pub mod line_buffer; pub mod proxy; pub mod redraw_throttler; +pub mod screen_engine; diff --git a/crates/claude-chill/src/proxy.rs b/crates/claude-chill/src/proxy.rs index a4a29d7..5e21a25 100644 --- a/crates/claude-chill/src/proxy.rs +++ b/crates/claude-chill/src/proxy.rs @@ -6,6 +6,7 @@ use crate::escape_sequences::{ }; use crate::history_filter::HistoryFilter; use crate::line_buffer::LineBuffer; +use crate::screen_engine::ScreenEngine; use anyhow::{Context, Result}; use log::debug; use memchr::memmem; @@ -102,8 +103,7 @@ pub struct Proxy { original_termios: Option, history: LineBuffer, history_filter: HistoryFilter, - vt_parser: vt100::Parser, - vt_prev_screen: Option, + screen: ScreenEngine, last_output_time: Option, last_render_time: Option, last_stdin_time: Option, @@ -270,7 +270,7 @@ impl Proxy { let stdout_fd = io::stdout(); write_all(&stdout_fd, BRACKETED_PASTE_ENABLE)?; - let vt_parser = vt100::Parser::new(winsize.ws_row, winsize.ws_col, 0); + let screen = ScreenEngine::new(winsize.ws_row, winsize.ws_col); // Seed history with clear screen so replay starts fresh let mut history = LineBuffer::new(config.max_history_lines); @@ -288,8 +288,7 @@ impl Proxy { pty_master: pty.master, child, original_termios: terminal_guard.take(), - vt_parser, - vt_prev_screen: None, + screen, last_output_time: None, last_render_time: None, last_stdin_time: None, @@ -330,7 +329,7 @@ impl Proxy { rows: u16, cols: u16, ) -> Self { - let vt_parser = vt100::Parser::new(rows, cols, 0); + let screen = ScreenEngine::new(rows, cols); let mut history = LineBuffer::new(config.max_history_lines); history.push_bytes(CLEAR_SCREEN); history.push_bytes(CURSOR_HOME); @@ -343,8 +342,7 @@ impl Proxy { pty_master, child, original_termios: None, - vt_parser, - vt_prev_screen: None, + screen, last_output_time: None, last_render_time: None, last_stdin_time: None, @@ -403,8 +401,8 @@ impl Proxy { } #[cfg(test)] - pub(crate) fn vt_screen_text(&self) -> String { - self.vt_parser.screen().contents() + pub(crate) fn vt_screen_text(&mut self) -> String { + self.screen.screen_text() } #[cfg(test)] @@ -532,7 +530,7 @@ impl Proxy { // Feed VT but NOT history while in alt screen // Alt screen content (TUI editors, etc.) shouldn't be in lookback history if feed_vt { - self.vt_parser.process(data); + self.screen.process(data); } return self.process_output_alt_screen(data, stdout_fd); } @@ -545,7 +543,7 @@ impl Proxy { // Feed data to VT emulator (unless already fed by caller) if feed_vt { - self.vt_parser.process(data); + self.screen.process(data); } self.vt_render_pending = true; self.last_output_time = Some(Instant::now()); @@ -621,7 +619,7 @@ impl Proxy { // Force full VT render to restore main screen content debug!("process_output_alt_screen: rendering VT screen after alt exit"); - self.vt_prev_screen = None; + self.screen.force_full_next(); self.render_vt_screen(stdout_fd)?; // Data after ALT_EXIT was already fed to VT and history when we processed @@ -828,32 +826,14 @@ impl Proxy { } fn render_vt_screen(&mut self, stdout_fd: &F) -> Result<()> { - let is_diff = self.vt_prev_screen.is_some(); + let body = self.screen.render()?; self.output_buffer.clear(); self.output_buffer.extend_from_slice(SYNC_START); - - match &self.vt_prev_screen { - Some(prev) => { - // Diff-based render: only send changes - self.output_buffer - .extend_from_slice(&self.vt_parser.screen().contents_diff(prev)); - } - None => { - // First render: full screen - self.output_buffer - .extend_from_slice(&self.vt_parser.screen().contents_formatted()); - } - } - - self.output_buffer - .extend_from_slice(&self.vt_parser.screen().cursor_state_formatted()); + self.output_buffer.extend_from_slice(&body); self.output_buffer.extend_from_slice(SYNC_END); - debug!( - "render_vt_screen: diff={} output_len={}\n", - is_diff, - self.output_buffer.len() - ); + debug!("render_vt_screen: output_len={}", self.output_buffer.len()); + // Can't use write_to_terminal here due to borrow checker - can't pass // &self.output_buffer while also taking &mut self Self::update_kitty_mode_helper( @@ -864,8 +844,6 @@ impl Proxy { ); write_all(stdout_fd, &self.output_buffer)?; - // Store current screen for next diff - self.vt_prev_screen = Some(self.vt_parser.screen().clone()); self.vt_render_pending = false; self.last_render_time = Some(Instant::now()); Ok(()) @@ -942,7 +920,7 @@ impl Proxy { write_all(stdout_fd, &self.output_buffer)?; // Force full VT render on next output since terminal now shows history - self.vt_prev_screen = None; + self.screen.force_full_next(); Ok(()) } @@ -1164,7 +1142,7 @@ impl Proxy { // Force full render since terminal was showing history debug!("exit_lookback_mode: rendering VT screen"); - self.vt_prev_screen = None; + self.screen.force_full_next(); self.render_vt_screen(stdout_fd)?; Ok(()) @@ -1177,11 +1155,7 @@ impl Proxy { winsize.ws_row, winsize.ws_col ); // Resize VT emulator - self.vt_parser - .screen_mut() - .set_size(winsize.ws_row, winsize.ws_col); - // Force full render on next frame since size changed - self.vt_prev_screen = None; + self.screen.resize(winsize.ws_row, winsize.ws_col); // Forward to child process unsafe { libc::ioctl( diff --git a/crates/claude-chill/src/screen_engine.rs b/crates/claude-chill/src/screen_engine.rs new file mode 100644 index 0000000..2302812 --- /dev/null +++ b/crates/claude-chill/src/screen_engine.rs @@ -0,0 +1,264 @@ +//! Screen emulator backed by `wezterm-term`. +//! +//! This replaces the previous `vt100` backing. wezterm-term gives us full +//! modern attribute coverage — OSC 8 hyperlinks, strikethrough, fancy +//! underline styles, underline color — that vt100 0.16 dropped on render. +//! +//! Architecture: +//! - `wezterm_term::Terminal` is the byte-driven VT emulator. Feed bytes +//! via `advance_bytes`; query state via `screen().visible_lines()`. +//! - A `termwiz::surface::Surface` mirrors the last bytes we *emitted* +//! downstream; the next render diffs current visible lines against +//! this Surface to compute the minimum change set. +//! - `termwiz::render::TerminfoRenderer` serializes those Changes into +//! bytes using a TrueColor / hyperlink-capable capability set. + +use anyhow::Result; +use std::io::Write; +use std::sync::Arc; +use termwiz::caps::{Capabilities, ColorLevel, ProbeHints}; +use termwiz::render::RenderTty; +use termwiz::render::terminfo::TerminfoRenderer; +use termwiz::surface::{Change, Position, Surface}; +use wezterm_term::color::ColorPalette; +use wezterm_term::{Terminal, TerminalConfiguration, TerminalSize}; + +#[derive(Debug)] +struct ProxyTermConfig; + +impl TerminalConfiguration for ProxyTermConfig { + fn color_palette(&self) -> ColorPalette { + ColorPalette::default() + } +} + +/// `Write + RenderTty` adapter that buffers everything in memory. +struct CapturedTty { + buf: Vec, + cols: usize, + rows: usize, +} + +impl Write for CapturedTty { + fn write(&mut self, data: &[u8]) -> std::io::Result { + self.buf.extend_from_slice(data); + Ok(data.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +impl RenderTty for CapturedTty { + fn get_size_in_cells(&mut self) -> termwiz::Result<(usize, usize)> { + Ok((self.cols, self.rows)) + } +} + +pub struct ScreenEngine { + terminal: Terminal, + /// Mirror of what we've *already emitted* downstream. Diffing the + /// current terminal screen against this gives us the minimal change + /// set to send. + mirror: Surface, + renderer: TerminfoRenderer, + rows: usize, + cols: usize, + /// When set, the next render emits the full screen instead of a diff. + force_full: bool, +} + +impl ScreenEngine { + pub fn new(rows: u16, cols: u16) -> Self { + let rows = rows as usize; + let cols = cols as usize; + + let size = TerminalSize { + rows, + cols, + ..Default::default() + }; + let config: Arc = Arc::new(ProxyTermConfig); + // We don't currently surface terminal responses (DA queries, cursor + // position reports, etc) back upstream. Matches the previous vt100 + // behavior, which simply ignored them. + let writer: Box = Box::new(std::io::sink()); + let terminal = Terminal::new( + size, + config, + "claude-chill", + env!("CARGO_PKG_VERSION"), + writer, + ); + + let mirror = Surface::new(cols, rows); + + let caps = Capabilities::new_with_hints( + ProbeHints::default() + .color_level(Some(ColorLevel::TrueColor)) + .hyperlinks(Some(true)) + .bracketed_paste(Some(true)), + ) + .expect("Capabilities::new_with_hints"); + let renderer = TerminfoRenderer::new(caps); + + Self { + terminal, + mirror, + renderer, + rows, + cols, + force_full: true, + } + } + + /// Feed bytes from the child pty into the emulator. + pub fn process(&mut self, data: &[u8]) { + self.terminal.advance_bytes(data); + } + + pub fn resize(&mut self, rows: u16, cols: u16) { + let rows = rows as usize; + let cols = cols as usize; + self.terminal.resize(TerminalSize { + rows, + cols, + ..Default::default() + }); + self.mirror.resize(cols, rows); + self.rows = rows; + self.cols = cols; + self.force_full = true; + } + + /// Mark the next `render()` call as a full screen redraw rather than a diff. + pub fn force_full_next(&mut self) { + self.force_full = true; + } + + /// Build the change stream needed to bring downstream from `mirror` to + /// the current emulator state, encode it as bytes, and update `mirror`. + pub fn render(&mut self) -> Result> { + let lines = { + let screen = self.terminal.screen(); + let rows = self.rows as i64; + let start = screen.phys_row(0); + let end = screen.phys_row(rows - 1) + 1; + screen.lines_in_phys_range(start..end) + }; + let line_refs: Vec<&_> = lines.iter().collect(); + + // If forced, reset the mirror so diff_lines emits the full screen. + if self.force_full { + self.mirror = Surface::new(self.cols, self.rows); + self.force_full = false; + } + + let mut changes = self.mirror.diff_lines(line_refs); + + // Position the downstream cursor where the emulator's cursor is. + let cursor = self.terminal.cursor_pos(); + let row = cursor.y.max(0) as usize; + let col = cursor.x; + changes.push(Change::CursorPosition { + x: Position::Absolute(col), + y: Position::Absolute(row), + }); + + // Keep the mirror in sync with what we just emitted (minus the final + // cursor reposition, which isn't a content change). + self.mirror.add_changes(changes.clone()); + + let mut tty = CapturedTty { + buf: Vec::new(), + cols: self.cols, + rows: self.rows, + }; + self.renderer + .render_to(&changes, &mut tty) + .map_err(|e| anyhow::anyhow!("renderer: {}", e))?; + + // Defensive OSC 8 close: TerminfoRenderer only emits the hyperlink + // close when transitioning to a non-hyperlinked cell. If our diff + // ends inside the hyperlinked region (rest of the row was blank + // and didn't need updating), the close is never emitted and the + // downstream terminal may keep the hyperlink active across the + // boundary. Appending a close here is a no-op when there's no + // active hyperlink. + tty.buf.extend_from_slice(b"\x1b]8;;\x1b\\"); + + Ok(tty.buf) + } + + /// Plain-text contents of the visible screen, for tests / lookback. + #[cfg(test)] + pub fn screen_text(&mut self) -> String { + let lines = { + let screen = self.terminal.screen(); + let rows = self.rows as i64; + let start = screen.phys_row(0); + let end = screen.phys_row(rows - 1) + 1; + screen.lines_in_phys_range(start..end) + }; + let mut out = String::new(); + for (i, line) in lines.iter().enumerate() { + if i > 0 { + out.push('\n'); + } + out.push_str(&line.as_str()); + } + out + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn contains(haystack: &[u8], needle: &[u8]) -> bool { + haystack.windows(needle.len()).any(|w| w == needle) + } + + fn render(input: &[u8]) -> Vec { + let mut e = ScreenEngine::new(24, 80); + e.process(input); + e.render().expect("render") + } + + #[test] + fn osc8_hyperlink_round_trip() { + let mut input = Vec::new(); + input.extend_from_slice(b"\x1b]8;;https://example.com\x1b\\"); + input.extend_from_slice(b"link"); + input.extend_from_slice(b"\x1b]8;;\x1b\\"); + let out = render(&input); + assert!( + contains(&out, b"\x1b]8;;https://example.com"), + "OSC 8 missing in: {:?}", + String::from_utf8_lossy(&out) + ); + } + + #[test] + fn strikethrough_round_trip() { + let out = render(b"\x1b[9mstruck\x1b[0m"); + assert!( + contains(&out, b"[9m") || contains(&out, b";9m"), + "SGR 9 missing in: {:?}", + String::from_utf8_lossy(&out) + ); + } + + #[test] + fn truecolor_round_trip() { + let out = render(b"\x1b[38;2;255;128;0morange\x1b[0m"); + assert!( + contains(&out, b"38:2::255:128:0") + || contains(&out, b"38;2;255;128;0") + || contains(&out, b"38:2:255:128:0"), + "truecolor fg missing in: {:?}", + String::from_utf8_lossy(&out) + ); + } +}