mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: expose selected/yanked files as API (#674)
This commit is contained in:
parent
ebe0257180
commit
95d2358100
36 changed files with 328 additions and 202 deletions
137
Cargo.lock
generated
137
Cargo.lock
generated
|
|
@ -19,9 +19,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
|||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.8.7"
|
||||
version = "0.8.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "77c3a9648d43b9cd48db467b3f87fdd6e146bcc88ab0180006cef2179fe11d01"
|
||||
checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"once_cell",
|
||||
|
|
@ -230,9 +230,9 @@ checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
|||
|
||||
[[package]]
|
||||
name = "bytemuck"
|
||||
version = "1.14.1"
|
||||
version = "1.14.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ed2490600f404f2b94c167e31d3ed1d5f3c225a0f3b80230053b3e0b7b962bd9"
|
||||
checksum = "a2ef034f05691a48569bd920a96c81b9d91bbad1ab5ac7c4616c1f6ef36cb79f"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
|
|
@ -278,9 +278,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||
|
||||
[[package]]
|
||||
name = "chrono"
|
||||
version = "0.4.33"
|
||||
version = "0.4.34"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb"
|
||||
checksum = "5bc015644b92d5890fab7489e49d21f879d5c990186827d42ec511919404f38b"
|
||||
dependencies = [
|
||||
"android-tzdata",
|
||||
"iana-time-zone",
|
||||
|
|
@ -290,9 +290,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.4.18"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
|
||||
checksum = "80c21025abd42669a92efc996ef13cfb2c5c627858421ea58d5c3b331a6c134f"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
|
@ -300,9 +300,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.4.18"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
|
||||
checksum = "458bf1f341769dfcf849846f65dffdf9146daa56bcd2a47cb4e1de9915567c99"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
|
@ -312,18 +312,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete"
|
||||
version = "4.4.10"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "abb745187d7f4d76267b37485a65e0149edd0e91a4cfcdd3f27524ad86cee9f3"
|
||||
checksum = "299353be8209bd133b049bf1c63582d184a8b39fd9c04f15fe65f50f88bdfe6c"
|
||||
dependencies = [
|
||||
"clap",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_complete_fig"
|
||||
version = "4.4.2"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87e571d70e22ec91d34e1c5317c8308035a2280d925167646bf094fc5de1737c"
|
||||
checksum = "54b3e65f91fabdd23cac3d57d39d5d938b4daabd070c335c006dccb866a61110"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
|
|
@ -331,9 +331,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_complete_nushell"
|
||||
version = "4.4.2"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "948bf70d7e1f179635d3ef819ce8baa2d3074d0d57816ac37387cd6f9eed0c31"
|
||||
checksum = "92cd8ac7c321605310e4b3bdc047daf27c6ca1b50f6ae59b22aa0661ab45e295"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"clap_complete",
|
||||
|
|
@ -341,9 +341,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.4.7"
|
||||
version = "4.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442"
|
||||
checksum = "307bc0538d5f0f83b8248db3087aa92fe504e4691294d0c96c0eabc33f47ba47"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro2",
|
||||
|
|
@ -353,9 +353,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.6.0"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
|
||||
[[package]]
|
||||
name = "clipboard-win"
|
||||
|
|
@ -422,9 +422,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f"
|
|||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.3.2"
|
||||
version = "1.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d"
|
||||
checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
|
@ -547,9 +547,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.9.0"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07"
|
||||
checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a"
|
||||
|
||||
[[package]]
|
||||
name = "encode_unicode"
|
||||
|
|
@ -853,9 +853,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
|
|||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.5"
|
||||
version = "0.3.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3"
|
||||
checksum = "bd5256b483761cd23699d0da46cc6fd2ee3be420bbe6d020ae4a091e70b7e9fd"
|
||||
|
||||
[[package]]
|
||||
name = "home"
|
||||
|
|
@ -941,9 +941,9 @@ checksum = "029d73f573d8e8d63e6d5020011d3255b28c3ba85d6cf870a07184ed23de9284"
|
|||
|
||||
[[package]]
|
||||
name = "indexmap"
|
||||
version = "2.2.2"
|
||||
version = "2.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "824b2ae422412366ba479e8111fd301f7b5faece8149317bb81925979a53f520"
|
||||
checksum = "233cf39063f058ea2caae4091bf4a3ef70a653afbc026f5c4a4135d114e3c177"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown",
|
||||
|
|
@ -1001,9 +1001,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.67"
|
||||
version = "0.3.68"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a1d36f1235bc969acba30b7f5990b864423a6068a10f7c90ae8f0112e3a59d1"
|
||||
checksum = "406cda4b368d531c842222cf9d2600a9a4acce8d29423695379c6868a143a9ee"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
|
@ -1276,9 +1276,9 @@ checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
|
|||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.17"
|
||||
version = "0.2.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c"
|
||||
checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
|
@ -1523,9 +1523,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.26.0"
|
||||
version = "0.26.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "154b85ef15a5d1719bcaa193c3c81fe645cd120c156874cd660fe49fd21d1373"
|
||||
checksum = "bcb12f8fbf6c62614b0d56eb352af54f6a22410c3b079eb53ee93c7b97dd31d8"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"cassowary",
|
||||
|
|
@ -1590,7 +1590,7 @@ dependencies = [
|
|||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-automata",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1601,15 +1601,9 @@ checksum = "5bb987efffd3c6d0d8f5f89510bb458559eab11e4f869acb20bf845e016259cd"
|
|||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
"regex-syntax 0.8.2",
|
||||
"regex-syntax",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da"
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.2"
|
||||
|
|
@ -1851,9 +1845,9 @@ checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0"
|
|||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.10.0"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
checksum = "5ee073c9e4cd00e28217186dbe12796d692868f432bf2e97ee73bed0c56dfa01"
|
||||
|
||||
[[package]]
|
||||
name = "strum"
|
||||
|
|
@ -1901,9 +1895,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "syntect"
|
||||
version = "5.1.0"
|
||||
version = "5.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e02b4b303bf8d08bfeb0445cba5068a3d306b6baece1d5582171a9bf49188f91"
|
||||
checksum = "874dcfa363995604333cf947ae9f751ca3af4522c60886774c4963943b4746b1"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"bitflags 1.3.2",
|
||||
|
|
@ -1912,8 +1906,9 @@ dependencies = [
|
|||
"once_cell",
|
||||
"onig",
|
||||
"plist",
|
||||
"regex-syntax 0.7.5",
|
||||
"regex-syntax",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"walkdir",
|
||||
|
|
@ -1921,18 +1916,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.56"
|
||||
version = "1.0.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -2084,9 +2079,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.8.9"
|
||||
version = "0.8.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6a4b9e8023eb94392d3dca65d717c53abc5dad49c07cb65bb8fcd87115fa325"
|
||||
checksum = "9a9aad4a3066010876e8dcf5a8a06e70a558751117a145c6ce2b82c2e2054290"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
|
@ -2106,9 +2101,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "toml_edit"
|
||||
version = "0.21.1"
|
||||
version = "0.22.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1"
|
||||
checksum = "99e68c159e8f5ba8a28c4eb7b0c0c190d77bb479047ca713270048145a9ad28a"
|
||||
dependencies = [
|
||||
"indexmap",
|
||||
"serde",
|
||||
|
|
@ -2188,9 +2183,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "trash"
|
||||
version = "3.2.1"
|
||||
version = "3.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55bb920006929bc37df8c151c3c063b6fc10f485dfe4937393f905861a632e53"
|
||||
checksum = "c658458d46d9d5a153a3b5cdd88d8579ad50d4fb85d53961e4526c8fc7c55a57"
|
||||
dependencies = [
|
||||
"chrono",
|
||||
"libc",
|
||||
|
|
@ -2231,9 +2226,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "unicode-segmentation"
|
||||
version = "1.10.1"
|
||||
version = "1.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36"
|
||||
checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-width"
|
||||
|
|
@ -2352,9 +2347,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1223296a201415c7fad14792dbefaace9bd52b62d33453ade1c5b5f07555406"
|
||||
checksum = "c1e124130aee3fb58c5bdd6b639a0509486b0338acaaae0c84a5124b0f588b7f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
|
|
@ -2362,9 +2357,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcdc935b63408d58a32f8cc9738a0bffd8f05cc7c002086c6ef20b7312ad9dcd"
|
||||
checksum = "c9e7e1900c352b609c8488ad12639a311045f40a35491fb69ba8c12f758af70b"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
|
|
@ -2377,9 +2372,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e4c238561b2d428924c49815533a8b9121c664599558a5d9ec51f8a1740a999"
|
||||
checksum = "b30af9e2d358182b5c7449424f017eba305ed32a7010509ede96cdc4696c46ed"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
|
|
@ -2387,9 +2382,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bae1abb6806dc1ad9e560ed242107c0f6c84335f1749dd4e8ddb012ebd5e25a7"
|
||||
checksum = "642f325be6301eb8107a83d12a8ac6c1e1c54345a7ef1a9261962dfefda09e66"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
@ -2400,9 +2395,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.90"
|
||||
version = "0.2.91"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b"
|
||||
checksum = "4f186bd2dcf04330886ce82d6f33dd75a7bfcf69ecf5763b89fcde53b6ac9838"
|
||||
|
||||
[[package]]
|
||||
name = "weezl"
|
||||
|
|
@ -2663,9 +2658,9 @@ checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
|||
|
||||
[[package]]
|
||||
name = "winnow"
|
||||
version = "0.5.37"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7cad8365489051ae9f054164e459304af2e7e9bb407c958076c8bf4aef52da5"
|
||||
checksum = "6b1dbce9e90e5404c5a52ed82b1d13fc8cfbdad85033b6f57546ffd1265f8451"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@ keymap = [
|
|||
{ on = [ "<PageUp>" ], exec = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = [ "<PageDown>" ], exec = "arrow 100%", desc = "Move cursor down one page" },
|
||||
|
||||
{ on = [ "h" ], exec = [ "leave", "escape --visual --select" ], desc = "Go back to the parent directory" },
|
||||
{ on = [ "l" ], exec = [ "enter", "escape --visual --select" ], desc = "Enter the child directory" },
|
||||
{ on = [ "h" ], exec = [ "escape --visual", "leave" ], desc = "Go back to the parent directory" },
|
||||
{ on = [ "l" ], exec = [ "escape --visual", "enter" ], desc = "Enter the child directory" },
|
||||
|
||||
{ on = [ "H" ], exec = "back", desc = "Go back to the previous directory" },
|
||||
{ on = [ "L" ], exec = "forward", desc = "Go forward to the next directory" },
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ ueberzug_offset = [ 0, 0, 0, 0 ]
|
|||
|
||||
[opener]
|
||||
edit = [
|
||||
{ exec = '[ -n "$EDITOR" ] && $EDITOR "$@"', desc = "$EDITOR", block = true, for = "unix" },
|
||||
{ exec = 'code "%*"', orphan = true, for = "windows" },
|
||||
{ exec = '${EDITOR:=vi} "$@"', desc = "$EDITOR", block = true, for = "unix" },
|
||||
{ exec = 'code "%*"', orphan = true, for = "windows" },
|
||||
]
|
||||
open = [
|
||||
{ exec = 'xdg-open "$@"', desc = "Open", for = "linux" },
|
||||
|
|
|
|||
|
|
@ -317,7 +317,7 @@ impl Files {
|
|||
impl Files {
|
||||
// --- Items
|
||||
#[inline]
|
||||
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| &f.url == url) }
|
||||
pub fn position(&self, url: &Url) -> Option<usize> { self.iter().position(|f| f.url == *url) }
|
||||
|
||||
// --- Ticket
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -15,12 +15,11 @@ impl From<Cmd> for Opt {
|
|||
|
||||
impl Manager {
|
||||
pub fn link(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
||||
let (cut, ref src) = self.yanked;
|
||||
if cut {
|
||||
if self.yanked.cut {
|
||||
return;
|
||||
}
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
tasks.file_link(src, self.cwd(), opt.relative, opt.force);
|
||||
tasks.file_link(&self.yanked, self.cwd(), opt.relative, opt.force);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ use yazi_config::{popup::SelectCfg, ARGS, OPEN};
|
|||
use yazi_plugin::isolate;
|
||||
use yazi_shared::{emit, event::{Cmd, EventQuit}, fs::{File, Url}, Layer, MIME_DIR};
|
||||
|
||||
use crate::{manager::Manager, select::Select, tasks::Tasks};
|
||||
use crate::{folder::Folder, manager::Manager, select::Select, tasks::Tasks};
|
||||
|
||||
pub struct Opt {
|
||||
targets: Vec<(Url, Option<String>)>,
|
||||
targets: Vec<(Url, String)>,
|
||||
interactive: bool,
|
||||
}
|
||||
|
||||
|
|
@ -23,7 +23,7 @@ impl From<Cmd> for Opt {
|
|||
|
||||
impl Manager {
|
||||
pub fn open(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
||||
let selected = self.selected();
|
||||
let selected = self.selected_or_hovered();
|
||||
if selected.is_empty() {
|
||||
return;
|
||||
} else if Self::quit_with_selected(&selected) {
|
||||
|
|
@ -31,13 +31,13 @@ impl Manager {
|
|||
}
|
||||
|
||||
let (mut done, mut todo) = (Vec::with_capacity(selected.len()), vec![]);
|
||||
for f in selected {
|
||||
if f.is_dir() {
|
||||
done.push((f.url(), Some(MIME_DIR.to_owned())));
|
||||
} else if self.mimetype.get(&f.url).is_some() {
|
||||
done.push((f.url(), None));
|
||||
for u in selected {
|
||||
if self.mimetype.get(u).is_some() {
|
||||
done.push((u.clone(), String::new()));
|
||||
} else if self.guess_folder(u) {
|
||||
done.push((u.clone(), MIME_DIR.to_owned()));
|
||||
} else {
|
||||
todo.push(f.clone());
|
||||
todo.push(u.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -48,8 +48,15 @@ impl Manager {
|
|||
}
|
||||
|
||||
tokio::spawn(async move {
|
||||
done.extend(todo.iter().map(|f| (f.url(), None)));
|
||||
if let Err(e) = isolate::preload("mime", todo, true).await {
|
||||
let mut files = Vec::with_capacity(todo.len());
|
||||
for u in todo {
|
||||
if let Ok(f) = File::from(u).await {
|
||||
files.push(f);
|
||||
}
|
||||
}
|
||||
|
||||
done.extend(files.iter().map(|f| (f.url(), String::new())));
|
||||
if let Err(e) = isolate::preload("mime", files, true).await {
|
||||
error!("preload in watcher failed: {e}");
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +65,7 @@ impl Manager {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn _open_do(interactive: bool, targets: Vec<(Url, Option<String>)>) {
|
||||
pub fn _open_do(interactive: bool, targets: Vec<(Url, String)>) {
|
||||
emit!(Call(
|
||||
Cmd::new("open_do").with_bool("interactive", interactive).with_data(targets),
|
||||
Layer::Manager
|
||||
|
|
@ -74,7 +81,9 @@ impl Manager {
|
|||
let targets: Vec<_> = opt
|
||||
.targets
|
||||
.into_iter()
|
||||
.filter_map(|(u, m)| m.or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m)))
|
||||
.filter_map(|(u, m)| {
|
||||
Some(m).filter(|m| !m.is_empty()).or_else(|| self.mimetype.get(&u).cloned()).map(|m| (u, m))
|
||||
})
|
||||
.collect();
|
||||
|
||||
if targets.is_empty() {
|
||||
|
|
@ -98,13 +107,30 @@ impl Manager {
|
|||
});
|
||||
}
|
||||
|
||||
fn quit_with_selected(selected: &[&File]) -> bool {
|
||||
fn guess_folder(&self, url: &Url) -> bool {
|
||||
let Some(p) = url.parent_url() else {
|
||||
return true;
|
||||
};
|
||||
|
||||
let find = |folder: Option<&Folder>| {
|
||||
folder.is_some_and(|folder| {
|
||||
folder.cwd == p && folder.files.iter().any(|f| f.is_dir() && f.url == *url)
|
||||
})
|
||||
};
|
||||
|
||||
find(Some(self.current()))
|
||||
|| find(self.parent())
|
||||
|| find(self.hovered_folder())
|
||||
|| find(self.active().history.get(&p))
|
||||
}
|
||||
|
||||
fn quit_with_selected(selected: &[&Url]) -> bool {
|
||||
if ARGS.chooser_file.is_none() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let paths = selected.iter().fold(OsString::new(), |mut s, &f| {
|
||||
s.push(f.url.as_os_str());
|
||||
let paths = selected.iter().fold(OsString::new(), |mut s, &u| {
|
||||
s.push(u.as_os_str());
|
||||
s.push("\n");
|
||||
s
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,14 +15,13 @@ impl From<Cmd> for Opt {
|
|||
|
||||
impl Manager {
|
||||
pub fn paste(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
||||
let dest = self.cwd();
|
||||
let (cut, ref src) = self.yanked;
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
if cut {
|
||||
tasks.file_cut(src, dest, opt.force);
|
||||
|
||||
let dest = self.cwd();
|
||||
if self.yanked.cut {
|
||||
tasks.file_cut(&self.yanked, dest, opt.force);
|
||||
} else {
|
||||
tasks.file_copy(src, dest, opt.force, opt.follow);
|
||||
tasks.file_copy(&self.yanked, dest, opt.force, opt.follow);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,11 +35,7 @@ impl Manager {
|
|||
return render!(self.active_mut().preview.reset());
|
||||
};
|
||||
|
||||
let folder = Some(())
|
||||
.filter(|_| hovered.is_dir())
|
||||
.and_then(|_| self.active().history.get(&hovered.url))
|
||||
.map(|f| (f.offset, f.mtime));
|
||||
|
||||
let folder = self.active().hovered_folder().map(|f| (f.offset, f.mtime));
|
||||
if !self.active().preview.same_url(&hovered.url) {
|
||||
self.active_mut().preview.skip = folder.map(|f| f.0).unwrap_or_default();
|
||||
render!(self.active_mut().preview.reset());
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ impl From<Cmd> for Opt {
|
|||
impl Manager {
|
||||
pub fn remove(&mut self, opt: impl Into<Opt>, tasks: &Tasks) {
|
||||
let opt = opt.into() as Opt;
|
||||
let targets = self.selected().into_iter().map(|f| f.url()).collect();
|
||||
let targets = self.selected_or_hovered().into_iter().cloned().collect();
|
||||
tasks.file_remove(targets, opt.force, opt.permanently);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ impl Manager {
|
|||
}
|
||||
|
||||
pub fn rename(&self, opt: impl Into<Opt>) {
|
||||
if self.active().in_selecting() {
|
||||
if !self.active().selected.is_empty() {
|
||||
return self.bulk_rename();
|
||||
}
|
||||
|
||||
|
|
@ -96,7 +96,7 @@ impl Manager {
|
|||
}
|
||||
|
||||
fn bulk_rename(&self) {
|
||||
let old: Vec<_> = self.selected().into_iter().map(|f| &f.url).collect();
|
||||
let old: Vec<_> = self.selected_or_hovered();
|
||||
|
||||
let root = max_common_root(&old);
|
||||
let old: Vec<_> = old.into_iter().map(|p| p.strip_prefix(&root).unwrap().to_owned()).collect();
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ use crate::manager::Manager;
|
|||
|
||||
impl Manager {
|
||||
pub fn unyank(&mut self, _: Cmd) {
|
||||
render!(!self.yanked.1.is_empty());
|
||||
render!(!self.yanked.is_empty());
|
||||
|
||||
self.yanked = Default::default();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use yazi_shared::{event::Cmd, render};
|
||||
|
||||
use crate::manager::Manager;
|
||||
use crate::manager::{Manager, Yanked};
|
||||
|
||||
pub struct Opt {
|
||||
cut: bool,
|
||||
|
|
@ -14,8 +14,8 @@ impl Manager {
|
|||
pub fn yank(&mut self, opt: impl Into<Opt>) {
|
||||
let opt = opt.into() as Opt;
|
||||
|
||||
self.yanked.0 = opt.cut;
|
||||
self.yanked.1 = self.selected().into_iter().map(|f| f.url()).collect();
|
||||
self.yanked =
|
||||
Yanked { cut: opt.cut, urls: self.selected_or_hovered().into_iter().cloned().collect() };
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,13 @@
|
|||
use std::collections::{HashMap, HashSet};
|
||||
use std::collections::HashMap;
|
||||
|
||||
use yazi_shared::fs::{File, Url};
|
||||
|
||||
use super::{Tabs, Watcher};
|
||||
use super::{Tabs, Watcher, Yanked};
|
||||
use crate::{folder::Folder, tab::Tab};
|
||||
|
||||
pub struct Manager {
|
||||
pub tabs: Tabs,
|
||||
pub yanked: (bool, HashSet<Url>),
|
||||
pub yanked: Yanked,
|
||||
|
||||
pub(super) watcher: Watcher,
|
||||
pub mimetype: HashMap<Url, String>,
|
||||
|
|
@ -48,5 +48,8 @@ impl Manager {
|
|||
pub fn hovered(&self) -> Option<&File> { self.tabs.active().current.hovered() }
|
||||
|
||||
#[inline]
|
||||
pub fn selected(&self) -> Vec<&File> { self.tabs.active().selected() }
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> { self.tabs.active().hovered_folder() }
|
||||
|
||||
#[inline]
|
||||
pub fn selected_or_hovered(&self) -> Vec<&Url> { self.tabs.active().selected_or_hovered() }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,8 +3,10 @@ mod linked;
|
|||
mod manager;
|
||||
mod tabs;
|
||||
mod watcher;
|
||||
mod yanked;
|
||||
|
||||
pub use linked::*;
|
||||
pub use manager::*;
|
||||
pub use tabs::*;
|
||||
pub use watcher::*;
|
||||
pub use yanked::*;
|
||||
|
|
|
|||
15
yazi-core/src/manager/yanked.rs
Normal file
15
yazi-core/src/manager/yanked.rs
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
use std::{collections::HashSet, ops::Deref};
|
||||
|
||||
use yazi_shared::fs::Url;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Yanked {
|
||||
pub cut: bool,
|
||||
pub(super) urls: HashSet<Url>,
|
||||
}
|
||||
|
||||
impl Deref for Yanked {
|
||||
type Target = HashSet<Url>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { &self.urls }
|
||||
}
|
||||
|
|
@ -17,13 +17,13 @@ impl Tab {
|
|||
let opt = opt.into() as Opt;
|
||||
|
||||
let mut s = OsString::new();
|
||||
let mut it = self.selected().into_iter().peekable();
|
||||
while let Some(f) = it.next() {
|
||||
let mut it = self.selected_or_hovered().into_iter().peekable();
|
||||
while let Some(u) = it.next() {
|
||||
s.push(match opt.type_.as_str() {
|
||||
"path" => f.url.as_os_str(),
|
||||
"dirname" => f.url.parent().map_or(OsStr::new(""), |p| p.as_os_str()),
|
||||
"filename" => f.name().unwrap_or(OsStr::new("")),
|
||||
"name_without_ext" => f.stem().unwrap_or(OsStr::new("")),
|
||||
"path" => u.as_os_str(),
|
||||
"dirname" => u.parent().map_or(OsStr::new(""), |p| p.as_os_str()),
|
||||
"filename" => u.file_name().unwrap_or(OsStr::new("")),
|
||||
"name_without_ext" => u.file_stem().unwrap_or(OsStr::new("")),
|
||||
_ => return,
|
||||
});
|
||||
if it.peek().is_some() {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use bitflags::bitflags;
|
||||
use yazi_shared::{event::Cmd, render};
|
||||
|
||||
use crate::tab::{Mode, Tab};
|
||||
use crate::{manager::Manager, tab::{Mode, Tab}};
|
||||
|
||||
bitflags! {
|
||||
pub struct Opt: u8 {
|
||||
|
|
@ -53,9 +53,15 @@ impl Tab {
|
|||
|
||||
#[inline]
|
||||
fn escape_select(&mut self) -> bool {
|
||||
let old = self.selected.len();
|
||||
self.select_all(Some(false));
|
||||
old != self.selected.len()
|
||||
if self.selected.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
||||
self.selected.clear();
|
||||
if self.current.hovered().is_some_and(|h| h.is_dir()) {
|
||||
Manager::_peek(true);
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ impl From<Cmd> for Opt {
|
|||
impl Tab {
|
||||
pub fn shell(&self, opt: impl Into<Opt>) {
|
||||
let mut opt = opt.into() as Opt;
|
||||
let selected: Vec<_> = self.selected().into_iter().map(|f| f.url()).collect();
|
||||
let selected: Vec<_> = self.selected_or_hovered().into_iter().cloned().collect();
|
||||
|
||||
tokio::spawn(async move {
|
||||
if !opt.confirm || opt.exec.is_empty() {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
use std::{borrow::Cow, collections::{BTreeMap, BTreeSet}};
|
||||
use std::collections::{BTreeMap, BTreeSet};
|
||||
|
||||
use anyhow::Result;
|
||||
use tokio::task::JoinHandle;
|
||||
use yazi_shared::{fs::{File, Url}, render};
|
||||
use yazi_shared::{fs::Url, render};
|
||||
|
||||
use super::{Backstack, Config, Finder, Mode, Preview};
|
||||
use crate::folder::{Folder, FolderStage};
|
||||
|
|
@ -50,41 +50,12 @@ impl From<&Url> for Tab {
|
|||
|
||||
impl Tab {
|
||||
// --- Current
|
||||
#[inline]
|
||||
pub fn in_selecting(&self) -> bool {
|
||||
!self.selected.is_empty() || self.mode.visual().is_some_and(|(_, indices)| !indices.is_empty())
|
||||
}
|
||||
|
||||
pub fn selected(&self) -> Vec<&File> {
|
||||
let pending = self.mode.visual().map(|(_, p)| Cow::Borrowed(p)).unwrap_or_default();
|
||||
let is_unset = self.mode.is_unset();
|
||||
if self.selected.is_empty() && (is_unset || pending.is_empty()) {
|
||||
return self.current.hovered().map(|h| vec![h]).unwrap_or_default();
|
||||
}
|
||||
|
||||
let selected: BTreeSet<_> = self.selected.iter().collect();
|
||||
let pending: BTreeSet<_> =
|
||||
pending.iter().filter_map(|&i| self.current.files.get(i)).map(|f| &f.url).collect();
|
||||
|
||||
let urls: BTreeSet<_> = if is_unset {
|
||||
selected.difference(&pending).copied().collect()
|
||||
pub fn selected_or_hovered(&self) -> Vec<&Url> {
|
||||
if self.selected.is_empty() {
|
||||
self.current.hovered().map(|h| vec![&h.url]).unwrap_or_default()
|
||||
} else {
|
||||
selected.union(&pending).copied().collect()
|
||||
};
|
||||
|
||||
let mut items = Vec::with_capacity(urls.len());
|
||||
for item in self.current.files.iter() {
|
||||
if urls.contains(&item.url) {
|
||||
items.push(item);
|
||||
if items.len() == urls.len() {
|
||||
break;
|
||||
}
|
||||
}
|
||||
self.selected.iter().collect()
|
||||
}
|
||||
Some(items)
|
||||
.filter(|v| !v.is_empty())
|
||||
.or_else(|| self.current.hovered().map(|h| vec![h]))
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
// --- History
|
||||
|
|
@ -93,6 +64,11 @@ impl Tab {
|
|||
self.history.remove(url).unwrap_or_else(|| Folder::from(url))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn hovered_folder(&self) -> Option<&Folder> {
|
||||
self.current.hovered().filter(|&h| h.is_dir()).and_then(|h| self.history.get(&h.url))
|
||||
}
|
||||
|
||||
pub fn apply_files_attrs(&mut self) {
|
||||
let apply = |f: &mut Folder| {
|
||||
if f.stage == FolderStage::Loading {
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ impl<'a> Widget for Layout<'a> {
|
|||
let help = &self.cx.help;
|
||||
widgets::Clear.render(area, buf);
|
||||
|
||||
let chunks = layout::Layout::vertical([Constraint::Min(0), Constraint::Length(1)]).split(area);
|
||||
let chunks = layout::Layout::vertical([Constraint::Fill(1), Constraint::Length(1)]).split(area);
|
||||
Line::styled(
|
||||
help.keyword().unwrap_or_else(|| format!("{}.help", help.layer.to_string())),
|
||||
THEME.help.footer,
|
||||
|
|
|
|||
|
|
@ -76,9 +76,9 @@ impl File {
|
|||
});
|
||||
reg.add_method("is_yanked", |lua, me, ()| {
|
||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
Ok(if !cx.manager.yanked.1.contains(&me.url) {
|
||||
Ok(if !cx.manager.yanked.contains(&me.url) {
|
||||
0u8
|
||||
} else if cx.manager.yanked.0 {
|
||||
} else if cx.manager.yanked.cut {
|
||||
2u8
|
||||
} else {
|
||||
1u8
|
||||
|
|
@ -88,8 +88,11 @@ impl File {
|
|||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
let selected = me.tab().selected.contains(&me.url);
|
||||
|
||||
#[allow(clippy::if_same_then_else)]
|
||||
Ok(if !cx.manager.active().mode.is_visual() {
|
||||
selected
|
||||
} else if me.folder().cwd != me.tab().current.cwd {
|
||||
selected
|
||||
} else {
|
||||
cx.manager.active().mode.pending(me.idx, selected)
|
||||
})
|
||||
|
|
|
|||
|
|
@ -20,9 +20,11 @@ impl Lives {
|
|||
super::Folder::register(&LUA)?;
|
||||
super::Mode::register(&LUA)?;
|
||||
super::Preview::register(&LUA)?;
|
||||
super::Selected::register(&LUA)?;
|
||||
super::Tab::register(&LUA)?;
|
||||
super::Tabs::register(&LUA)?;
|
||||
super::Tasks::register(&LUA)?;
|
||||
super::Yanked::register(&LUA)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
@ -42,6 +44,7 @@ impl Lives {
|
|||
("active", super::Tab::make(cx.manager.active())?),
|
||||
("tabs", super::Tabs::make(&cx.manager.tabs)?),
|
||||
("tasks", super::Tasks::make(&cx.tasks)?),
|
||||
("yanked", scope.create_any_userdata_ref(&cx.manager.yanked)?),
|
||||
])?,
|
||||
)?;
|
||||
|
||||
|
|
|
|||
|
|
@ -7,9 +7,11 @@ mod folder;
|
|||
mod lives;
|
||||
mod mode;
|
||||
mod preview;
|
||||
mod selected;
|
||||
mod tab;
|
||||
mod tabs;
|
||||
mod tasks;
|
||||
mod yanked;
|
||||
|
||||
use config::*;
|
||||
use file::*;
|
||||
|
|
@ -18,8 +20,10 @@ use folder::*;
|
|||
pub(super) use lives::*;
|
||||
use mode::*;
|
||||
use preview::*;
|
||||
use selected::*;
|
||||
use tab::*;
|
||||
use tabs::*;
|
||||
use tasks::*;
|
||||
use yanked::*;
|
||||
|
||||
type CtxRef<'lua> = mlua::UserDataRef<'lua, crate::Ctx>;
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ impl Preview {
|
|||
reg.add_field_method_get("skip", |_, me| Ok(me.skip));
|
||||
reg.add_field_method_get("folder", |_, me| {
|
||||
me.tab()
|
||||
.current
|
||||
.hovered()
|
||||
.filter(|&f| f.is_dir())
|
||||
.and_then(|f| me.tab().history.get(&f.url))
|
||||
.hovered_folder()
|
||||
.map(|f| {
|
||||
let limit = LAYOUT.load().preview.height as usize;
|
||||
Folder::make(Some(me.skip..f.files.len().min(me.skip + limit)), f, me.tab())
|
||||
|
|
|
|||
52
yazi-fm/src/lives/selected.rs
Normal file
52
yazi-fm/src/lives/selected.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
use std::{collections::{btree_set, BTreeSet}, ops::Deref};
|
||||
|
||||
use mlua::{AnyUserData, Lua, MetaMethod, UserDataMethods, UserDataRefMut};
|
||||
use yazi_plugin::{bindings::Cast, url::Url};
|
||||
|
||||
use super::SCOPE;
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(super) struct Selected {
|
||||
inner: *const BTreeSet<yazi_shared::fs::Url>,
|
||||
}
|
||||
|
||||
impl Deref for Selected {
|
||||
type Target = BTreeSet<yazi_shared::fs::Url>;
|
||||
|
||||
fn deref(&self) -> &Self::Target { self.inner() }
|
||||
}
|
||||
|
||||
impl Selected {
|
||||
#[inline]
|
||||
pub(crate) fn make(inner: &BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
|
||||
SCOPE.create_any_userdata(Self { inner })
|
||||
}
|
||||
|
||||
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<Self>(|reg| {
|
||||
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
|
||||
|
||||
reg.add_meta_method(MetaMethod::Pairs, |lua, me, ()| {
|
||||
let iter = lua.create_function(|lua, mut iter: UserDataRefMut<SelectedIter>| {
|
||||
Ok(if let Some(url) = iter.0.next() { Some(Url::cast(lua, url.clone())?) } else { None })
|
||||
})?;
|
||||
|
||||
Ok((iter, SelectedIter::make(me.inner())))
|
||||
});
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn inner(&self) -> &'static BTreeSet<yazi_shared::fs::Url> { unsafe { &*self.inner } }
|
||||
}
|
||||
|
||||
struct SelectedIter(btree_set::Iter<'static, yazi_shared::fs::Url>);
|
||||
|
||||
impl SelectedIter {
|
||||
#[inline]
|
||||
fn make(selected: &'static BTreeSet<yazi_shared::fs::Url>) -> mlua::Result<AnyUserData<'static>> {
|
||||
SCOPE.create_any_userdata(Self(selected.iter()))
|
||||
}
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@ use std::ops::Deref;
|
|||
|
||||
use mlua::{AnyUserData, Lua, UserDataFields, UserDataMethods};
|
||||
|
||||
use super::{Config, Folder, Mode, Preview, SCOPE};
|
||||
use super::{Config, Folder, Mode, Preview, Selected, SCOPE};
|
||||
|
||||
pub(super) struct Tab {
|
||||
inner: *const yazi_core::tab::Tab,
|
||||
|
|
@ -36,10 +36,13 @@ impl Tab {
|
|||
|
||||
reg.add_field_method_get("mode", |_, me| Mode::make(&me.mode));
|
||||
reg.add_field_method_get("conf", |_, me| Config::make(&me.conf));
|
||||
reg.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));
|
||||
reg.add_field_method_get("parent", |_, me| {
|
||||
me.parent.as_ref().map(|f| Folder::make(None, f, me)).transpose()
|
||||
});
|
||||
reg.add_field_method_get("current", |_, me| Folder::make(None, &me.current, me));
|
||||
|
||||
reg.add_field_method_get("selected", |_, me| Selected::make(&me.selected));
|
||||
|
||||
reg.add_field_method_get("preview", |_, me| Preview::make(me));
|
||||
})?;
|
||||
|
||||
|
|
|
|||
13
yazi-fm/src/lives/yanked.rs
Normal file
13
yazi-fm/src/lives/yanked.rs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
use mlua::{Lua, MetaMethod, UserDataFields, UserDataMethods};
|
||||
|
||||
pub(super) struct Yanked;
|
||||
|
||||
impl Yanked {
|
||||
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<yazi_core::manager::Yanked>(|reg| {
|
||||
reg.add_field_method_get("is_cut", |_, me| Ok(me.cut));
|
||||
|
||||
reg.add_meta_method(MetaMethod::Len, |_, me, ()| Ok(me.len()));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
@ -13,7 +13,11 @@ impl<'a> Notify<'a> {
|
|||
pub(crate) fn new(cx: &'a Ctx) -> Self { Self { cx } }
|
||||
|
||||
fn chunks(area: Rect, messages: &[Message]) -> Rc<[Rect]> {
|
||||
let chunks = Layout::horizontal([Constraint::Percentage(100), Constraint::Min(40)]).split(area);
|
||||
let chunks =
|
||||
Layout::horizontal([Constraint::Fill(1), Constraint::Length(40), Constraint::Max(1)])
|
||||
.split(area);
|
||||
|
||||
let chunks = Layout::vertical([Constraint::Max(1), Constraint::Min(1)]).split(chunks[1]);
|
||||
|
||||
Layout::vertical(messages.iter().map(|m| Constraint::Length(m.height() as u16)))
|
||||
.spacing(1)
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ impl<'a> Root<'a> {
|
|||
impl<'a> Widget for Root<'a> {
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let chunks =
|
||||
Layout::vertical([Constraint::Length(1), Constraint::Min(0), Constraint::Length(1)])
|
||||
Layout::vertical([Constraint::Length(1), Constraint::Fill(1), Constraint::Length(1)])
|
||||
.split(area);
|
||||
|
||||
components::Header.render(chunks[0], buf);
|
||||
|
|
|
|||
|
|
@ -5,9 +5,13 @@ Current = {
|
|||
function Current:render(area)
|
||||
self.area = area
|
||||
|
||||
local markers = {}
|
||||
local items = {}
|
||||
for i, f in ipairs(Folder:by_kind(Folder.CURRENT).window) do
|
||||
local files = Folder:by_kind(Folder.CURRENT).window
|
||||
if #files == 0 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(files) do
|
||||
local name = Folder:highlighted_name(f)
|
||||
|
||||
-- Highlight hovered file
|
||||
|
|
@ -27,5 +31,10 @@ function Current:render(area)
|
|||
markers[#markers + 1] = { i, 3 }
|
||||
end
|
||||
end
|
||||
return ya.flat { ui.List(area, items), Folder:linemode(area), Folder:markers(area, markers) }
|
||||
|
||||
return ya.flat {
|
||||
ui.List(area, items),
|
||||
Folder:linemode(area, files),
|
||||
Folder:markers(area, markers),
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ function Folder:icon(file)
|
|||
end
|
||||
|
||||
function Folder:highlight_ranges(s, ranges)
|
||||
if ranges == nil or #ranges == 0 then
|
||||
if not ranges or #ranges == 0 then
|
||||
return { ui.Span(s) }
|
||||
end
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ function Folder:highlighted_name(file)
|
|||
spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic()
|
||||
end
|
||||
|
||||
if highlights == nil or not file:is_hovered() then
|
||||
if not highlights or not file:is_hovered() then
|
||||
return spans
|
||||
end
|
||||
|
||||
|
|
@ -67,14 +67,14 @@ function Folder:highlighted_name(file)
|
|||
return spans
|
||||
end
|
||||
|
||||
function Folder:linemode(area)
|
||||
function Folder:linemode(area, files)
|
||||
local mode = cx.active.conf.linemode
|
||||
if mode == "none" then
|
||||
return {}
|
||||
end
|
||||
|
||||
local lines = {}
|
||||
for _, f in ipairs(self:by_kind(self.CURRENT).window) do
|
||||
for _, f in ipairs(files) do
|
||||
local spans = { ui.Span(" ") }
|
||||
if mode == "size" then
|
||||
local size = f:size()
|
||||
|
|
|
|||
|
|
@ -6,21 +6,32 @@ function Parent:render(area)
|
|||
self.area = area
|
||||
|
||||
local folder = Folder:by_kind(Folder.PARENT)
|
||||
if folder == nil then
|
||||
if not folder then
|
||||
return {}
|
||||
end
|
||||
|
||||
local items = {}
|
||||
for _, f in ipairs(folder.window) do
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(folder.window) do
|
||||
-- Highlight hovered file
|
||||
local item = ui.ListItem(ui.Line { Folder:icon(f), ui.Span(f.name) })
|
||||
if f:is_hovered() then
|
||||
item = item:style(THEME.manager.hovered)
|
||||
else
|
||||
item = item:style(f:style())
|
||||
end
|
||||
|
||||
items[#items + 1] = item
|
||||
|
||||
-- Mark yanked/selected files
|
||||
local yanked = f:is_yanked()
|
||||
if yanked ~= 0 then
|
||||
markers[#markers + 1] = { i, yanked }
|
||||
elseif f:is_selected() then
|
||||
markers[#markers + 1] = { i, 3 }
|
||||
end
|
||||
end
|
||||
|
||||
return { ui.List(area, items) }
|
||||
return ya.flat {
|
||||
ui.List(area, items),
|
||||
Folder:markers(area, markers),
|
||||
}
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ end
|
|||
|
||||
function Status:size()
|
||||
local h = cx.active.current.hovered
|
||||
if h == nil then
|
||||
if not h then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
|
|
@ -40,7 +40,7 @@ end
|
|||
|
||||
function Status:name()
|
||||
local h = cx.active.current.hovered
|
||||
if h == nil then
|
||||
if not h then
|
||||
return ui.Span("")
|
||||
end
|
||||
|
||||
|
|
@ -49,12 +49,12 @@ end
|
|||
|
||||
function Status:permissions()
|
||||
local h = cx.active.current.hovered
|
||||
if h == nil then
|
||||
if not h then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
local perm = h.cha:permissions()
|
||||
if perm == nil then
|
||||
if not perm then
|
||||
return ui.Line {}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -304,9 +304,3 @@ setmetatable(inspect, {
|
|||
|
||||
ya = ya or {}
|
||||
ya.inspect = inspect
|
||||
ya.print = function(...)
|
||||
local args = { ... }
|
||||
for i = 1, #args do
|
||||
print(inspect(args[i]))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ local M = {}
|
|||
|
||||
function M:peek()
|
||||
local folder = Folder:by_kind(Folder.PREVIEW)
|
||||
if folder == nil or folder.cwd ~= self.file.url then
|
||||
if not folder or folder.cwd ~= self.file.url then
|
||||
return {}
|
||||
end
|
||||
|
||||
|
|
@ -11,8 +11,9 @@ function M:peek()
|
|||
ya.manager_emit("peek", { tostring(bound), only_if = tostring(self.file.url), upper_bound = "" })
|
||||
end
|
||||
|
||||
local items = {}
|
||||
for _, f in ipairs(folder.window) do
|
||||
local items, markers = {}, {}
|
||||
for i, f in ipairs(folder.window) do
|
||||
-- Highlight hovered file
|
||||
local item = ui.ListItem(ui.Line { Folder:icon(f), ui.Span(f.name) })
|
||||
if f:is_hovered() then
|
||||
item = item:style(THEME.manager.preview_hovered)
|
||||
|
|
@ -20,8 +21,23 @@ function M:peek()
|
|||
item = item:style(f:style())
|
||||
end
|
||||
items[#items + 1] = item
|
||||
|
||||
-- Mark yanked/selected files
|
||||
local yanked = f:is_yanked()
|
||||
if yanked ~= 0 then
|
||||
markers[#markers + 1] = { i, yanked }
|
||||
elseif f:is_selected() then
|
||||
markers[#markers + 1] = { i, 3 }
|
||||
end
|
||||
end
|
||||
ya.preview_widgets(self, { ui.List(self.area, items) })
|
||||
|
||||
ya.preview_widgets(
|
||||
self,
|
||||
ya.flat {
|
||||
ui.List(self.area, items),
|
||||
Folder:markers(self.area, markers),
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
function M:seek(units)
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ end
|
|||
|
||||
function ya.readable_path(path)
|
||||
local home = os.getenv("HOME") or os.getenv("USERPROFILE")
|
||||
if home == nil then
|
||||
if not home then
|
||||
return path
|
||||
elseif string.sub(path, 1, #home) == home then
|
||||
return "~" .. string.sub(path, #home + 1)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue