diff --git a/.gitignore b/.gitignore index ea8c4bf7..0a5819ba 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/target +target/ + +.DS_Store diff --git a/Cargo.lock b/Cargo.lock index b4703982..98e737fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -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" @@ -58,6 +66,27 @@ version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b13c32d80ecc7ab747b80c3784bce54ee8a7a0cc4fbda9bf4cda2cf6fe90854" +[[package]] +name = "app" +version = "0.1.0" +dependencies = [ + "adaptor", + "ansi-to-tui", + "anyhow", + "config", + "core", + "crossterm", + "futures", + "libc", + "ratatui", + "shared", + "signal-hook-tokio", + "tokio", + "tracing", + "tracing-appender", + "tracing-subscriber", +] + [[package]] name = "async-channel" version = "1.9.0" @@ -69,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" @@ -146,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" @@ -217,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" @@ -255,39 +225,44 @@ dependencies = [ ] [[package]] -name = "console-api" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2895653b4d9f1538a83970077cb01dfc77a4810524e51a110944688e916b18e" +name = "config" +version = "0.1.0" dependencies = [ - "prost", - "prost-types", - "tonic", - "tracing-core", + "anyhow", + "crossterm", + "futures", + "glob", + "once_cell", + "ratatui", + "serde", + "shared", + "toml", + "xdg", ] [[package]] -name = "console-subscriber" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4cf42660ac07fcebed809cfe561dd8730bcd35b075215e6479c516bcd0d11cb" +name = "core" +version = "0.1.0" dependencies = [ - "console-api", - "crossbeam-channel", - "crossbeam-utils", + "adaptor", + "anyhow", + "async-channel", + "config", + "crossterm", "futures", - "hdrhistogram", - "humantime", - "prost-types", + "indexmap 2.0.0", + "notify", + "once_cell", + "parking_lot", + "ratatui", "serde", "serde_json", - "thread_local", + "shared", + "syntect", "tokio", - "tokio-stream", - "tonic", "tracing", - "tracing-core", - "tracing-subscriber", + "trash", + "unicode-width", ] [[package]] @@ -380,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" @@ -538,7 +519,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -606,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" @@ -646,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" @@ -839,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" @@ -950,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" @@ -986,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" @@ -1210,7 +1053,7 @@ checksum = "ec2e072ecce94ec471b13398d5402c188e76ac03cf74dd1a975161b23a3f6d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -1237,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", @@ -1258,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" @@ -1273,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" @@ -1332,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" @@ -1417,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" @@ -1467,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" @@ -1502,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]] @@ -1549,6 +1280,18 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "shared" +version = "0.1.0" +dependencies = [ + "anyhow", + "crossterm", + "libc", + "parking_lot", + "ratatui", + "tokio", +] + [[package]] name = "signal-hook" version = "0.3.17" @@ -1633,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", @@ -1699,7 +1423,7 @@ checksum = "090198534930841fab3a5d1bb637cde49e339654e606195f8d9c76eeb081dc96" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -1725,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", @@ -1743,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", ] @@ -1782,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" @@ -1804,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]] @@ -1867,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" @@ -1958,7 +1587,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", ] [[package]] @@ -1988,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", ] @@ -2016,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" @@ -2082,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" @@ -2118,7 +1728,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.27", + "syn", "wasm-bindgen-shared", ] @@ -2140,7 +1750,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.27", + "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -2340,9 +1950,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winnow" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b5872fa2e10bd067ae946f927e726d7d603eaeb6e02fa6a350e0722d2b8c11" +checksum = "f46aab759304e4d7b2075a9aecba26228bb073ee8c50db796b2c72c676b5d807" dependencies = [ "memchr", ] @@ -2362,40 +1972,6 @@ dependencies = [ "linked-hash-map", ] -[[package]] -name = "yazi" -version = "0.1.2" -dependencies = [ - "ansi-to-tui", - "anyhow", - "async-channel", - "base64 0.21.2", - "console-subscriber", - "crossterm", - "futures", - "glob", - "image", - "indexmap 2.0.0", - "libc", - "md5", - "notify", - "once_cell", - "parking_lot", - "ratatui", - "serde", - "serde_json", - "signal-hook-tokio", - "syntect", - "tokio", - "toml", - "tracing", - "tracing-appender", - "tracing-subscriber", - "trash", - "unicode-width", - "xdg", -] - [[package]] name = "zune-inflate" version = "0.2.54" diff --git a/Cargo.toml b/Cargo.toml index 3e18f4ca..7f2c7137 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,39 +1,14 @@ -[package] -name = "yazi" -version = "0.1.2" -edition = "2021" - -[dependencies] -ansi-to-tui = "^3" -anyhow = "^1" -async-channel = "^1" -base64 = "^0" -console-subscriber = "^0" -crossterm = { version = "^0", features = [ "event-stream" ] } -futures = "^0" -glob = "^0" -image = "^0" -indexmap = "^2" -libc = "^0" -md5 = "^0" -notify = { version = "^6", default-features = false, features = [ "macos_fsevent" ] } -once_cell = "^1" -parking_lot = "^0" -ratatui = "^0" -serde = { version = "^1", features = [ "derive" ] } -serde_json = "^1" -signal-hook-tokio = { version = "^0", features = [ "futures-v0_3" ] } -syntect = "^5" -tokio = { version = "^1", features = [ "parking_lot", "macros", "rt-multi-thread", "sync", "fs", "process", "io-std", "io-util" ] } -toml = { version = "^0", features = [ "preserve_order" ] } -tracing = "^0" -tracing-appender = "^0" -tracing-subscriber = "^0" -trash = "^3" -unicode-width = "^0" -xdg = "^2" +[workspace] +resolver = "2" +members = [ + "adaptor", + "app", + "config", + "core", + "shared", +] [profile.release] -strip = true lto = true +strip = true panic = "abort" diff --git a/README.md b/README.md index 809f6fda..aea19cfe 100644 --- a/README.md +++ b/README.md @@ -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 | diff --git a/adaptor/Cargo.toml b/adaptor/Cargo.toml new file mode 100644 index 00000000..12a801b5 --- /dev/null +++ b/adaptor/Cargo.toml @@ -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" diff --git a/src/core/adaptor/adaptor.rs b/adaptor/src/adaptor.rs similarity index 71% rename from src/core/adaptor/adaptor.rs rename to adaptor/src/adaptor.rs index 141a4aa2..f5a96de0 100644 --- a/src/core/adaptor/adaptor.rs +++ b/adaptor/src/adaptor.rs @@ -1,12 +1,13 @@ use std::{path::{Path, PathBuf}, sync::atomic::{AtomicBool, Ordering}}; 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 crate::config::{preview::PreviewAdaptor, PREVIEW}; +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(); diff --git a/adaptor/src/image.rs b/adaptor/src/image.rs new file mode 100644 index 00000000..cc645bdc --- /dev/null +++ b/adaptor/src/image.rs @@ -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 { + 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 { + 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() + } +} diff --git a/src/core/adaptor/iterm2.rs b/adaptor/src/iterm2.rs similarity index 92% rename from src/core/adaptor/iterm2.rs rename to adaptor/src/iterm2.rs index ee5fc03a..de00a740 100644 --- a/src/core/adaptor/iterm2.rs +++ b/adaptor/src/iterm2.rs @@ -4,15 +4,15 @@ use anyhow::Result; use base64::{engine::general_purpose, Engine}; use image::{codecs::jpeg::JpegEncoder, DynamicImage}; use ratatui::prelude::Rect; +use shared::Term; use super::image::Image; -use crate::ui::Term; 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(); diff --git a/src/core/adaptor/kitty.rs b/adaptor/src/kitty.rs similarity index 94% rename from src/core/adaptor/kitty.rs rename to adaptor/src/kitty.rs index 896778e9..a533f1ac 100644 --- a/src/core/adaptor/kitty.rs +++ b/adaptor/src/kitty.rs @@ -4,15 +4,15 @@ use anyhow::Result; use base64::{engine::general_purpose, Engine}; use image::DynamicImage; use ratatui::prelude::Rect; +use shared::Term; use super::image::Image; -use crate::ui::Term; 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(); diff --git a/adaptor/src/lib.rs b/adaptor/src/lib.rs new file mode 100644 index 00000000..60a9d09c --- /dev/null +++ b/adaptor/src/lib.rs @@ -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::*; diff --git a/adaptor/src/sixel.rs b/adaptor/src/sixel.rs new file mode 100644 index 00000000..9110553f --- /dev/null +++ b/adaptor/src/sixel.rs @@ -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> { + 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 = 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? + } +} diff --git a/src/core/adaptor/ueberzug.rs b/adaptor/src/ueberzug.rs similarity index 98% rename from src/core/adaptor/ueberzug.rs rename to adaptor/src/ueberzug.rs index bca5c1aa..4049d75b 100644 --- a/src/core/adaptor/ueberzug.rs +++ b/adaptor/src/ueberzug.rs @@ -1,11 +1,10 @@ use std::{path::PathBuf, process::Stdio}; use anyhow::Result; +use config::PREVIEW; use ratatui::prelude::Rect; use tokio::{io::AsyncWriteExt, process::{Child, Command}, sync::mpsc::{self, UnboundedSender}}; -use crate::config::PREVIEW; - pub(super) struct Ueberzug; impl Ueberzug { diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 00000000..dc0f145a --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,25 @@ +[package] +name = "app" +version = "0.1.0" +edition = "2021" + +[dependencies] +adaptor = { path = "../adaptor" } +config = { path = "../config" } +core = { path = "../core" } +shared = { path = "../shared" } + +# External dependencies +ansi-to-tui = "^3" +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" +tracing-appender = "^0" +tracing-subscriber = "^0" diff --git a/src/ui/app.rs b/app/src/app.rs similarity index 92% rename from src/ui/app.rs rename to app/src/app.rs index 3a8ef940..821d549b 100644 --- a/src/ui/app.rs +++ b/app/src/app.rs @@ -1,25 +1,28 @@ +use core::{emit, files::FilesOp, input::InputMode, Event}; + use anyhow::{Ok, Result}; +use config::keymap::{Control, Key, KeymapLayer}; use crossterm::event::KeyEvent; -use tokio::sync::oneshot::{self}; +use shared::{absolute_path, Term}; +use tokio::sync::oneshot; -use super::{root::Root, Ctx, Executor, Logs, Signals, Term}; -use crate::{config::keymap::{Control, Key, KeymapLayer}, core::{files::FilesOp, input::InputMode, Event}, emit, misc::absolute_path}; +use crate::{Ctx, Executor, Logs, Root, Signals}; -pub struct App { +pub(super) struct App { cx: Ctx, term: Option, signals: Signals, } impl App { - pub async fn run() -> Result<()> { + pub(super) async fn run() -> Result<()> { let _log = Logs::init()?; let term = Term::start()?; 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), diff --git a/src/ui/context.rs b/app/src/context.rs similarity index 74% rename from src/ui/context.rs rename to app/src/context.rs index 0c18dace..3c047e5c 100644 --- a/src/ui/context.rs +++ b/app/src/context.rs @@ -1,4 +1,7 @@ -use crate::{config::keymap::KeymapLayer, core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position}, misc::tty_size}; +use core::{input::Input, manager::Manager, select::Select, tasks::Tasks, which::Which, Position}; + +use config::keymap::KeymapLayer; +use shared::tty_size; pub struct Ctx { pub manager: Manager, @@ -9,7 +12,7 @@ pub struct Ctx { } impl Ctx { - pub fn new() -> Self { + pub(super) fn new() -> Self { Self { manager: Manager::new(), which: Default::default(), @@ -20,7 +23,7 @@ impl Ctx { } #[inline] - pub fn cursor(&self) -> Option<(u16, u16)> { + pub(super) fn cursor(&self) -> Option<(u16, u16)> { if self.input.visible { return Some(self.input.cursor()); } @@ -28,7 +31,7 @@ impl Ctx { } #[inline] - pub fn layer(&self) -> KeymapLayer { + pub(super) fn layer(&self) -> KeymapLayer { if self.which.visible { KeymapLayer::Which } else if self.input.visible { @@ -43,7 +46,7 @@ impl Ctx { } #[inline] - pub fn image_layer(&self) -> bool { + pub(super) fn image_layer(&self) -> bool { match self.layer() { KeymapLayer::Which => false, KeymapLayer::Tasks => false, @@ -51,7 +54,7 @@ impl Ctx { } } - pub fn position(&self, pos: Position) -> Position { + pub(super) fn position(&self, pos: Position) -> Position { match pos { Position::Top => Position::Coords((tty_size().ws_col / 2).saturating_sub(25), 2), Position::Hovered => self diff --git a/src/ui/dispatcher.rs b/app/src/executor.rs similarity index 94% rename from src/ui/dispatcher.rs rename to app/src/executor.rs index 5be44529..607c34a5 100644 --- a/src/ui/dispatcher.rs +++ b/app/src/executor.rs @@ -1,12 +1,15 @@ +use core::{emit, files::FilesSort, input::InputMode}; use std::path::PathBuf; -use super::Ctx; -use crate::{config::{keymap::{Control, Exec, Key, KeymapLayer}, manager::SortBy, KEYMAP}, core::{files::FilesSort, input::InputMode}, emit, misc::optional_bool}; +use config::{keymap::{Control, Exec, Key, KeymapLayer}, manager::SortBy, KEYMAP}; +use shared::optional_bool; -pub struct Executor; +use super::Ctx; + +pub(super) struct Executor; impl Executor { - pub fn handle(cx: &mut Ctx, key: Key) -> bool { + pub(super) fn handle(cx: &mut Ctx, key: Key) -> bool { let layer = cx.layer(); if layer == KeymapLayer::Which { return cx.which.press(key); @@ -33,7 +36,7 @@ impl Executor { } #[inline] - pub fn dispatch(cx: &mut Ctx, exec: &Vec, layer: KeymapLayer) -> bool { + pub(super) fn dispatch(cx: &mut Ctx, exec: &Vec, layer: KeymapLayer) -> bool { let mut render = false; for e in exec { render |= match layer { diff --git a/src/ui/header/layout.rs b/app/src/header/layout.rs similarity index 70% rename from src/ui/header/layout.rs rename to app/src/header/layout.rs index 59b517fb..60978d01 100644 --- a/src/ui/header/layout.rs +++ b/app/src/header/layout.rs @@ -1,14 +1,15 @@ -use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Paragraph, Widget}}; +use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Paragraph, Widget}}; +use shared::readable_home; -use super::tabs::Tabs; -use crate::{misc::readable_home, ui::Ctx}; +use super::Tabs; +use crate::Ctx; -pub struct Layout<'a> { +pub(crate) struct Layout<'a> { cx: &'a Ctx, } impl<'a> Layout<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Layout<'a> { diff --git a/app/src/header/mod.rs b/app/src/header/mod.rs new file mode 100644 index 00000000..6587c464 --- /dev/null +++ b/app/src/header/mod.rs @@ -0,0 +1,5 @@ +mod layout; +mod tabs; + +pub(super) use layout::*; +pub(self) use tabs::*; diff --git a/src/ui/header/tabs.rs b/app/src/header/tabs.rs similarity index 84% rename from src/ui/header/tabs.rs rename to app/src/header/tabs.rs index 89c29bfe..02f8ca44 100644 --- a/src/ui/header/tabs.rs +++ b/app/src/header/tabs.rs @@ -1,13 +1,14 @@ +use config::THEME; use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}}; -use crate::{config::THEME, ui::Ctx}; +use crate::Ctx; -pub struct Tabs<'a> { +pub(super) struct Tabs<'a> { cx: &'a Ctx, } impl<'a> Tabs<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Tabs<'a> { diff --git a/src/ui/input.rs b/app/src/input/input.rs similarity index 86% rename from src/ui/input.rs rename to app/src/input/input.rs index 01bed7d1..d7856746 100644 --- a/src/ui/input.rs +++ b/app/src/input/input.rs @@ -1,14 +1,16 @@ +use core::input::InputMode; + use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, text::Line, widgets::{Block, BorderType, Borders, Clear, Paragraph, Widget}}; +use shared::Term; -use super::{Ctx, Term}; -use crate::core::input::InputMode; +use crate::Ctx; -pub struct Input<'a> { +pub(crate) struct Input<'a> { cx: &'a Ctx, } impl<'a> Input<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Input<'a> { diff --git a/app/src/input/mod.rs b/app/src/input/mod.rs new file mode 100644 index 00000000..bfe62746 --- /dev/null +++ b/app/src/input/mod.rs @@ -0,0 +1,3 @@ +mod input; + +pub(super) use input::*; diff --git a/src/ui/logs.rs b/app/src/logs.rs similarity index 66% rename from src/ui/logs.rs rename to app/src/logs.rs index de5c5f53..d45ced55 100644 --- a/src/ui/logs.rs +++ b/app/src/logs.rs @@ -1,16 +1,13 @@ use anyhow::{Context, Result}; +use config::LOG; use tracing_appender::non_blocking::WorkerGuard; use tracing_subscriber::{fmt, prelude::__tracing_subscriber_SubscriberExt, Registry}; -pub struct Logs {} +pub(super) struct Logs {} impl Logs { - pub fn init() -> Result { - let root = xdg::BaseDirectories::with_prefix("yazi") - .context("failed to get XDG base directories")? - .get_state_home(); - - let appender = tracing_appender::rolling::never(root, "yazi.log"); + pub(super) fn init() -> Result { + let appender = tracing_appender::rolling::never(&LOG.root, "yazi.log"); let (handle, guard) = tracing_appender::non_blocking(appender); // let filter = EnvFilter::from_default_env(); diff --git a/app/src/main.rs b/app/src/main.rs new file mode 100644 index 00000000..049ddd3f --- /dev/null +++ b/app/src/main.rs @@ -0,0 +1,31 @@ +mod app; +mod context; +mod executor; +mod header; +mod input; +mod logs; +mod manager; +mod root; +mod select; +mod signals; +mod status; +mod tasks; +mod which; + +pub(self) use app::*; +pub(self) use context::*; +pub(self) use executor::*; +pub(self) use logs::*; +pub(self) use root::*; +pub(self) use signals::*; + +#[tokio::main] +async fn main() -> anyhow::Result<()> { + // console_subscriber::init(); + + config::init(); + + adaptor::Adaptor::init(); + + App::run().await +} diff --git a/src/ui/manager/folder.rs b/app/src/manager/folder.rs similarity index 84% rename from src/ui/manager/folder.rs rename to app/src/manager/folder.rs index d0ef0123..53738ca4 100644 --- a/src/ui/manager/folder.rs +++ b/app/src/manager/folder.rs @@ -1,8 +1,12 @@ +use core::files::File; + +use config::THEME; use ratatui::{buffer::Buffer, layout::Rect, style::Style, widgets::{List, ListItem, Widget}}; +use shared::readable_path; -use crate::{config::THEME, core::{self, files::File}, misc::readable_path, ui::Ctx}; +use crate::Ctx; -pub struct Folder<'a> { +pub(super) struct Folder<'a> { cx: &'a Ctx, folder: &'a core::manager::Folder, is_preview: bool, @@ -10,18 +14,18 @@ pub struct Folder<'a> { } impl<'a> Folder<'a> { - pub fn new(cx: &'a Ctx, folder: &'a core::manager::Folder) -> Self { + pub(super) fn new(cx: &'a Ctx, folder: &'a core::manager::Folder) -> Self { Self { cx, folder, is_preview: false, is_selection: true } } #[inline] - pub fn with_preview(mut self, state: bool) -> Self { + pub(super) fn with_preview(mut self, state: bool) -> Self { self.is_preview = state; self } #[inline] - pub fn with_selection(mut self, state: bool) -> Self { + pub(super) fn with_selection(mut self, state: bool) -> Self { self.is_selection = state; self } diff --git a/src/ui/manager/layout.rs b/app/src/manager/layout.rs similarity index 86% rename from src/ui/manager/layout.rs rename to app/src/manager/layout.rs index d998c772..073f5aeb 100644 --- a/src/ui/manager/layout.rs +++ b/app/src/manager/layout.rs @@ -1,14 +1,16 @@ +use core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}; + use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::{Block, Borders, Padding, Widget}}; use super::{Folder, Preview}; -use crate::{core::manager::{Mode, ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_RATIO}, ui::Ctx}; +use crate::Ctx; -pub struct Layout<'a> { +pub(crate) struct Layout<'a> { cx: &'a Ctx, } impl<'a> Layout<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Layout<'a> { diff --git a/app/src/manager/mod.rs b/app/src/manager/mod.rs new file mode 100644 index 00000000..3a32499f --- /dev/null +++ b/app/src/manager/mod.rs @@ -0,0 +1,7 @@ +mod folder; +mod layout; +mod preview; + +pub(self) use folder::*; +pub(super) use layout::*; +pub(self) use preview::*; diff --git a/src/ui/manager/preview.rs b/app/src/manager/preview.rs similarity index 86% rename from src/ui/manager/preview.rs rename to app/src/manager/preview.rs index 137b51ec..dc48ebe5 100644 --- a/src/ui/manager/preview.rs +++ b/app/src/manager/preview.rs @@ -1,15 +1,17 @@ +use core::manager::{PreviewData, PREVIEW_BORDER}; + use ansi_to_tui::IntoText; use ratatui::{buffer::Buffer, layout::Rect, widgets::{Clear, Paragraph, Widget}}; use super::Folder; -use crate::{core::manager::{PreviewData, PREVIEW_BORDER}, ui::Ctx}; +use crate::Ctx; -pub struct Preview<'a> { +pub(super) struct Preview<'a> { cx: &'a Ctx, } impl<'a> Preview<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Preview<'a> { diff --git a/src/ui/root.rs b/app/src/root.rs similarity index 71% rename from src/ui/root.rs rename to app/src/root.rs index c202aa2f..0460be6a 100644 --- a/src/ui/root.rs +++ b/app/src/root.rs @@ -1,13 +1,13 @@ use ratatui::{buffer::Buffer, layout::{Constraint, Direction, Layout, Rect}, widgets::Widget}; -use super::{header, manager, status, tasks, which::Which, Ctx, Input, Select}; +use super::{header, input, manager, select, status, tasks, which, Ctx}; -pub struct Root<'a> { +pub(super) struct Root<'a> { cx: &'a Ctx, } impl<'a> Root<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Root<'a> { @@ -26,15 +26,15 @@ impl<'a> Widget for Root<'a> { } if self.cx.select.visible { - Select::new(self.cx).render(area, buf); + select::Select::new(self.cx).render(area, buf); } if self.cx.input.visible { - Input::new(self.cx).render(area, buf); + input::Input::new(self.cx).render(area, buf); } if self.cx.which.visible { - Which::new(self.cx).render(area, buf); + which::Which::new(self.cx).render(area, buf); } } } diff --git a/app/src/select/mod.rs b/app/src/select/mod.rs new file mode 100644 index 00000000..d4c70f1a --- /dev/null +++ b/app/src/select/mod.rs @@ -0,0 +1,3 @@ +mod select; + +pub(super) use select::*; diff --git a/src/ui/select.rs b/app/src/select/select.rs similarity index 89% rename from src/ui/select.rs rename to app/src/select/select.rs index f99533b5..a0f9a609 100644 --- a/src/ui/select.rs +++ b/app/src/select/select.rs @@ -1,13 +1,13 @@ use ratatui::{buffer::Buffer, layout::Rect, style::{Color, Style}, widgets::{Block, BorderType, Borders, Clear, List, ListItem, Widget}}; -use super::Ctx; +use crate::Ctx; -pub struct Select<'a> { +pub(crate) struct Select<'a> { cx: &'a Ctx, } impl<'a> Select<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Select<'a> { diff --git a/src/ui/signals.rs b/app/src/signals.rs similarity index 87% rename from src/ui/signals.rs rename to app/src/signals.rs index 3636c703..94e696ea 100644 --- a/src/ui/signals.rs +++ b/app/src/signals.rs @@ -1,21 +1,21 @@ +use core::Event; + use anyhow::Result; use crossterm::event::{Event as CrosstermEvent, EventStream}; use futures::StreamExt; use libc::{SIGHUP, SIGINT, SIGQUIT, SIGTERM}; use tokio::{select, sync::{mpsc::{self, UnboundedReceiver, UnboundedSender}, oneshot}, task::JoinHandle}; -use crate::core::Event; - -pub struct Signals { - pub tx: UnboundedSender, - pub rx: UnboundedReceiver, +pub(super) struct Signals { + tx: UnboundedSender, + rx: UnboundedReceiver, term_stop_tx: Option>, term_stop_rx: Option>, } impl Signals { - pub fn start() -> Result { + pub(super) fn start() -> Result { let (tx, rx) = mpsc::unbounded_channel(); let (term_tx, term_rx) = oneshot::channel(); @@ -29,6 +29,23 @@ impl Signals { Ok(signals) } + #[inline] + pub(super) async fn recv(&mut self) -> Option { 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> { let tx = self.tx.clone(); let mut signals = signal_hook_tokio::Signals::new([SIGHUP, SIGTERM, SIGINT, SIGQUIT])?; @@ -72,18 +89,4 @@ impl Signals { } }) } - - pub 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(); - } - } } diff --git a/src/ui/status/layout.rs b/app/src/status/layout.rs similarity index 83% rename from src/ui/status/layout.rs rename to app/src/status/layout.rs index eefbd034..233f7d1f 100644 --- a/src/ui/status/layout.rs +++ b/app/src/status/layout.rs @@ -1,14 +1,14 @@ use ratatui::{buffer::Buffer, layout::{self, Constraint, Direction, Rect}, widgets::Widget}; use super::{Left, Right}; -use crate::ui::Ctx; +use crate::Ctx; -pub struct Layout<'a> { +pub(crate) struct Layout<'a> { cx: &'a Ctx, } impl<'a> Layout<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Layout<'a> { diff --git a/src/ui/status/left.rs b/app/src/status/left.rs similarity index 87% rename from src/ui/status/left.rs rename to app/src/status/left.rs index 8f36574a..b87fc180 100644 --- a/src/ui/status/left.rs +++ b/app/src/status/left.rs @@ -1,13 +1,15 @@ +use config::THEME; use ratatui::{buffer::Buffer, layout::Rect, style::Modifier, text::{Line, Span}, widgets::{Paragraph, Widget}}; +use shared::readable_size; -use crate::{config::THEME, misc::readable_size, ui::Ctx}; +use crate::Ctx; -pub struct Left<'a> { +pub(super) struct Left<'a> { cx: &'a Ctx, } impl<'a> Left<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Left<'a> { diff --git a/app/src/status/mod.rs b/app/src/status/mod.rs new file mode 100644 index 00000000..a020bb96 --- /dev/null +++ b/app/src/status/mod.rs @@ -0,0 +1,9 @@ +mod layout; +mod left; +mod progress; +mod right; + +pub(super) use layout::*; +pub(self) use left::*; +pub(self) use progress::*; +pub(self) use right::*; diff --git a/src/ui/status/progress.rs b/app/src/status/progress.rs similarity index 81% rename from src/ui/status/progress.rs rename to app/src/status/progress.rs index 431d2f6c..0985e0a3 100644 --- a/src/ui/status/progress.rs +++ b/app/src/status/progress.rs @@ -1,13 +1,14 @@ +use config::THEME; use ratatui::{buffer::Buffer, layout::Rect, text::Span, widgets::{Gauge, Widget}}; -use crate::{config::THEME, ui::Ctx}; +use crate::Ctx; -pub struct Progress<'a> { +pub(super) struct Progress<'a> { cx: &'a Ctx, } impl<'a> Progress<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl<'a> Widget for Progress<'a> { diff --git a/src/ui/status/right.rs b/app/src/status/right.rs similarity index 94% rename from src/ui/status/right.rs rename to app/src/status/right.rs index 6aa2411e..03172e55 100644 --- a/src/ui/status/right.rs +++ b/app/src/status/right.rs @@ -1,16 +1,18 @@ use std::os::unix::prelude::PermissionsExt; +use config::THEME; use ratatui::{buffer::Buffer, layout::{Alignment, Rect}, text::{Line, Span}, widgets::{Paragraph, Widget}}; +use shared::file_mode; use super::Progress; -use crate::{config::THEME, misc::file_mode, ui::Ctx}; +use crate::Ctx; -pub struct Right<'a> { +pub(super) struct Right<'a> { cx: &'a Ctx, } impl<'a> Right<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(super) fn new(cx: &'a Ctx) -> Self { Self { cx } } fn permissions(&self, s: &str) -> Vec { // Colors diff --git a/src/ui/tasks/clear.rs b/app/src/tasks/clear.rs similarity index 92% rename from src/ui/tasks/clear.rs rename to app/src/tasks/clear.rs index d9526402..2aaa073e 100644 --- a/src/ui/tasks/clear.rs +++ b/app/src/tasks/clear.rs @@ -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) { diff --git a/src/ui/tasks/layout.rs b/app/src/tasks/layout.rs similarity index 90% rename from src/ui/tasks/layout.rs rename to app/src/tasks/layout.rs index cd5fc327..7e0b2ddc 100644 --- a/src/ui/tasks/layout.rs +++ b/app/src/tasks/layout.rs @@ -1,16 +1,18 @@ +use core::tasks::TASKS_PERCENT; + use ratatui::{buffer::Buffer, layout::{self, Alignment, Constraint, Direction, Rect}, style::{Color, Modifier, Style}, widgets::{Block, BorderType, Borders, List, ListItem, Padding, Widget}}; use super::Clear; -use crate::{core::tasks::TASKS_PERCENT, ui::Ctx}; +use crate::Ctx; -pub struct Layout<'a> { +pub(crate) struct Layout<'a> { cx: &'a Ctx, } impl<'a> Layout<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } - pub fn area(area: Rect) -> Rect { + pub(super) fn area(area: Rect) -> Rect { let chunk = layout::Layout::new() .direction(Direction::Vertical) .constraints( diff --git a/app/src/tasks/mod.rs b/app/src/tasks/mod.rs new file mode 100644 index 00000000..0bf8cc59 --- /dev/null +++ b/app/src/tasks/mod.rs @@ -0,0 +1,5 @@ +mod clear; +mod layout; + +pub(self) use clear::*; +pub(super) use layout::*; diff --git a/src/ui/which/layout.rs b/app/src/which/layout.rs similarity index 92% rename from src/ui/which/layout.rs rename to app/src/which/layout.rs index 285ac8d1..a7a1935c 100644 --- a/src/ui/which/layout.rs +++ b/app/src/which/layout.rs @@ -1,14 +1,14 @@ use ratatui::{layout, prelude::{Buffer, Constraint, Direction, Rect}, style::{Color, Style}, widgets::{Block, Clear, Widget}}; use super::Side; -use crate::ui::Ctx; +use crate::Ctx; -pub struct Which<'a> { +pub(crate) struct Which<'a> { cx: &'a Ctx, } impl<'a> Which<'a> { - pub fn new(cx: &'a Ctx) -> Self { Self { cx } } + pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } } } impl Widget for Which<'_> { diff --git a/app/src/which/mod.rs b/app/src/which/mod.rs new file mode 100644 index 00000000..2b637f9b --- /dev/null +++ b/app/src/which/mod.rs @@ -0,0 +1,5 @@ +mod layout; +mod side; + +pub(super) use layout::*; +pub(self) use side::*; diff --git a/src/ui/which/side.rs b/app/src/which/side.rs similarity index 88% rename from src/ui/which/side.rs rename to app/src/which/side.rs index bccbd31a..bbdd95e8 100644 --- a/src/ui/which/side.rs +++ b/app/src/which/side.rs @@ -1,14 +1,13 @@ +use config::keymap::Control; use ratatui::{prelude::{Buffer, Rect}, style::{Color, Style}, text::{Line, Span}, widgets::{Block, List, ListItem, Padding, Widget}}; -use crate::config::keymap::Control; - -pub struct Side<'a> { +pub(super) struct Side<'a> { times: usize, cands: Vec<&'a Control>, } impl<'a> Side<'a> { - pub fn new(times: usize, cands: Vec<&'a Control>) -> Self { Self { times, cands } } + pub(super) fn new(times: usize, cands: Vec<&'a Control>) -> Self { Self { times, cands } } } impl Widget for Side<'_> { diff --git a/config/Cargo.toml b/config/Cargo.toml new file mode 100644 index 00000000..f259b1ef --- /dev/null +++ b/config/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "config" +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" diff --git a/config/README.md b/config/README.md deleted file mode 100644 index 04e2139a..00000000 --- a/config/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Configuration - -[See ../docs for more information.](../docs) diff --git a/docs/keymap.md b/config/docs/keymap.md similarity index 100% rename from docs/keymap.md rename to config/docs/keymap.md diff --git a/docs/theme.md b/config/docs/theme.md similarity index 100% rename from docs/theme.md rename to config/docs/theme.md diff --git a/docs/yazi.md b/config/docs/yazi.md similarity index 100% rename from docs/yazi.md rename to config/docs/yazi.md diff --git a/config/keymap.toml b/config/preset/keymap.toml similarity index 87% rename from config/keymap.toml rename to config/preset/keymap.toml index ee6d49c2..059f6ae4 100644 --- a/config/keymap.toml +++ b/config/preset/keymap.toml @@ -22,7 +22,6 @@ keymap = [ { on = [ "" ], exec = "arrow 1" }, { on = [ "" ], exec = "leave" }, { on = [ "" ], exec = "enter" }, - { on = [ "" ], exec = "open" }, # Selection { on = [ "" ], exec = [ "select --state=none", "arrow 1" ] }, @@ -34,13 +33,17 @@ keymap = [ # Operation { on = [ "o" ], exec = "open" }, { on = [ "O" ], exec = "open --interactive" }, + { on = [ "" ], exec = "open" }, + { on = [ "" ], exec = "open --interactive" }, # It's cool if you're using a terminal that supports CSI u { on = [ "y" ], exec = "yank" }, { on = [ "x" ], exec = "yank --cut" }, { on = [ "p" ], exec = "paste" }, { on = [ "P" ], exec = "paste --force" }, + { on = [ "k" ], exec = "paste --follow" }, + { on = [ "K" ], exec = "paste --follow --force" }, { on = [ "d" ], exec = "remove" }, { on = [ "D" ], exec = "remove --permanently" }, - { on = [ "c" ], exec = "create" }, + { on = [ "a" ], exec = "create" }, { on = [ "r" ], exec = "rename" }, { on = [ "." ], exec = "hidden toggle" }, { on = [ "s" ], exec = "search fd" }, @@ -49,6 +52,12 @@ keymap = [ { on = [ "z" ], exec = "jump zoxide" }, { on = [ "Z" ], exec = "jump fzf" }, + # Copy + { on = [ "c", "c" ], exec = "copy path" }, + { on = [ "c", "d" ], exec = "copy dirname" }, + { on = [ "c", "f" ], exec = "copy filename" }, + { on = [ "c", "n" ], exec = "copy name_without_ext" }, + # Sorting { on = [ ",", "a" ], exec = "sort alphabetical" }, { on = [ ",", "A" ], exec = "sort alphabetical --reverse" }, @@ -67,6 +76,10 @@ keymap = [ { on = [ "3" ], exec = "tab_switch 2" }, { on = [ "4" ], exec = "tab_switch 3" }, { on = [ "5" ], exec = "tab_switch 4" }, + { on = [ "6" ], exec = "tab_switch 5" }, + { on = [ "7" ], exec = "tab_switch 6" }, + { on = [ "8" ], exec = "tab_switch 7" }, + { on = [ "9" ], exec = "tab_switch 8" }, { on = [ "[" ], exec = "tab_switch -1 --relative" }, { on = [ "]" ], exec = "tab_switch 1 --relative" }, @@ -151,7 +164,7 @@ keymap = [ { on = [ "c" ], exec = "delete --cut --insert" }, { on = [ "x" ], exec = [ "delete --cut", "move 1 --in-operating" ] }, - # Copy/Paste + # Yank/Paste { on = [ "y" ], exec = [ "yank" ] }, { on = [ "p" ], exec = [ "paste" ] }, { on = [ "P" ], exec = [ "paste --before" ] }, diff --git a/config/theme.toml b/config/preset/theme.toml similarity index 100% rename from config/theme.toml rename to config/preset/theme.toml diff --git a/config/yazi.toml b/config/preset/yazi.toml similarity index 95% rename from config/yazi.toml rename to config/preset/yazi.toml index 6c7eb5c1..076d1fbc 100644 --- a/config/yazi.toml +++ b/config/preset/yazi.toml @@ -11,7 +11,7 @@ max_height = 900 [opener] folder = [ { cmd = "open", args = [ "-R", "$*" ] }, - { cmd = "code", args = [ "$*" ] }, + { cmd = "vim", args = [ "$*" ] }, ] archive = [ { cmd = "unar", args = [ "$1" ] }, @@ -54,3 +54,6 @@ rules = [ { mime = "application/zip", use = "archive" }, { mime = "application/x-7z-compressed", use = "archive" }, ] + +[log] +enabled = false diff --git a/src/config/keymap/exec.rs b/config/src/keymap/exec.rs similarity index 100% rename from src/config/keymap/exec.rs rename to config/src/keymap/exec.rs diff --git a/src/config/keymap/key.rs b/config/src/keymap/key.rs similarity index 100% rename from src/config/keymap/key.rs rename to config/src/keymap/key.rs diff --git a/src/config/keymap/keymap.rs b/config/src/keymap/keymap.rs similarity index 97% rename from src/config/keymap/keymap.rs rename to config/src/keymap/keymap.rs index 140f2b43..862d6b43 100644 --- a/src/config/keymap/keymap.rs +++ b/config/src/keymap/keymap.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Deserializer}; use super::{Exec, Key}; -use crate::config::MERGED_KEYMAP; +use crate::MERGED_KEYMAP; #[derive(Clone, Debug, Deserialize)] pub struct Control { diff --git a/src/config/keymap/mod.rs b/config/src/keymap/mod.rs similarity index 100% rename from src/config/keymap/mod.rs rename to config/src/keymap/mod.rs diff --git a/src/config/mod.rs b/config/src/lib.rs similarity index 90% rename from src/config/mod.rs rename to config/src/lib.rs index 1ddd9df4..1758c142 100644 --- a/src/config/mod.rs +++ b/config/src/lib.rs @@ -1,6 +1,7 @@ use once_cell::sync::Lazy; pub mod keymap; +mod log; pub mod manager; pub mod open; mod pattern; @@ -16,6 +17,7 @@ static MERGED_THEME: Lazy = Lazy::new(|| Preset::theme()); static MERGED_YAZI: Lazy = Lazy::new(|| Preset::yazi()); pub static KEYMAP: Lazy = Lazy::new(|| keymap::Keymap::new()); +pub static LOG: Lazy = Lazy::new(|| log::Log::new()); pub static MANAGER: Lazy = Lazy::new(|| manager::Manager::new()); pub static OPEN: Lazy = Lazy::new(|| open::Open::new()); pub static PREVIEW: Lazy = Lazy::new(|| preview::Preview::new()); @@ -23,6 +25,7 @@ pub static THEME: Lazy = Lazy::new(|| theme::Theme::new()); pub fn init() { Lazy::force(&KEYMAP); + Lazy::force(&LOG); Lazy::force(&MANAGER); Lazy::force(&OPEN); Lazy::force(&PREVIEW); diff --git a/config/src/log/log.rs b/config/src/log/log.rs new file mode 100644 index 00000000..f112cf1a --- /dev/null +++ b/config/src/log/log.rs @@ -0,0 +1,42 @@ +use std::path::PathBuf; + +use serde::{de, Deserialize, Deserializer}; + +use crate::MERGED_YAZI; + +#[derive(Debug)] +pub struct Log { + pub enabled: bool, + pub root: PathBuf, +} + +impl Log { + pub fn new() -> Self { toml::from_str(&MERGED_YAZI).unwrap() } +} + +impl<'de> Deserialize<'de> for Log { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + #[derive(Deserialize)] + struct Outer { + log: Shadow, + } + #[derive(Deserialize)] + struct Shadow { + enabled: bool, + } + + let outer = Outer::deserialize(deserializer)?; + + let root = xdg::BaseDirectories::with_prefix("yazi") + .map_err(|e| de::Error::custom(e.to_string()))? + .get_state_home(); + if !root.is_dir() { + std::fs::create_dir_all(&root).map_err(|e| de::Error::custom(e.to_string()))?; + } + + Ok(Self { enabled: outer.log.enabled, root }) + } +} diff --git a/config/src/log/mod.rs b/config/src/log/mod.rs new file mode 100644 index 00000000..b19c0087 --- /dev/null +++ b/config/src/log/mod.rs @@ -0,0 +1,3 @@ +mod log; + +pub use log::*; diff --git a/src/config/manager/manager.rs b/config/src/manager/manager.rs similarity index 95% rename from src/config/manager/manager.rs rename to config/src/manager/manager.rs index d09ae776..64c83603 100644 --- a/src/config/manager/manager.rs +++ b/config/src/manager/manager.rs @@ -3,7 +3,7 @@ use std::{env, fs, path::PathBuf}; use serde::Deserialize; use super::SortBy; -use crate::config::MERGED_YAZI; +use crate::MERGED_YAZI; #[derive(Debug, Deserialize)] pub struct Manager { diff --git a/src/config/manager/mod.rs b/config/src/manager/mod.rs similarity index 100% rename from src/config/manager/mod.rs rename to config/src/manager/mod.rs diff --git a/src/config/manager/sorting.rs b/config/src/manager/sorting.rs similarity index 100% rename from src/config/manager/sorting.rs rename to config/src/manager/sorting.rs diff --git a/src/config/open/mod.rs b/config/src/open/mod.rs similarity index 100% rename from src/config/open/mod.rs rename to config/src/open/mod.rs diff --git a/src/config/open/open.rs b/config/src/open/open.rs similarity index 96% rename from src/config/open/open.rs rename to config/src/open/open.rs index a1f95fdc..68b43d91 100644 --- a/src/config/open/open.rs +++ b/config/src/open/open.rs @@ -1,9 +1,10 @@ use std::{collections::{BTreeMap, BTreeSet}, path::Path}; use serde::{Deserialize, Deserializer}; +use shared::MIME_DIR; use super::Opener; -use crate::{config::{Pattern, MERGED_YAZI}, misc::MIME_DIR}; +use crate::{Pattern, MERGED_YAZI}; #[derive(Debug)] pub struct Open { diff --git a/src/config/open/opener.rs b/config/src/open/opener.rs similarity index 100% rename from src/config/open/opener.rs rename to config/src/open/opener.rs diff --git a/src/config/pattern.rs b/config/src/pattern.rs similarity index 100% rename from src/config/pattern.rs rename to config/src/pattern.rs diff --git a/src/config/preset.rs b/config/src/preset.rs similarity index 80% rename from src/config/preset.rs rename to config/src/preset.rs index d9e4ac0f..cd745c7d 100644 --- a/src/config/preset.rs +++ b/config/src/preset.rs @@ -40,16 +40,16 @@ impl Preset { #[inline] pub(crate) fn keymap() -> String { - Self::merge_str("yazi/keymap.toml", include_str!("../../config/keymap.toml")) + Self::merge_str("yazi/keymap.toml", include_str!("../preset/keymap.toml")) } #[inline] pub(crate) fn theme() -> String { - Self::merge_str("yazi/theme.toml", include_str!("../../config/theme.toml")) + Self::merge_str("yazi/theme.toml", include_str!("../preset/theme.toml")) } #[inline] pub(crate) fn yazi() -> String { - Self::merge_str("yazi/yazi.toml", include_str!("../../config/yazi.toml")) + Self::merge_str("yazi/yazi.toml", include_str!("../preset/yazi.toml")) } } diff --git a/src/config/preview/adaptor.rs b/config/src/preview/adaptor.rs similarity index 95% rename from src/config/preview/adaptor.rs rename to config/src/preview/adaptor.rs index c0662d1c..f961026f 100644 --- a/src/config/preview/adaptor.rs +++ b/config/src/preview/adaptor.rs @@ -4,9 +4,9 @@ use std::env; pub enum PreviewAdaptor { Kitty, Iterm2, + Sixel, // Supported by Überzug++ - Sixel, X11, Wayland, Chafa, @@ -28,6 +28,7 @@ impl Default for PreviewAdaptor { } match env::var("TERM_PROGRAM").unwrap_or_default().as_str() { "iTerm.app" => return Self::Iterm2, + "Hyper" => return Self::Sixel, _ => {} } match env::var("XDG_SESSION_TYPE").unwrap_or_default().as_str() { @@ -58,6 +59,7 @@ impl PreviewAdaptor { match self { PreviewAdaptor::Kitty => false, PreviewAdaptor::Iterm2 => false, + PreviewAdaptor::Sixel => false, _ => true, } } diff --git a/src/config/preview/mod.rs b/config/src/preview/mod.rs similarity index 100% rename from src/config/preview/mod.rs rename to config/src/preview/mod.rs diff --git a/src/config/preview/preview.rs b/config/src/preview/preview.rs similarity index 92% rename from src/config/preview/preview.rs rename to config/src/preview/preview.rs index 613ca510..d5180bc2 100644 --- a/src/config/preview/preview.rs +++ b/config/src/preview/preview.rs @@ -1,7 +1,7 @@ use serde::Deserialize; use super::PreviewAdaptor; -use crate::config::MERGED_YAZI; +use crate::MERGED_YAZI; #[derive(Debug, Deserialize)] pub struct Preview { diff --git a/src/config/theme/color.rs b/config/src/theme/color.rs similarity index 100% rename from src/config/theme/color.rs rename to config/src/theme/color.rs diff --git a/src/config/theme/filetype.rs b/config/src/theme/filetype.rs similarity index 96% rename from src/config/theme/filetype.rs rename to config/src/theme/filetype.rs index b31bc95c..6512269d 100644 --- a/src/config/theme/filetype.rs +++ b/config/src/theme/filetype.rs @@ -3,7 +3,7 @@ use std::path::Path; use serde::{Deserialize, Deserializer}; use super::Style; -use crate::config::{theme::Color, Pattern}; +use crate::{theme::Color, Pattern}; pub struct Filetype { pub name: Option, diff --git a/src/config/theme/icon.rs b/config/src/theme/icon.rs similarity index 97% rename from src/config/theme/icon.rs rename to config/src/theme/icon.rs index 5a3792ae..7d4c9ccd 100644 --- a/src/config/theme/icon.rs +++ b/config/src/theme/icon.rs @@ -2,7 +2,7 @@ use std::fmt; use serde::{de::{self, Visitor}, Deserializer}; -use crate::config::Pattern; +use crate::Pattern; #[derive(Debug)] pub struct Icon { diff --git a/src/config/theme/mod.rs b/config/src/theme/mod.rs similarity index 100% rename from src/config/theme/mod.rs rename to config/src/theme/mod.rs diff --git a/src/config/theme/style.rs b/config/src/theme/style.rs similarity index 100% rename from src/config/theme/style.rs rename to config/src/theme/style.rs diff --git a/src/config/theme/theme.rs b/config/src/theme/theme.rs similarity index 96% rename from src/config/theme/theme.rs rename to config/src/theme/theme.rs index 952ce5ab..1ff80bba 100644 --- a/src/config/theme/theme.rs +++ b/config/src/theme/theme.rs @@ -1,9 +1,10 @@ use std::path::PathBuf; use serde::Deserialize; +use shared::absolute_path; use super::{ColorGroup, Filetype, Icon, Style}; -use crate::{config::MERGED_THEME, misc::absolute_path}; +use crate::MERGED_THEME; #[derive(Deserialize)] pub struct Tab { diff --git a/core/Cargo.toml b/core/Cargo.toml new file mode 100644 index 00000000..ffb73f4d --- /dev/null +++ b/core/Cargo.toml @@ -0,0 +1,27 @@ +[package] +name = "core" +version = "0.1.0" +edition = "2021" + +[dependencies] +adaptor = { path = "../adaptor" } +config = { path = "../config" } +shared = { path = "../shared" } + +# External dependencies +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" diff --git a/src/core/blocker.rs b/core/src/blocker.rs similarity index 100% rename from src/core/blocker.rs rename to core/src/blocker.rs diff --git a/src/core/event.rs b/core/src/event.rs similarity index 68% rename from src/core/event.rs rename to core/src/event.rs index b9b65f07..698db623 100644 --- a/src/core/event.rs +++ b/core/src/event.rs @@ -1,11 +1,11 @@ use std::{collections::BTreeMap, path::PathBuf}; use anyhow::Result; +use config::{keymap::{Control, KeymapLayer}, open::Opener}; use crossterm::event::KeyEvent; use tokio::sync::{mpsc::UnboundedSender, oneshot}; use super::{files::{File, FilesOp}, input::InputOpt, manager::PreviewData, select::SelectOpt}; -use crate::config::{keymap::{Control, KeymapLayer}, open::Opener}; static mut TX: Option> = None; @@ -60,61 +60,61 @@ impl Event { #[macro_export] macro_rules! emit { (Key($key:expr)) => { - $crate::core::Event::Key($key).emit(); + $crate::Event::Key($key).emit(); }; (Render) => { - $crate::core::Event::Render(format!("{}:{}", file!(), line!())).emit(); + $crate::Event::Render(format!("{}:{}", file!(), line!())).emit(); }; (Resize($cols:expr, $rows:expr)) => { - $crate::core::Event::Resize($cols, $rows).emit(); + $crate::Event::Resize($cols, $rows).emit(); }; (Stop($state:expr)) => {{ let (tx, rx) = tokio::sync::oneshot::channel(); - $crate::core::Event::Stop($state, Some(tx)).wait(rx) + $crate::Event::Stop($state, Some(tx)).wait(rx) }}; (Ctrl($exec:expr, $layer:expr)) => { - $crate::core::Event::Ctrl($exec, $layer).emit(); + $crate::Event::Ctrl($exec, $layer).emit(); }; (Cd($op:expr)) => { - $crate::core::Event::Cd($op).emit(); + $crate::Event::Cd($op).emit(); }; (Files($op:expr)) => { - $crate::core::Event::Files($op).emit(); + $crate::Event::Files($op).emit(); }; (Pages($page:expr)) => { - $crate::core::Event::Pages($page).emit(); + $crate::Event::Pages($page).emit(); }; (Mimetype($mimes:expr)) => { - $crate::core::Event::Mimetype($mimes).emit(); + $crate::Event::Mimetype($mimes).emit(); }; (Hover) => { - $crate::core::Event::Hover(None).emit(); + $crate::Event::Hover(None).emit(); }; (Hover($file:expr)) => { - $crate::core::Event::Hover(Some($file)).emit(); + $crate::Event::Hover(Some($file)).emit(); }; (Preview($path:expr, $mime:expr, $data:expr)) => { - $crate::core::Event::Preview($path, $mime, $data).emit(); + $crate::Event::Preview($path, $mime, $data).emit(); }; (Select($opt:expr)) => {{ let (tx, rx) = tokio::sync::oneshot::channel(); - $crate::core::Event::Select($opt, tx).wait(rx) + $crate::Event::Select($opt, tx).wait(rx) }}; (Input($opt:expr)) => {{ let (tx, rx) = tokio::sync::oneshot::channel(); - $crate::core::Event::Input($opt, tx).wait(rx) + $crate::Event::Input($opt, tx).wait(rx) }}; (Open($targets:expr, $opener:expr)) => { - $crate::core::Event::Open($targets, $opener).emit(); + $crate::Event::Open($targets, $opener).emit(); }; (Progress($percent:expr, $tasks:expr)) => { - $crate::core::Event::Progress($percent, $tasks).emit(); + $crate::Event::Progress($percent, $tasks).emit(); }; ($event:ident) => { - $crate::core::Event::$event.emit(); + $crate::Event::$event.emit(); }; } diff --git a/src/core/external/clipboard.rs b/core/src/external/clipboard.rs similarity index 100% rename from src/core/external/clipboard.rs rename to core/src/external/clipboard.rs diff --git a/src/core/external/fd.rs b/core/src/external/fd.rs similarity index 96% rename from src/core/external/fd.rs rename to core/src/external/fd.rs index 349687e1..91b8106b 100644 --- a/src/core/external/fd.rs +++ b/core/src/external/fd.rs @@ -1,10 +1,9 @@ use std::{path::PathBuf, process::Stdio, time::Duration}; use anyhow::Result; +use shared::DelayedBuffer; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver}; -use crate::misc::DelayedBuffer; - pub struct FdOpt { pub cwd: PathBuf, pub hidden: bool, diff --git a/src/core/external/ffmpegthumbnailer.rs b/core/src/external/ffmpegthumbnailer.rs similarity index 94% rename from src/core/external/ffmpegthumbnailer.rs rename to core/src/external/ffmpegthumbnailer.rs index f5663ca6..7a909dcb 100644 --- a/src/core/external/ffmpegthumbnailer.rs +++ b/core/src/external/ffmpegthumbnailer.rs @@ -1,10 +1,9 @@ use std::path::Path; use anyhow::{bail, Result}; +use config::PREVIEW; use tokio::process::Command; -use crate::config::PREVIEW; - pub async fn ffmpegthumbnailer(path: &Path, dest: &Path) -> Result<()> { let output = Command::new("ffmpegthumbnailer") .arg("-i") diff --git a/src/core/external/file.rs b/core/src/external/file.rs similarity index 96% rename from src/core/external/file.rs rename to core/src/external/file.rs index f878e280..5b2c2913 100644 --- a/src/core/external/file.rs +++ b/core/src/external/file.rs @@ -1,10 +1,9 @@ use std::{collections::BTreeMap, ffi::OsStr, path::PathBuf}; use anyhow::{bail, Result}; +use shared::MimeKind; use tokio::process::Command; -use crate::misc::MimeKind; - pub async fn file(files: &[impl AsRef]) -> Result> { if files.is_empty() { bail!("no files to get mime types for"); diff --git a/src/core/external/fzf.rs b/core/src/external/fzf.rs similarity index 100% rename from src/core/external/fzf.rs rename to core/src/external/fzf.rs diff --git a/src/core/external/jq.rs b/core/src/external/jq.rs similarity index 94% rename from src/core/external/jq.rs rename to core/src/external/jq.rs index 3c1beffc..1cdfc3d4 100644 --- a/src/core/external/jq.rs +++ b/core/src/external/jq.rs @@ -1,10 +1,9 @@ use std::path::Path; use anyhow::{bail, Result}; +use config::PREVIEW; use tokio::process::Command; -use crate::config::PREVIEW; - pub async fn jq(path: &Path) -> Result { let output = Command::new("jq") .args(["-C", "--indent", &PREVIEW.tab_size.to_string(), "."]) diff --git a/src/core/external/lsar.rs b/core/src/external/lsar.rs similarity index 100% rename from src/core/external/lsar.rs rename to core/src/external/lsar.rs diff --git a/src/core/external/mod.rs b/core/src/external/mod.rs similarity index 100% rename from src/core/external/mod.rs rename to core/src/external/mod.rs diff --git a/src/core/external/rg.rs b/core/src/external/rg.rs similarity index 96% rename from src/core/external/rg.rs rename to core/src/external/rg.rs index c8491326..9705f9c3 100644 --- a/src/core/external/rg.rs +++ b/core/src/external/rg.rs @@ -1,10 +1,9 @@ use std::{path::PathBuf, process::Stdio, time::Duration}; use anyhow::Result; +use shared::DelayedBuffer; use tokio::{io::{AsyncBufReadExt, BufReader}, process::Command, sync::mpsc::UnboundedReceiver}; -use crate::misc::DelayedBuffer; - pub struct RgOpt { pub cwd: PathBuf, pub hidden: bool, diff --git a/src/core/external/unar.rs b/core/src/external/unar.rs similarity index 100% rename from src/core/external/unar.rs rename to core/src/external/unar.rs diff --git a/src/core/external/zoxide.rs b/core/src/external/zoxide.rs similarity index 100% rename from src/core/external/zoxide.rs rename to core/src/external/zoxide.rs diff --git a/src/core/files/file.rs b/core/src/files/file.rs similarity index 100% rename from src/core/files/file.rs rename to core/src/files/file.rs diff --git a/src/core/files/files.rs b/core/src/files/files.rs similarity index 98% rename from src/core/files/files.rs rename to core/src/files/files.rs index ac13eba0..ac7a6be9 100644 --- a/src/core/files/files.rs +++ b/core/src/files/files.rs @@ -1,11 +1,11 @@ use std::{collections::BTreeMap, ops::{Deref, DerefMut}, path::{Path, PathBuf}}; use anyhow::Result; +use config::{manager::SortBy, MANAGER}; use indexmap::IndexMap; use tokio::fs; use super::File; -use crate::config::{manager::SortBy, MANAGER}; #[derive(Default)] pub struct Files { diff --git a/src/core/files/mod.rs b/core/src/files/mod.rs similarity index 100% rename from src/core/files/mod.rs rename to core/src/files/mod.rs diff --git a/src/core/input/input.rs b/core/src/input/input.rs similarity index 99% rename from src/core/input/input.rs rename to core/src/input/input.rs index 28b54069..1a132bab 100644 --- a/src/core/input/input.rs +++ b/core/src/input/input.rs @@ -2,11 +2,12 @@ use std::ops::Range; use anyhow::{anyhow, Result}; use ratatui::layout::Rect; +use shared::CharKind; use tokio::sync::oneshot::Sender; use unicode_width::UnicodeWidthStr; use super::{mode::InputMode, op::InputOp, InputSnap, InputSnaps}; -use crate::{core::{external, Position}, misc::CharKind}; +use crate::{external, Position}; #[derive(Default)] pub struct Input { diff --git a/src/core/input/mod.rs b/core/src/input/mod.rs similarity index 100% rename from src/core/input/mod.rs rename to core/src/input/mod.rs diff --git a/src/core/input/mode.rs b/core/src/input/mode.rs similarity index 100% rename from src/core/input/mode.rs rename to core/src/input/mode.rs diff --git a/src/core/input/op.rs b/core/src/input/op.rs similarity index 100% rename from src/core/input/op.rs rename to core/src/input/op.rs diff --git a/src/core/input/snap.rs b/core/src/input/snap.rs similarity index 100% rename from src/core/input/snap.rs rename to core/src/input/snap.rs diff --git a/src/core/input/snaps.rs b/core/src/input/snaps.rs similarity index 100% rename from src/core/input/snaps.rs rename to core/src/input/snaps.rs diff --git a/src/core/mod.rs b/core/src/lib.rs similarity index 92% rename from src/core/mod.rs rename to core/src/lib.rs index f2843f2d..a2a124e9 100644 --- a/src/core/mod.rs +++ b/core/src/lib.rs @@ -1,4 +1,3 @@ -pub mod adaptor; mod blocker; mod event; pub mod external; diff --git a/src/core/manager/folder.rs b/core/src/manager/folder.rs similarity index 98% rename from src/core/manager/folder.rs rename to core/src/manager/folder.rs index 648fa2ff..5f66f94e 100644 --- a/src/core/manager/folder.rs +++ b/core/src/manager/folder.rs @@ -2,9 +2,10 @@ use std::path::{Path, PathBuf}; use indexmap::map::Slice; use ratatui::layout::Rect; +use shared::tty_size; use super::{ALL_RATIO, CURRENT_RATIO, DIR_PADDING, PARENT_RATIO}; -use crate::{core::files::{File, Files, FilesOp}, emit, misc::tty_size}; +use crate::{emit, files::{File, Files, FilesOp}}; #[derive(Default)] pub struct Folder { diff --git a/src/core/manager/manager.rs b/core/src/manager/manager.rs similarity index 98% rename from src/core/manager/manager.rs rename to core/src/manager/manager.rs index 434d113e..edf93b07 100644 --- a/src/core/manager/manager.rs +++ b/core/src/manager/manager.rs @@ -1,10 +1,12 @@ use std::{collections::{BTreeMap, BTreeSet, HashMap, HashSet}, env, mem, path::PathBuf}; use anyhow::Error; +use config::OPEN; +use shared::MIME_DIR; use tokio::fs; use super::{PreviewData, Tab, Tabs, Watcher}; -use crate::{config::OPEN, core::{external, files::{File, FilesOp}, input::InputOpt, manager::Folder, select::SelectOpt, tasks::Tasks, Position}, emit, misc::MIME_DIR}; +use crate::{emit, external, files::{File, FilesOp}, input::InputOpt, manager::Folder, select::SelectOpt, tasks::Tasks, Position}; pub struct Manager { tabs: Tabs, diff --git a/src/core/manager/mod.rs b/core/src/manager/mod.rs similarity index 100% rename from src/core/manager/mod.rs rename to core/src/manager/mod.rs diff --git a/src/core/manager/mode.rs b/core/src/manager/mode.rs similarity index 94% rename from src/core/manager/mode.rs rename to core/src/manager/mode.rs index 39d3b98d..eded7dae 100644 --- a/src/core/manager/mode.rs +++ b/core/src/manager/mode.rs @@ -1,6 +1,6 @@ use std::fmt::Display; -use crate::config::theme::{self, ColorGroup}; +use config::theme::{self, ColorGroup}; #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum Mode { diff --git a/src/core/manager/preview.rs b/core/src/manager/preview.rs similarity index 93% rename from src/core/manager/preview.rs rename to core/src/manager/preview.rs index 8294f209..b634cb12 100644 --- a/src/core/manager/preview.rs +++ b/core/src/manager/preview.rs @@ -1,12 +1,15 @@ 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; +use shared::{tty_size, MimeKind}; use syntect::{easy::HighlightFile, highlighting::{Theme, ThemeSet}, parsing::SyntaxSet, util::as_24_bit_terminal_escaped}; use tokio::{fs, task::JoinHandle}; use super::{ALL_RATIO, CURRENT_RATIO, PARENT_RATIO, PREVIEW_BORDER, PREVIEW_MARGIN, PREVIEW_RATIO}; -use crate::{config::{PREVIEW, THEME}, core::{adaptor::Adaptor, external, files::{Files, FilesOp}, tasks::Precache}, emit, misc::{tty_size, MimeKind}}; +use crate::{emit, external, files::{Files, FilesOp}}; static SYNTECT_SYNTAX: OnceLock = OnceLock::new(); static SYNTECT_THEME: OnceLock = OnceLock::new(); @@ -100,18 +103,13 @@ impl Preview { Ok(PreviewData::Folder) } - pub async fn image(mut path: &Path) -> Result { - let cache = Precache::cache(path); - if fs::metadata(&cache).await.is_ok() { - path = cache.as_path(); - } - + pub async fn image(path: &Path) -> Result { Adaptor::image_show(path, Self::rect()).await?; Ok(PreviewData::Image) } pub async fn video(path: &Path) -> Result { - let cache = Precache::cache(path); + let cache = Image::cache(path); if fs::metadata(&cache).await.is_err() { external::ffmpegthumbnailer(path, &cache).await?; } diff --git a/src/core/manager/tab.rs b/core/src/manager/tab.rs similarity index 97% rename from src/core/manager/tab.rs rename to core/src/manager/tab.rs index 796d8d07..aa3cd018 100644 --- a/src/core/manager/tab.rs +++ b/core/src/manager/tab.rs @@ -1,10 +1,11 @@ use std::{collections::BTreeMap, mem, path::{Path, PathBuf}}; use anyhow::{Error, Result}; +use shared::Defer; use tokio::task::JoinHandle; use super::{Folder, Mode, Preview}; -use crate::{core::{external::{self, FzfOpt, ZoxideOpt}, files::{File, Files, FilesOp}, input::InputOpt, Event, Position, BLOCKER}, emit, misc::Defer}; +use crate::{emit, external::{self, FzfOpt, ZoxideOpt}, files::{File, Files, FilesOp}, input::InputOpt, Event, Position, BLOCKER}; pub struct Tab { pub(super) mode: Mode, diff --git a/src/core/manager/tabs.rs b/core/src/manager/tabs.rs similarity index 97% rename from src/core/manager/tabs.rs rename to core/src/manager/tabs.rs index dc88b10c..2e7f8682 100644 --- a/src/core/manager/tabs.rs +++ b/core/src/manager/tabs.rs @@ -1,7 +1,9 @@ use std::path::Path; +use config::MANAGER; + use super::Tab; -use crate::{config::MANAGER, emit}; +use crate::emit; const MAX_TABS: usize = 9; diff --git a/src/core/manager/watcher.rs b/core/src/manager/watcher.rs similarity index 98% rename from src/core/manager/watcher.rs rename to core/src/manager/watcher.rs index d4728703..5f99843b 100644 --- a/src/core/manager/watcher.rs +++ b/core/src/manager/watcher.rs @@ -5,7 +5,7 @@ use notify::{event::{MetadataKind, ModifyKind}, EventKind, RecommendedWatcher, R use parking_lot::RwLock; use tokio::{fs, sync::mpsc::{self, Receiver, Sender}}; -use crate::{core::files::{Files, FilesOp}, emit}; +use crate::{emit, files::{Files, FilesOp}}; pub struct Watcher { tx: Sender, diff --git a/src/core/position.rs b/core/src/position.rs similarity index 100% rename from src/core/position.rs rename to core/src/position.rs diff --git a/src/core/select/mod.rs b/core/src/select/mod.rs similarity index 100% rename from src/core/select/mod.rs rename to core/src/select/mod.rs diff --git a/src/core/select/select.rs b/core/src/select/select.rs similarity index 98% rename from src/core/select/select.rs rename to core/src/select/select.rs index e0c57dd2..6142344b 100644 --- a/src/core/select/select.rs +++ b/core/src/select/select.rs @@ -1,9 +1,10 @@ use anyhow::{anyhow, Result}; use ratatui::prelude::Rect; +use shared::tty_size; use tokio::sync::oneshot::Sender; use super::SELECT_PADDING; -use crate::{core::Position, misc::tty_size}; +use crate::Position; #[derive(Default)] pub struct Select { diff --git a/src/core/tasks/file.rs b/core/src/tasks/file.rs similarity index 99% rename from src/core/tasks/file.rs rename to core/src/tasks/file.rs index 0b99302e..1c5e6ce3 100644 --- a/src/core/tasks/file.rs +++ b/core/src/tasks/file.rs @@ -2,11 +2,11 @@ use std::{collections::VecDeque, fs::Metadata, path::{Path, PathBuf}}; use anyhow::Result; use futures::{future::BoxFuture, FutureExt}; +use shared::{calculate_size, copy_with_progress}; use tokio::{fs, io::{self, ErrorKind::{AlreadyExists, NotFound}}, sync::mpsc}; use tracing::{info, trace}; use super::TaskOp; -use crate::misc::{calculate_size, copy_with_progress}; pub(super) struct File { rx: async_channel::Receiver, diff --git a/src/core/tasks/mod.rs b/core/src/tasks/mod.rs similarity index 100% rename from src/core/tasks/mod.rs rename to core/src/tasks/mod.rs diff --git a/src/core/tasks/precache.rs b/core/src/tasks/precache.rs similarity index 76% rename from src/core/tasks/precache.rs rename to core/src/tasks/precache.rs index 8f9ccd07..60340779 100644 --- a/src/core/tasks/precache.rs +++ b/core/src/tasks/precache.rs @@ -1,12 +1,13 @@ -use std::{collections::{BTreeMap, BTreeSet}, path::{Path, PathBuf}, sync::Arc}; +use std::{collections::{BTreeMap, BTreeSet}, path::PathBuf, sync::Arc}; -use anyhow::{Error, Result}; -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}; use super::TaskOp; -use crate::{config::PREVIEW, core::{external, files::{File, FilesOp}}, emit, misc::{calculate_size, Throttle}}; +use crate::{emit, external, files::{File, FilesOp}}; pub struct Precache { rx: async_channel::Receiver, @@ -65,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))?); } @@ -149,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() - } } diff --git a/src/core/tasks/process.rs b/core/src/tasks/process.rs similarity index 98% rename from src/core/tasks/process.rs rename to core/src/tasks/process.rs index 5e3cfb1e..e53f5c10 100644 --- a/src/core/tasks/process.rs +++ b/core/src/tasks/process.rs @@ -5,7 +5,7 @@ use tokio::{process::Command, select, sync::{mpsc, oneshot}}; use tracing::trace; use super::TaskOp; -use crate::{core::BLOCKER, emit}; +use crate::{emit, BLOCKER}; pub(super) struct Process { rx: async_channel::Receiver, diff --git a/src/core/tasks/scheduler.rs b/core/src/tasks/scheduler.rs similarity index 99% rename from src/core/tasks/scheduler.rs rename to core/src/tasks/scheduler.rs index a07aea2d..7607748d 100644 --- a/src/core/tasks/scheduler.rs +++ b/core/src/tasks/scheduler.rs @@ -1,13 +1,15 @@ use std::{collections::BTreeMap, ffi::{OsStr, OsString}, path::PathBuf, sync::Arc, time::Duration}; use async_channel::{Receiver, Sender}; +use config::open::Opener; use futures::{future::BoxFuture, FutureExt}; use parking_lot::RwLock; +use shared::{unique_path, Throttle}; use tokio::{fs, select, sync::{mpsc::{self, UnboundedReceiver}, oneshot}, time::sleep}; use tracing::{info, trace}; use super::{File, FileOpDelete, FileOpPaste, FileOpTrash, Precache, PrecacheOpMime, PrecacheOpSize, Process, ProcessOpOpen, Task, TaskOp, TaskStage}; -use crate::{config::open::Opener, emit, misc::{unique_path, Throttle}}; +use crate::emit; #[derive(Default)] pub(super) struct Running { diff --git a/src/core/tasks/tasks.rs b/core/src/tasks/tasks.rs similarity index 97% rename from src/core/tasks/tasks.rs rename to core/src/tasks/tasks.rs index 13941e94..23ef5817 100644 --- a/src/core/tasks/tasks.rs +++ b/core/src/tasks/tasks.rs @@ -1,9 +1,11 @@ use std::{collections::{BTreeMap, HashMap, HashSet}, ffi::OsStr, path::{Path, PathBuf}, sync::Arc}; +use config::{manager::SortBy, open::Opener, OPEN}; +use shared::{tty_size, MimeKind}; use tracing::trace; use super::{Scheduler, TASKS_PADDING, TASKS_PERCENT}; -use crate::{config::{manager::SortBy, open::Opener, OPEN}, core::{files::{File, Files}, input::InputOpt, Position}, emit, misc::{tty_size, MimeKind}}; +use crate::{emit, files::{File, Files}, input::InputOpt, Position}; #[derive(Clone, Debug)] pub struct Task { diff --git a/src/core/which/mod.rs b/core/src/which/mod.rs similarity index 100% rename from src/core/which/mod.rs rename to core/src/which/mod.rs diff --git a/src/core/which/which.rs b/core/src/which/which.rs similarity index 94% rename from src/core/which/which.rs rename to core/src/which/which.rs index b50add1f..f33e28ea 100644 --- a/src/core/which/which.rs +++ b/core/src/which/which.rs @@ -1,6 +1,8 @@ use std::mem; -use crate::{config::{keymap::{Control, Key, KeymapLayer}, KEYMAP}, emit}; +use config::{keymap::{Control, Key, KeymapLayer}, KEYMAP}; + +use crate::emit; pub struct Which { layer: KeymapLayer, diff --git a/shared/Cargo.toml b/shared/Cargo.toml new file mode 100644 index 00000000..e07b4d20 --- /dev/null +++ b/shared/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "shared" +version = "0.1.0" +edition = "2021" + +[dependencies] +anyhow = "^1" +crossterm = "^0" +libc = "^0" +parking_lot = "^0" +ratatui = { version = "^0" } +tokio = { version = "^1", features = [ "parking_lot" ] } diff --git a/src/misc/buffer.rs b/shared/src/buffer.rs similarity index 100% rename from src/misc/buffer.rs rename to shared/src/buffer.rs diff --git a/src/misc/chars.rs b/shared/src/chars.rs similarity index 100% rename from src/misc/chars.rs rename to shared/src/chars.rs diff --git a/src/misc/defer.rs b/shared/src/defer.rs similarity index 100% rename from src/misc/defer.rs rename to shared/src/defer.rs diff --git a/src/misc/fns.rs b/shared/src/fns.rs similarity index 100% rename from src/misc/fns.rs rename to shared/src/fns.rs diff --git a/src/misc/fs.rs b/shared/src/fs.rs similarity index 100% rename from src/misc/fs.rs rename to shared/src/fs.rs diff --git a/src/misc/mod.rs b/shared/src/lib.rs similarity index 89% rename from src/misc/mod.rs rename to shared/src/lib.rs index f9421683..b1d7811b 100644 --- a/src/misc/mod.rs +++ b/shared/src/lib.rs @@ -4,6 +4,7 @@ mod defer; mod fns; mod fs; mod mime; +mod term; mod throttle; mod tty; @@ -13,5 +14,6 @@ pub use defer::*; pub use fns::*; pub use fs::*; pub use mime::*; +pub use term::*; pub use throttle::*; pub use tty::*; diff --git a/src/misc/mime.rs b/shared/src/mime.rs similarity index 100% rename from src/misc/mime.rs rename to shared/src/mime.rs diff --git a/src/ui/term.rs b/shared/src/term.rs similarity index 100% rename from src/ui/term.rs rename to shared/src/term.rs diff --git a/src/misc/throttle.rs b/shared/src/throttle.rs similarity index 100% rename from src/misc/throttle.rs rename to shared/src/throttle.rs diff --git a/src/misc/tty.rs b/shared/src/tty.rs similarity index 100% rename from src/misc/tty.rs rename to shared/src/tty.rs diff --git a/src/core/adaptor/image.rs b/src/core/adaptor/image.rs deleted file mode 100644 index 65e1b26f..00000000 --- a/src/core/adaptor/image.rs +++ /dev/null @@ -1,31 +0,0 @@ -use std::path::Path; - -use anyhow::Result; -use image::{imageops::FilterType, DynamicImage}; -use tokio::fs; - -use crate::{config::PREVIEW, misc::tty_ratio}; - -pub(super) struct Image; - -impl Image { - pub(super) async fn resize(path: &Path, size: (u16, u16)) -> Result { - 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 { - 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??) - } -} diff --git a/src/core/adaptor/mod.rs b/src/core/adaptor/mod.rs deleted file mode 100644 index 1c99201e..00000000 --- a/src/core/adaptor/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod adaptor; -mod image; -mod iterm2; -mod kitty; -mod ueberzug; - -pub use adaptor::*; diff --git a/src/main.rs b/src/main.rs deleted file mode 100644 index 7bde7263..00000000 --- a/src/main.rs +++ /dev/null @@ -1,17 +0,0 @@ -use ui::App; - -mod config; -mod core; -mod misc; -mod ui; - -#[tokio::main] -async fn main() -> anyhow::Result<()> { - // console_subscriber::init(); - - config::init(); - - core::adaptor::Adaptor::init(); - - App::run().await -} diff --git a/src/ui/header/mod.rs b/src/ui/header/mod.rs deleted file mode 100644 index c8ea98ef..00000000 --- a/src/ui/header/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod layout; -mod tabs; - -pub use layout::*; -pub use tabs::*; diff --git a/src/ui/manager/mod.rs b/src/ui/manager/mod.rs deleted file mode 100644 index 763a990b..00000000 --- a/src/ui/manager/mod.rs +++ /dev/null @@ -1,8 +0,0 @@ -mod folder; -mod layout; -mod preview; - -pub use folder::*; -pub use layout::*; -pub use preview::*; - diff --git a/src/ui/mod.rs b/src/ui/mod.rs deleted file mode 100644 index dd154e5d..00000000 --- a/src/ui/mod.rs +++ /dev/null @@ -1,23 +0,0 @@ -mod app; -mod context; -mod dispatcher; -mod header; -mod input; -mod logs; -mod manager; -mod root; -mod select; -mod signals; -mod status; -mod tasks; -mod term; -mod which; - -pub use app::*; -pub use context::*; -pub use dispatcher::*; -pub use input::*; -pub use logs::*; -pub use select::*; -pub use signals::*; -pub use term::*; diff --git a/src/ui/status/mod.rs b/src/ui/status/mod.rs deleted file mode 100644 index dbed3bca..00000000 --- a/src/ui/status/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod layout; -mod left; -mod progress; -mod right; - -pub use layout::*; -pub use left::*; -pub use progress::*; -pub use right::*; diff --git a/src/ui/tasks/mod.rs b/src/ui/tasks/mod.rs deleted file mode 100644 index edda6bea..00000000 --- a/src/ui/tasks/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod clear; -mod layout; - -pub use clear::*; -pub use layout::*; diff --git a/src/ui/which/mod.rs b/src/ui/which/mod.rs deleted file mode 100644 index 55cb2643..00000000 --- a/src/ui/which/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod layout; -mod side; - -pub use layout::*; -pub use side::*;