mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-07 12:05:34 +00:00
Merging with origin
This commit is contained in:
commit
32c4c042e7
473
Cargo.lock
generated
473
Cargo.lock
generated
@ -154,9 +154,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "avif-serialize"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62"
|
||||
checksum = "98922d6a4cfbcb08820c69d8eeccc05bb1f29bfa06b4f5b1dbfe9a868bd7608e"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
]
|
||||
@ -173,7 +173,7 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -265,12 +265,6 @@ version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "1.11.3"
|
||||
@ -283,9 +277,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "built"
|
||||
version = "0.7.6"
|
||||
version = "0.7.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73848a43c5d63a1251d17adf6c2bf78aa94830e60a335a95eeea45d6ba9e1e4d"
|
||||
checksum = "56ed6191a7e78c36abdb16ab65341eefd73d64d303fffccdbb00d51e4205967b"
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
@ -323,32 +317,6 @@ version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a3e368af43e418a04d52505cf3dbc23dda4e3407ae2fa99fd0e4f308ce546acc"
|
||||
|
||||
[[package]]
|
||||
name = "calloop"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"log",
|
||||
"polling",
|
||||
"rustix",
|
||||
"slab",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "calloop-wayland-source"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20"
|
||||
dependencies = [
|
||||
"calloop",
|
||||
"rustix",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cassowary"
|
||||
version = "0.3.0"
|
||||
@ -466,12 +434,11 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
version = "3.1.1"
|
||||
version = "5.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fdf5e01086b6be750428ba4a40619f847eb2e95756eee84b18e06e5f0b50342"
|
||||
checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
|
||||
dependencies = [
|
||||
"lazy-bytes-cast",
|
||||
"winapi",
|
||||
"error-code",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -511,15 +478,6 @@ dependencies = [
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "concurrent-queue"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "console"
|
||||
version = "0.15.10"
|
||||
@ -542,20 +500,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "copypasta"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "deb85422867ca93da58b7f95fb5c0c10f6183ed6e1ef8841568968a896d3a858"
|
||||
dependencies = [
|
||||
"clipboard-win",
|
||||
"objc",
|
||||
"objc-foundation",
|
||||
"objc_id",
|
||||
"smithay-clipboard",
|
||||
"x11-clipboard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.4.2"
|
||||
@ -661,12 +605,6 @@ version = "0.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "43da5946c66ffcc7745f48db692ffbb10a83bfe0afd96235c5c2a4fb23994929"
|
||||
|
||||
[[package]]
|
||||
name = "cursor-icon"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "96a6ac251f4a2aca6b3f91340350eab87ae57c3f127ffeb585e92bd336717991"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.10"
|
||||
@ -741,21 +679,6 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "330c60081dcc4c72131f8eb70510f1ac07223e5d4163db481a04a0befcffa412"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "downcast-rs"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.13.0"
|
||||
@ -793,6 +716,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "error-code"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5d9305ccc6942a704f4335694ecd3de2ea531b114ac2d51f5f843750787a92f"
|
||||
|
||||
[[package]]
|
||||
name = "exr"
|
||||
version = "1.73.0"
|
||||
@ -927,16 +856,6 @@ dependencies = [
|
||||
"tempfile",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "gethostname"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0176e0459c2e4a1fe232f984bca6890e681076abb9934f6cea7c326f3fc47818"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
@ -957,7 +876,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.13.3+wasi-0.2.2",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1224,12 +1143,6 @@ dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy-bytes-cast"
|
||||
version = "5.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b"
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
@ -1258,16 +1171,6 @@ dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.8.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.3"
|
||||
@ -1318,15 +1221,6 @@ dependencies = [
|
||||
"hashbrown",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "matchers"
|
||||
version = "0.1.0"
|
||||
@ -1352,15 +1246,6 @@ version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memmap2"
|
||||
version = "0.9.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
@ -1507,35 +1392,6 @@ dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc-foundation"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
|
||||
dependencies = [
|
||||
"block",
|
||||
"objc",
|
||||
"objc_id",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_id"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
|
||||
dependencies = [
|
||||
"objc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "object"
|
||||
version = "0.36.7"
|
||||
@ -1622,7 +1478,7 @@ dependencies = [
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1666,7 +1522,7 @@ checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016"
|
||||
dependencies = [
|
||||
"base64",
|
||||
"indexmap",
|
||||
"quick-xml 0.32.0",
|
||||
"quick-xml",
|
||||
"serde",
|
||||
"time",
|
||||
]
|
||||
@ -1712,21 +1568,6 @@ dependencies = [
|
||||
"miniz_oxide",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "powerfmt"
|
||||
version = "0.2.0"
|
||||
@ -1794,15 +1635,6 @@ dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-xml"
|
||||
version = "0.37.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.38"
|
||||
@ -2053,12 +1885,6 @@ dependencies = [
|
||||
"winapi-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scoped-tls"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
@ -2214,57 +2040,12 @@ version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "smithay-client-toolkit"
|
||||
version = "0.19.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"calloop",
|
||||
"calloop-wayland-source",
|
||||
"cursor-icon",
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2",
|
||||
"rustix",
|
||||
"thiserror 1.0.69",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-csd-frame",
|
||||
"wayland-cursor",
|
||||
"wayland-protocols",
|
||||
"wayland-protocols-wlr",
|
||||
"wayland-scanner",
|
||||
"xkeysym",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smithay-clipboard"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"smithay-client-toolkit",
|
||||
"wayland-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.5.8"
|
||||
@ -2370,10 +2151,11 @@ name = "television"
|
||||
version = "0.10.6"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"base64",
|
||||
"bat",
|
||||
"better-panic",
|
||||
"clap",
|
||||
"copypasta",
|
||||
"clipboard-win",
|
||||
"criterion",
|
||||
"crossterm",
|
||||
"devicons",
|
||||
@ -2382,7 +2164,6 @@ dependencies = [
|
||||
"human-panic",
|
||||
"ignore",
|
||||
"image",
|
||||
"lazy_static",
|
||||
"nom",
|
||||
"nucleo",
|
||||
"parking_lot",
|
||||
@ -2844,102 +2625,6 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-backend"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b7208998eaa3870dad37ec8836979581506e0c5c64c20c9e79e9d2a10d6f47bf"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"downcast-rs",
|
||||
"rustix",
|
||||
"scoped-tls",
|
||||
"smallvec",
|
||||
"wayland-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-client"
|
||||
version = "0.31.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2120de3d33638aaef5b9f4472bff75f07c56379cf76ea320bd3a3d65ecaf73f"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"rustix",
|
||||
"wayland-backend",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-csd-frame"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"cursor-icon",
|
||||
"wayland-backend",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-cursor"
|
||||
version = "0.31.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a93029cbb6650748881a00e4922b076092a6a08c11e7fbdb923f064b23968c5d"
|
||||
dependencies = [
|
||||
"rustix",
|
||||
"wayland-client",
|
||||
"xcursor",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols"
|
||||
version = "0.32.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-protocols-wlr"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2"
|
||||
dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
"wayland-backend",
|
||||
"wayland-client",
|
||||
"wayland-protocols",
|
||||
"wayland-scanner",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-scanner"
|
||||
version = "0.31.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "896fdafd5d28145fce7958917d69f2fd44469b1d4e861cb5961bcbeebc6d1484"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quick-xml 0.37.2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wayland-sys"
|
||||
version = "0.31.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbcebb399c77d5aa9fa5db874806ee7b4eba4e73650948e8f93963f128896615"
|
||||
dependencies = [
|
||||
"dlib",
|
||||
"log",
|
||||
"once_cell",
|
||||
"pkg-config",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.77"
|
||||
@ -2994,7 +2679,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1de69df01bdf1ead2f4ac895dc77c9351aefff65b2f3db429a343f9cbf05e132"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3006,7 +2691,7 @@ dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3037,7 +2722,7 @@ version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3046,7 +2731,7 @@ version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3055,22 +2740,7 @@ version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
|
||||
dependencies = [
|
||||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.48.5",
|
||||
"windows_aarch64_msvc 0.48.5",
|
||||
"windows_i686_gnu 0.48.5",
|
||||
"windows_i686_msvc 0.48.5",
|
||||
"windows_x86_64_gnu 0.48.5",
|
||||
"windows_x86_64_gnullvm 0.48.5",
|
||||
"windows_x86_64_msvc 0.48.5",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3079,46 +2749,28 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm 0.52.6",
|
||||
"windows_aarch64_msvc 0.52.6",
|
||||
"windows_i686_gnu 0.52.6",
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc 0.52.6",
|
||||
"windows_x86_64_gnu 0.52.6",
|
||||
"windows_x86_64_gnullvm 0.52.6",
|
||||
"windows_x86_64_msvc 0.52.6",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.6"
|
||||
@ -3131,48 +2783,24 @@ version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.48.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.6"
|
||||
@ -3197,45 +2825,6 @@ dependencies = [
|
||||
"bitflags 2.8.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11-clipboard"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12"
|
||||
dependencies = [
|
||||
"gethostname",
|
||||
"rustix",
|
||||
"x11rb-protocol",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "x11rb-protocol"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d"
|
||||
|
||||
[[package]]
|
||||
name = "xcursor"
|
||||
version = "0.3.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61"
|
||||
|
||||
[[package]]
|
||||
name = "xkeysym"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56"
|
||||
|
||||
[[package]]
|
||||
name = "xterm-color"
|
||||
version = "1.0.1"
|
||||
|
@ -31,9 +31,9 @@ path = "television/lib.rs"
|
||||
television-derive = { path = "television-derive", version = "0.0.25" }
|
||||
|
||||
anyhow = "1.0"
|
||||
base64 = "0.22.1"
|
||||
directories = "6.0"
|
||||
devicons = "0.6"
|
||||
lazy_static = "1.5"
|
||||
tokio = { version = "1.43", features = ["full"] }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
|
||||
@ -46,7 +46,6 @@ ratatui = { version = "0.29", features = ["serde", "macros"] }
|
||||
better-panic = "0.3"
|
||||
signal-hook = "0.3"
|
||||
human-panic = "2.0"
|
||||
copypasta = "0.10"
|
||||
ignore = "0.4"
|
||||
strum = { version = "0.26", features = ["derive"] }
|
||||
regex = "1.11"
|
||||
@ -64,6 +63,7 @@ image = "0.25"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi-util = "0.1.9"
|
||||
clipboard-win = "5.4.0"
|
||||
|
||||
[dev-dependencies]
|
||||
criterion = { version = "0.5", features = ["async_tokio"] }
|
||||
|
@ -33,7 +33,7 @@
|
||||
pkgs.rustChannelOf
|
||||
{
|
||||
rustToolchain = ./rust-toolchain.toml;
|
||||
sha256 = "VZZnlyP69+Y3crrLHQyJirqlHrTtGTsyiSnZB8jEvVo=";
|
||||
sha256 = "s1RPtyvDGJaX/BisLT+ifVfuhDT1nZkZ1NcK8sbwELM=";
|
||||
}
|
||||
)
|
||||
.rust;
|
||||
|
@ -8,6 +8,7 @@ use crate::channels::entry::Entry;
|
||||
use crate::channels::TelevisionChannel;
|
||||
use crate::config::{parse_key, Config};
|
||||
use crate::keymap::Keymap;
|
||||
use crate::render::UiState;
|
||||
use crate::television::{Mode, Television};
|
||||
use crate::{
|
||||
action::Action,
|
||||
@ -37,6 +38,9 @@ pub struct App {
|
||||
event_abort_tx: mpsc::UnboundedSender<()>,
|
||||
/// A sender channel for rendering tasks.
|
||||
render_tx: mpsc::UnboundedSender<RenderingTask>,
|
||||
/// A channel that listens to UI updates.
|
||||
ui_state_rx: mpsc::UnboundedReceiver<UiState>,
|
||||
ui_state_tx: mpsc::UnboundedSender<UiState>,
|
||||
}
|
||||
|
||||
/// The outcome of an action.
|
||||
@ -104,6 +108,7 @@ impl App {
|
||||
.collect(),
|
||||
)?;
|
||||
debug!("{:?}", keymap);
|
||||
let (ui_state_tx, ui_state_rx) = mpsc::unbounded_channel();
|
||||
let television =
|
||||
Television::new(action_tx.clone(), channel, config, input);
|
||||
|
||||
@ -118,6 +123,8 @@ impl App {
|
||||
event_rx,
|
||||
event_abort_tx,
|
||||
render_tx,
|
||||
ui_state_rx,
|
||||
ui_state_tx,
|
||||
})
|
||||
}
|
||||
|
||||
@ -145,9 +152,10 @@ impl App {
|
||||
debug!("Starting rendering loop");
|
||||
let (render_tx, render_rx) = mpsc::unbounded_channel();
|
||||
self.render_tx = render_tx.clone();
|
||||
let ui_state_tx = self.ui_state_tx.clone();
|
||||
let action_tx_r = self.action_tx.clone();
|
||||
let rendering_task = tokio::spawn(async move {
|
||||
render(render_rx, action_tx_r, is_output_tty).await
|
||||
render(render_rx, action_tx_r, ui_state_tx, is_output_tty).await
|
||||
});
|
||||
self.action_tx.send(Action::Render)?;
|
||||
|
||||
@ -298,9 +306,14 @@ impl App {
|
||||
self.render_tx.send(RenderingTask::Resize(w, h))?;
|
||||
}
|
||||
Action::Render => {
|
||||
// forward to the rendering task
|
||||
self.render_tx.send(RenderingTask::Render(
|
||||
self.television.dump_context(),
|
||||
Box::new(self.television.dump_context()),
|
||||
))?;
|
||||
// update the television UI state with the previous frame
|
||||
if let Ok(ui_state) = self.ui_state_rx.try_recv() {
|
||||
self.television.update_ui_state(ui_state);
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ use std::io::{BufRead, BufReader};
|
||||
use std::process::Stdio;
|
||||
|
||||
use anyhow::Result;
|
||||
use lazy_static::lazy_static;
|
||||
use regex::Regex;
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use tracing::debug;
|
||||
@ -64,13 +63,10 @@ impl From<CableChannelPrototype> for Channel {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref BUILTIN_PREVIEW_RE: Regex = Regex::new(r"^:(\w+):$").unwrap();
|
||||
}
|
||||
|
||||
fn parse_preview_kind(command: &PreviewCommand) -> Result<PreviewKind> {
|
||||
debug!("Parsing preview kind for command: {:?}", command);
|
||||
if let Some(captures) = BUILTIN_PREVIEW_RE.captures(&command.command) {
|
||||
let re = Regex::new(r"^\:(\w+)\:$").unwrap();
|
||||
if let Some(captures) = re.captures(&command.command) {
|
||||
let preview_type = PreviewType::try_from(&captures[1])?;
|
||||
Ok(PreviewKind::Builtin(preview_type))
|
||||
} else {
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::channels::entry::{Entry, PreviewCommand, PreviewType};
|
||||
use crate::channels::{OnAir, TelevisionChannel};
|
||||
use crate::matcher::{config::Config, injector::Injector, Matcher};
|
||||
use crate::utils::files::{walk_builder, DEFAULT_NUM_THREADS};
|
||||
use crate::utils::files::{get_default_num_threads, walk_builder};
|
||||
use devicons::FileIcon;
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use std::collections::HashSet;
|
||||
@ -151,7 +151,7 @@ async fn load_dirs(paths: Vec<PathBuf>, injector: Injector<String>) {
|
||||
}
|
||||
let current_dir = std::env::current_dir().unwrap();
|
||||
let mut builder =
|
||||
walk_builder(&paths[0], *DEFAULT_NUM_THREADS, None, None);
|
||||
walk_builder(&paths[0], get_default_num_threads(), None, None);
|
||||
paths[1..].iter().for_each(|path| {
|
||||
builder.add(path);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
use crate::channels::entry::{Entry, PreviewType};
|
||||
use crate::channels::{OnAir, TelevisionChannel};
|
||||
use crate::matcher::{config::Config, injector::Injector, Matcher};
|
||||
use crate::utils::files::{walk_builder, DEFAULT_NUM_THREADS};
|
||||
use crate::utils::files::{get_default_num_threads, walk_builder};
|
||||
use devicons::FileIcon;
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use std::collections::HashSet;
|
||||
@ -157,7 +157,7 @@ async fn load_files(paths: Vec<PathBuf>, injector: Injector<String>) {
|
||||
}
|
||||
let current_dir = std::env::current_dir().unwrap();
|
||||
let mut builder =
|
||||
walk_builder(&paths[0], *DEFAULT_NUM_THREADS, None, None);
|
||||
walk_builder(&paths[0], get_default_num_threads(), None, None);
|
||||
paths[1..].iter().for_each(|path| {
|
||||
builder.add(path);
|
||||
});
|
||||
|
@ -1,7 +1,6 @@
|
||||
use devicons::FileIcon;
|
||||
use directories::BaseDirs;
|
||||
use ignore::overrides::OverrideBuilder;
|
||||
use lazy_static::lazy_static;
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
@ -11,13 +10,14 @@ use tracing::debug;
|
||||
use crate::channels::entry::{Entry, PreviewCommand, PreviewType};
|
||||
use crate::channels::OnAir;
|
||||
use crate::matcher::{config::Config, injector::Injector, Matcher};
|
||||
use crate::utils::files::{walk_builder, DEFAULT_NUM_THREADS};
|
||||
use crate::utils::files::{get_default_num_threads, walk_builder};
|
||||
|
||||
pub struct Channel {
|
||||
matcher: Matcher<String>,
|
||||
icon: FileIcon,
|
||||
crawl_handle: JoinHandle<()>,
|
||||
selected_entries: FxHashSet<Entry>,
|
||||
preview_command: PreviewCommand,
|
||||
}
|
||||
|
||||
impl Channel {
|
||||
@ -28,11 +28,20 @@ impl Channel {
|
||||
base_dirs.home_dir().to_path_buf(),
|
||||
matcher.injector(),
|
||||
));
|
||||
|
||||
let preview_command = PreviewCommand {
|
||||
command: String::from(
|
||||
"cd {} && git log -n 200 --pretty=medium --all --graph --color",
|
||||
),
|
||||
delimiter: ":".to_string(),
|
||||
};
|
||||
|
||||
Channel {
|
||||
matcher,
|
||||
icon: FileIcon::from("git"),
|
||||
crawl_handle,
|
||||
selected_entries: HashSet::with_hasher(FxBuildHasher),
|
||||
preview_command,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -43,15 +52,6 @@ impl Default for Channel {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref PREVIEW_COMMAND: PreviewCommand = PreviewCommand {
|
||||
command: String::from(
|
||||
"cd {} && git log -n 200 --pretty=medium --all --graph --color",
|
||||
),
|
||||
delimiter: ":".to_string(),
|
||||
};
|
||||
}
|
||||
|
||||
impl OnAir for Channel {
|
||||
fn find(&mut self, pattern: &str) {
|
||||
self.matcher.find(pattern);
|
||||
@ -64,9 +64,12 @@ impl OnAir for Channel {
|
||||
.into_iter()
|
||||
.map(|item| {
|
||||
let path = item.matched_string;
|
||||
Entry::new(path, PreviewType::Command(PREVIEW_COMMAND.clone()))
|
||||
.with_name_match_ranges(&item.match_indices)
|
||||
.with_icon(self.icon)
|
||||
Entry::new(
|
||||
path,
|
||||
PreviewType::Command(self.preview_command.clone()),
|
||||
)
|
||||
.with_name_match_ranges(&item.match_indices)
|
||||
.with_icon(self.icon)
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@ -74,8 +77,11 @@ impl OnAir for Channel {
|
||||
fn get_result(&self, index: u32) -> Option<Entry> {
|
||||
self.matcher.get_result(index).map(|item| {
|
||||
let path = item.matched_string;
|
||||
Entry::new(path, PreviewType::Command(PREVIEW_COMMAND.clone()))
|
||||
.with_icon(self.icon)
|
||||
Entry::new(
|
||||
path,
|
||||
PreviewType::Command(self.preview_command.clone()),
|
||||
)
|
||||
.with_icon(self.icon)
|
||||
})
|
||||
}
|
||||
|
||||
@ -162,7 +168,7 @@ async fn crawl_for_repos(starting_point: PathBuf, injector: Injector<String>) {
|
||||
walker_overrides_builder.add(".git").unwrap();
|
||||
let walker = walk_builder(
|
||||
&starting_point,
|
||||
*DEFAULT_NUM_THREADS,
|
||||
get_default_num_threads(),
|
||||
Some(walker_overrides_builder.build().unwrap()),
|
||||
Some(get_ignored_paths()),
|
||||
)
|
||||
|
@ -1,7 +1,7 @@
|
||||
use super::{OnAir, TelevisionChannel};
|
||||
use crate::channels::entry::{Entry, PreviewType};
|
||||
use crate::matcher::{config::Config, injector::Injector, Matcher};
|
||||
use crate::utils::files::{walk_builder, DEFAULT_NUM_THREADS};
|
||||
use crate::utils::files::{get_default_num_threads, walk_builder};
|
||||
use crate::utils::strings::{
|
||||
proportion_of_printable_ascii_characters, PRINTABLE_ASCII_THRESHOLD,
|
||||
};
|
||||
@ -277,7 +277,7 @@ async fn crawl_for_candidates(
|
||||
}
|
||||
let current_dir = std::env::current_dir().unwrap();
|
||||
let mut walker =
|
||||
walk_builder(&directories[0], *DEFAULT_NUM_THREADS, None, None);
|
||||
walk_builder(&directories[0], get_default_num_threads(), None, None);
|
||||
directories[1..].iter().for_each(|path| {
|
||||
walker.add(path);
|
||||
});
|
||||
|
@ -9,7 +9,6 @@ use anyhow::{Context, Result};
|
||||
use directories::ProjectDirs;
|
||||
use keybindings::merge_keybindings;
|
||||
pub use keybindings::{parse_key, Binding, KeyBindings};
|
||||
use lazy_static::lazy_static;
|
||||
use previewers::PreviewersConfig;
|
||||
use serde::Deserialize;
|
||||
use shell_integration::ShellIntegrationConfig;
|
||||
@ -70,23 +69,7 @@ pub struct Config {
|
||||
pub shell_integration: ShellIntegrationConfig,
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PROJECT_NAME: String = String::from("television");
|
||||
pub static ref PROJECT_NAME_UPPER: String = PROJECT_NAME.to_uppercase();
|
||||
pub static ref DATA_FOLDER: Option<PathBuf> =
|
||||
// if `TELEVISION_DATA` is set, use that as the data directory
|
||||
env::var_os(format!("{}_DATA", PROJECT_NAME_UPPER.clone())).map(PathBuf::from).or_else(|| {
|
||||
// otherwise, use the XDG data directory
|
||||
env::var_os("XDG_DATA_HOME").map(PathBuf::from).map(|p| p.join(PROJECT_NAME.as_str())).filter(|p| p.is_absolute())
|
||||
});
|
||||
pub static ref CONFIG_FOLDER: Option<PathBuf> =
|
||||
// if `TELEVISION_CONFIG` is set, use that as the television config directory
|
||||
env::var_os(format!("{}_CONFIG", PROJECT_NAME_UPPER.clone())).map(PathBuf::from).or_else(|| {
|
||||
// otherwise, use the XDG config directory + 'television'
|
||||
env::var_os("XDG_CONFIG_HOME").map(PathBuf::from).map(|p| p.join(PROJECT_NAME.as_str())).filter(|p| p.is_absolute())
|
||||
});
|
||||
}
|
||||
|
||||
const PROJECT_NAME: &str = "television";
|
||||
const CONFIG_FILE_NAME: &str = "config.toml";
|
||||
|
||||
pub struct ConfigEnv {
|
||||
@ -184,7 +167,19 @@ impl Config {
|
||||
}
|
||||
|
||||
pub fn get_data_dir() -> PathBuf {
|
||||
let directory = if let Some(s) = DATA_FOLDER.clone() {
|
||||
// if `TELEVISION_DATA` is set, use that as the data directory
|
||||
let data_folder =
|
||||
env::var_os(format!("{}_DATA", PROJECT_NAME.to_uppercase()))
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| {
|
||||
// otherwise, use the XDG data directory
|
||||
env::var_os("XDG_DATA_HOME")
|
||||
.map(PathBuf::from)
|
||||
.map(|p| p.join(PROJECT_NAME))
|
||||
.filter(|p| p.is_absolute())
|
||||
});
|
||||
|
||||
let directory = if let Some(s) = data_folder {
|
||||
debug!("Using data directory: {:?}", s);
|
||||
s
|
||||
} else if let Some(proj_dirs) = project_directory() {
|
||||
@ -197,7 +192,18 @@ pub fn get_data_dir() -> PathBuf {
|
||||
}
|
||||
|
||||
pub fn get_config_dir() -> PathBuf {
|
||||
let directory = if let Some(s) = CONFIG_FOLDER.clone() {
|
||||
// if `TELEVISION_CONFIG` is set, use that as the television config directory
|
||||
let config_dir =
|
||||
env::var_os(format!("{}_CONFIG", PROJECT_NAME.to_uppercase()))
|
||||
.map(PathBuf::from)
|
||||
.or_else(|| {
|
||||
// otherwise, use the XDG config directory + 'television'
|
||||
env::var_os("XDG_CONFIG_HOME")
|
||||
.map(PathBuf::from)
|
||||
.map(|p| p.join(PROJECT_NAME))
|
||||
.filter(|p| p.is_absolute())
|
||||
});
|
||||
let directory = if let Some(s) = config_dir {
|
||||
debug!("Config directory: {:?}", s);
|
||||
s
|
||||
} else if cfg!(unix) {
|
||||
|
@ -128,10 +128,10 @@ impl Theme {
|
||||
pub fn from_builtin(
|
||||
name: &str,
|
||||
) -> Result<Self, Box<dyn std::error::Error>> {
|
||||
let theme_content: &str = builtin::BUILTIN_THEMES.get(name).map_or(
|
||||
builtin::BUILTIN_THEMES.get(DEFAULT_THEME).unwrap(),
|
||||
|t| *t,
|
||||
);
|
||||
let builtin_themes = builtin::builtin_themes();
|
||||
let theme_content: &str = builtin_themes
|
||||
.get(name)
|
||||
.map_or(builtin_themes.get(DEFAULT_THEME).unwrap(), |t| *t);
|
||||
let theme = toml::from_str(theme_content)?;
|
||||
Ok(theme)
|
||||
}
|
||||
|
@ -1,43 +1,39 @@
|
||||
use rustc_hash::FxHashMap;
|
||||
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
lazy_static! {
|
||||
pub static ref BUILTIN_THEMES: FxHashMap<&'static str, &'static str> = {
|
||||
let mut m = FxHashMap::default();
|
||||
m.insert("default", include_str!("../../../themes/default.toml"));
|
||||
m.insert(
|
||||
"television",
|
||||
include_str!("../../../themes/television.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"gruvbox-dark",
|
||||
include_str!("../../../themes/gruvbox-dark.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"gruvbox-light",
|
||||
include_str!("../../../themes/gruvbox-light.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"catppuccin",
|
||||
include_str!("../../../themes/catppuccin.toml"),
|
||||
);
|
||||
m.insert("nord-dark", include_str!("../../../themes/nord-dark.toml"));
|
||||
m.insert(
|
||||
"solarized-dark",
|
||||
include_str!("../../../themes/solarized-dark.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"solarized-light",
|
||||
include_str!("../../../themes/solarized-light.toml"),
|
||||
);
|
||||
m.insert("dracula", include_str!("../../../themes/dracula.toml"));
|
||||
m.insert("monokai", include_str!("../../../themes/monokai.toml"));
|
||||
m.insert("onedark", include_str!("../../../themes/onedark.toml"));
|
||||
m.insert(
|
||||
"tokyonight",
|
||||
include_str!("../../../themes/tokyonight.toml"),
|
||||
);
|
||||
m
|
||||
};
|
||||
pub fn builtin_themes() -> FxHashMap<&'static str, &'static str> {
|
||||
let mut m = FxHashMap::default();
|
||||
m.insert("default", include_str!("../../../themes/default.toml"));
|
||||
m.insert(
|
||||
"television",
|
||||
include_str!("../../../themes/television.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"gruvbox-dark",
|
||||
include_str!("../../../themes/gruvbox-dark.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"gruvbox-light",
|
||||
include_str!("../../../themes/gruvbox-light.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"catppuccin",
|
||||
include_str!("../../../themes/catppuccin.toml"),
|
||||
);
|
||||
m.insert("nord-dark", include_str!("../../../themes/nord-dark.toml"));
|
||||
m.insert(
|
||||
"solarized-dark",
|
||||
include_str!("../../../themes/solarized-dark.toml"),
|
||||
);
|
||||
m.insert(
|
||||
"solarized-light",
|
||||
include_str!("../../../themes/solarized-light.toml"),
|
||||
);
|
||||
m.insert("dracula", include_str!("../../../themes/dracula.toml"));
|
||||
m.insert("monokai", include_str!("../../../themes/monokai.toml"));
|
||||
m.insert("onedark", include_str!("../../../themes/onedark.toml"));
|
||||
m.insert(
|
||||
"tokyonight",
|
||||
include_str!("../../../themes/tokyonight.toml"),
|
||||
);
|
||||
m
|
||||
}
|
||||
|
@ -3,7 +3,6 @@ use std::{hash::Hash, time::Instant};
|
||||
use anyhow::Result;
|
||||
use ratatui::{layout::Rect, Frame};
|
||||
use rustc_hash::FxHashSet;
|
||||
use tokio::sync::mpsc::Sender;
|
||||
|
||||
use crate::{
|
||||
action::Action,
|
||||
@ -18,7 +17,7 @@ use crate::{
|
||||
remote_control::draw_remote_control, results::draw_results_list,
|
||||
spinner::Spinner,
|
||||
},
|
||||
television::{Message, Mode},
|
||||
television::Mode,
|
||||
utils::metadata::AppMetadata,
|
||||
};
|
||||
|
||||
@ -61,7 +60,6 @@ impl Hash for ChannelState {
|
||||
pub struct TvState {
|
||||
pub mode: Mode,
|
||||
pub selected_entry: Option<Entry>,
|
||||
pub results_area_height: u16,
|
||||
pub results_picker: Picker,
|
||||
pub rc_picker: Picker,
|
||||
pub channel_state: ChannelState,
|
||||
@ -74,7 +72,6 @@ impl TvState {
|
||||
pub fn new(
|
||||
mode: Mode,
|
||||
selected_entry: Option<Entry>,
|
||||
results_area_height: u16,
|
||||
results_picker: Picker,
|
||||
rc_picker: Picker,
|
||||
channel_state: ChannelState,
|
||||
@ -84,7 +81,6 @@ impl TvState {
|
||||
Self {
|
||||
mode,
|
||||
selected_entry,
|
||||
results_area_height,
|
||||
results_picker,
|
||||
rc_picker,
|
||||
channel_state,
|
||||
@ -100,8 +96,8 @@ pub struct Ctx {
|
||||
pub config: Config,
|
||||
pub colorscheme: Colorscheme,
|
||||
pub app_metadata: AppMetadata,
|
||||
pub tv_tx_handle: Sender<Message>,
|
||||
pub instant: Instant,
|
||||
pub layout: Layout,
|
||||
}
|
||||
|
||||
impl Ctx {
|
||||
@ -110,16 +106,16 @@ impl Ctx {
|
||||
config: Config,
|
||||
colorscheme: Colorscheme,
|
||||
app_metadata: AppMetadata,
|
||||
tv_tx_handle: Sender<Message>,
|
||||
instant: Instant,
|
||||
layout: Layout,
|
||||
) -> Self {
|
||||
Self {
|
||||
tv_state,
|
||||
config,
|
||||
colorscheme,
|
||||
app_metadata,
|
||||
tv_tx_handle,
|
||||
instant,
|
||||
layout,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -156,7 +152,7 @@ impl Ord for Ctx {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn draw(ctx: &Ctx, f: &mut Frame<'_>, area: Rect) -> Result<()> {
|
||||
pub fn draw(ctx: &Ctx, f: &mut Frame<'_>, area: Rect) -> Result<Layout> {
|
||||
let selected_entry = ctx
|
||||
.tv_state
|
||||
.selected_entry
|
||||
@ -185,14 +181,6 @@ pub fn draw(ctx: &Ctx, f: &mut Frame<'_>, area: Rect) -> Result<()> {
|
||||
&ctx.colorscheme,
|
||||
);
|
||||
|
||||
if layout.results.height.saturating_sub(2)
|
||||
!= ctx.tv_state.results_area_height
|
||||
{
|
||||
ctx.tv_tx_handle.try_send(Message::ResultListHeightChanged(
|
||||
layout.results.height.saturating_sub(2),
|
||||
))?;
|
||||
}
|
||||
|
||||
// results list
|
||||
draw_results_list(
|
||||
f,
|
||||
@ -259,5 +247,5 @@ pub fn draw(ctx: &Ctx, f: &mut Frame<'_>, area: Rect) -> Result<()> {
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
Ok(layout)
|
||||
}
|
||||
|
@ -3,14 +3,10 @@ use tracing_subscriber::{fmt, prelude::*, EnvFilter};
|
||||
|
||||
use crate::config::get_data_dir;
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref LOG_FILE: String = format!("{}.log", env!("CARGO_PKG_NAME"));
|
||||
}
|
||||
|
||||
pub fn init() -> Result<()> {
|
||||
let directory = get_data_dir();
|
||||
std::fs::create_dir_all(directory.clone())?;
|
||||
let log_path = directory.join(LOG_FILE.clone());
|
||||
let log_path = directory.join(format!("{}.log", env!("CARGO_PKG_NAME")));
|
||||
let log_file = std::fs::File::create(log_path)?;
|
||||
let file_subscriber = fmt::layer()
|
||||
.with_file(true)
|
||||
|
@ -5,6 +5,7 @@ use std::process::exit;
|
||||
|
||||
use anyhow::Result;
|
||||
use clap::Parser;
|
||||
use television::utils::clipboard::CLIPBOARD;
|
||||
use tracing::{debug, error, info};
|
||||
|
||||
use television::app::App;
|
||||
@ -77,6 +78,8 @@ async fn main() -> Result<()> {
|
||||
env::set_current_dir(path)?;
|
||||
}
|
||||
|
||||
CLIPBOARD.with(<_>::default);
|
||||
|
||||
match App::new(
|
||||
{
|
||||
if is_readable_stdin() {
|
||||
|
@ -2,7 +2,6 @@ use crate::channels::entry::{Entry, PreviewCommand};
|
||||
use crate::preview::cache::PreviewCache;
|
||||
use crate::preview::{Preview, PreviewContent};
|
||||
use crate::utils::command::shell_command;
|
||||
use lazy_static::lazy_static;
|
||||
use parking_lot::Mutex;
|
||||
use regex::Regex;
|
||||
use rustc_hash::FxHashSet;
|
||||
@ -11,12 +10,19 @@ use std::sync::Arc;
|
||||
use tracing::debug;
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct CommandPreviewer {
|
||||
cache: Arc<Mutex<PreviewCache>>,
|
||||
config: CommandPreviewerConfig,
|
||||
concurrent_preview_tasks: Arc<AtomicU8>,
|
||||
in_flight_previews: Arc<Mutex<FxHashSet<String>>>,
|
||||
command_re: Regex,
|
||||
}
|
||||
|
||||
impl Default for CommandPreviewer {
|
||||
fn default() -> Self {
|
||||
CommandPreviewer::new(None)
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
@ -53,6 +59,7 @@ impl CommandPreviewer {
|
||||
config,
|
||||
concurrent_preview_tasks: Arc::new(AtomicU8::new(0)),
|
||||
in_flight_previews: Arc::new(Mutex::new(FxHashSet::default())),
|
||||
command_re: Regex::new(r"\{(\d+)\}").unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -96,6 +103,7 @@ impl CommandPreviewer {
|
||||
let concurrent_tasks = self.concurrent_preview_tasks.clone();
|
||||
let command = command.clone();
|
||||
let in_flight_previews = self.in_flight_previews.clone();
|
||||
let command_re = self.command_re.clone();
|
||||
tokio::spawn(async move {
|
||||
try_preview(
|
||||
&command,
|
||||
@ -103,6 +111,7 @@ impl CommandPreviewer {
|
||||
&cache,
|
||||
&concurrent_tasks,
|
||||
&in_flight_previews,
|
||||
&command_re,
|
||||
);
|
||||
});
|
||||
} else {
|
||||
@ -114,11 +123,6 @@ impl CommandPreviewer {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref COMMAND_PLACEHOLDER_REGEX: Regex =
|
||||
Regex::new(r"\{(\d+)\}").unwrap();
|
||||
}
|
||||
|
||||
/// Format the command with the entry name and provided placeholders
|
||||
///
|
||||
/// # Example
|
||||
@ -131,11 +135,15 @@ lazy_static! {
|
||||
/// delimiter: ":".to_string(),
|
||||
/// };
|
||||
/// let entry = Entry::new("a:given:entry:to:preview".to_string(), PreviewType::Command(command.clone()));
|
||||
/// let formatted_command = format_command(&command, &entry);
|
||||
/// let formatted_command = format_command(&command, &entry, ®ex::Regex::new(r"\{(\d+)\}").unwrap());
|
||||
///
|
||||
/// assert_eq!(formatted_command, "something 'a:given:entry:to:preview' 'entry' 'a'");
|
||||
/// ```
|
||||
pub fn format_command(command: &PreviewCommand, entry: &Entry) -> String {
|
||||
pub fn format_command(
|
||||
command: &PreviewCommand,
|
||||
entry: &Entry,
|
||||
command_re: &Regex,
|
||||
) -> String {
|
||||
let parts = entry.name.split(&command.delimiter).collect::<Vec<&str>>();
|
||||
debug!("Parts: {:?}", parts);
|
||||
|
||||
@ -143,7 +151,7 @@ pub fn format_command(command: &PreviewCommand, entry: &Entry) -> String {
|
||||
.command
|
||||
.replace("{}", format!("'{}'", entry.name).as_str());
|
||||
|
||||
formatted_command = COMMAND_PLACEHOLDER_REGEX
|
||||
formatted_command = command_re
|
||||
.replace_all(&formatted_command, |caps: ®ex::Captures| {
|
||||
let index =
|
||||
caps.get(1).unwrap().as_str().parse::<usize>().unwrap();
|
||||
@ -160,9 +168,10 @@ pub fn try_preview(
|
||||
cache: &Arc<Mutex<PreviewCache>>,
|
||||
concurrent_tasks: &Arc<AtomicU8>,
|
||||
in_flight_previews: &Arc<Mutex<FxHashSet<String>>>,
|
||||
command_re: &Regex,
|
||||
) {
|
||||
debug!("Computing preview for {:?}", entry.name);
|
||||
let command = format_command(command, entry);
|
||||
let command = format_command(command, entry, command_re);
|
||||
debug!("Formatted preview command: {:?}", command);
|
||||
|
||||
let child = shell_command()
|
||||
@ -212,7 +221,11 @@ mod tests {
|
||||
"an:entry:to:preview".to_string(),
|
||||
PreviewType::Command(command.clone()),
|
||||
);
|
||||
let formatted_command = format_command(&command, &entry);
|
||||
let formatted_command = format_command(
|
||||
&command,
|
||||
&entry,
|
||||
&Regex::new(r"\{(\d+)\}").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(
|
||||
formatted_command,
|
||||
@ -230,7 +243,11 @@ mod tests {
|
||||
"an:entry:to:preview".to_string(),
|
||||
PreviewType::Command(command.clone()),
|
||||
);
|
||||
let formatted_command = format_command(&command, &entry);
|
||||
let formatted_command = format_command(
|
||||
&command,
|
||||
&entry,
|
||||
&Regex::new(r"\{(\d+)\}").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(formatted_command, "something");
|
||||
}
|
||||
@ -245,7 +262,11 @@ mod tests {
|
||||
"an:entry:to:preview".to_string(),
|
||||
PreviewType::Command(command.clone()),
|
||||
);
|
||||
let formatted_command = format_command(&command, &entry);
|
||||
let formatted_command = format_command(
|
||||
&command,
|
||||
&entry,
|
||||
&Regex::new(r"\{(\d+)\}").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(formatted_command, "something 'an:entry:to:preview'");
|
||||
}
|
||||
@ -260,7 +281,11 @@ mod tests {
|
||||
"an:entry:to:preview".to_string(),
|
||||
PreviewType::Command(command.clone()),
|
||||
);
|
||||
let formatted_command = format_command(&command, &entry);
|
||||
let formatted_command = format_command(
|
||||
&command,
|
||||
&entry,
|
||||
&Regex::new(r"\{(\d+)\}").unwrap(),
|
||||
);
|
||||
|
||||
assert_eq!(formatted_command, "something 'an' -t 'to'");
|
||||
}
|
||||
|
@ -8,12 +8,13 @@ use tracing::{debug, warn};
|
||||
use tokio::sync::mpsc;
|
||||
|
||||
use crate::draw::Ctx;
|
||||
use crate::screen::layout::Layout;
|
||||
use crate::{action::Action, draw::draw, tui::Tui};
|
||||
|
||||
#[derive(Debug, PartialEq, PartialOrd, Ord, Eq, Clone)]
|
||||
pub enum RenderingTask {
|
||||
ClearScreen,
|
||||
Render(Ctx),
|
||||
Render(Box<Ctx>),
|
||||
Resize(u16, u16),
|
||||
Resume,
|
||||
Suspend,
|
||||
@ -35,9 +36,21 @@ impl IoStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UiState {
|
||||
pub layout: Layout,
|
||||
}
|
||||
|
||||
impl UiState {
|
||||
pub fn new(layout: Layout) -> Self {
|
||||
Self { layout }
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn render(
|
||||
mut render_rx: mpsc::UnboundedReceiver<RenderingTask>,
|
||||
action_tx: mpsc::UnboundedSender<Action>,
|
||||
ui_state_tx: mpsc::UnboundedSender<UiState>,
|
||||
is_output_tty: bool,
|
||||
) -> Result<()> {
|
||||
let stream = if is_output_tty {
|
||||
@ -73,13 +86,19 @@ pub async fn render(
|
||||
if size.width.checked_mul(size.height).is_some() {
|
||||
queue!(stderr(), BeginSynchronizedUpdate).ok();
|
||||
tui.terminal.draw(|frame| {
|
||||
if let Err(err) =
|
||||
draw(&context, frame, frame.area())
|
||||
{
|
||||
warn!("Failed to draw: {:?}", err);
|
||||
let _ = action_tx.send(Action::Error(
|
||||
format!("Failed to draw: {err:?}"),
|
||||
));
|
||||
match draw(&context, frame, frame.area()) {
|
||||
Ok(layout) => {
|
||||
if layout != context.layout {
|
||||
let _ = ui_state_tx
|
||||
.send(UiState::new(layout));
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
warn!("Failed to draw: {:?}", err);
|
||||
let _ = action_tx.send(Action::Error(
|
||||
format!("Failed to draw: {err:?}"),
|
||||
));
|
||||
}
|
||||
}
|
||||
})?;
|
||||
execute!(stderr(), EndSynchronizedUpdate).ok();
|
||||
|
@ -29,7 +29,7 @@ impl Default for Dimensions {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct HelpBarLayout {
|
||||
pub left: Rect,
|
||||
pub middle: Rect,
|
||||
@ -82,6 +82,7 @@ impl Display for PreviewTitlePosition {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||
pub struct Layout {
|
||||
pub help_bar: Option<HelpBarLayout>,
|
||||
pub results: Rect,
|
||||
@ -90,6 +91,17 @@ pub struct Layout {
|
||||
pub remote_control: Option<Rect>,
|
||||
}
|
||||
|
||||
impl Default for Layout {
|
||||
/// Having a default layout with a non-zero height for the results area
|
||||
/// is important for the initial rendering of the application. For the first
|
||||
/// frame, this avoids not rendering any results at all since the picker's contents
|
||||
/// depend on the height of the results area which is not known until the first
|
||||
/// frame is rendered.
|
||||
fn default() -> Self {
|
||||
Self::new(None, Rect::new(0, 0, 0, 100), Rect::default(), None, None)
|
||||
}
|
||||
}
|
||||
|
||||
impl Layout {
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub fn new(
|
||||
|
@ -10,18 +10,18 @@ use crate::draw::{ChannelState, Ctx, TvState};
|
||||
use crate::input::convert_action_to_input_request;
|
||||
use crate::picker::Picker;
|
||||
use crate::preview::{PreviewState, Previewer};
|
||||
use crate::render::UiState;
|
||||
use crate::screen::colors::Colorscheme;
|
||||
use crate::screen::layout::InputPosition;
|
||||
use crate::screen::spinner::{Spinner, SpinnerState};
|
||||
use crate::utils::clipboard::CLIPBOARD;
|
||||
use crate::utils::metadata::AppMetadata;
|
||||
use crate::utils::strings::EMPTY_STRING;
|
||||
use anyhow::Result;
|
||||
use copypasta::{ClipboardContext, ClipboardProvider};
|
||||
use rustc_hash::{FxBuildHasher, FxHashSet};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashSet;
|
||||
use tokio::sync::mpsc::{Receiver, Sender, UnboundedSender};
|
||||
use tracing::error;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
#[derive(PartialEq, Copy, Clone, Hash, Eq, Debug, Serialize, Deserialize)]
|
||||
pub enum Mode {
|
||||
@ -39,7 +39,6 @@ pub struct Television {
|
||||
pub current_pattern: String,
|
||||
pub results_picker: Picker,
|
||||
pub rc_picker: Picker,
|
||||
results_area_height: u16,
|
||||
pub previewer: Previewer,
|
||||
pub preview_state: PreviewState,
|
||||
pub spinner: Spinner,
|
||||
@ -47,16 +46,7 @@ pub struct Television {
|
||||
pub app_metadata: AppMetadata,
|
||||
pub colorscheme: Colorscheme,
|
||||
pub ticks: u64,
|
||||
// these are really here as a means to communicate between the render thread
|
||||
// and the main thread to update `Television`'s state without needing to pass
|
||||
// a mutable reference to `draw`
|
||||
pub inner_rx: Receiver<Message>,
|
||||
pub inner_tx: Sender<Message>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub enum Message {
|
||||
ResultListHeightChanged(u16),
|
||||
pub ui_state: UiState,
|
||||
}
|
||||
|
||||
impl Television {
|
||||
@ -88,8 +78,6 @@ impl Television {
|
||||
|
||||
channel.find(&input.unwrap_or(EMPTY_STRING.to_string()));
|
||||
let spinner = Spinner::default();
|
||||
// capacity is quite arbitrary here, we can adjust it later
|
||||
let (inner_tx, inner_rx) = tokio::sync::mpsc::channel(10);
|
||||
|
||||
Self {
|
||||
action_tx,
|
||||
@ -102,7 +90,6 @@ impl Television {
|
||||
current_pattern: EMPTY_STRING.to_string(),
|
||||
results_picker,
|
||||
rc_picker: Picker::default(),
|
||||
results_area_height: 0,
|
||||
previewer,
|
||||
preview_state: PreviewState::default(),
|
||||
spinner,
|
||||
@ -110,11 +97,14 @@ impl Television {
|
||||
app_metadata,
|
||||
colorscheme,
|
||||
ticks: 0,
|
||||
inner_rx,
|
||||
inner_tx,
|
||||
ui_state: UiState::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update_ui_state(&mut self, ui_state: UiState) {
|
||||
self.ui_state = ui_state;
|
||||
}
|
||||
|
||||
pub fn init_remote_control(&mut self) {
|
||||
let cable_channels = load_cable_channels().unwrap_or_default();
|
||||
let builtin_channels = load_builtin_channels(Some(
|
||||
@ -135,7 +125,6 @@ impl Television {
|
||||
let tv_state = TvState::new(
|
||||
self.mode,
|
||||
self.get_selected_entry(Some(Mode::Channel)),
|
||||
self.results_area_height,
|
||||
self.results_picker.clone(),
|
||||
self.rc_picker.clone(),
|
||||
channel_state,
|
||||
@ -148,9 +137,9 @@ impl Television {
|
||||
self.config.clone(),
|
||||
self.colorscheme.clone(),
|
||||
self.app_metadata.clone(),
|
||||
self.inner_tx.clone(),
|
||||
// now timestamp
|
||||
std::time::Instant::now(),
|
||||
self.ui_state.layout,
|
||||
)
|
||||
}
|
||||
|
||||
@ -230,7 +219,7 @@ impl Television {
|
||||
picker.select_prev(
|
||||
step,
|
||||
result_count as usize,
|
||||
self.results_area_height as usize,
|
||||
self.ui_state.layout.results.height.saturating_sub(2) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
@ -249,7 +238,7 @@ impl Television {
|
||||
picker.select_next(
|
||||
step,
|
||||
result_count as usize,
|
||||
self.results_area_height as usize,
|
||||
self.ui_state.layout.results.height.saturating_sub(2) as usize,
|
||||
);
|
||||
}
|
||||
|
||||
@ -316,6 +305,7 @@ impl Television {
|
||||
{
|
||||
// preview content
|
||||
if let Some(preview) = self.previewer.preview(selected_entry) {
|
||||
// only update if the preview content has changed
|
||||
if self.preview_state.preview.title != preview.title {
|
||||
self.preview_state.update(
|
||||
preview,
|
||||
@ -324,7 +314,13 @@ impl Television {
|
||||
.line_number
|
||||
.unwrap_or(0)
|
||||
.saturating_sub(
|
||||
(self.results_area_height / 2).into(),
|
||||
(self
|
||||
.ui_state
|
||||
.layout
|
||||
.preview_window
|
||||
.map_or(0, |w| w.height)
|
||||
/ 2)
|
||||
.into(),
|
||||
)
|
||||
.try_into()?,
|
||||
selected_entry
|
||||
@ -349,7 +345,7 @@ impl Television {
|
||||
}
|
||||
|
||||
self.results_picker.entries = self.channel.results(
|
||||
self.results_area_height.into(),
|
||||
self.ui_state.layout.results.height.into(),
|
||||
u32::try_from(self.results_picker.offset()).unwrap(),
|
||||
);
|
||||
self.results_picker.total_items = self.channel.result_count();
|
||||
@ -365,7 +361,7 @@ impl Television {
|
||||
|
||||
self.rc_picker.entries = self.remote_control.results(
|
||||
// this'll be more than the actual rc height but it's fine
|
||||
self.results_area_height.into(),
|
||||
self.ui_state.layout.results.height.into(),
|
||||
u32::try_from(self.rc_picker.offset()).unwrap(),
|
||||
);
|
||||
self.rc_picker.total_items = self.remote_control.total_count();
|
||||
@ -480,20 +476,13 @@ impl Television {
|
||||
pub fn handle_copy_entry_to_clipboard(&mut self) {
|
||||
if self.mode == Mode::Channel {
|
||||
if let Some(entries) = self.get_selected_entries(None) {
|
||||
if let Ok(mut ctx) = ClipboardContext::new() {
|
||||
ctx.set_contents(
|
||||
entries
|
||||
.iter()
|
||||
.map(|e| e.name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" "),
|
||||
)
|
||||
.unwrap_or_else(|_| {
|
||||
error!("Could not copy to clipboard");
|
||||
});
|
||||
} else {
|
||||
error!("Could not copy to clipboard");
|
||||
}
|
||||
let copied_string = entries
|
||||
.iter()
|
||||
.map(|e| e.name.clone())
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
tokio::spawn(CLIPBOARD.set(copied_string));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -521,11 +510,25 @@ impl Television {
|
||||
}
|
||||
Action::SelectNextPage => {
|
||||
self.preview_state.reset();
|
||||
self.select_next_entry(self.results_area_height.into());
|
||||
self.select_next_entry(
|
||||
self.ui_state
|
||||
.layout
|
||||
.results
|
||||
.height
|
||||
.saturating_sub(2)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
Action::SelectPrevPage => {
|
||||
self.preview_state.reset();
|
||||
self.select_prev_entry(self.results_area_height.into());
|
||||
self.select_prev_entry(
|
||||
self.ui_state
|
||||
.layout
|
||||
.results
|
||||
.height
|
||||
.saturating_sub(2)
|
||||
.into(),
|
||||
);
|
||||
}
|
||||
Action::ScrollPreviewDown => self.preview_state.scroll_down(1),
|
||||
Action::ScrollPreviewUp => self.preview_state.scroll_up(1),
|
||||
@ -567,13 +570,6 @@ impl Television {
|
||||
///
|
||||
/// This function may return an Action that'll be processed by the parent `App`.
|
||||
pub fn update(&mut self, action: &Action) -> Result<Option<Action>> {
|
||||
if let Ok(Message::ResultListHeightChanged(height)) =
|
||||
self.inner_rx.try_recv()
|
||||
{
|
||||
self.results_area_height = height;
|
||||
self.action_tx.send(Action::Render)?;
|
||||
}
|
||||
|
||||
self.handle_action(action)?;
|
||||
|
||||
self.update_results_picker_state();
|
||||
|
177
television/utils/clipboard.rs
Normal file
177
television/utils/clipboard.rs
Normal file
@ -0,0 +1,177 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 - sxyazi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
use std::ffi::OsString;
|
||||
|
||||
use crate::utils::rocell::RoCell;
|
||||
use parking_lot::Mutex;
|
||||
|
||||
pub static CLIPBOARD: RoCell<Clipboard> = RoCell::new();
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Clipboard {
|
||||
content: Mutex<OsString>,
|
||||
}
|
||||
|
||||
impl Clipboard {
|
||||
#[cfg(unix)]
|
||||
pub async fn get(&self) -> OsString {
|
||||
use std::os::unix::prelude::OsStringExt;
|
||||
|
||||
use tokio::process::Command;
|
||||
|
||||
let all = [
|
||||
("pbpaste", &[][..]),
|
||||
("termux-clipboard-get", &[]),
|
||||
("wl-paste", &[]),
|
||||
("xclip", &["-o", "-selection", "clipboard"]),
|
||||
("xsel", &["-ob"]),
|
||||
];
|
||||
|
||||
for (bin, args) in all {
|
||||
let Ok(output) = Command::new(bin)
|
||||
.args(args)
|
||||
.kill_on_drop(true)
|
||||
.output()
|
||||
.await
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
if output.status.success() {
|
||||
return OsString::from_vec(output.stdout);
|
||||
}
|
||||
}
|
||||
self.content.lock().clone()
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub async fn get(&self) -> OsString {
|
||||
use clipboard_win::{formats, get_clipboard};
|
||||
|
||||
let result = tokio::task::spawn_blocking(|| {
|
||||
get_clipboard::<String, _>(formats::Unicode)
|
||||
});
|
||||
if let Ok(Ok(s)) = result.await {
|
||||
return s.into();
|
||||
}
|
||||
|
||||
self.content.lock().clone()
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub async fn set(&self, s: impl AsRef<std::ffi::OsStr>) {
|
||||
use std::{
|
||||
io::{stderr, BufWriter},
|
||||
process::Stdio,
|
||||
};
|
||||
|
||||
use crossterm::execute;
|
||||
use tokio::{io::AsyncWriteExt, process::Command};
|
||||
|
||||
s.as_ref().clone_into(&mut self.content.lock());
|
||||
execute!(
|
||||
BufWriter::new(stderr()),
|
||||
osc52::SetClipboard::new(s.as_ref())
|
||||
)
|
||||
.ok();
|
||||
|
||||
let all = [
|
||||
("pbcopy", &[][..]),
|
||||
("termux-clipboard-set", &[]),
|
||||
("wl-copy", &[]),
|
||||
("xclip", &["-selection", "clipboard"]),
|
||||
("xsel", &["-ib"]),
|
||||
];
|
||||
|
||||
for (bin, args) in all {
|
||||
let cmd = Command::new(bin)
|
||||
.args(args)
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::null())
|
||||
.stderr(Stdio::null())
|
||||
.kill_on_drop(true)
|
||||
.spawn();
|
||||
|
||||
let Ok(mut child) = cmd else { continue };
|
||||
|
||||
let mut stdin = child.stdin.take().unwrap();
|
||||
if stdin
|
||||
.write_all(s.as_ref().as_encoded_bytes())
|
||||
.await
|
||||
.is_err()
|
||||
{
|
||||
continue;
|
||||
}
|
||||
drop(stdin);
|
||||
|
||||
if child.wait().await.is_ok_and(|s| s.success()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub async fn set(&self, s: impl AsRef<std::ffi::OsStr>) {
|
||||
use clipboard_win::{formats, set_clipboard};
|
||||
|
||||
let s = s.as_ref().to_owned();
|
||||
*self.content.lock() = s.clone();
|
||||
|
||||
tokio::task::spawn_blocking(move || {
|
||||
set_clipboard(formats::Unicode, s.to_string_lossy())
|
||||
})
|
||||
.await
|
||||
.ok();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
mod osc52 {
|
||||
use std::ffi::OsStr;
|
||||
|
||||
use base64::{engine::general_purpose, Engine};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SetClipboard {
|
||||
content: String,
|
||||
}
|
||||
|
||||
impl SetClipboard {
|
||||
pub fn new(content: &OsStr) -> Self {
|
||||
Self {
|
||||
content: general_purpose::STANDARD
|
||||
.encode(content.as_encoded_bytes()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl crossterm::Command for SetClipboard {
|
||||
fn write_ansi(
|
||||
&self,
|
||||
f: &mut impl std::fmt::Write,
|
||||
) -> std::fmt::Result {
|
||||
write!(f, "\x1b]52;c;{}\x1b\\", self.content)
|
||||
}
|
||||
}
|
||||
}
|
@ -6,9 +6,9 @@ use std::io::BufReader;
|
||||
use std::io::Read;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::OnceLock;
|
||||
|
||||
use ignore::{overrides::Override, types::TypesBuilder, WalkBuilder};
|
||||
use lazy_static::lazy_static;
|
||||
use tracing::{debug, warn};
|
||||
|
||||
use crate::utils::strings::{
|
||||
@ -61,8 +61,10 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static::lazy_static! {
|
||||
pub static ref DEFAULT_NUM_THREADS: usize = default_num_threads().into();
|
||||
pub static DEFAULT_NUM_THREADS: OnceLock<usize> = OnceLock::new();
|
||||
|
||||
pub fn get_default_num_threads() -> usize {
|
||||
*DEFAULT_NUM_THREADS.get_or_init(default_num_threads)
|
||||
}
|
||||
|
||||
pub fn walk_builder(
|
||||
@ -147,342 +149,347 @@ where
|
||||
path.as_ref()
|
||||
.extension()
|
||||
.and_then(|ext| ext.to_str())
|
||||
.is_some_and(|ext| KNOWN_TEXT_FILE_EXTENSIONS.contains(ext))
|
||||
.is_some_and(|ext| get_known_text_file_extensions().contains(ext))
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
static ref KNOWN_TEXT_FILE_EXTENSIONS: FxHashSet<&'static str> = [
|
||||
"ada",
|
||||
"adb",
|
||||
"ads",
|
||||
"applescript",
|
||||
"as",
|
||||
"asc",
|
||||
"ascii",
|
||||
"ascx",
|
||||
"asm",
|
||||
"asmx",
|
||||
"asp",
|
||||
"aspx",
|
||||
"atom",
|
||||
"au3",
|
||||
"awk",
|
||||
"bas",
|
||||
"bash",
|
||||
"bashrc",
|
||||
"bat",
|
||||
"bbcolors",
|
||||
"bcp",
|
||||
"bdsgroup",
|
||||
"bdsproj",
|
||||
"bib",
|
||||
"bowerrc",
|
||||
"c",
|
||||
"cbl",
|
||||
"cc",
|
||||
"cfc",
|
||||
"cfg",
|
||||
"cfm",
|
||||
"cfml",
|
||||
"cgi",
|
||||
"cjs",
|
||||
"clj",
|
||||
"cljs",
|
||||
"cls",
|
||||
"cmake",
|
||||
"cmd",
|
||||
"cnf",
|
||||
"cob",
|
||||
"code-snippets",
|
||||
"coffee",
|
||||
"coffeekup",
|
||||
"conf",
|
||||
"cp",
|
||||
"cpp",
|
||||
"cpt",
|
||||
"cpy",
|
||||
"crt",
|
||||
"cs",
|
||||
"csh",
|
||||
"cson",
|
||||
"csproj",
|
||||
"csr",
|
||||
"css",
|
||||
"csslintrc",
|
||||
"csv",
|
||||
"ctl",
|
||||
"curlrc",
|
||||
"cxx",
|
||||
"d",
|
||||
"dart",
|
||||
"dfm",
|
||||
"diff",
|
||||
"dof",
|
||||
"dpk",
|
||||
"dpr",
|
||||
"dproj",
|
||||
"dtd",
|
||||
"eco",
|
||||
"editorconfig",
|
||||
"ejs",
|
||||
"el",
|
||||
"elm",
|
||||
"emacs",
|
||||
"eml",
|
||||
"ent",
|
||||
"erb",
|
||||
"erl",
|
||||
"eslintignore",
|
||||
"eslintrc",
|
||||
"ex",
|
||||
"exs",
|
||||
"f",
|
||||
"f03",
|
||||
"f77",
|
||||
"f90",
|
||||
"f95",
|
||||
"fish",
|
||||
"for",
|
||||
"fpp",
|
||||
"frm",
|
||||
"fs",
|
||||
"fsproj",
|
||||
"fsx",
|
||||
"ftn",
|
||||
"gemrc",
|
||||
"gemspec",
|
||||
"gitattributes",
|
||||
"gitconfig",
|
||||
"gitignore",
|
||||
"gitkeep",
|
||||
"gitmodules",
|
||||
"go",
|
||||
"gpp",
|
||||
"gradle",
|
||||
"graphql",
|
||||
"groovy",
|
||||
"groupproj",
|
||||
"grunit",
|
||||
"gtmpl",
|
||||
"gvimrc",
|
||||
"h",
|
||||
"haml",
|
||||
"hbs",
|
||||
"hgignore",
|
||||
"hh",
|
||||
"hpp",
|
||||
"hrl",
|
||||
"hs",
|
||||
"hta",
|
||||
"htaccess",
|
||||
"htc",
|
||||
"htm",
|
||||
"html",
|
||||
"htpasswd",
|
||||
"hxx",
|
||||
"iced",
|
||||
"iml",
|
||||
"inc",
|
||||
"inf",
|
||||
"info",
|
||||
"ini",
|
||||
"ino",
|
||||
"int",
|
||||
"irbrc",
|
||||
"itcl",
|
||||
"itermcolors",
|
||||
"itk",
|
||||
"jade",
|
||||
"java",
|
||||
"jhtm",
|
||||
"jhtml",
|
||||
"js",
|
||||
"jscsrc",
|
||||
"jshintignore",
|
||||
"jshintrc",
|
||||
"json",
|
||||
"json5",
|
||||
"jsonld",
|
||||
"jsp",
|
||||
"jspx",
|
||||
"jsx",
|
||||
"ksh",
|
||||
"less",
|
||||
"lhs",
|
||||
"lisp",
|
||||
"log",
|
||||
"ls",
|
||||
"lsp",
|
||||
"lua",
|
||||
"m",
|
||||
"m4",
|
||||
"mak",
|
||||
"map",
|
||||
"markdown",
|
||||
"master",
|
||||
"md",
|
||||
"mdown",
|
||||
"mdwn",
|
||||
"mdx",
|
||||
"metadata",
|
||||
"mht",
|
||||
"mhtml",
|
||||
"mjs",
|
||||
"mk",
|
||||
"mkd",
|
||||
"mkdn",
|
||||
"mkdown",
|
||||
"ml",
|
||||
"mli",
|
||||
"mm",
|
||||
"mxml",
|
||||
"nfm",
|
||||
"nfo",
|
||||
"noon",
|
||||
"npmignore",
|
||||
"npmrc",
|
||||
"nuspec",
|
||||
"nvmrc",
|
||||
"ops",
|
||||
"pas",
|
||||
"pasm",
|
||||
"patch",
|
||||
"pbxproj",
|
||||
"pch",
|
||||
"pem",
|
||||
"pg",
|
||||
"php",
|
||||
"php3",
|
||||
"php4",
|
||||
"php5",
|
||||
"phpt",
|
||||
"phtml",
|
||||
"pir",
|
||||
"pl",
|
||||
"pm",
|
||||
"pmc",
|
||||
"pod",
|
||||
"pot",
|
||||
"prettierrc",
|
||||
"properties",
|
||||
"props",
|
||||
"pt",
|
||||
"pug",
|
||||
"purs",
|
||||
"py",
|
||||
"pyx",
|
||||
"r",
|
||||
"rake",
|
||||
"rb",
|
||||
"rbw",
|
||||
"rc",
|
||||
"rdoc",
|
||||
"rdoc_options",
|
||||
"resx",
|
||||
"rexx",
|
||||
"rhtml",
|
||||
"rjs",
|
||||
"rlib",
|
||||
"ron",
|
||||
"rs",
|
||||
"rss",
|
||||
"rst",
|
||||
"rtf",
|
||||
"rvmrc",
|
||||
"rxml",
|
||||
"s",
|
||||
"sass",
|
||||
"scala",
|
||||
"scm",
|
||||
"scss",
|
||||
"seestyle",
|
||||
"sh",
|
||||
"shtml",
|
||||
"sln",
|
||||
"sls",
|
||||
"spec",
|
||||
"sql",
|
||||
"sqlite",
|
||||
"sqlproj",
|
||||
"srt",
|
||||
"ss",
|
||||
"sss",
|
||||
"st",
|
||||
"strings",
|
||||
"sty",
|
||||
"styl",
|
||||
"stylus",
|
||||
"sub",
|
||||
"sublime-build",
|
||||
"sublime-commands",
|
||||
"sublime-completions",
|
||||
"sublime-keymap",
|
||||
"sublime-macro",
|
||||
"sublime-menu",
|
||||
"sublime-project",
|
||||
"sublime-settings",
|
||||
"sublime-workspace",
|
||||
"sv",
|
||||
"svc",
|
||||
"svg",
|
||||
"swift",
|
||||
"t",
|
||||
"tcl",
|
||||
"tcsh",
|
||||
"terminal",
|
||||
"tex",
|
||||
"text",
|
||||
"textile",
|
||||
"tg",
|
||||
"tk",
|
||||
"tmLanguage",
|
||||
"tmpl",
|
||||
"tmTheme",
|
||||
"toml",
|
||||
"tpl",
|
||||
"ts",
|
||||
"tsv",
|
||||
"tsx",
|
||||
"tt",
|
||||
"tt2",
|
||||
"ttml",
|
||||
"twig",
|
||||
"txt",
|
||||
"v",
|
||||
"vb",
|
||||
"vbproj",
|
||||
"vbs",
|
||||
"vcproj",
|
||||
"vcxproj",
|
||||
"vh",
|
||||
"vhd",
|
||||
"vhdl",
|
||||
"vim",
|
||||
"viminfo",
|
||||
"vimrc",
|
||||
"vm",
|
||||
"vue",
|
||||
"webapp",
|
||||
"webmanifest",
|
||||
"wsc",
|
||||
"x-php",
|
||||
"xaml",
|
||||
"xht",
|
||||
"xhtml",
|
||||
"xml",
|
||||
"xs",
|
||||
"xsd",
|
||||
"xsl",
|
||||
"xslt",
|
||||
"y",
|
||||
"yaml",
|
||||
"yml",
|
||||
"zsh",
|
||||
"zshrc",
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect();
|
||||
pub static KNOWN_TEXT_FILE_EXTENSIONS: OnceLock<FxHashSet<&'static str>> =
|
||||
OnceLock::new();
|
||||
|
||||
pub fn get_known_text_file_extensions() -> &'static FxHashSet<&'static str> {
|
||||
KNOWN_TEXT_FILE_EXTENSIONS.get_or_init(|| {
|
||||
[
|
||||
"ada",
|
||||
"adb",
|
||||
"ads",
|
||||
"applescript",
|
||||
"as",
|
||||
"asc",
|
||||
"ascii",
|
||||
"ascx",
|
||||
"asm",
|
||||
"asmx",
|
||||
"asp",
|
||||
"aspx",
|
||||
"atom",
|
||||
"au3",
|
||||
"awk",
|
||||
"bas",
|
||||
"bash",
|
||||
"bashrc",
|
||||
"bat",
|
||||
"bbcolors",
|
||||
"bcp",
|
||||
"bdsgroup",
|
||||
"bdsproj",
|
||||
"bib",
|
||||
"bowerrc",
|
||||
"c",
|
||||
"cbl",
|
||||
"cc",
|
||||
"cfc",
|
||||
"cfg",
|
||||
"cfm",
|
||||
"cfml",
|
||||
"cgi",
|
||||
"cjs",
|
||||
"clj",
|
||||
"cljs",
|
||||
"cls",
|
||||
"cmake",
|
||||
"cmd",
|
||||
"cnf",
|
||||
"cob",
|
||||
"code-snippets",
|
||||
"coffee",
|
||||
"coffeekup",
|
||||
"conf",
|
||||
"cp",
|
||||
"cpp",
|
||||
"cpt",
|
||||
"cpy",
|
||||
"crt",
|
||||
"cs",
|
||||
"csh",
|
||||
"cson",
|
||||
"csproj",
|
||||
"csr",
|
||||
"css",
|
||||
"csslintrc",
|
||||
"csv",
|
||||
"ctl",
|
||||
"curlrc",
|
||||
"cxx",
|
||||
"d",
|
||||
"dart",
|
||||
"dfm",
|
||||
"diff",
|
||||
"dof",
|
||||
"dpk",
|
||||
"dpr",
|
||||
"dproj",
|
||||
"dtd",
|
||||
"eco",
|
||||
"editorconfig",
|
||||
"ejs",
|
||||
"el",
|
||||
"elm",
|
||||
"emacs",
|
||||
"eml",
|
||||
"ent",
|
||||
"erb",
|
||||
"erl",
|
||||
"eslintignore",
|
||||
"eslintrc",
|
||||
"ex",
|
||||
"exs",
|
||||
"f",
|
||||
"f03",
|
||||
"f77",
|
||||
"f90",
|
||||
"f95",
|
||||
"fish",
|
||||
"for",
|
||||
"fpp",
|
||||
"frm",
|
||||
"fs",
|
||||
"fsproj",
|
||||
"fsx",
|
||||
"ftn",
|
||||
"gemrc",
|
||||
"gemspec",
|
||||
"gitattributes",
|
||||
"gitconfig",
|
||||
"gitignore",
|
||||
"gitkeep",
|
||||
"gitmodules",
|
||||
"go",
|
||||
"gpp",
|
||||
"gradle",
|
||||
"graphql",
|
||||
"groovy",
|
||||
"groupproj",
|
||||
"grunit",
|
||||
"gtmpl",
|
||||
"gvimrc",
|
||||
"h",
|
||||
"haml",
|
||||
"hbs",
|
||||
"hgignore",
|
||||
"hh",
|
||||
"hpp",
|
||||
"hrl",
|
||||
"hs",
|
||||
"hta",
|
||||
"htaccess",
|
||||
"htc",
|
||||
"htm",
|
||||
"html",
|
||||
"htpasswd",
|
||||
"hxx",
|
||||
"iced",
|
||||
"iml",
|
||||
"inc",
|
||||
"inf",
|
||||
"info",
|
||||
"ini",
|
||||
"ino",
|
||||
"int",
|
||||
"irbrc",
|
||||
"itcl",
|
||||
"itermcolors",
|
||||
"itk",
|
||||
"jade",
|
||||
"java",
|
||||
"jhtm",
|
||||
"jhtml",
|
||||
"js",
|
||||
"jscsrc",
|
||||
"jshintignore",
|
||||
"jshintrc",
|
||||
"json",
|
||||
"json5",
|
||||
"jsonld",
|
||||
"jsp",
|
||||
"jspx",
|
||||
"jsx",
|
||||
"ksh",
|
||||
"less",
|
||||
"lhs",
|
||||
"lisp",
|
||||
"log",
|
||||
"ls",
|
||||
"lsp",
|
||||
"lua",
|
||||
"m",
|
||||
"m4",
|
||||
"mak",
|
||||
"map",
|
||||
"markdown",
|
||||
"master",
|
||||
"md",
|
||||
"mdown",
|
||||
"mdwn",
|
||||
"mdx",
|
||||
"metadata",
|
||||
"mht",
|
||||
"mhtml",
|
||||
"mjs",
|
||||
"mk",
|
||||
"mkd",
|
||||
"mkdn",
|
||||
"mkdown",
|
||||
"ml",
|
||||
"mli",
|
||||
"mm",
|
||||
"mxml",
|
||||
"nfm",
|
||||
"nfo",
|
||||
"noon",
|
||||
"npmignore",
|
||||
"npmrc",
|
||||
"nuspec",
|
||||
"nvmrc",
|
||||
"ops",
|
||||
"pas",
|
||||
"pasm",
|
||||
"patch",
|
||||
"pbxproj",
|
||||
"pch",
|
||||
"pem",
|
||||
"pg",
|
||||
"php",
|
||||
"php3",
|
||||
"php4",
|
||||
"php5",
|
||||
"phpt",
|
||||
"phtml",
|
||||
"pir",
|
||||
"pl",
|
||||
"pm",
|
||||
"pmc",
|
||||
"pod",
|
||||
"pot",
|
||||
"prettierrc",
|
||||
"properties",
|
||||
"props",
|
||||
"pt",
|
||||
"pug",
|
||||
"purs",
|
||||
"py",
|
||||
"pyx",
|
||||
"r",
|
||||
"rake",
|
||||
"rb",
|
||||
"rbw",
|
||||
"rc",
|
||||
"rdoc",
|
||||
"rdoc_options",
|
||||
"resx",
|
||||
"rexx",
|
||||
"rhtml",
|
||||
"rjs",
|
||||
"rlib",
|
||||
"ron",
|
||||
"rs",
|
||||
"rss",
|
||||
"rst",
|
||||
"rtf",
|
||||
"rvmrc",
|
||||
"rxml",
|
||||
"s",
|
||||
"sass",
|
||||
"scala",
|
||||
"scm",
|
||||
"scss",
|
||||
"seestyle",
|
||||
"sh",
|
||||
"shtml",
|
||||
"sln",
|
||||
"sls",
|
||||
"spec",
|
||||
"sql",
|
||||
"sqlite",
|
||||
"sqlproj",
|
||||
"srt",
|
||||
"ss",
|
||||
"sss",
|
||||
"st",
|
||||
"strings",
|
||||
"sty",
|
||||
"styl",
|
||||
"stylus",
|
||||
"sub",
|
||||
"sublime-build",
|
||||
"sublime-commands",
|
||||
"sublime-completions",
|
||||
"sublime-keymap",
|
||||
"sublime-macro",
|
||||
"sublime-menu",
|
||||
"sublime-project",
|
||||
"sublime-settings",
|
||||
"sublime-workspace",
|
||||
"sv",
|
||||
"svc",
|
||||
"svg",
|
||||
"swift",
|
||||
"t",
|
||||
"tcl",
|
||||
"tcsh",
|
||||
"terminal",
|
||||
"tex",
|
||||
"text",
|
||||
"textile",
|
||||
"tg",
|
||||
"tk",
|
||||
"tmLanguage",
|
||||
"tmpl",
|
||||
"tmTheme",
|
||||
"toml",
|
||||
"tpl",
|
||||
"ts",
|
||||
"tsv",
|
||||
"tsx",
|
||||
"tt",
|
||||
"tt2",
|
||||
"ttml",
|
||||
"twig",
|
||||
"txt",
|
||||
"v",
|
||||
"vb",
|
||||
"vbproj",
|
||||
"vbs",
|
||||
"vcproj",
|
||||
"vcxproj",
|
||||
"vh",
|
||||
"vhd",
|
||||
"vhdl",
|
||||
"vim",
|
||||
"viminfo",
|
||||
"vimrc",
|
||||
"vm",
|
||||
"vue",
|
||||
"webapp",
|
||||
"webmanifest",
|
||||
"wsc",
|
||||
"x-php",
|
||||
"xaml",
|
||||
"xht",
|
||||
"xhtml",
|
||||
"xml",
|
||||
"xs",
|
||||
"xsd",
|
||||
"xsl",
|
||||
"xslt",
|
||||
"y",
|
||||
"yaml",
|
||||
"yml",
|
||||
"zsh",
|
||||
"zshrc",
|
||||
]
|
||||
.iter()
|
||||
.copied()
|
||||
.collect()
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_accepted_image_extension<P>(path: P) -> bool
|
||||
|
@ -1,4 +1,5 @@
|
||||
pub mod cache;
|
||||
pub mod clipboard;
|
||||
pub mod command;
|
||||
pub mod files;
|
||||
pub mod hashmaps;
|
||||
@ -6,6 +7,7 @@ pub mod image;
|
||||
pub mod indices;
|
||||
pub mod input;
|
||||
pub mod metadata;
|
||||
pub mod rocell;
|
||||
pub mod shell;
|
||||
pub mod stdin;
|
||||
pub mod strings;
|
||||
|
99
television/utils/rocell.rs
Normal file
99
television/utils/rocell.rs
Normal file
@ -0,0 +1,99 @@
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 - sxyazi
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
use std::{
|
||||
cell::UnsafeCell,
|
||||
fmt::{self, Display},
|
||||
mem,
|
||||
ops::Deref,
|
||||
};
|
||||
|
||||
// Read-only cell. It's safe to use this in a static variable, but it's not safe
|
||||
// to mutate it. This is useful for storing static data that is expensive to
|
||||
// initialize, but is immutable once.
|
||||
pub struct RoCell<T>(UnsafeCell<Option<T>>);
|
||||
|
||||
unsafe impl<T> Sync for RoCell<T> {}
|
||||
|
||||
impl<T> RoCell<T> {
|
||||
#[inline]
|
||||
pub const fn new() -> Self {
|
||||
Self(UnsafeCell::new(None))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub const fn new_const(value: T) -> Self {
|
||||
Self(UnsafeCell::new(Some(value)))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn init(&self, value: T) {
|
||||
debug_assert!(!self.initialized());
|
||||
unsafe {
|
||||
*self.0.get() = Some(value);
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn with<F>(&self, f: F)
|
||||
where
|
||||
F: FnOnce() -> T,
|
||||
{
|
||||
self.init(f());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn drop(&self) -> T {
|
||||
debug_assert!(self.initialized());
|
||||
unsafe { mem::take(&mut *self.0.get()).unwrap_unchecked() }
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn initialized(&self) -> bool {
|
||||
unsafe { (*self.0.get()).is_some() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Default for RoCell<T> {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Deref for RoCell<T> {
|
||||
type Target = T;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
debug_assert!(self.initialized());
|
||||
unsafe { (*self.0.get()).as_ref().unwrap_unchecked() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Display for RoCell<T>
|
||||
where
|
||||
T: Display,
|
||||
{
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.deref().fmt(f)
|
||||
}
|
||||
}
|
@ -1,5 +1,3 @@
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
/// Returns the index of the next character boundary in the given string.
|
||||
///
|
||||
/// If the given index is already a character boundary, it is returned as is.
|
||||
@ -151,14 +149,11 @@ pub fn try_parse_utf8_char(input: &[u8]) -> Option<(char, usize)> {
|
||||
decoded.map(|(seq, n)| (seq.chars().next().unwrap(), n))
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// The Unicode symbol to use for non-printable characters.
|
||||
static ref NULL_SYMBOL: char = char::from_u32(0x2400).unwrap();
|
||||
}
|
||||
|
||||
pub const EMPTY_STRING: &str = "";
|
||||
pub const TAB_WIDTH: usize = 4;
|
||||
|
||||
/// The Unicode symbol to use for non-printable characters.
|
||||
const NULL_SYMBOL: char = '\u{2400}';
|
||||
const TAB_CHARACTER: char = '\t';
|
||||
const LINE_FEED_CHARACTER: char = '\x0A';
|
||||
const DELETE_CHARACTER: char = '\x7F';
|
||||
@ -304,7 +299,7 @@ pub fn replace_non_printable(
|
||||
| BOM_CHARACTER
|
||||
if config.replace_control_characters =>
|
||||
{
|
||||
output.push(*NULL_SYMBOL);
|
||||
output.push(NULL_SYMBOL);
|
||||
}
|
||||
// CJK Unified Ideographs
|
||||
// ex: 解
|
||||
@ -337,13 +332,13 @@ pub fn replace_non_printable(
|
||||
}
|
||||
// Unicode characters above 0x0700 seem unstable with ratatui
|
||||
c if c > '\u{0700}' => {
|
||||
output.push(*NULL_SYMBOL);
|
||||
output.push(NULL_SYMBOL);
|
||||
}
|
||||
// everything else
|
||||
c => output.push(c),
|
||||
}
|
||||
} else {
|
||||
output.push(*NULL_SYMBOL);
|
||||
output.push(NULL_SYMBOL);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
@ -224,7 +224,6 @@ pub fn compute_highlights_for_line<'a>(
|
||||
// SOFTWARE.
|
||||
|
||||
use directories::BaseDirs;
|
||||
use lazy_static::lazy_static;
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
use std::env;
|
||||
@ -258,13 +257,11 @@ impl BatProjectDirs {
|
||||
}
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
pub static ref PROJECT_DIRS: BatProjectDirs = BatProjectDirs::new()
|
||||
.unwrap_or_else(|| panic!("Could not get home directory"));
|
||||
}
|
||||
|
||||
pub fn load_highlighting_assets() -> HighlightingAssets {
|
||||
HighlightingAssets::from_cache(PROJECT_DIRS.cache_dir())
|
||||
let project_dirs = BatProjectDirs::new()
|
||||
.unwrap_or_else(|| panic!("Could not get home directory"));
|
||||
|
||||
HighlightingAssets::from_cache(project_dirs.cache_dir())
|
||||
.unwrap_or_else(|_| HighlightingAssets::from_binary())
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@ use std::num::NonZeroUsize;
|
||||
/// This will use the number of available threads if possible, but will default to 1 if the number
|
||||
/// of available threads cannot be determined. It will also never use more than 32 threads to avoid
|
||||
/// startup overhead.
|
||||
pub fn default_num_threads() -> NonZeroUsize {
|
||||
pub fn default_num_threads() -> usize {
|
||||
// default to 1 thread if we can't determine the number of available threads
|
||||
let default = NonZeroUsize::MIN;
|
||||
// never use more than 32 threads to avoid startup overhead
|
||||
@ -14,4 +14,5 @@ pub fn default_num_threads() -> NonZeroUsize {
|
||||
std::thread::available_parallelism()
|
||||
.unwrap_or(default)
|
||||
.min(limit)
|
||||
.get()
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user