This commit is contained in:
sxyazi 2023-08-02 10:27:39 +08:00
parent a0533f75bb
commit c96190f046
No known key found for this signature in database
27 changed files with 332 additions and 670 deletions

577
Cargo.lock generated
View file

@ -2,6 +2,23 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "adaptor"
version = "0.1.0"
dependencies = [
"anyhow",
"base64",
"color_quant",
"config",
"image",
"md5",
"once_cell",
"ratatui",
"shared",
"tokio",
"tracing",
]
[[package]]
name = "addr2line"
version = "0.20.0"
@ -17,15 +34,6 @@ version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
[[package]]
name = "aho-corasick"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
dependencies = [
"memchr",
]
[[package]]
name = "android-tzdata"
version = "0.1.1"
@ -62,6 +70,7 @@ checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854"
name = "app"
version = "0.1.0"
dependencies = [
"adaptor",
"ansi-to-tui",
"anyhow",
"config",
@ -89,68 +98,12 @@ dependencies = [
"futures-core",
]
[[package]]
name = "async-trait"
version = "0.1.72"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc6dde6e4ed435a4c1ee4e73592f5ba9da2151af10076cc04858746af9352d09"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
]
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "axum"
version = "0.6.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a6a1de45611fdb535bfde7b7de4fd54f4fd2b17b1737c0a59b69bf9b92074b8c"
dependencies = [
"async-trait",
"axum-core",
"bitflags 1.3.2",
"bytes",
"futures-util",
"http",
"http-body",
"hyper",
"itoa",
"matchit",
"memchr",
"mime",
"percent-encoding",
"pin-project-lite",
"rustversion",
"serde",
"sync_wrapper",
"tower",
"tower-layer",
"tower-service",
]
[[package]]
name = "axum-core"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c"
dependencies = [
"async-trait",
"bytes",
"futures-util",
"http",
"http-body",
"mime",
"rustversion",
"tower-layer",
"tower-service",
]
[[package]]
name = "backtrace"
version = "0.3.68"
@ -166,12 +119,6 @@ dependencies = [
"rustc-demangle",
]
[[package]]
name = "base64"
version = "0.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8"
[[package]]
name = "base64"
version = "0.21.2"
@ -237,9 +184,12 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]]
name = "cc"
version = "1.0.79"
version = "1.0.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f"
checksum = "51f1226cd9da55587234753d1245dd5b132343ea240f26b6a9003d68706141ba"
dependencies = [
"libc",
]
[[package]]
name = "cfg-if"
@ -290,57 +240,17 @@ dependencies = [
"xdg",
]
[[package]]
name = "console-api"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e"
dependencies = [
"prost",
"prost-types",
"tonic",
"tracing-core",
]
[[package]]
name = "console-subscriber"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb"
dependencies = [
"console-api",
"crossbeam-channel",
"crossbeam-utils",
"futures",
"hdrhistogram",
"humantime",
"prost-types",
"serde",
"serde_json",
"thread_local",
"tokio",
"tokio-stream",
"tonic",
"tracing",
"tracing-core",
"tracing-subscriber",
]
[[package]]
name = "core"
version = "0.1.0"
dependencies = [
"adaptor",
"anyhow",
"async-channel",
"base64 0.21.2",
"config",
"console-subscriber",
"crossterm",
"futures",
"image",
"indexmap 2.0.0",
"libc",
"md5",
"notify",
"once_cell",
"parking_lot",
@ -445,6 +355,12 @@ version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7"
[[package]]
name = "deranged"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8810e7e2cf385b1e9b50d68264908ec367ba642c96d02edfe61c39e88e2a3c01"
[[package]]
name = "either"
version = "1.9.0"
@ -603,7 +519,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
]
[[package]]
@ -671,25 +587,6 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
[[package]]
name = "h2"
version = "0.3.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049"
dependencies = [
"bytes",
"fnv",
"futures-core",
"futures-sink",
"futures-util",
"http",
"indexmap 1.9.3",
"slab",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "half"
version = "2.2.1"
@ -711,101 +608,12 @@ version = "0.14.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2c6201b9ff9fd90a5a3bac2e56a830d0caa509576f0e503818ee82c181b3437a"
[[package]]
name = "hdrhistogram"
version = "7.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7f19b9f54f7c7f55e31401bb647626ce0cf0f67b0004982ce815b3ee72a02aa8"
dependencies = [
"base64 0.13.1",
"byteorder",
"flate2",
"nom",
"num-traits",
]
[[package]]
name = "hermit-abi"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b"
[[package]]
name = "http"
version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http-body"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1"
dependencies = [
"bytes",
"http",
"pin-project-lite",
]
[[package]]
name = "httparse"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]]
name = "httpdate"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421"
[[package]]
name = "humantime"
version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
[[package]]
name = "hyper"
version = "0.14.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468"
dependencies = [
"bytes",
"futures-channel",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"httparse",
"httpdate",
"itoa",
"pin-project-lite",
"socket2",
"tokio",
"tower-service",
"tracing",
"want",
]
[[package]]
name = "hyper-timeout"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1"
dependencies = [
"hyper",
"pin-project-lite",
"tokio",
"tokio-io-timeout",
]
[[package]]
name = "iana-time-zone"
version = "0.1.57"
@ -904,15 +712,6 @@ dependencies = [
"libc",
]
[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473"
dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.9"
@ -1015,21 +814,6 @@ dependencies = [
"libc",
]
[[package]]
name = "matchers"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558"
dependencies = [
"regex-automata 0.1.10",
]
[[package]]
name = "matchit"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "67827e6ea8ee8a7c4a72227ef4fc08957040acffdb5f122733b24fa12daff41b"
[[package]]
name = "md5"
version = "0.7.0"
@ -1051,12 +835,6 @@ dependencies = [
"autocfg",
]
[[package]]
name = "mime"
version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
[[package]]
name = "minimal-lexical"
version = "0.2.1"
@ -1275,7 +1053,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
]
[[package]]
@ -1302,7 +1080,7 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06"
dependencies = [
"base64 0.21.2",
"base64",
"indexmap 1.9.3",
"line-wrap",
"quick-xml",
@ -1323,12 +1101,6 @@ dependencies = [
"miniz_oxide",
]
[[package]]
name = "ppv-lite86"
version = "0.2.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
[[package]]
name = "proc-macro2"
version = "1.0.66"
@ -1338,38 +1110,6 @@ dependencies = [
"unicode-ident",
]
[[package]]
name = "prost"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd"
dependencies = [
"bytes",
"prost-derive",
]
[[package]]
name = "prost-derive"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4"
dependencies = [
"anyhow",
"itertools",
"proc-macro2",
"quote",
"syn 1.0.109",
]
[[package]]
name = "prost-types"
version = "0.11.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "213622a1460818959ac1181aaeb2dc9c7f63df720db7d788b3e24eacd1983e13"
dependencies = [
"prost",
]
[[package]]
name = "qoi"
version = "0.4.1"
@ -1397,36 +1137,6 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
"libc",
"rand_chacha",
"rand_core",
]
[[package]]
name = "rand_chacha"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
]
[[package]]
name = "rand_core"
version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
dependencies = [
"getrandom",
]
[[package]]
name = "ratatui"
version = "0.22.0"
@ -1482,44 +1192,6 @@ dependencies = [
"bitflags 1.3.2",
]
[[package]]
name = "regex"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b2eae68fc220f7cf2532e4494aded17545fce192d59cd996e0fe7887f4ceb575"
dependencies = [
"aho-corasick",
"memchr",
"regex-automata 0.3.4",
"regex-syntax 0.7.4",
]
[[package]]
name = "regex-automata"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132"
dependencies = [
"regex-syntax 0.6.29",
]
[[package]]
name = "regex-automata"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7b6d6190b7594385f61bd3911cd1be99dfddcfc365a4160cc2ab5bff4aed294"
dependencies = [
"aho-corasick",
"memchr",
"regex-syntax 0.7.4",
]
[[package]]
name = "regex-syntax"
version = "0.6.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
[[package]]
name = "regex-syntax"
version = "0.7.4"
@ -1532,12 +1204,6 @@ version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
[[package]]
name = "rustversion"
version = "1.0.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4"
[[package]]
name = "ryu"
version = "1.0.15"
@ -1567,22 +1233,22 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
[[package]]
name = "serde"
version = "1.0.178"
version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60363bdd39a7be0266a520dab25fdc9241d2f987b08a01e01f0ec6d06a981348"
checksum = "0ea67f183f058fe88a4e3ec6e2788e003840893b91bac4559cabedd00863b3ed"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.178"
version = "1.0.180"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f28482318d6641454cb273da158647922d1be6b5a2fcc6165cd89ebdd7ed576b"
checksum = "24e744d7782b686ab3b73267ef05697159cc0e5abbed3f47f9933165e5219036"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
]
[[package]]
@ -1710,49 +1376,30 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.109"
version = "2.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
checksum = "04361975b3f5e348b2189d8dc55bc942f278b2d482a6a0365de5bdd62d351567"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "syn"
version = "2.0.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
dependencies = [
"proc-macro2",
"quote",
"unicode-ident",
]
[[package]]
name = "sync_wrapper"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160"
[[package]]
name = "syntect"
version = "5.0.0"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c6c454c27d9d7d9a84c7803aaa3c50cd088d2906fe3c6e42da3209aa623576a8"
checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"
dependencies = [
"bincode",
"bitflags 1.3.2",
"flate2",
"fnv",
"lazy_static",
"once_cell",
"onig",
"plist",
"regex-syntax 0.6.29",
"regex-syntax",
"serde",
"serde_derive",
"serde_json",
"thiserror",
"walkdir",
@ -1776,7 +1423,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
]
[[package]]
@ -1802,10 +1449,11 @@ dependencies = [
[[package]]
name = "time"
version = "0.3.23"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446"
checksum = "b79eabcd964882a646b3584543ccabeae7869e9ac32a46f6f22b7a5bd405308b"
dependencies = [
"deranged",
"itoa",
"serde",
"time-core",
@ -1820,9 +1468,9 @@ checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb"
[[package]]
name = "time-macros"
version = "0.2.10"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4"
checksum = "eb71511c991639bb078fd5bf97757e03914361c48100d52878b8e52b46fb92cd"
dependencies = [
"time-core",
]
@ -1859,20 +1507,9 @@ dependencies = [
"signal-hook-registry",
"socket2",
"tokio-macros",
"tracing",
"windows-sys 0.48.0",
]
[[package]]
name = "tokio-io-timeout"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf"
dependencies = [
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-macros"
version = "2.1.0"
@ -1881,32 +1518,7 @@ checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
]
[[package]]
name = "tokio-stream"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "tokio-util"
version = "0.7.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d"
dependencies = [
"bytes",
"futures-core",
"futures-sink",
"pin-project-lite",
"tokio",
"tracing",
"syn",
]
[[package]]
@ -1944,66 +1556,6 @@ dependencies = [
"winnow",
]
[[package]]
name = "tonic"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3082666a3a6433f7f511c7192923fa1fe07c69332d3c6a2e6bb040b569199d5a"
dependencies = [
"async-trait",
"axum",
"base64 0.21.2",
"bytes",
"futures-core",
"futures-util",
"h2",
"http",
"http-body",
"hyper",
"hyper-timeout",
"percent-encoding",
"pin-project",
"prost",
"tokio",
"tokio-stream",
"tower",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower"
version = "0.4.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c"
dependencies = [
"futures-core",
"futures-util",
"indexmap 1.9.3",
"pin-project",
"pin-project-lite",
"rand",
"slab",
"tokio",
"tokio-util",
"tower-layer",
"tower-service",
"tracing",
]
[[package]]
name = "tower-layer"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0"
[[package]]
name = "tower-service"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52"
[[package]]
name = "tracing"
version = "0.1.37"
@ -2035,7 +1587,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
]
[[package]]
@ -2065,14 +1617,10 @@ version = "0.3.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77"
dependencies = [
"matchers",
"nu-ansi-term",
"once_cell",
"regex",
"sharded-slab",
"smallvec",
"thread_local",
"tracing",
"tracing-core",
"tracing-log",
]
@ -2093,12 +1641,6 @@ dependencies = [
"windows 0.44.0",
]
[[package]]
name = "try-lock"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed"
[[package]]
name = "unicode-bidi"
version = "0.3.13"
@ -2159,15 +1701,6 @@ dependencies = [
"winapi-util",
]
[[package]]
name = "want"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e"
dependencies = [
"try-lock",
]
[[package]]
name = "wasi"
version = "0.11.0+wasi-snapshot-preview1"
@ -2195,7 +1728,7 @@ dependencies = [
"once_cell",
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
"wasm-bindgen-shared",
]
@ -2217,7 +1750,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.27",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
@ -2417,9 +1950,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a"
[[package]]
name = "winnow"
version = "0.5.2"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8bd122eb777186e60c3fdf765a58ac76e41c582f1f535fbf3314434c6b58f3f7"
checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807"
dependencies = [
"memchr",
]

View file

@ -1,6 +1,7 @@
[workspace]
resolver = "2"
members = [
"adaptor",
"app",
"config",
"core",
@ -8,6 +9,6 @@ members = [
]
[profile.release]
strip = true
lto = true
strip = true
panic = "abort"

View file

@ -91,8 +91,8 @@ If you want to use your own config, copy the [config folder](https://github.com/
| WezTerm | [Terminal graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) | ✅ Built-in |
| Konsole | [Terminal graphics protocol](https://sw.kovidgoyal.net/kitty/graphics-protocol/) | ✅ Built-in |
| iTerm2 | [Inline Images Protocol](https://iterm2.com/documentation-images.html) | ✅ Built-in |
| Hyper | Sixel | ☑️ Überzug++ required |
| foot | Sixel | ☑️ Überzug++ required |
| Hyper | Sixel | ✅ Built-in |
| foot | Sixel | ✅ Built-in |
| X11 / Wayland | Window system protocol | ☑️ Überzug++ required |
| Fallback | [Chafa](https://hpjansson.org/chafa/) | ☑️ Überzug++ required |

21
adaptor/Cargo.toml Normal file
View file

@ -0,0 +1,21 @@
[package]
name = "adaptor"
version = "0.1.0"
edition = "2021"
[dependencies]
config = { path = "../config" }
shared = { path = "../shared" }
# External dependencies
anyhow = "^1"
base64 = "^0"
color_quant = "^1"
image = "^0"
md5 = "^0"
once_cell = "^1"
ratatui = "^0"
tokio = { version = "^1", features = [ "parking_lot" ] }
# Logging
tracing = "^0"

View file

@ -4,9 +4,10 @@ use anyhow::Result;
use config::{preview::PreviewAdaptor, PREVIEW};
use once_cell::sync::Lazy;
use ratatui::prelude::Rect;
use tokio::sync::mpsc::UnboundedSender;
use tokio::{fs, sync::mpsc::UnboundedSender};
use super::{iterm2::Iterm2, kitty::Kitty, ueberzug::Ueberzug};
use super::{Iterm2, Kitty, Ueberzug};
use crate::{Image, Sixel};
static IMAGE_SHOWN: AtomicBool = AtomicBool::new(false);
@ -18,14 +19,20 @@ pub struct Adaptor;
impl Adaptor {
pub fn init() { Lazy::force(&UEBERZUG); }
pub async fn image_show(path: &Path, rect: Rect) -> Result<()> {
pub async fn image_show(mut path: &Path, rect: Rect) -> Result<()> {
if IMAGE_SHOWN.swap(true, Ordering::Relaxed) {
Self::image_hide(rect);
}
let cache = Image::cache(path);
if fs::metadata(&cache).await.is_ok() {
path = cache.as_path();
}
match PREVIEW.adaptor {
PreviewAdaptor::Kitty => Kitty::image_show(path, rect).await,
PreviewAdaptor::Iterm2 => Iterm2::image_show(path, rect).await,
PreviewAdaptor::Sixel => Sixel::image_show(path, rect).await,
_ => {
if let Some(tx) = &*UEBERZUG {
tx.send(Some((path.to_path_buf(), rect))).ok();
@ -43,6 +50,7 @@ impl Adaptor {
match PREVIEW.adaptor {
PreviewAdaptor::Kitty => Kitty::image_hide(),
PreviewAdaptor::Iterm2 => Iterm2::image_hide(rect),
PreviewAdaptor::Sixel => Sixel::image_hide(rect),
_ => {
if let Some(tx) = &*UEBERZUG {
tx.send(None).ok();

56
adaptor/src/image.rs Normal file
View file

@ -0,0 +1,56 @@
use std::path::{Path, PathBuf};
use anyhow::{Error, Result};
use config::PREVIEW;
use image::{imageops::FilterType, DynamicImage, ImageFormat};
use shared::tty_ratio;
use tokio::fs;
pub struct Image;
impl Image {
pub(super) async fn crop(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
let (w, h) = {
let r = tty_ratio();
let (w, h) = ((size.0 as f64 * r.0) as u32, (size.1 as f64 * r.1) as u32);
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
};
let img = fs::read(path).await?;
let img = tokio::task::spawn_blocking(move || -> Result<DynamicImage> {
let img = image::load_from_memory(&img)?;
Ok(if img.width() > w || img.height() > h {
img.resize(w, h, FilterType::Triangle)
} else {
img
})
});
Ok(img.await??)
}
pub async fn precache(path: &Path) -> Result<()> {
let cache = Self::cache(path);
if fs::metadata(&cache).await.is_ok() {
return Ok(());
}
let img = fs::read(&path).await?;
let result = tokio::task::spawn_blocking(move || {
let img = image::load_from_memory(&img)?;
let (w, h) = (PREVIEW.max_width, PREVIEW.max_height);
if img.width() > w || img.height() > h {
img.resize(w, h, FilterType::Triangle).save_with_format(cache, ImageFormat::Jpeg)?;
}
Ok::<(), Error>(())
});
Ok(result.await??)
}
#[inline]
pub fn cache(path: &Path) -> PathBuf {
format!("/tmp/yazi/{:x}", md5::compute(path.to_string_lossy().as_bytes())).into()
}
}

View file

@ -12,7 +12,7 @@ pub(super) struct Iterm2;
impl Iterm2 {
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
let img = Image::resize(path, (rect.width, rect.height)).await?;
let img = Image::crop(path, (rect.width, rect.height)).await?;
let b = Self::encode(img).await?;
Term::move_to(rect.x, rect.y).ok();

View file

@ -12,7 +12,7 @@ pub(super) struct Kitty;
impl Kitty {
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
let img = Image::resize(path, (rect.width, rect.height)).await?;
let img = Image::crop(path, (rect.width, rect.height)).await?;
let b = Self::encode(img).await?;
Term::move_to(rect.x, rect.y).ok();

13
adaptor/src/lib.rs Normal file
View file

@ -0,0 +1,13 @@
mod adaptor;
mod image;
mod iterm2;
mod kitty;
mod sixel;
mod ueberzug;
pub use adaptor::*;
pub use image::*;
pub(self) use iterm2::*;
pub(self) use kitty::*;
pub(self) use sixel::*;
pub(self) use ueberzug::*;

97
adaptor/src/sixel.rs Normal file
View file

@ -0,0 +1,97 @@
use std::{io::{stdout, Write}, path::Path};
use anyhow::{bail, Result};
use color_quant::NeuQuant;
use image::DynamicImage;
use ratatui::prelude::Rect;
use shared::Term;
use crate::Image;
pub(super) struct Sixel;
impl Sixel {
pub(super) async fn image_show(path: &Path, rect: Rect) -> Result<()> {
let img = Image::crop(path, (rect.width, rect.height)).await?;
let b = Self::encode(img).await?;
Term::move_to(rect.x, rect.y).ok();
stdout().write_all(&b).ok();
Ok(())
}
#[inline]
pub(super) fn image_hide(rect: Rect) {
let s = " ".repeat(rect.width as usize);
for y in rect.top()..=rect.bottom() {
Term::move_to(rect.x, y).ok();
stdout().write_all(s.as_bytes()).ok();
}
}
async fn encode(img: DynamicImage) -> Result<Vec<u8>> {
let alpha = img.color().has_alpha();
if img.width() == 0 || img.height() == 0 {
bail!("image is empty");
}
tokio::task::spawn_blocking(move || {
let img = img.into_rgba8();
let nq = NeuQuant::new(10, 256 - alpha as usize, &img);
let mut buf: Vec<u8> = Vec::with_capacity(1 << 16);
write!(buf, "\x1bP0;0;8q\"1;1;{};{}", img.width(), img.height())?;
// Palette
for (i, c) in nq.color_map_rgba().chunks(4).enumerate() {
write!(
buf,
"#{};2;{};{};{}",
i + alpha as usize,
c[0] as u16 * 100 / 255,
c[1] as u16 * 100 / 255,
c[2] as u16 * 100 / 255
)?;
}
for y in 0..img.height() {
let c = (b'?' + (1 << (y % 6))) as u8 as char;
let mut last = 0;
let mut repeat = 0usize;
for x in 0..img.width() {
let pixel = img.get_pixel(x, y).0;
let idx = if pixel[3] == 0 { 0 } else { nq.index_of(&pixel) as u8 + alpha as u8 };
if idx == last || repeat == 0 {
(last, repeat) = (idx, repeat + 1);
continue;
}
if repeat > 1 {
write!(buf, "#{}!{}{}", last, repeat, c)?;
} else {
write!(buf, "#{}{}", last, c)?;
}
(last, repeat) = (idx, 1);
}
if repeat > 1 {
write!(buf, "#{}!{}{}", last, repeat, c)?;
} else {
write!(buf, "#{}{}", last, c)?;
}
write!(buf, "$")?;
if y % 6 == 5 {
write!(buf, "-")?;
}
}
write!(buf, "\x1b\\")?;
Ok(buf)
})
.await?
}
}

View file

@ -4,19 +4,20 @@ version = "0.1.0"
edition = "2021"
[dependencies]
config = { path = "../config" }
core = { path = "../core" }
shared = { path = "../shared" }
adaptor = { path = "../adaptor" }
config = { path = "../config" }
core = { path = "../core" }
shared = { path = "../shared" }
# External dependencies
anyhow = "^1"
tokio = { version = "^1", features = [ "parking_lot" ] }
crossterm = { version = "^0", features = [ "event-stream" ] }
ratatui = { version = "^0" }
ansi-to-tui = "^3"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
libc = "^0"
anyhow = "^1"
crossterm = { version = "^0", features = [ "event-stream" ] }
futures = "^0"
libc = "^0"
ratatui = "^0"
signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] }
tokio = { version = "^1", features = [ "parking_lot" ] }
# Logging
tracing = "^0"

View file

@ -22,7 +22,7 @@ impl App {
let signals = Signals::start()?;
let mut app = Self { cx: Ctx::new(), term: Some(term), signals };
while let Some(event) = app.signals.rx.recv().await {
while let Some(event) = app.signals.recv().await {
match event {
Event::Quit => break,
Event::Key(key) => app.dispatch_key(key),

View file

@ -25,7 +25,7 @@ async fn main() -> anyhow::Result<()> {
config::init();
core::adaptor::Adaptor::init();
adaptor::Adaptor::init();
App::run().await
}

View file

@ -6,7 +6,7 @@ use shared::readable_path;
use crate::Ctx;
pub struct Folder<'a> {
pub(super) struct Folder<'a> {
cx: &'a Ctx,
folder: &'a core::manager::Folder,
is_preview: bool,

View file

@ -2,6 +2,6 @@ mod folder;
mod layout;
mod preview;
pub(super) use folder::*;
pub(self) use folder::*;
pub(super) use layout::*;
pub(self) use preview::*;

View file

@ -7,8 +7,8 @@ use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM};
use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, oneshot}, task::JoinHandle};
pub(super) struct Signals {
pub tx: UnboundedSender<Event>,
pub rx: UnboundedReceiver<Event>,
tx: UnboundedSender<Event>,
rx: UnboundedReceiver<Event>,
term_stop_tx: Option<oneshot::Sender<()>>,
term_stop_rx: Option<oneshot::Receiver<()>>,
@ -29,6 +29,23 @@ impl Signals {
Ok(signals)
}
#[inline]
pub(super) async fn recv(&mut self) -> Option<Event> { self.rx.recv().await }
pub(super) fn stop_term(&mut self, state: bool) {
if state == self.term_stop_tx.is_none() {
return;
}
if let Some(tx) = self.term_stop_tx.take() {
tx.send(()).ok();
} else {
let (tx, rx) = oneshot::channel();
(self.term_stop_tx, self.term_stop_rx) = (Some(tx), Some(rx));
self.spawn_crossterm_task();
}
}
fn spawn_system_task(&self) -> Result<JoinHandle<()>> {
let tx = self.tx.clone();
let mut signals = signal_hook_tokio::Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?;
@ -72,18 +89,4 @@ impl Signals {
}
})
}
pub(super) fn stop_term(&mut self, state: bool) {
if state == self.term_stop_tx.is_none() {
return;
}
if let Some(tx) = self.term_stop_tx.take() {
tx.send(()).ok();
} else {
let (tx, rx) = oneshot::channel();
(self.term_stop_tx, self.term_stop_rx) = (Some(tx), Some(rx));
self.spawn_crossterm_task();
}
}
}

View file

@ -1,6 +1,6 @@
use ratatui::{buffer::Buffer, layout::Rect, widgets::{self, Widget}};
pub struct Clear;
pub(super) struct Clear;
impl Widget for Clear {
fn render(self, mut area: Rect, buf: &mut Buffer) {

View file

@ -4,16 +4,15 @@ version = "0.1.0"
edition = "2021"
[dependencies]
shared = { path = "../shared" }
# External dependencies
anyhow = "^1"
crossterm = "^0"
futures = "^0"
glob = "^0"
once_cell = "^1"
ratatui = "^0"
serde = { version = "^1", features = [ "derive" ] }
toml = { version = "^0", features = [ "preserve_order" ] }
xdg = "^2"
serde = { version = "^1", features = [ "derive" ] }
once_cell = "^1"
crossterm = { version = "^0" }
anyhow = "^1"
ratatui = "^0"
glob = "^0"
futures = "^0"

View file

@ -4,9 +4,9 @@ use std::env;
pub enum PreviewAdaptor {
Kitty,
Iterm2,
Sixel,
// Supported by Überzug++
Sixel,
X11,
Wayland,
Chafa,
@ -59,6 +59,7 @@ impl PreviewAdaptor {
match self {
PreviewAdaptor::Kitty => false,
PreviewAdaptor::Iterm2 => false,
PreviewAdaptor::Sixel => false,
_ => true,
}
}

View file

@ -4,28 +4,24 @@ version = "0.1.0"
edition = "2021"
[dependencies]
config = { path = "../config" }
shared = { path = "../shared" }
adaptor = { path = "../adaptor" }
config = { path = "../config" }
shared = { path = "../shared" }
# External dependencies
serde = { version = "^1" }
anyhow = "^1"
async-channel = "^1"
base64 = "^0"
console-subscriber = "^0"
crossterm = { version = "^0" }
futures = "^0"
image = "^0"
indexmap = "^2"
libc = "^0"
md5 = "^0"
notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] }
parking_lot = "^0"
ratatui = "^0"
serde_json = "^1"
syntect = "^5"
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "fs", "process", "io-std", "io-util" ] }
trash = "^3"
unicode-width = "^0"
once_cell = "^1"
tracing = "^0"
anyhow = "^1"
async-channel = "^1"
crossterm = "^0"
futures = "^0"
indexmap = "^2"
notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] }
once_cell = "^1"
parking_lot = "^0"
ratatui = "^0"
serde = "^1"
serde_json = "^1"
syntect = "^5"
tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "time", "fs", "process", "io-util" ] }
tracing = "^0"
trash = "^3"
unicode-width = "^0"

View file

@ -1,31 +0,0 @@
use std::path::Path;
use anyhow::Result;
use config::PREVIEW;
use image::{imageops::FilterType, DynamicImage};
use shared::tty_ratio;
use tokio::fs;
pub(super) struct Image;
impl Image {
pub(super) async fn resize(path: &Path, size: (u16, u16)) -> Result<DynamicImage> {
let (w, h) = {
let r = tty_ratio();
let (w, h) = ((size.0 as f64 * r.0) as u32, (size.1 as f64 * r.1) as u32);
(w.min(PREVIEW.max_width), h.min(PREVIEW.max_height))
};
let img = fs::read(path).await?;
let img = tokio::task::spawn_blocking(move || -> Result<DynamicImage> {
let img = image::load_from_memory(&img)?;
Ok(if img.width() > w || img.height() > h {
img.resize(w, h, FilterType::Triangle)
} else {
img
})
});
Ok(img.await??)
}
}

View file

@ -1,7 +0,0 @@
mod adaptor;
mod image;
mod iterm2;
mod kitty;
mod ueberzug;
pub use adaptor::*;

View file

@ -1,4 +1,3 @@
pub mod adaptor;
mod blocker;
mod event;
pub mod external;

View file

@ -1,5 +1,6 @@
use std::{fs::File, io::{BufRead, BufReader}, mem, path::{Path, PathBuf}, sync::OnceLock};
use adaptor::{Adaptor, Image};
use anyhow::{anyhow, Result};
use config::{PREVIEW, THEME};
use ratatui::prelude::Rect;
@ -8,7 +9,7 @@ use syntect::{easy::HighlightFile, highlighting::{Theme, ThemeSet}, parsing::Syn
use tokio::{fs, task::JoinHandle};
use super::{ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_BORDER, PREVIEW_MARGIN, PREVIEW_RATIO};
use crate::{adaptor::Adaptor, emit, external, files::{Files, FilesOp}, tasks::Precache};
use crate::{emit, external, files::{Files, FilesOp}};
static SYNTECT_SYNTAX: OnceLock<SyntaxSet> = OnceLock::new();
static SYNTECT_THEME: OnceLock<Theme> = OnceLock::new();
@ -102,18 +103,13 @@ impl Preview {
Ok(PreviewData::Folder)
}
pub async fn image(mut path: &Path) -> Result<PreviewData> {
let cache = Precache::cache(path);
if fs::metadata(&cache).await.is_ok() {
path = cache.as_path();
}
pub async fn image(path: &Path) -> Result<PreviewData> {
Adaptor::image_show(path, Self::rect()).await?;
Ok(PreviewData::Image)
}
pub async fn video(path: &Path) -> Result<PreviewData> {
let cache = Precache::cache(path);
let cache = Image::cache(path);
if fs::metadata(&cache).await.is_err() {
external::ffmpegthumbnailer(path, &cache).await?;
}

View file

@ -1,8 +1,7 @@
use std::{collections::{BTreeMap, BTreeSet}, path::{Path, PathBuf}, sync::Arc};
use std::{collections::{BTreeMap, BTreeSet}, path::PathBuf, sync::Arc};
use anyhow::{Error, Result};
use config::PREVIEW;
use image::{imageops::FilterType, ImageFormat};
use adaptor::Image;
use anyhow::Result;
use parking_lot::Mutex;
use shared::{calculate_size, Throttle};
use tokio::{fs, sync::mpsc};
@ -67,28 +66,11 @@ impl Precache {
pub(super) async fn work(&self, task: &mut PrecacheOp) -> Result<()> {
match task {
PrecacheOp::Image(task) => {
let cache = Self::cache(&task.target);
if fs::metadata(&cache).await.is_ok() {
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
}
let img = fs::read(&task.target).await;
tokio::task::spawn_blocking(move || {
let img = image::load_from_memory(&img?)?;
let (w, h) = (PREVIEW.max_width, PREVIEW.max_height);
if img.width() > w || img.height() > h {
img.resize(w, h, FilterType::Triangle).save_with_format(&cache, ImageFormat::Jpeg).ok();
}
Ok::<(), Error>(())
})
.await
.ok();
Image::precache(&task.target).await.ok();
self.sch.send(TaskOp::Adv(task.id, 1, 0))?;
}
PrecacheOp::Video(task) => {
let cache = Self::cache(&task.target);
let cache = Image::cache(&task.target);
if fs::metadata(&cache).await.is_ok() {
return Ok(self.sch.send(TaskOp::Adv(task.id, 1, 0))?);
}
@ -151,9 +133,4 @@ impl Precache {
}
self.done(id)
}
#[inline]
pub fn cache(path: &Path) -> PathBuf {
format!("/tmp/yazi/{:x}", md5::compute(path.to_string_lossy().as_bytes())).into()
}
}

View file

@ -4,10 +4,9 @@ version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "^1"
crossterm = "^0"
libc = "^0"
tokio = { version = "^1", features = [ "parking_lot" ] }
parking_lot = "^0"
crossterm = { version = "^0" }
ratatui = { version = "^0" }
tokio = { version = "^1", features = [ "parking_lot" ] }