mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
fix: escape control characters in filenames (#3400)
This commit is contained in:
parent
c6e03e91d2
commit
dccc9b2c2a
16 changed files with 374 additions and 188 deletions
267
Cargo.lock
generated
267
Cargo.lock
generated
|
|
@ -24,7 +24,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d122413f284cf2d62fb1b7db97e02edb8cda96d769b16e443a4f6195e35662b0"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -283,7 +283,7 @@ dependencies = [
|
|||
"miniz_oxide",
|
||||
"object",
|
||||
"rustc-demangle",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -300,9 +300,9 @@ checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
|||
|
||||
[[package]]
|
||||
name = "base64ct"
|
||||
version = "1.6.0"
|
||||
version = "1.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
|
||||
|
||||
[[package]]
|
||||
name = "bcrypt-pbkdf"
|
||||
|
|
@ -391,7 +391,7 @@ version = "0.10.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -400,7 +400,7 @@ version = "0.3.3"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -548,7 +548,7 @@ dependencies = [
|
|||
"js-sys",
|
||||
"num-traits",
|
||||
"wasm-bindgen",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -694,9 +694,9 @@ checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
|||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.7.1"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb402b8d4c85569410425650ce3eddc7d698ed96d39a73f941b08fb63082f1e7"
|
||||
checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9"
|
||||
dependencies = [
|
||||
"unicode-segmentation",
|
||||
]
|
||||
|
|
@ -709,9 +709,9 @@ checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
|
|||
|
||||
[[package]]
|
||||
name = "core-models"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94950e87ea550d6d68f1993f3e7bebc8cb7235157bff84337d46195c3aa0b3f0"
|
||||
checksum = "0940496e5c83c54f3b753d5317daec82e8edac71c33aaa1f666d76f518de2444"
|
||||
dependencies = [
|
||||
"hax-lib",
|
||||
"pastey",
|
||||
|
|
@ -837,7 +837,7 @@ version = "0.5.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0dc92fb57ca44df6db8059111ab3af99a63d5d0f8375d9972e319a379c6bab76"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
"rand_core 0.6.4",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
|
@ -849,7 +849,7 @@ version = "0.1.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a"
|
||||
dependencies = [
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
|
|
@ -1015,22 +1015,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "derive_more"
|
||||
version = "2.0.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
|
||||
checksum = "10b768e943bed7bf2cab53df09f4bc34bfd217cdb57d971e769874c9a6710618"
|
||||
dependencies = [
|
||||
"derive_more-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_more-impl"
|
||||
version = "2.0.1"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
|
||||
checksum = "6d286bfdaf75e988b4a78e013ecd79c581e06399ab53fbacd2d916c2f904f30b"
|
||||
dependencies = [
|
||||
"convert_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rustc_version",
|
||||
"syn",
|
||||
]
|
||||
|
||||
|
|
@ -1131,7 +1132,7 @@ dependencies = [
|
|||
"crypto-bigint",
|
||||
"digest",
|
||||
"ff",
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
"group",
|
||||
"hkdf",
|
||||
"pem-rfc7468",
|
||||
|
|
@ -1445,6 +1446,17 @@ dependencies = [
|
|||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "generic-array"
|
||||
version = "1.3.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "eaf57c49a95fd1fe24b90b3033bee6dc7e8f1288d51494cb44e627c295e38542"
|
||||
dependencies = [
|
||||
"generic-array 0.14.7",
|
||||
"rustversion",
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.16"
|
||||
|
|
@ -1482,9 +1494,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "gif"
|
||||
version = "0.14.0"
|
||||
version = "0.14.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f954a9e9159ec994f73a30a12b96a702dde78f5547bcb561174597924f7d4162"
|
||||
checksum = "f5df2ba84018d80c213569363bdcd0c64e6933c67fe4c1d60ecf822971a3c35e"
|
||||
dependencies = [
|
||||
"color_quant",
|
||||
"weezl",
|
||||
|
|
@ -1759,7 +1771,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
|
||||
dependencies = [
|
||||
"block-padding",
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1901,15 +1913,15 @@ checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.177"
|
||||
version = "0.2.178"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2874a2af47a2325c2001a6e6fad9b16a53b802102b528163885171cf92b15976"
|
||||
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
|
||||
|
||||
[[package]]
|
||||
name = "libcrux-intrinsics"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d3b41dcbc21a5fb7efbbb5af7405b2e79c4bfe443924e90b13afc0080318d31"
|
||||
checksum = "bc9ee7ef66569dd7516454fe26de4e401c0c62073929803486b96744594b9632"
|
||||
dependencies = [
|
||||
"core-models",
|
||||
"hax-lib",
|
||||
|
|
@ -1917,16 +1929,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libcrux-ml-kem"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5d368d3e8d6a74e277178d54921eca112a1e6b7837d7d8bc555091acb5d817f5"
|
||||
checksum = "4bb6a88086bf11bd2ec90926c749c4a427f2e59841437dbdede8cde8a96334ab"
|
||||
dependencies = [
|
||||
"hax-lib",
|
||||
"libcrux-intrinsics",
|
||||
"libcrux-platform",
|
||||
"libcrux-secrets",
|
||||
"libcrux-sha3",
|
||||
"libcrux-traits",
|
||||
"rand 0.9.2",
|
||||
"tls_codec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1940,22 +1954,33 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libcrux-secrets"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "332737e629fe6ba7547f5c0f90559eac865d5dbecf98138ffae8f16ab8cbe33f"
|
||||
checksum = "6e4dbbf6bc9f2bc0f20dc3bea3e5c99adff3bdccf6d2a40488963da69e2ec307"
|
||||
dependencies = [
|
||||
"hax-lib",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libcrux-sha3"
|
||||
version = "0.0.3"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29d95de4257eafdfaf3bffecadb615219b0ca920c553722b3646d32dde76c797"
|
||||
checksum = "2400bec764d1c75b8a496d5747cffe32f1fb864a12577f0aca2f55a92021c962"
|
||||
dependencies = [
|
||||
"hax-lib",
|
||||
"libcrux-intrinsics",
|
||||
"libcrux-platform",
|
||||
"libcrux-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libcrux-traits"
|
||||
version = "0.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9adfd58e79d860f6b9e40e35127bfae9e5bd3ade33201d1347459011a2add034"
|
||||
dependencies = [
|
||||
"libcrux-secrets",
|
||||
"rand 0.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2013,9 +2038,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.28"
|
||||
version = "0.4.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34080505efa8e45a4b816c349525ebe327ceaa8559756f0356cba97ef3bf7432"
|
||||
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
|
||||
|
||||
[[package]]
|
||||
name = "loop9"
|
||||
|
|
@ -2501,9 +2526,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "pageant"
|
||||
version = "0.1.0"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb28bd89a207e5cad59072ac4b364b08459d05f90ccfbcdaa920a95857d94430"
|
||||
checksum = "1b537f975f6d8dcf48db368d7ec209d583b015713b5df0f5d92d2631e4ff5595"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"bytes",
|
||||
|
|
@ -2511,9 +2536,11 @@ dependencies = [
|
|||
"futures",
|
||||
"log",
|
||||
"rand 0.8.5",
|
||||
"sha2",
|
||||
"thiserror 1.0.69",
|
||||
"tokio",
|
||||
"windows 0.59.0",
|
||||
"windows 0.62.2",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -2566,7 +2593,7 @@ dependencies = [
|
|||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3139,12 +3166,11 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "russh"
|
||||
version = "0.54.6"
|
||||
version = "0.55.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23ca8e9091b72afdc9979bddcd1988ad898fa7bc0b85c8da8c154c29d44319eb"
|
||||
checksum = "82b4d036bb45d7bbe99dbfef4ec60eaeb614708d22ff107124272f8ef6b54548"
|
||||
dependencies = [
|
||||
"aes",
|
||||
"base64ct",
|
||||
"bitflags 2.10.0",
|
||||
"block-padding",
|
||||
"byteorder",
|
||||
|
|
@ -3161,7 +3187,7 @@ dependencies = [
|
|||
"elliptic-curve",
|
||||
"enum_dispatch",
|
||||
"futures",
|
||||
"generic-array",
|
||||
"generic-array 1.3.5",
|
||||
"getrandom 0.2.16",
|
||||
"hex-literal",
|
||||
"hmac",
|
||||
|
|
@ -3172,7 +3198,6 @@ dependencies = [
|
|||
"log",
|
||||
"md5",
|
||||
"num-bigint",
|
||||
"once_cell",
|
||||
"p256",
|
||||
"p384",
|
||||
"p521",
|
||||
|
|
@ -3336,7 +3361,7 @@ checksum = "d3e97a565f76233a6003f9f5c54be1d9c5bdfa3eccfb189469f11ec4901c47dc"
|
|||
dependencies = [
|
||||
"base16ct",
|
||||
"der",
|
||||
"generic-array",
|
||||
"generic-array 0.14.7",
|
||||
"pkcs8",
|
||||
"subtle",
|
||||
"zeroize",
|
||||
|
|
@ -3772,6 +3797,27 @@ dependencies = [
|
|||
"time-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tls_codec"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0de2e01245e2bb89d6f05801c564fa27624dbd7b1846859876c7dad82e90bf6b"
|
||||
dependencies = [
|
||||
"tls_codec_derive",
|
||||
"zeroize",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tls_codec_derive"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2d2e76690929402faae40aebdda620a2c0e25dd6d3b9afe48867dfd95991f4bd"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.48.0"
|
||||
|
|
@ -4046,9 +4092,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
|
|||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.18.1"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
|
||||
checksum = "e2e054861b4bd027cd373e18e8d8d8e6548085000e41290d95ce0c373a654b4a"
|
||||
dependencies = [
|
||||
"getrandom 0.3.4",
|
||||
"js-sys",
|
||||
|
|
@ -4290,12 +4336,23 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.59.0"
|
||||
version = "0.62.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
|
||||
checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580"
|
||||
dependencies = [
|
||||
"windows-core 0.59.0",
|
||||
"windows-targets 0.53.5",
|
||||
"windows-collections",
|
||||
"windows-core 0.62.2",
|
||||
"windows-future",
|
||||
"windows-numerics",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-collections"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4310,19 +4367,6 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
|
||||
dependencies = [
|
||||
"windows-implement 0.59.0",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-result 0.3.4",
|
||||
"windows-strings 0.3.1",
|
||||
"windows-targets 0.53.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.62.2"
|
||||
|
|
@ -4331,9 +4375,20 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb"
|
|||
dependencies = [
|
||||
"windows-implement 0.60.2",
|
||||
"windows-interface 0.59.3",
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
"windows-result 0.4.1",
|
||||
"windows-strings 0.5.1",
|
||||
"windows-strings",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-future"
|
||||
version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link",
|
||||
"windows-threading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4347,17 +4402,6 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.59.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.60.2"
|
||||
|
|
@ -4391,18 +4435,22 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
|
||||
|
||||
[[package]]
|
||||
name = "windows-link"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5"
|
||||
|
||||
[[package]]
|
||||
name = "windows-numerics"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26"
|
||||
dependencies = [
|
||||
"windows-core 0.62.2",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.1.2"
|
||||
|
|
@ -4412,31 +4460,13 @@ dependencies = [
|
|||
"windows-targets 0.52.6",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.3.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319"
|
||||
dependencies = [
|
||||
"windows-link 0.1.3",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4445,7 +4475,7 @@ version = "0.5.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4481,7 +4511,7 @@ version = "0.61.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -4506,7 +4536,7 @@ version = "0.53.5"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3"
|
||||
dependencies = [
|
||||
"windows-link 0.2.1",
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.1",
|
||||
"windows_aarch64_msvc 0.53.1",
|
||||
"windows_i686_gnu 0.53.1",
|
||||
|
|
@ -4517,6 +4547,15 @@ dependencies = [
|
|||
"windows_x86_64_msvc 0.53.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-threading"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.6"
|
||||
|
|
@ -5176,18 +5215,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.8.30"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ea879c944afe8a2b25fef16bb4ba234f47c694565e97383b36f3a878219065c"
|
||||
checksum = "fd74ec98b9250adb3ca554bdde269adf631549f51d8a8f8f0a10b50f1cb298c3"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.8.30"
|
||||
version = "0.8.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf955aa904d6040f70dc8e9384444cb1030aed272ba3cb09bbc4ab9e7c1f34f5"
|
||||
checksum = "d8a8d209fdf45cf5138cbb5a506f6b52522a25afccc534d1475dad8e31105c6a"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -5199,6 +5238,20 @@ name = "zeroize"
|
|||
version = "1.8.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
|
||||
dependencies = [
|
||||
"zeroize_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zeroize_derive"
|
||||
version = "1.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zune-core"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ futures = "0.3.31"
|
|||
globset = "0.4.18"
|
||||
hashbrown = { version = "0.16.1", features = [ "serde" ] }
|
||||
indexmap = { version = "2.12.1", features = [ "serde" ] }
|
||||
libc = "0.2.177"
|
||||
libc = "0.2.178"
|
||||
lru = "0.16.2"
|
||||
mlua = { version = "0.11.5", features = [ "anyhow", "async", "error-send", "lua54", "macros", "serde" ] }
|
||||
objc2 = "0.6.3"
|
||||
|
|
@ -44,7 +44,7 @@ percent-encoding = "2.3.2"
|
|||
rand = { version = "0.9.2", default-features = false, features = [ "os_rng", "small_rng", "std" ] }
|
||||
ratatui = { version = "0.29.0", features = [ "unstable-rendered-line-info", "unstable-widget-ref" ] }
|
||||
regex = "1.12.2"
|
||||
russh = { version = "0.54.6", default-features = false, features = [ "ring", "rsa" ] }
|
||||
russh = { version = "0.55.0", default-features = false, features = [ "ring", "rsa" ] }
|
||||
scopeguard = "1.2.0"
|
||||
serde = { version = "1.0.228", features = [ "derive" ] }
|
||||
serde_json = "1.0.145"
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
use std::{mem, path::MAIN_SEPARATOR_STR};
|
||||
use std::mem;
|
||||
|
||||
use anyhow::Result;
|
||||
use yazi_fs::{CWD, path::expand_url, provider::{DirReader, FileHolder}};
|
||||
use yazi_fs::{CWD, path::clean_url, provider::{DirReader, FileHolder}};
|
||||
use yazi_macro::{act, render, succ};
|
||||
use yazi_parser::cmp::{CmpItem, ShowOpt, TriggerOpt};
|
||||
use yazi_proxy::CmpProxy;
|
||||
use yazi_shared::{AnyAsciiChar, data::Data, natsort, path::{PathBufDyn, PathDyn, PathLike}, scheme::{SchemeCow, SchemeLike}, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}};
|
||||
use yazi_shared::{AnyAsciiChar, data::Data, natsort, path::{AsPath, PathBufDyn, PathCow, PathDyn, PathLike}, scheme::{SchemeCow, SchemeLike}, strand::{AsStrand, StrandLike}, url::{UrlBuf, UrlCow, UrlLike}};
|
||||
use yazi_vfs::provider;
|
||||
|
||||
use crate::{Actor, Ctx};
|
||||
|
|
@ -74,24 +74,25 @@ impl Trigger {
|
|||
return None; // We don't autocomplete a `~`, but `~/`
|
||||
}
|
||||
|
||||
let cwd = CWD.load();
|
||||
let abs = if !path.is_absolute() && cwd.scheme().covariant(&scheme) {
|
||||
cwd.loc().try_join(&path).ok()?.into()
|
||||
} else {
|
||||
PathCow::from(&path)
|
||||
};
|
||||
|
||||
let sep = if cfg!(windows) {
|
||||
AnyAsciiChar::new(b"/\\").unwrap()
|
||||
} else {
|
||||
AnyAsciiChar::new(b"/").unwrap()
|
||||
};
|
||||
|
||||
Some(match path.rsplit_pred(sep) {
|
||||
Some((p, c)) if p.is_empty() => {
|
||||
let root = PathDyn::with_str(scheme.kind(), MAIN_SEPARATOR_STR);
|
||||
(UrlCow::try_from((scheme, root)).ok()?.into_owned(), c.into())
|
||||
}
|
||||
Some((p, c)) => (expand_url(UrlCow::try_from((scheme, p)).ok()?), c.into()),
|
||||
None if CWD.load().scheme().covariant(&scheme) => (CWD.load().as_ref().clone(), path.into()),
|
||||
None => {
|
||||
let empty = PathDyn::with_str(scheme.kind(), "");
|
||||
(UrlCow::try_from((scheme, empty)).ok()?.into_owned(), path.into())
|
||||
}
|
||||
})
|
||||
let child = path.rsplit_pred(sep).map_or(path.as_path(), |(_, c)| c);
|
||||
let parent =
|
||||
PathDyn::with(scheme.kind(), abs.encoded_bytes().strip_suffix(child.encoded_bytes())?)
|
||||
.ok()?;
|
||||
|
||||
Some((clean_url(UrlCow::try_from((scheme, parent)).ok()?), child.into()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -130,11 +131,11 @@ mod tests {
|
|||
compare("/foo/bar", "/foo/", "bar");
|
||||
compare("///foo/bar", "/foo/", "bar");
|
||||
|
||||
CWD.set(&"sftp://test/".parse::<UrlBuf>().unwrap(), || {});
|
||||
compare("sftp://test/a", "sftp://test/", "a");
|
||||
compare("sftp://test//a", "sftp://test:0//", "a");
|
||||
compare("sftp://test2/a", "sftp://test2/", "a");
|
||||
compare("sftp://test2//a", "sftp://test2:0//", "a");
|
||||
CWD.set(&"sftp://test".parse::<UrlBuf>().unwrap(), || {});
|
||||
compare("sftp://test/a", "sftp://test/.", "a");
|
||||
compare("sftp://test//a", "sftp://test//", "a");
|
||||
compare("sftp://test2/a", "sftp://test2/.", "a");
|
||||
compare("sftp://test2//a", "sftp://test2//", "a");
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use tokio::pin;
|
|||
use tokio_stream::{StreamExt, wrappers::UnboundedReceiverStream};
|
||||
use yazi_config::popup::InputCfg;
|
||||
use yazi_dds::Pubsub;
|
||||
use yazi_fs::{File, FilesOp, path::expand_url};
|
||||
use yazi_fs::{File, FilesOp, path::{clean_url, expand_url}};
|
||||
use yazi_macro::{act, err, render, succ};
|
||||
use yazi_parser::mgr::CdOpt;
|
||||
use yazi_proxy::{CmpProxy, InputProxy, MgrProxy};
|
||||
|
|
@ -71,6 +71,7 @@ impl Cd {
|
|||
Ok(s) => {
|
||||
let Ok(url) = UrlBuf::try_from(s).map(expand_url) else { return };
|
||||
let Ok(url) = provider::absolute(&url).await else { return };
|
||||
let url = clean_url(url);
|
||||
|
||||
let Ok(file) = File::new(&url).await else { return };
|
||||
if file.is_dir() {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ fn clean_path_impl(path: PathDyn, base: usize, trail: usize) -> (PathBufDyn, usi
|
|||
|
||||
macro_rules! push {
|
||||
($i:ident, $c:ident) => {{
|
||||
out.push($c);
|
||||
out.push(($i, $c));
|
||||
if $i >= base {
|
||||
uri_count += 1;
|
||||
}
|
||||
|
|
@ -31,12 +31,25 @@ fn clean_path_impl(path: PathDyn, base: usize, trail: usize) -> (PathBufDyn, usi
|
|||
}};
|
||||
}
|
||||
|
||||
macro_rules! pop {
|
||||
() => {{
|
||||
if let Some((i, _)) = out.pop() {
|
||||
if i >= base {
|
||||
uri_count -= 1;
|
||||
}
|
||||
if i >= trail {
|
||||
urn_count -= 1;
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
for (i, c) in path.components().enumerate() {
|
||||
match c {
|
||||
CurDir => {}
|
||||
ParentDir => match out.last() {
|
||||
ParentDir => match out.last().map(|(_, c)| c) {
|
||||
Some(RootDir) => {}
|
||||
Some(Normal(_)) => _ = out.pop(),
|
||||
Some(Normal(_)) => pop!(),
|
||||
None | Some(CurDir) | Some(ParentDir) | Some(Prefix(_)) => push!(i, c),
|
||||
},
|
||||
c => push!(i, c),
|
||||
|
|
@ -47,7 +60,8 @@ fn clean_path_impl(path: PathDyn, base: usize, trail: usize) -> (PathBufDyn, usi
|
|||
let path = if out.is_empty() {
|
||||
PathBufDyn::with_str(kind, ".")
|
||||
} else {
|
||||
PathBufDyn::from_components(kind, out).expect("components with same kind")
|
||||
PathBufDyn::from_components(kind, out.into_iter().map(|(_, c)| c))
|
||||
.expect("components with same kind")
|
||||
};
|
||||
|
||||
(path, uri_count, urn_count)
|
||||
|
|
@ -70,10 +84,11 @@ mod tests {
|
|||
("archive://:3:2//../../tmp/test.zip/foo/bar", "archive://:3:2//tmp/test.zip/foo/bar"),
|
||||
("archive://:3:2//tmp/../../test.zip/foo/bar", "archive://:3:2//test.zip/foo/bar"),
|
||||
("archive://:4:2//tmp/test.zip/../../foo/bar", "archive://:2:2//foo/bar"),
|
||||
("archive://:5:2//tmp/test.zip/../../foo/bar", "archive://:3:2//foo/bar"),
|
||||
("archive://:4:4//tmp/test.zip/foo/bar/../../", "archive://:1:1//tmp/test.zip"),
|
||||
("archive://:5:4//tmp/test.zip/foo/bar/../../", "archive://:2:1//tmp/test.zip"),
|
||||
("archive://:5:2//tmp/test.zip/../../foo/bar", "archive://:2:2//foo/bar"),
|
||||
("archive://:4:4//tmp/test.zip/foo/bar/../../", "archive:////tmp/test.zip"),
|
||||
("archive://:5:4//tmp/test.zip/foo/bar/../../", "archive://:1//tmp/test.zip"),
|
||||
("archive://:4:4//tmp/test.zip/foo/bar/../../../", "archive:////tmp"),
|
||||
("sftp://test//root/.config/yazi/../../Downloads", "sftp://test//root/Downloads"),
|
||||
];
|
||||
|
||||
for (input, expected) in cases {
|
||||
|
|
|
|||
|
|
@ -31,22 +31,22 @@ function Entity:prefix()
|
|||
end
|
||||
|
||||
function Entity:highlights()
|
||||
local name = self._file.name:gsub("\r", "?", 1)
|
||||
local name, p = self._file.name, ui.printable
|
||||
local highlights = self._file:highlights()
|
||||
if not highlights or #highlights == 0 then
|
||||
return name
|
||||
return p(name)
|
||||
end
|
||||
|
||||
local spans, last = {}, 0
|
||||
for _, h in ipairs(highlights) do
|
||||
if h[1] > last then
|
||||
spans[#spans + 1] = name:sub(last + 1, h[1])
|
||||
spans[#spans + 1] = p(name:sub(last + 1, h[1]))
|
||||
end
|
||||
spans[#spans + 1] = ui.Span(name:sub(h[1] + 1, h[2])):style(th.mgr.find_keyword)
|
||||
spans[#spans + 1] = ui.Span(p(name:sub(h[1] + 1, h[2]))):style(th.mgr.find_keyword)
|
||||
last = h[2]
|
||||
end
|
||||
if last < #name then
|
||||
spans[#spans + 1] = name:sub(last + 1)
|
||||
spans[#spans + 1] = p(name:sub(last + 1))
|
||||
end
|
||||
return ui.Line(spans)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ function Status:name()
|
|||
return ""
|
||||
end
|
||||
|
||||
return " " .. h.name:gsub("\r", "?", 1)
|
||||
return " " .. ui.printable(h.name)
|
||||
end
|
||||
|
||||
function Status:perm()
|
||||
|
|
|
|||
|
|
@ -1,19 +1,23 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use mlua::{AnyUserData, ExternalError, IntoLua, Lua, ObjectLike, Table, Value};
|
||||
use tracing::error;
|
||||
use unicode_width::{UnicodeWidthChar, UnicodeWidthStr};
|
||||
use yazi_binding::{Composer, ComposerGet, ComposerSet, Permit, PermitRef, elements::{Line, Rect, Span}};
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_proxy::{AppProxy, HIDER};
|
||||
use yazi_shared::replace_to_printable;
|
||||
|
||||
pub fn compose() -> Composer<ComposerGet, ComposerSet> {
|
||||
fn get(lua: &Lua, key: &[u8]) -> mlua::Result<Value> {
|
||||
match key {
|
||||
b"area" => area(lua)?,
|
||||
b"hide" => hide(lua)?,
|
||||
b"width" => width(lua)?,
|
||||
b"printable" => printable(lua)?,
|
||||
b"redraw" => redraw(lua)?,
|
||||
b"render" => render(lua)?,
|
||||
b"truncate" => truncate(lua)?,
|
||||
b"width" => width(lua)?,
|
||||
_ => return Ok(Value::Nil),
|
||||
}
|
||||
.into_lua(lua)
|
||||
|
|
@ -54,28 +58,12 @@ pub(super) fn hide(lua: &Lua) -> mlua::Result<Value> {
|
|||
f.into_lua(lua)
|
||||
}
|
||||
|
||||
pub(super) fn width(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|_, v: Value| match v {
|
||||
Value::String(s) => {
|
||||
let (mut acc, b) = (0, s.as_bytes());
|
||||
for c in b.utf8_chunks() {
|
||||
acc += c.valid().width();
|
||||
if !c.invalid().is_empty() {
|
||||
acc += 1;
|
||||
}
|
||||
}
|
||||
Ok(acc)
|
||||
}
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(line) = ud.borrow::<Line>() {
|
||||
Ok(line.width())
|
||||
} else if let Ok(span) = ud.borrow::<Span>() {
|
||||
Ok(span.width())
|
||||
} else {
|
||||
Err("expected a string, Line, or Span".into_lua_err())?
|
||||
}
|
||||
}
|
||||
_ => Err("expected a string, Line, or Span".into_lua_err())?,
|
||||
pub(super) fn printable(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|lua, s: mlua::String| {
|
||||
Ok(match replace_to_printable(&*s.as_bytes(), false, 1, true) {
|
||||
Cow::Borrowed(_) => s,
|
||||
Cow::Owned(new) => lua.create_string(&new)?,
|
||||
})
|
||||
})?;
|
||||
|
||||
f.into_lua(lua)
|
||||
|
|
@ -176,6 +164,33 @@ pub(super) fn truncate(lua: &Lua) -> mlua::Result<Value> {
|
|||
f.into_lua(lua)
|
||||
}
|
||||
|
||||
pub(super) fn width(lua: &Lua) -> mlua::Result<Value> {
|
||||
let f = lua.create_function(|_, v: Value| match v {
|
||||
Value::String(s) => {
|
||||
let (mut acc, b) = (0, s.as_bytes());
|
||||
for c in b.utf8_chunks() {
|
||||
acc += c.valid().width();
|
||||
if !c.invalid().is_empty() {
|
||||
acc += 1;
|
||||
}
|
||||
}
|
||||
Ok(acc)
|
||||
}
|
||||
Value::UserData(ud) => {
|
||||
if let Ok(line) = ud.borrow::<Line>() {
|
||||
Ok(line.width())
|
||||
} else if let Ok(span) = ud.borrow::<Span>() {
|
||||
Ok(span.width())
|
||||
} else {
|
||||
Err("expected a string, Line, or Span".into_lua_err())?
|
||||
}
|
||||
}
|
||||
_ => Err("expected a string, Line, or Span".into_lua_err())?,
|
||||
})?;
|
||||
|
||||
f.into_lua(lua)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use mlua::{Lua, chunk};
|
||||
|
|
|
|||
14
yazi-plugin/src/external/highlighter.rs
vendored
14
yazi-plugin/src/external/highlighter.rs
vendored
|
|
@ -6,7 +6,7 @@ use syntect::{LoadingError, dumps, easy::HighlightLines, highlighting::{self, Th
|
|||
use tokio::io::{AsyncBufReadExt, AsyncSeekExt, BufReader};
|
||||
use yazi_config::{THEME, YAZI, preview::PreviewWrap};
|
||||
use yazi_fs::provider::{Provider, local::Local};
|
||||
use yazi_shared::{Ids, errors::PeekError, replace_to_printable};
|
||||
use yazi_shared::{Ids, errors::PeekError, push_printable_char};
|
||||
|
||||
static INCR: Ids = Ids::new();
|
||||
static SYNTECT: OnceLock<(Theme, SyntaxSet)> = OnceLock::new();
|
||||
|
|
@ -95,7 +95,7 @@ impl Highlighter {
|
|||
}
|
||||
|
||||
Ok(if plain {
|
||||
Text::from(replace_to_printable(&after, YAZI.preview.tab_size))
|
||||
Text::from(Self::merge_highlight_lines(&after, YAZI.preview.tab_size))
|
||||
} else {
|
||||
Self::highlight_with(before, after, syntax.unwrap()).await?
|
||||
})
|
||||
|
|
@ -203,6 +203,16 @@ impl Highlighter {
|
|||
*b = b'\n';
|
||||
}
|
||||
}
|
||||
|
||||
fn merge_highlight_lines(s: &[String], tab_size: u8) -> String {
|
||||
let mut buf = Vec::new();
|
||||
buf.reserve_exact(s.iter().map(|s| s.len()).sum::<usize>() | 15);
|
||||
|
||||
for &b in s.iter().flat_map(|s| s.as_bytes()) {
|
||||
push_printable_char(&mut buf, b, true, tab_size, false);
|
||||
}
|
||||
unsafe { String::from_utf8_unchecked(buf) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Highlighter {
|
||||
|
|
|
|||
|
|
@ -94,26 +94,48 @@ pub fn replace_vec_cow<'a>(v: &'a [u8], from: &[u8], to: &[u8]) -> Cow<'a, [u8]>
|
|||
Cow::Owned(out)
|
||||
}
|
||||
|
||||
pub fn replace_to_printable(s: &[String], tab_size: u8) -> String {
|
||||
let mut buf = Vec::new();
|
||||
buf.try_reserve_exact(s.iter().map(|s| s.len()).sum::<usize>() | 15).unwrap_or_else(|_| panic!());
|
||||
pub fn replace_to_printable(b: &[u8], lf: bool, tab_size: u8, replacement: bool) -> Cow<'_, [u8]> {
|
||||
// Fast path to skip over printable chars at the beginning of the string
|
||||
let printable_len = b.iter().take_while(|&&c| !c.is_ascii_control()).count();
|
||||
if printable_len >= b.len() {
|
||||
return Cow::Borrowed(b);
|
||||
}
|
||||
|
||||
for &b in s.iter().flat_map(|s| s.as_bytes()) {
|
||||
match b {
|
||||
b'\n' => buf.push(b'\n'),
|
||||
b'\t' => {
|
||||
buf.extend((0..tab_size).map(|_| b' '));
|
||||
}
|
||||
b'\0'..=b'\x1F' => {
|
||||
let (printable, rest) = b.split_at(printable_len);
|
||||
|
||||
let mut out = Vec::new();
|
||||
out.reserve_exact(b.len() | 15);
|
||||
out.extend_from_slice(printable);
|
||||
|
||||
for &c in rest {
|
||||
push_printable_char(&mut out, c, lf, tab_size, replacement);
|
||||
}
|
||||
Cow::Owned(out)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn push_printable_char(buf: &mut Vec<u8>, c: u8, lf: bool, tab_size: u8, replacement: bool) {
|
||||
match c {
|
||||
b'\n' if lf => buf.push(b'\n'),
|
||||
b'\t' => {
|
||||
buf.extend((0..tab_size).map(|_| b' '));
|
||||
}
|
||||
b'\0'..=b'\x1F' => {
|
||||
if replacement {
|
||||
buf.extend_from_slice(&[0xef, 0xbf, 0xbd]);
|
||||
} else {
|
||||
buf.push(b'^');
|
||||
buf.push(b + b'@');
|
||||
buf.push(c + b'@');
|
||||
}
|
||||
0x7f => {
|
||||
}
|
||||
0x7f => {
|
||||
if replacement {
|
||||
buf.extend_from_slice(&[0xef, 0xbf, 0xbd]);
|
||||
} else {
|
||||
buf.push(b'^');
|
||||
buf.push(b'?');
|
||||
}
|
||||
_ => buf.push(b),
|
||||
}
|
||||
_ => buf.push(c),
|
||||
}
|
||||
unsafe { String::from_utf8_unchecked(buf) }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -107,7 +107,22 @@ impl<'p> LocAbleImpl<'p> for &'p std::path::Path {
|
|||
where
|
||||
T: AsStrandView<'a, Self::Strand<'a>>,
|
||||
{
|
||||
self.strip_prefix(base.as_strand_view()).ok()
|
||||
use std::path::is_separator;
|
||||
|
||||
let p = self.strip_prefix(base.as_strand_view()).ok()?;
|
||||
let mut b = p.as_encoded_bytes();
|
||||
|
||||
if b.last().is_none_or(|&c| !is_separator(c as char)) || p.parent().is_none() {
|
||||
return Some(p);
|
||||
}
|
||||
|
||||
while let [head @ .., last] = b
|
||||
&& is_separator(*last as char)
|
||||
{
|
||||
b = head;
|
||||
}
|
||||
|
||||
Some(unsafe { Self::from_encoded_bytes_unchecked(b) })
|
||||
}
|
||||
|
||||
fn to_path_buf(self) -> Self::Owned { self.to_path_buf() }
|
||||
|
|
@ -139,7 +154,18 @@ impl<'p> LocAbleImpl<'p> for &'p typed_path::UnixPath {
|
|||
where
|
||||
T: AsStrandView<'a, Self::Strand<'a>>,
|
||||
{
|
||||
self.strip_prefix(base.as_strand_view()).ok()
|
||||
let p = self.strip_prefix(base.as_strand_view()).ok()?;
|
||||
let mut b = p.as_bytes();
|
||||
|
||||
if b.last().is_none_or(|&c| c != b'/') || p.parent().is_none() {
|
||||
return Some(p);
|
||||
}
|
||||
|
||||
while let [head @ .., b'/'] = b {
|
||||
b = head;
|
||||
}
|
||||
|
||||
Some(typed_path::UnixPath::new(b))
|
||||
}
|
||||
|
||||
fn to_path_buf(self) -> Self::Owned { self.to_path_buf() }
|
||||
|
|
|
|||
|
|
@ -85,8 +85,8 @@ where
|
|||
{
|
||||
let path = path.as_path_view();
|
||||
let Some(name) = path.file_name() else {
|
||||
let uri = path.strip_prefix(P::empty()).unwrap().len();
|
||||
return Self { inner: path, uri, urn: 0, _phantom: PhantomData };
|
||||
let p = path.strip_prefix(P::empty()).unwrap();
|
||||
return Self { inner: p, uri: p.len(), urn: 0, _phantom: PhantomData };
|
||||
};
|
||||
|
||||
let name_len = name.len();
|
||||
|
|
@ -244,3 +244,38 @@ where
|
|||
loc
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_with() -> Result<()> {
|
||||
let cases = [
|
||||
// Relative paths
|
||||
("tmp/test.zip/foo/bar", 3, 2, "test.zip/foo/bar", "foo/bar"),
|
||||
("tmp/test.zip/foo/bar/", 3, 2, "test.zip/foo/bar", "foo/bar"),
|
||||
// Absolute paths
|
||||
("/tmp/test.zip/foo/bar", 3, 2, "test.zip/foo/bar", "foo/bar"),
|
||||
("/tmp/test.zip/foo/bar/", 3, 2, "test.zip/foo/bar", "foo/bar"),
|
||||
// Relative path with parent components
|
||||
("tmp/test.zip/foo/bar/../..", 5, 4, "test.zip/foo/bar/../..", "foo/bar/../.."),
|
||||
("tmp/test.zip/foo/bar/../../", 5, 4, "test.zip/foo/bar/../..", "foo/bar/../.."),
|
||||
// Absolute path with parent components
|
||||
("/tmp/test.zip/foo/bar/../..", 5, 4, "test.zip/foo/bar/../..", "foo/bar/../.."),
|
||||
("/tmp/test.zip/foo/bar/../../", 5, 4, "test.zip/foo/bar/../..", "foo/bar/../.."),
|
||||
];
|
||||
|
||||
for (path, uri, urn, expect_uri, expect_urn) in cases {
|
||||
let loc = Loc::with(std::path::Path::new(path), uri, urn)?;
|
||||
assert_eq!(loc.uri().to_str().unwrap(), expect_uri);
|
||||
assert_eq!(loc.urn().to_str().unwrap(), expect_urn);
|
||||
|
||||
let loc = Loc::with(typed_path::UnixPath::new(path), uri, urn)?;
|
||||
assert_eq!(loc.uri().to_str().unwrap(), expect_uri);
|
||||
assert_eq!(loc.urn().to_str().unwrap(), expect_urn);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,10 @@ impl From<PathBufDyn> for PathCow<'_> {
|
|||
fn from(value: PathBufDyn) -> Self { Self::Owned(value) }
|
||||
}
|
||||
|
||||
impl<'a> From<&'a PathCow<'_>> for PathCow<'a> {
|
||||
fn from(value: &'a PathCow<'_>) -> Self { Self::Borrowed(value.as_path()) }
|
||||
}
|
||||
|
||||
impl From<PathCow<'_>> for PathBufDyn {
|
||||
fn from(value: PathCow<'_>) -> Self { value.into_owned() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -98,6 +98,10 @@ impl AsStrand for PathCow<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsStrand for &PathCow<'_> {
|
||||
fn as_strand(&self) -> Strand<'_> { (**self).as_strand() }
|
||||
}
|
||||
|
||||
impl AsStrand for Strand<'_> {
|
||||
fn as_strand(&self) -> Strand<'_> { *self }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -109,7 +109,7 @@ impl<'a> Strand<'a> {
|
|||
|
||||
let (skip, rest) = bytes.split_at(skip_len);
|
||||
let mut out = Vec::new();
|
||||
out.try_reserve_exact(bytes.len()).unwrap_or_else(|_| panic!());
|
||||
out.reserve_exact(bytes.len());
|
||||
out.extend(skip);
|
||||
|
||||
for &b in rest {
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl Transliterator for &[u8] {
|
|||
// but instead of `+ 16` uses `| 15` to stay in the smallest allocation bucket
|
||||
// for short strings
|
||||
let mut out = String::new();
|
||||
out.try_reserve_exact(self.len() | 15).unwrap_or_else(|_| panic!());
|
||||
out.reserve_exact(self.len() | 15);
|
||||
out.push_str(unsafe { str::from_utf8_unchecked(ascii) });
|
||||
|
||||
for c in String::from_utf8_lossy(rest).chars() {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue