mirror of
https://github.com/sxyazi/yazi.git
synced 2024-10-05 14:47:19 +03:00
Compare commits
7 Commits
83b8a16740
...
6a64d6aa6b
Author | SHA1 | Date | |
---|---|---|---|
|
6a64d6aa6b | ||
|
987b1d5c49 | ||
|
1a1da216ca | ||
|
9961251248 | ||
|
626053da25 | ||
|
c64530b35b | ||
|
9a5b75662a |
22
Cargo.lock
generated
22
Cargo.lock
generated
@ -1024,6 +1024,15 @@ dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itertools"
|
||||
version = "0.13.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
|
||||
dependencies = [
|
||||
"either",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
@ -1242,7 +1251,7 @@ version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "09697a6cec88e7f58a02c7ab5c18c611c6907c8654613df9cc0192658a4fb859"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"once_cell",
|
||||
"proc-macro-error",
|
||||
"proc-macro2",
|
||||
@ -1575,19 +1584,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ratatui"
|
||||
version = "0.26.3"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f44c9e68fd46eda15c646fbb85e1040b657a58cdc8c98db1d97a55930d991eef"
|
||||
checksum = "d16546c5b5962abf8ce6e2881e722b4e0ae3b6f1a08a26ae3573c55853ca68d3"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"cassowary",
|
||||
"compact_str",
|
||||
"crossterm",
|
||||
"itertools",
|
||||
"itertools 0.13.0",
|
||||
"lru",
|
||||
"paste",
|
||||
"stability",
|
||||
"strum",
|
||||
"strum_macros",
|
||||
"unicode-segmentation",
|
||||
"unicode-truncate",
|
||||
"unicode-width",
|
||||
@ -2291,7 +2301,7 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a5fbabedabe362c618c714dbefda9927b5afc8e2a8102f47f081089a9019226"
|
||||
dependencies = [
|
||||
"itertools",
|
||||
"itertools 0.12.1",
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
@ -2892,8 +2902,6 @@ dependencies = [
|
||||
"mlua",
|
||||
"parking_lot",
|
||||
"ratatui",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shell-escape",
|
||||
"shell-words",
|
||||
"syntect",
|
||||
|
@ -23,7 +23,7 @@ futures = "0.3.30"
|
||||
image = "=0.24.9"
|
||||
imagesize = "0.13.0"
|
||||
kamadak-exif = "0.5.5"
|
||||
ratatui = "0.26.3"
|
||||
ratatui = "0.27.0"
|
||||
scopeguard = "1.2.0"
|
||||
tokio = { version = "1.38.0", features = [ "full" ] }
|
||||
|
||||
|
@ -8,7 +8,7 @@ use tracing::{debug, warn};
|
||||
use yazi_config::PREVIEW;
|
||||
use yazi_shared::RoCell;
|
||||
|
||||
use crate::{Adapter, Image};
|
||||
use crate::{Adapter, Dimension};
|
||||
|
||||
#[allow(clippy::type_complexity)]
|
||||
static DEMON: RoCell<Option<UnboundedSender<Option<(PathBuf, Rect)>>>> = RoCell::new();
|
||||
@ -50,9 +50,16 @@ impl Ueberzug {
|
||||
let ImageSize { width: w, height: h } =
|
||||
tokio::task::spawn_blocking(move || imagesize::size(p)).await??;
|
||||
|
||||
let area = Image::pixel_area((w as u32, h as u32), max);
|
||||
tx.send(Some((path.to_owned(), area)))?;
|
||||
let area = Dimension::ratio()
|
||||
.map(|(r1, r2)| Rect {
|
||||
x: max.x,
|
||||
y: max.y,
|
||||
width: max.width.min((w.min(PREVIEW.max_width as _) as f64 / r1).ceil() as _),
|
||||
height: max.height.min((h.min(PREVIEW.max_height as _) as f64 / r2).ceil() as _),
|
||||
})
|
||||
.unwrap_or(max);
|
||||
|
||||
tx.send(Some((path.to_owned(), area)))?;
|
||||
Adapter::shown_store(area);
|
||||
Ok(area)
|
||||
}
|
||||
|
@ -45,7 +45,7 @@ impl CommandPub {
|
||||
pub(super) fn receiver(&self) -> Result<u64> {
|
||||
if let Some(receiver) = self.receiver {
|
||||
Ok(receiver)
|
||||
} else if let Ok(s) = std::env::var("YAZI_ID") {
|
||||
} else if let Some(s) = std::env::var("YAZI_PID").ok().filter(|s| !s.is_empty()) {
|
||||
Ok(s.parse()?)
|
||||
} else {
|
||||
bail!("No receiver ID provided, also no YAZI_ID environment variable found.")
|
||||
|
@ -18,7 +18,7 @@ bitflags = "2.5.0"
|
||||
crossterm = "0.27.0"
|
||||
globset = "0.4.14"
|
||||
indexmap = "2.2.6"
|
||||
ratatui = "0.26.3"
|
||||
ratatui = "0.27.0"
|
||||
serde = { version = "1.0.203", features = [ "derive" ] }
|
||||
toml = { version = "0.8.14", features = [ "preserve_order" ] }
|
||||
validator = { version = "0.18.1", features = [ "derive" ] }
|
||||
|
@ -5,84 +5,84 @@
|
||||
[manager]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<Esc>" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||
{ on = [ "<C-[>" ], run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||
{ on = [ "q" ], run = "quit", desc = "Exit the process" },
|
||||
{ on = [ "Q" ], run = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" },
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Close the current tab, or quit if it is last tab" },
|
||||
{ on = [ "<C-z>" ], run = "suspend", desc = "Suspend the process" },
|
||||
{ on = "<Esc>", run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||
{ on = "<C-[>", run = "escape", desc = "Exit visual mode, clear selected, or cancel search" },
|
||||
{ on = "q", run = "quit", desc = "Exit the process" },
|
||||
{ on = "Q", run = "quit --no-cwd-file", desc = "Exit the process without writing cwd-file" },
|
||||
{ on = "<C-c>", run = "close", desc = "Close the current tab, or quit if it is last tab" },
|
||||
{ on = "<C-z>", run = "suspend", desc = "Suspend the process" },
|
||||
|
||||
# Navigation
|
||||
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "k", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "j", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "<S-Up>", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "<S-Down>", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
{ on = [ "<C-u>" ], run = "arrow -50%", desc = "Move cursor up half page" },
|
||||
{ on = [ "<C-d>" ], run = "arrow 50%", desc = "Move cursor down half page" },
|
||||
{ on = [ "<C-b>" ], run = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = [ "<C-f>" ], run = "arrow 100%", desc = "Move cursor down one page" },
|
||||
{ on = "<C-u>", run = "arrow -50%", desc = "Move cursor up half page" },
|
||||
{ on = "<C-d>", run = "arrow 50%", desc = "Move cursor down half page" },
|
||||
{ on = "<C-b>", run = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = "<C-f>", run = "arrow 100%", desc = "Move cursor down one page" },
|
||||
|
||||
{ on = [ "<C-PageUp>" ], run = "arrow -50%", desc = "Move cursor up half page" },
|
||||
{ on = [ "<C-PageDown>" ], run = "arrow 50%", desc = "Move cursor down half page" },
|
||||
{ on = [ "<PageUp>" ], run = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = [ "<PageDown>" ], run = "arrow 100%", desc = "Move cursor down one page" },
|
||||
{ on = "<C-PageUp>", run = "arrow -50%", desc = "Move cursor up half page" },
|
||||
{ on = "<C-PageDown>", run = "arrow 50%", desc = "Move cursor down half page" },
|
||||
{ on = "<PageUp>", run = "arrow -100%", desc = "Move cursor up one page" },
|
||||
{ on = "<PageDown>", run = "arrow 100%", desc = "Move cursor down one page" },
|
||||
|
||||
{ on = [ "h" ], run = "leave", desc = "Go back to the parent directory" },
|
||||
{ on = [ "l" ], run = "enter", desc = "Enter the child directory" },
|
||||
{ on = "h", run = "leave", desc = "Go back to the parent directory" },
|
||||
{ on = "l", run = "enter", desc = "Enter the child directory" },
|
||||
|
||||
{ on = [ "H" ], run = "back", desc = "Go back to the previous directory" },
|
||||
{ on = [ "L" ], run = "forward", desc = "Go forward to the next directory" },
|
||||
{ on = "H", run = "back", desc = "Go back to the previous directory" },
|
||||
{ on = "L", run = "forward", desc = "Go forward to the next directory" },
|
||||
|
||||
{ on = [ "<A-k>" ], run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||
{ on = [ "<A-j>" ], run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||
{ on = [ "<A-PageUp>" ], run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||
{ on = [ "<A-PageDown>" ], run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||
{ on = "<A-k>", run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||
{ on = "<A-j>", run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||
{ on = "<A-PageUp>", run = "seek -5", desc = "Seek up 5 units in the preview" },
|
||||
{ on = "<A-PageDown>", run = "seek 5", desc = "Seek down 5 units in the preview" },
|
||||
|
||||
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = [ "<Left>" ], run = "leave", desc = "Go back to the parent directory" },
|
||||
{ on = [ "<Right>" ], run = "enter", desc = "Enter the child directory" },
|
||||
{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<Left>", run = "leave", desc = "Go back to the parent directory" },
|
||||
{ on = "<Right>", run = "enter", desc = "Enter the child directory" },
|
||||
|
||||
{ on = [ "g", "g" ], run = "arrow -99999999", desc = "Move cursor to the top" },
|
||||
{ on = [ "G" ], run = "arrow 99999999", desc = "Move cursor to the bottom" },
|
||||
{ on = "G", run = "arrow 99999999", desc = "Move cursor to the bottom" },
|
||||
|
||||
# Selection
|
||||
{ on = [ "<Space>" ], run = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" },
|
||||
{ on = [ "v" ], run = "visual_mode", desc = "Enter visual mode (selection mode)" },
|
||||
{ on = [ "V" ], run = "visual_mode --unset", desc = "Enter visual mode (unset mode)" },
|
||||
{ on = [ "<C-a>" ], run = "select_all --state=true", desc = "Select all files" },
|
||||
{ on = [ "<C-r>" ], run = "select_all --state=none", desc = "Inverse selection of all files" },
|
||||
{ on = "<Space>", run = [ "select --state=none", "arrow 1" ], desc = "Toggle the current selection state" },
|
||||
{ on = "v", run = "visual_mode", desc = "Enter visual mode (selection mode)" },
|
||||
{ on = "V", run = "visual_mode --unset", desc = "Enter visual mode (unset mode)" },
|
||||
{ on = "<C-a>", run = "select_all --state=true", desc = "Select all files" },
|
||||
{ on = "<C-r>", run = "select_all --state=none", desc = "Inverse selection of all files" },
|
||||
|
||||
# Operation
|
||||
{ on = [ "o" ], run = "open", desc = "Open the selected files" },
|
||||
{ on = [ "O" ], run = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = [ "<Enter>" ], run = "open", desc = "Open the selected files" },
|
||||
{ on = [ "<S-Enter>" ], run = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = [ "y" ], run = "yank", desc = "Copy the selected files" },
|
||||
{ on = [ "Y" ], run = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = [ "x" ], run = "yank --cut", desc = "Cut the selected files" },
|
||||
{ on = [ "X" ], run = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = [ "p" ], run = "paste", desc = "Paste the files" },
|
||||
{ on = [ "P" ], run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||
{ on = [ "-" ], run = "link", desc = "Symlink the absolute path of files" },
|
||||
{ on = [ "_" ], run = "link --relative", desc = "Symlink the relative path of files" },
|
||||
{ on = [ "d" ], run = "remove", desc = "Move the files to the trash" },
|
||||
{ on = [ "D" ], run = "remove --permanently", desc = "Permanently delete the files" },
|
||||
{ on = [ "a" ], run = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
{ on = [ "r" ], run = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
||||
{ on = [ ";" ], run = "shell", desc = "Run a shell command" },
|
||||
{ on = [ ":" ], run = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" },
|
||||
{ on = [ "." ], run = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||
{ on = [ "s" ], run = "search fd", desc = "Search files by name using fd" },
|
||||
{ on = [ "S" ], run = "search rg", desc = "Search files by content using ripgrep" },
|
||||
{ on = [ "<C-s>" ], run = "search none", desc = "Cancel the ongoing search" },
|
||||
{ on = [ "z" ], run = "plugin zoxide", desc = "Jump to a directory using zoxide" },
|
||||
{ on = [ "Z" ], run = "plugin fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
||||
{ on = "o", run = "open", desc = "Open the selected files" },
|
||||
{ on = "O", run = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = "<Enter>", run = "open", desc = "Open the selected files" },
|
||||
{ on = "<S-Enter>", run = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = "y", run = "yank", desc = "Copy the selected files" },
|
||||
{ on = "Y", run = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = "x", run = "yank --cut", desc = "Cut the selected files" },
|
||||
{ on = "X", run = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = "p", run = "paste", desc = "Paste the files" },
|
||||
{ on = "P", run = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||
{ on = "-", run = "link", desc = "Symlink the absolute path of files" },
|
||||
{ on = "_", run = "link --relative", desc = "Symlink the relative path of files" },
|
||||
{ on = "d", run = "remove", desc = "Move the files to the trash" },
|
||||
{ on = "D", run = "remove --permanently", desc = "Permanently delete the files" },
|
||||
{ on = "a", run = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
{ on = "r", run = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
||||
{ on = ";", run = "shell --interactive", desc = "Run a shell command" },
|
||||
{ on = ":", run = "shell --block --interactive", desc = "Run a shell command (block the UI until the command finishes)" },
|
||||
{ on = ".", run = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||
{ on = "s", run = "search fd", desc = "Search files by name using fd" },
|
||||
{ on = "S", run = "search rg", desc = "Search files by content using ripgrep" },
|
||||
{ on = "<C-s>", run = "search none", desc = "Cancel the ongoing search" },
|
||||
{ on = "z", run = "plugin zoxide", desc = "Jump to a directory using zoxide" },
|
||||
{ on = "Z", run = "plugin fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
||||
|
||||
# Linemode
|
||||
{ on = [ "m", "s" ], run = "linemode size", desc = "Set linemode to size" },
|
||||
@ -97,13 +97,13 @@ keymap = [
|
||||
{ on = [ "c", "n" ], run = "copy name_without_ext", desc = "Copy the name of the file without the extension" },
|
||||
|
||||
# Filter
|
||||
{ on = [ "f" ], run = "filter --smart", desc = "Filter the files" },
|
||||
{ on = "f", run = "filter --smart", desc = "Filter the files" },
|
||||
|
||||
# Find
|
||||
{ on = [ "/" ], run = "find --smart", desc = "Find next file" },
|
||||
{ on = [ "?" ], run = "find --previous --smart", desc = "Find previous file" },
|
||||
{ on = [ "n" ], run = "find_arrow", desc = "Go to next found file" },
|
||||
{ on = [ "N" ], run = "find_arrow --previous", desc = "Go to previous found file" },
|
||||
{ on = "/", run = "find --smart", desc = "Find next file" },
|
||||
{ on = "?", run = "find --previous --smart", desc = "Find previous file" },
|
||||
{ on = "n", run = "find_arrow", desc = "Go to next found file" },
|
||||
{ on = "N", run = "find_arrow --previous", desc = "Go to previous found file" },
|
||||
|
||||
# Sorting
|
||||
{ on = [ ",", "m" ], run = "sort modified --reverse=no", desc = "Sort by modified time" },
|
||||
@ -120,26 +120,26 @@ keymap = [
|
||||
{ on = [ ",", "S" ], run = "sort size --reverse", desc = "Sort by size (reverse)" },
|
||||
|
||||
# Tabs
|
||||
{ on = [ "t" ], run = "tab_create --current", desc = "Create a new tab using the current path" },
|
||||
{ on = "t", run = "tab_create --current", desc = "Create a new tab using the current path" },
|
||||
|
||||
{ on = [ "1" ], run = "tab_switch 0", desc = "Switch to the first tab" },
|
||||
{ on = [ "2" ], run = "tab_switch 1", desc = "Switch to the second tab" },
|
||||
{ on = [ "3" ], run = "tab_switch 2", desc = "Switch to the third tab" },
|
||||
{ on = [ "4" ], run = "tab_switch 3", desc = "Switch to the fourth tab" },
|
||||
{ on = [ "5" ], run = "tab_switch 4", desc = "Switch to the fifth tab" },
|
||||
{ on = [ "6" ], run = "tab_switch 5", desc = "Switch to the sixth tab" },
|
||||
{ on = [ "7" ], run = "tab_switch 6", desc = "Switch to the seventh tab" },
|
||||
{ on = [ "8" ], run = "tab_switch 7", desc = "Switch to the eighth tab" },
|
||||
{ on = [ "9" ], run = "tab_switch 8", desc = "Switch to the ninth tab" },
|
||||
{ on = "1", run = "tab_switch 0", desc = "Switch to the first tab" },
|
||||
{ on = "2", run = "tab_switch 1", desc = "Switch to the second tab" },
|
||||
{ on = "3", run = "tab_switch 2", desc = "Switch to the third tab" },
|
||||
{ on = "4", run = "tab_switch 3", desc = "Switch to the fourth tab" },
|
||||
{ on = "5", run = "tab_switch 4", desc = "Switch to the fifth tab" },
|
||||
{ on = "6", run = "tab_switch 5", desc = "Switch to the sixth tab" },
|
||||
{ on = "7", run = "tab_switch 6", desc = "Switch to the seventh tab" },
|
||||
{ on = "8", run = "tab_switch 7", desc = "Switch to the eighth tab" },
|
||||
{ on = "9", run = "tab_switch 8", desc = "Switch to the ninth tab" },
|
||||
|
||||
{ on = [ "[" ], run = "tab_switch -1 --relative", desc = "Switch to the previous tab" },
|
||||
{ on = [ "]" ], run = "tab_switch 1 --relative", desc = "Switch to the next tab" },
|
||||
{ on = "[", run = "tab_switch -1 --relative", desc = "Switch to the previous tab" },
|
||||
{ on = "]", run = "tab_switch 1 --relative", desc = "Switch to the next tab" },
|
||||
|
||||
{ on = [ "{" ], run = "tab_swap -1", desc = "Swap the current tab with the previous tab" },
|
||||
{ on = [ "}" ], run = "tab_swap 1", desc = "Swap the current tab with the next tab" },
|
||||
{ on = "{", run = "tab_swap -1", desc = "Swap the current tab with the previous tab" },
|
||||
{ on = "}", run = "tab_swap 1", desc = "Swap the current tab with the next tab" },
|
||||
|
||||
# Tasks
|
||||
{ on = [ "w" ], run = "tasks_show", desc = "Show the tasks manager" },
|
||||
{ on = "w", run = "tasks_show", desc = "Show the tasks manager" },
|
||||
|
||||
# Goto
|
||||
{ on = [ "g", "h" ], run = "cd ~", desc = "Go to the home directory" },
|
||||
@ -148,161 +148,161 @@ keymap = [
|
||||
{ on = [ "g", "<Space>" ], run = "cd --interactive", desc = "Go to a directory interactively" },
|
||||
|
||||
# Help
|
||||
{ on = [ "~" ], run = "help", desc = "Open help" },
|
||||
{ on = "~", run = "help", desc = "Open help" },
|
||||
]
|
||||
|
||||
[tasks]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<Esc>" ], run = "close", desc = "Hide the task manager" },
|
||||
{ on = [ "<C-[>" ], run = "close", desc = "Hide the task manager" },
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Hide the task manager" },
|
||||
{ on = [ "w" ], run = "close", desc = "Hide the task manager" },
|
||||
{ on = "<Esc>", run = "close", desc = "Hide the task manager" },
|
||||
{ on = "<C-[>", run = "close", desc = "Hide the task manager" },
|
||||
{ on = "<C-c>", run = "close", desc = "Hide the task manager" },
|
||||
{ on = "w", run = "close", desc = "Hide the task manager" },
|
||||
|
||||
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "k", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "j", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<Enter>" ], run = "inspect", desc = "Inspect the task" },
|
||||
{ on = [ "x" ], run = "cancel", desc = "Cancel the task" },
|
||||
{ on = "<Enter>", run = "inspect", desc = "Inspect the task" },
|
||||
{ on = "x", run = "cancel", desc = "Cancel the task" },
|
||||
|
||||
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||
{ on = "~", run = "help", desc = "Open help" }
|
||||
]
|
||||
|
||||
[select]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<Esc>" ], run = "close", desc = "Cancel selection" },
|
||||
{ on = [ "<C-[>" ], run = "close", desc = "Cancel selection" },
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Cancel selection" },
|
||||
{ on = [ "<Enter>" ], run = "close --submit", desc = "Submit the selection" },
|
||||
{ on = "<Esc>", run = "close", desc = "Cancel selection" },
|
||||
{ on = "<C-[>", run = "close", desc = "Cancel selection" },
|
||||
{ on = "<C-c>", run = "close", desc = "Cancel selection" },
|
||||
{ on = "<Enter>", run = "close --submit", desc = "Submit the selection" },
|
||||
|
||||
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "k", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "j", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "<S-Up>", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "<S-Down>", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||
{ on = "~", run = "help", desc = "Open help" }
|
||||
]
|
||||
|
||||
[input]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Cancel input" },
|
||||
{ on = [ "<Enter>" ], run = "close --submit", desc = "Submit the input" },
|
||||
{ on = [ "<Esc>" ], run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||
{ on = [ "<C-[>" ], run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||
{ on = "<C-c>", run = "close", desc = "Cancel input" },
|
||||
{ on = "<Enter>", run = "close --submit", desc = "Submit the input" },
|
||||
{ on = "<Esc>", run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||
{ on = "<C-[>", run = "escape", desc = "Go back the normal mode, or cancel input" },
|
||||
|
||||
# Mode
|
||||
{ on = [ "i" ], run = "insert", desc = "Enter insert mode" },
|
||||
{ on = [ "a" ], run = "insert --append", desc = "Enter append mode" },
|
||||
{ on = [ "I" ], run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" },
|
||||
{ on = [ "A" ], run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
|
||||
{ on = [ "v" ], run = "visual", desc = "Enter visual mode" },
|
||||
{ on = [ "V" ], run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" },
|
||||
{ on = "i", run = "insert", desc = "Enter insert mode" },
|
||||
{ on = "a", run = "insert --append", desc = "Enter append mode" },
|
||||
{ on = "I", run = [ "move -999", "insert" ], desc = "Move to the BOL, and enter insert mode" },
|
||||
{ on = "A", run = [ "move 999", "insert --append" ], desc = "Move to the EOL, and enter append mode" },
|
||||
{ on = "v", run = "visual", desc = "Enter visual mode" },
|
||||
{ on = "V", run = [ "move -999", "visual", "move 999" ], desc = "Enter visual mode and select all" },
|
||||
|
||||
# Character-wise movement
|
||||
{ on = [ "h" ], run = "move -1", desc = "Move back a character" },
|
||||
{ on = [ "l" ], run = "move 1", desc = "Move forward a character" },
|
||||
{ on = [ "<Left>" ], run = "move -1", desc = "Move back a character" },
|
||||
{ on = [ "<Right>" ], run = "move 1", desc = "Move forward a character" },
|
||||
{ on = [ "<C-b>" ], run = "move -1", desc = "Move back a character" },
|
||||
{ on = [ "<C-f>" ], run = "move 1", desc = "Move forward a character" },
|
||||
{ on = "h", run = "move -1", desc = "Move back a character" },
|
||||
{ on = "l", run = "move 1", desc = "Move forward a character" },
|
||||
{ on = "<Left>", run = "move -1", desc = "Move back a character" },
|
||||
{ on = "<Right>", run = "move 1", desc = "Move forward a character" },
|
||||
{ on = "<C-b>", run = "move -1", desc = "Move back a character" },
|
||||
{ on = "<C-f>", run = "move 1", desc = "Move forward a character" },
|
||||
|
||||
# Word-wise movement
|
||||
{ on = [ "b" ], run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = [ "w" ], run = "forward", desc = "Move forward to the start of the next word" },
|
||||
{ on = [ "e" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = [ "<A-b>" ], run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = [ "<A-f>" ], run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "b", run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "w", run = "forward", desc = "Move forward to the start of the next word" },
|
||||
{ on = "e", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
{ on = "<A-b>", run = "backward", desc = "Move back to the start of the current or previous word" },
|
||||
{ on = "<A-f>", run = "forward --end-of-word", desc = "Move forward to the end of the current or next word" },
|
||||
|
||||
# Line-wise movement
|
||||
{ on = [ "0" ], run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = [ "$" ], run = "move 999", desc = "Move to the EOL" },
|
||||
{ on = [ "<C-a>" ], run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = [ "<C-e>" ], run = "move 999", desc = "Move to the EOL" },
|
||||
{ on = [ "<Home>" ], run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = [ "<End>" ], run = "move 999", desc = "Move to the EOL" },
|
||||
{ on = "0", run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = "$", run = "move 999", desc = "Move to the EOL" },
|
||||
{ on = "<C-a>", run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = "<C-e>", run = "move 999", desc = "Move to the EOL" },
|
||||
{ on = "<Home>", run = "move -999", desc = "Move to the BOL" },
|
||||
{ on = "<End>", run = "move 999", desc = "Move to the EOL" },
|
||||
|
||||
# Delete
|
||||
{ on = [ "<Backspace>" ], run = "backspace", desc = "Delete the character before the cursor" },
|
||||
{ on = [ "<Delete>" ], run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||
{ on = [ "<C-h>" ], run = "backspace", desc = "Delete the character before the cursor" },
|
||||
{ on = [ "<C-d>" ], run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||
{ on = "<Backspace>", run = "backspace", desc = "Delete the character before the cursor" },
|
||||
{ on = "<Delete>", run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||
{ on = "<C-h>", run = "backspace", desc = "Delete the character before the cursor" },
|
||||
{ on = "<C-d>", run = "backspace --under", desc = "Delete the character under the cursor" },
|
||||
|
||||
# Kill
|
||||
{ on = [ "<C-u>" ], run = "kill bol", desc = "Kill backwards to the BOL" },
|
||||
{ on = [ "<C-k>" ], run = "kill eol", desc = "Kill forwards to the EOL" },
|
||||
{ on = [ "<C-w>" ], run = "kill backward", desc = "Kill backwards to the start of the current word" },
|
||||
{ on = [ "<A-d>" ], run = "kill forward", desc = "Kill forwards to the end of the current word" },
|
||||
{ on = "<C-u>", run = "kill bol", desc = "Kill backwards to the BOL" },
|
||||
{ on = "<C-k>", run = "kill eol", desc = "Kill forwards to the EOL" },
|
||||
{ on = "<C-w>", run = "kill backward", desc = "Kill backwards to the start of the current word" },
|
||||
{ on = "<A-d>", run = "kill forward", desc = "Kill forwards to the end of the current word" },
|
||||
|
||||
# Cut/Yank/Paste
|
||||
{ on = [ "d" ], run = "delete --cut", desc = "Cut the selected characters" },
|
||||
{ on = [ "D" ], run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" },
|
||||
{ on = [ "c" ], run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
|
||||
{ on = [ "C" ], run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" },
|
||||
{ on = [ "x" ], run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
|
||||
{ on = [ "y" ], run = "yank", desc = "Copy the selected characters" },
|
||||
{ on = [ "p" ], run = "paste", desc = "Paste the copied characters after the cursor" },
|
||||
{ on = [ "P" ], run = "paste --before", desc = "Paste the copied characters before the cursor" },
|
||||
{ on = "d", run = "delete --cut", desc = "Cut the selected characters" },
|
||||
{ on = "D", run = [ "delete --cut", "move 999" ], desc = "Cut until the EOL" },
|
||||
{ on = "c", run = "delete --cut --insert", desc = "Cut the selected characters, and enter insert mode" },
|
||||
{ on = "C", run = [ "delete --cut --insert", "move 999" ], desc = "Cut until the EOL, and enter insert mode" },
|
||||
{ on = "x", run = [ "delete --cut", "move 1 --in-operating" ], desc = "Cut the current character" },
|
||||
{ on = "y", run = "yank", desc = "Copy the selected characters" },
|
||||
{ on = "p", run = "paste", desc = "Paste the copied characters after the cursor" },
|
||||
{ on = "P", run = "paste --before", desc = "Paste the copied characters before the cursor" },
|
||||
|
||||
# Undo/Redo
|
||||
{ on = [ "u" ], run = "undo", desc = "Undo the last operation" },
|
||||
{ on = [ "<C-r>" ], run = "redo", desc = "Redo the last operation" },
|
||||
{ on = "u", run = "undo", desc = "Undo the last operation" },
|
||||
{ on = "<C-r>", run = "redo", desc = "Redo the last operation" },
|
||||
|
||||
# Help
|
||||
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||
{ on = "~", run = "help", desc = "Open help" }
|
||||
]
|
||||
|
||||
[completion]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Cancel completion" },
|
||||
{ on = [ "<Tab>" ], run = "close --submit", desc = "Submit the completion" },
|
||||
{ on = [ "<Enter>" ], run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" },
|
||||
{ on = "<C-c>", run = "close", desc = "Cancel completion" },
|
||||
{ on = "<Tab>", run = "close --submit", desc = "Submit the completion" },
|
||||
{ on = "<Enter>", run = [ "close --submit", "close_input --submit" ], desc = "Submit the completion and input" },
|
||||
|
||||
{ on = [ "<A-k>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<A-j>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<A-k>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<A-j>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<C-p>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<C-n>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<C-p>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<C-n>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "~" ], run = "help", desc = "Open help" }
|
||||
{ on = "~", run = "help", desc = "Open help" }
|
||||
]
|
||||
|
||||
[help]
|
||||
|
||||
keymap = [
|
||||
{ on = [ "<Esc>" ], run = "escape", desc = "Clear the filter, or hide the help" },
|
||||
{ on = [ "<C-[>" ], run = "escape", desc = "Clear the filter, or hide the help" },
|
||||
{ on = [ "q" ], run = "close", desc = "Exit the process" },
|
||||
{ on = [ "<C-c>" ], run = "close", desc = "Hide the help" },
|
||||
{ on = "<Esc>", run = "escape", desc = "Clear the filter, or hide the help" },
|
||||
{ on = "<C-[>", run = "escape", desc = "Clear the filter, or hide the help" },
|
||||
{ on = "q", run = "close", desc = "Exit the process" },
|
||||
{ on = "<C-c>", run = "close", desc = "Hide the help" },
|
||||
|
||||
# Navigation
|
||||
{ on = [ "k" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "j" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "k", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "j", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "K" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "J" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "K", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "J", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
{ on = [ "<Up>" ], run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = [ "<Down>" ], run = "arrow 1", desc = "Move cursor down" },
|
||||
{ on = "<Up>", run = "arrow -1", desc = "Move cursor up" },
|
||||
{ on = "<Down>", run = "arrow 1", desc = "Move cursor down" },
|
||||
|
||||
{ on = [ "<S-Up>" ], run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = [ "<S-Down>" ], run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
{ on = "<S-Up>", run = "arrow -5", desc = "Move cursor up 5 lines" },
|
||||
{ on = "<S-Down>", run = "arrow 5", desc = "Move cursor down 5 lines" },
|
||||
|
||||
# Filtering
|
||||
{ on = [ "/" ], run = "filter", desc = "Apply a filter for the help items" },
|
||||
{ on = "/", run = "filter", desc = "Apply a filter for the help items" },
|
||||
]
|
||||
|
@ -764,18 +764,18 @@ exts = [
|
||||
]
|
||||
conds = [
|
||||
# Special files
|
||||
{ cond = "orphan", text = "" },
|
||||
{ cond = "link" , text = "" },
|
||||
{ cond = "block" , text = "" },
|
||||
{ cond = "char" , text = "" },
|
||||
{ cond = "fifo" , text = "" },
|
||||
{ cond = "sock" , text = "" },
|
||||
{ cond = "sticky", text = "" },
|
||||
{ if = "orphan", text = "" },
|
||||
{ if = "link" , text = "" },
|
||||
{ if = "block" , text = "" },
|
||||
{ if = "char" , text = "" },
|
||||
{ if = "fifo" , text = "" },
|
||||
{ if = "sock" , text = "" },
|
||||
{ if = "sticky", text = "" },
|
||||
|
||||
# Fallback
|
||||
{ cond = "dir", text = "" },
|
||||
{ cond = "exec", text = "" },
|
||||
{ cond = "!dir", text = "" },
|
||||
{ if = "dir", text = "" },
|
||||
{ if = "exec", text = "" },
|
||||
{ if = "!dir", text = "" },
|
||||
]
|
||||
|
||||
# : }}}
|
||||
|
@ -83,7 +83,7 @@ suppress_preload = false
|
||||
|
||||
fetchers = [
|
||||
# Mimetype
|
||||
{ id = "mime", name = "*", cond = "!mime", run = "mime", prio = "high" },
|
||||
{ id = "mime", name = "*", run = "mime", if = "!mime", prio = "high" },
|
||||
]
|
||||
preloaders = [
|
||||
# Image
|
||||
@ -113,7 +113,7 @@ previewers = [
|
||||
{ mime = "application/pdf", run = "pdf" },
|
||||
# Archive
|
||||
{ mime = "application/{,g}zip", run = "archive" },
|
||||
{ mime = "application/x-{tar,bzip*,7z-compressed,xz,rar}", run = "archive" },
|
||||
{ mime = "application/x-{tar,bzip*,7z-compressed,xz,rar,iso9660-image}", run = "archive" },
|
||||
# Font
|
||||
{ mime = "font/*", run = "font" },
|
||||
{ mime = "application/vnd.ms-opentype", run = "font" },
|
||||
|
@ -7,8 +7,9 @@ use super::Key;
|
||||
|
||||
#[derive(Debug, Default, Deserialize)]
|
||||
pub struct Control {
|
||||
#[serde(deserialize_with = "super::deserialize_on")]
|
||||
pub on: Vec<Key>,
|
||||
#[serde(deserialize_with = "super::run_deserialize")]
|
||||
#[serde(deserialize_with = "super::deserialize_run")]
|
||||
pub run: Vec<Cmd>,
|
||||
pub desc: Option<String>,
|
||||
}
|
||||
@ -24,7 +25,7 @@ impl Control {
|
||||
|
||||
#[inline]
|
||||
pub fn run(&self) -> String {
|
||||
self.run.iter().map(|e| e.to_string()).collect::<Vec<_>>().join("; ")
|
||||
self.run.iter().map(|c| c.to_string()).collect::<Vec<_>>().join("; ")
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
83
yazi-config/src/keymap/deserializers.rs
Normal file
83
yazi-config/src/keymap/deserializers.rs
Normal file
@ -0,0 +1,83 @@
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
use anyhow::Result;
|
||||
use serde::{de::{self, Visitor}, Deserializer};
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
use crate::keymap::Key;
|
||||
|
||||
pub(super) fn deserialize_on<'de, D>(deserializer: D) -> Result<Vec<Key>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct OnVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for OnVisitor {
|
||||
type Value = Vec<Key>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a `on` string or array of strings within keymap.toml")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
let mut cmds = vec![];
|
||||
while let Some(value) = &seq.next_element::<String>()? {
|
||||
cmds.push(Key::from_str(value).map_err(de::Error::custom)?);
|
||||
}
|
||||
if cmds.is_empty() {
|
||||
return Err(de::Error::custom("`on` within keymap.toml cannot be empty"));
|
||||
}
|
||||
Ok(cmds)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![Key::from_str(value).map_err(de::Error::custom)?])
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(OnVisitor)
|
||||
}
|
||||
|
||||
pub(super) fn deserialize_run<'de, D>(deserializer: D) -> Result<Vec<Cmd>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct RunVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for RunVisitor {
|
||||
type Value = Vec<Cmd>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a `run` string or array of strings within keymap.toml")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
let mut cmds = vec![];
|
||||
while let Some(value) = &seq.next_element::<String>()? {
|
||||
cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?);
|
||||
}
|
||||
if cmds.is_empty() {
|
||||
return Err(de::Error::custom("`run` within keymap.toml cannot be empty"));
|
||||
}
|
||||
Ok(cmds)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![Cmd::from_str(value).map_err(de::Error::custom)?])
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(RunVisitor)
|
||||
}
|
@ -2,10 +2,8 @@ use std::{fmt::{Display, Write}, str::FromStr};
|
||||
|
||||
use anyhow::bail;
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, PartialEq, Eq, Hash)]
|
||||
#[serde(try_from = "String")]
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
|
||||
pub struct Key {
|
||||
pub code: KeyCode,
|
||||
pub shift: bool,
|
||||
@ -126,12 +124,6 @@ impl FromStr for Key {
|
||||
}
|
||||
}
|
||||
|
||||
impl TryFrom<String> for Key {
|
||||
type Error = anyhow::Error;
|
||||
|
||||
fn try_from(s: String) -> Result<Self, Self::Error> { Self::from_str(&s) }
|
||||
}
|
||||
|
||||
impl Display for Key {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
if let Some(c) = self.plain() {
|
||||
|
@ -1,12 +1,11 @@
|
||||
mod control;
|
||||
mod cow;
|
||||
mod deserializers;
|
||||
mod key;
|
||||
mod keymap;
|
||||
mod run;
|
||||
|
||||
pub use control::*;
|
||||
pub use cow::*;
|
||||
use deserializers::*;
|
||||
pub use key::*;
|
||||
pub use keymap::*;
|
||||
#[allow(unused_imports)]
|
||||
pub use run::*;
|
||||
|
@ -1,43 +0,0 @@
|
||||
use std::{fmt, str::FromStr};
|
||||
|
||||
use anyhow::Result;
|
||||
use serde::{de::{self, Visitor}, Deserializer};
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
pub(super) fn run_deserialize<'de, D>(deserializer: D) -> Result<Vec<Cmd>, D::Error>
|
||||
where
|
||||
D: Deserializer<'de>,
|
||||
{
|
||||
struct RunVisitor;
|
||||
|
||||
impl<'de> Visitor<'de> for RunVisitor {
|
||||
type Value = Vec<Cmd>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
|
||||
formatter.write_str("a `run` string or array of strings within keymap.toml")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: de::SeqAccess<'de>,
|
||||
{
|
||||
let mut cmds = vec![];
|
||||
while let Some(value) = &seq.next_element::<String>()? {
|
||||
cmds.push(Cmd::from_str(value).map_err(de::Error::custom)?);
|
||||
}
|
||||
if cmds.is_empty() {
|
||||
return Err(de::Error::custom("`run` within keymap.toml cannot be empty"));
|
||||
}
|
||||
Ok(cmds)
|
||||
}
|
||||
|
||||
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
|
||||
where
|
||||
E: de::Error,
|
||||
{
|
||||
Ok(vec![Cmd::from_str(value).map_err(de::Error::custom)?])
|
||||
}
|
||||
}
|
||||
|
||||
deserializer.deserialize_any(RunVisitor)
|
||||
}
|
@ -58,5 +58,19 @@ pub fn init() -> anyhow::Result<()> {
|
||||
SELECT.init(<_>::from_str(yazi_toml)?);
|
||||
WHICH.init(<_>::from_str(yazi_toml)?);
|
||||
|
||||
// TODO: Remove in v0.3.2
|
||||
for c in &KEYMAP.manager {
|
||||
for r in &c.run {
|
||||
if r.name == "shell" && !r.bool("confirm") && !r.bool("interactive") {
|
||||
eprintln!(
|
||||
r#"WARNING: In Yazi v0.3, the behavior of the interactive `shell` (i.e., shell templates) must be explicitly specified with `--interactive`.
|
||||
|
||||
Please replace e.g. `shell` with `shell --interactive`, `shell "my-template"` with `shell "my-template" --interactive`, in your keymap.toml"#
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -9,7 +9,8 @@ pub struct Fetcher {
|
||||
pub idx: u8,
|
||||
|
||||
pub id: String,
|
||||
pub cond: Option<Condition>,
|
||||
#[serde(rename = "if")]
|
||||
pub if_: Option<Condition>,
|
||||
pub name: Option<Pattern>,
|
||||
pub mime: Option<Pattern>,
|
||||
pub run: Cmd,
|
||||
|
@ -25,7 +25,7 @@ impl Plugin {
|
||||
.fetchers
|
||||
.iter()
|
||||
.filter(|&p| {
|
||||
p.cond.as_ref().and_then(|c| c.eval(f)) != Some(false)
|
||||
p.if_.as_ref().and_then(|c| c.eval(f)) != Some(false)
|
||||
&& (p.mime.as_ref().zip(mime).map_or(false, |(p, m)| p.match_mime(m))
|
||||
|| p.name.as_ref().is_some_and(|p| p.match_path(path, is_dir)))
|
||||
})
|
||||
|
@ -16,11 +16,11 @@ pub struct Icons {
|
||||
|
||||
impl Icons {
|
||||
pub fn matches(&self, file: &File) -> Option<&Icon> {
|
||||
if let Some((_, i)) = self.globs.iter().find(|(p, _)| p.match_path(&file.url, file.is_dir())) {
|
||||
if let Some(i) = self.match_by_glob(file) {
|
||||
return Some(i);
|
||||
}
|
||||
|
||||
if let Some(i) = self.match_name(file) {
|
||||
if let Some(i) = self.match_by_name(file) {
|
||||
return Some(i);
|
||||
}
|
||||
|
||||
@ -41,7 +41,12 @@ impl Icons {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn match_name(&self, file: &File) -> Option<&Icon> {
|
||||
fn match_by_glob(&self, file: &File) -> Option<&Icon> {
|
||||
self.globs.iter().find(|(p, _)| p.match_path(&file.url, file.is_dir())).map(|(_, i)| i)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn match_by_name(&self, file: &File) -> Option<&Icon> {
|
||||
let name = file.name()?.to_str()?;
|
||||
if file.is_dir() {
|
||||
self.dirs.get(name).or_else(|| self.dirs.get(&name.to_ascii_lowercase()))
|
||||
@ -110,7 +115,8 @@ impl<'de> Deserialize<'de> for Icons {
|
||||
}
|
||||
#[derive(Deserialize)]
|
||||
pub struct ShadowCond {
|
||||
cond: Condition,
|
||||
#[serde(rename = "if")]
|
||||
if_: Condition,
|
||||
text: String,
|
||||
fg_dark: Option<Color>,
|
||||
#[allow(dead_code)]
|
||||
@ -136,7 +142,7 @@ impl<'de> Deserialize<'de> for Icons {
|
||||
.conds
|
||||
.into_iter()
|
||||
.map(|v| {
|
||||
(v.cond, Icon { text: v.text, style: Style { fg: v.fg_dark, ..Default::default() } })
|
||||
(v.if_, Icon { text: v.text, style: Style { fg: v.fg_dark, ..Default::default() } })
|
||||
})
|
||||
.collect();
|
||||
|
||||
|
@ -26,7 +26,7 @@ dirs = "5.0.1"
|
||||
futures = "0.3.30"
|
||||
notify = { version = "6.1.1", default-features = false, features = [ "macos_fsevent" ] }
|
||||
parking_lot = "0.12.3"
|
||||
ratatui = "0.26.3"
|
||||
ratatui = "0.27.0"
|
||||
regex = "1.10.5"
|
||||
scopeguard = "1.2.0"
|
||||
serde = "1.0.203"
|
||||
|
@ -19,6 +19,10 @@ impl InputSnaps {
|
||||
}
|
||||
|
||||
pub(super) fn tag(&mut self, limit: usize) -> bool {
|
||||
if self.versions.len() <= self.idx {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Sync *current* cursor position to the *last* version:
|
||||
// Save offset/cursor/ect. of the *current* as the last version,
|
||||
// while keeping the *last* value unchanged.
|
||||
@ -49,7 +53,7 @@ impl InputSnaps {
|
||||
}
|
||||
|
||||
pub(super) fn redo(&mut self) -> bool {
|
||||
if self.idx + 1 == self.versions.len() {
|
||||
if self.idx + 1 >= self.versions.len() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -64,7 +64,7 @@ impl Manager {
|
||||
|
||||
done.extend(files.iter().map(|f| (f.url(), String::new())));
|
||||
if let Err(e) = isolate::fetch("mime", files).await {
|
||||
error!("fetch `mime` failed in opening: {e}");
|
||||
error!("Fetch `mime` failed in opening: {e}");
|
||||
}
|
||||
|
||||
ManagerProxy::open_do(OpenDoOpt { hovered, targets: done, interactive: opt.interactive });
|
||||
|
@ -7,6 +7,7 @@ use crate::{manager::Manager, tasks::Tasks};
|
||||
pub struct Opt {
|
||||
force: bool,
|
||||
permanently: bool,
|
||||
hovered: bool,
|
||||
targets: Vec<Url>,
|
||||
}
|
||||
|
||||
@ -15,6 +16,7 @@ impl From<Cmd> for Opt {
|
||||
Self {
|
||||
force: c.bool("force"),
|
||||
permanently: c.bool("permanently"),
|
||||
hovered: c.bool("hovered"),
|
||||
targets: c.take_any("targets").unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
@ -25,9 +27,16 @@ impl Manager {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
}
|
||||
let Some(hovered) = self.hovered().map(|h| &h.url) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let mut opt = opt.into() as Opt;
|
||||
opt.targets = self.selected_or_hovered(false).cloned().collect();
|
||||
opt.targets = if opt.hovered {
|
||||
vec![hovered.clone()]
|
||||
} else {
|
||||
self.selected_or_hovered(false).cloned().collect()
|
||||
};
|
||||
|
||||
if opt.force {
|
||||
return self.remove_do(opt, tasks);
|
||||
|
@ -10,17 +10,19 @@ use yazi_shared::{event::Cmd, fs::{maybe_exists, ok_or_not_found, paths_to_same_
|
||||
use crate::manager::Manager;
|
||||
|
||||
pub struct Opt {
|
||||
force: bool,
|
||||
empty: String,
|
||||
cursor: String,
|
||||
hovered: bool,
|
||||
force: bool,
|
||||
empty: String,
|
||||
cursor: String,
|
||||
}
|
||||
|
||||
impl From<Cmd> for Opt {
|
||||
fn from(mut c: Cmd) -> Self {
|
||||
Self {
|
||||
force: c.bool("force"),
|
||||
empty: c.take_str("empty").unwrap_or_default(),
|
||||
cursor: c.take_str("cursor").unwrap_or_default(),
|
||||
hovered: c.bool("hovered"),
|
||||
force: c.bool("force"),
|
||||
empty: c.take_str("empty").unwrap_or_default(),
|
||||
cursor: c.take_str("cursor").unwrap_or_default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -29,15 +31,16 @@ impl Manager {
|
||||
pub fn rename(&mut self, opt: impl Into<Opt>) {
|
||||
if !self.active_mut().try_escape_visual() {
|
||||
return;
|
||||
} else if !self.active().selected.is_empty() {
|
||||
return self.bulk_rename();
|
||||
}
|
||||
|
||||
let Some(hovered) = self.hovered().map(|h| h.url()) else {
|
||||
return;
|
||||
};
|
||||
|
||||
let opt = opt.into() as Opt;
|
||||
if !opt.hovered && !self.active().selected.is_empty() {
|
||||
return self.bulk_rename();
|
||||
}
|
||||
|
||||
let name = Self::empty_url_part(&hovered, &opt.empty);
|
||||
let cursor = match opt.cursor.as_str() {
|
||||
"start" => Some(0),
|
||||
|
@ -130,7 +130,7 @@ impl Watcher {
|
||||
continue;
|
||||
}
|
||||
if let Err(e) = isolate::fetch("mime", reload).await {
|
||||
error!("fetch `mime` failed in watcher: {e}");
|
||||
error!("Fetch `mime` failed in watcher: {e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,25 +1,27 @@
|
||||
use std::borrow::Cow;
|
||||
|
||||
use yazi_config::{open::Opener, popup::InputCfg};
|
||||
use yazi_proxy::{InputProxy, TasksProxy};
|
||||
use yazi_proxy::{AppProxy, InputProxy, TasksProxy};
|
||||
use yazi_shared::event::Cmd;
|
||||
|
||||
use crate::tab::Tab;
|
||||
|
||||
pub struct Opt {
|
||||
run: String,
|
||||
block: bool,
|
||||
orphan: bool,
|
||||
confirm: bool,
|
||||
run: String,
|
||||
block: bool,
|
||||
orphan: bool,
|
||||
confirm: bool,
|
||||
interactive: bool,
|
||||
}
|
||||
|
||||
impl From<Cmd> for Opt {
|
||||
fn from(mut c: Cmd) -> Self {
|
||||
Self {
|
||||
run: c.take_first_str().unwrap_or_default(),
|
||||
block: c.bool("block"),
|
||||
orphan: c.bool("orphan"),
|
||||
confirm: c.bool("confirm"),
|
||||
run: c.take_first_str().unwrap_or_default(),
|
||||
block: c.bool("block"),
|
||||
orphan: c.bool("orphan"),
|
||||
confirm: c.bool("confirm"),
|
||||
interactive: c.bool("interactive"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -31,6 +33,24 @@ impl Tab {
|
||||
}
|
||||
|
||||
let mut opt = opt.into() as Opt;
|
||||
|
||||
// TODO: Remove in v0.3.2
|
||||
if !opt.interactive && !opt.confirm {
|
||||
AppProxy::notify_error(
|
||||
"`shell` command",
|
||||
r#"In Yazi v0.3, the behavior of the interactive `shell` (i.e., shell templates) must be explicitly specified with `--interactive`.
|
||||
|
||||
Please replace e.g. `shell` with `shell --interactive`, `shell "my-template"` with `shell "my-template" --interactive`, in your keymap.toml"#,
|
||||
);
|
||||
return;
|
||||
} else if opt.interactive && opt.confirm {
|
||||
AppProxy::notify_error(
|
||||
"`shell` command",
|
||||
"The `shell` command cannot specify both `--confirm` and `--interactive` at the same time.",
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let selected = self.hovered_and_selected(true).cloned().collect();
|
||||
|
||||
tokio::spawn(async move {
|
||||
|
@ -42,6 +42,9 @@ pub fn init() {
|
||||
USERS_CACHE.with(Default::default);
|
||||
|
||||
// Env
|
||||
if let Some(s) = std::env::var("YAZI_ID").ok().filter(|s| !s.is_empty()) {
|
||||
std::env::set_var("YAZI_PID", s);
|
||||
}
|
||||
std::env::set_var("YAZI_ID", ID.to_string());
|
||||
std::env::set_var(
|
||||
"YAZI_LEVEL",
|
||||
|
@ -29,7 +29,7 @@ crossterm = { version = "0.27.0", features = [ "event-stream" ] }
|
||||
fdlimit = "0.3.0"
|
||||
futures = "0.3.30"
|
||||
mlua = { version = "0.9.9", features = [ "lua54" ] }
|
||||
ratatui = "0.26.3"
|
||||
ratatui = "0.27.0"
|
||||
scopeguard = "1.2.0"
|
||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
tokio = { version = "1.38.0", features = [ "full" ] }
|
||||
|
@ -2,7 +2,7 @@ use std::ops::Deref;
|
||||
|
||||
use mlua::{AnyUserData, IntoLua, Lua, UserDataFields, UserDataMethods};
|
||||
use yazi_config::THEME;
|
||||
use yazi_plugin::{bindings::{Cast, Cha, Icon, Range}, elements::Style, url::Url};
|
||||
use yazi_plugin::{bindings::Range, elements::Style};
|
||||
use yazi_shared::MIME_DIR;
|
||||
|
||||
use super::{CtxRef, SCOPE};
|
||||
@ -19,6 +19,10 @@ impl Deref for File {
|
||||
fn deref(&self) -> &Self::Target { &self.folder().files[self.idx] }
|
||||
}
|
||||
|
||||
impl AsRef<yazi_shared::fs::File> for File {
|
||||
fn as_ref(&self) -> &yazi_shared::fs::File { self }
|
||||
}
|
||||
|
||||
impl File {
|
||||
#[inline]
|
||||
pub(super) fn make(
|
||||
@ -31,16 +35,9 @@ impl File {
|
||||
|
||||
pub(super) fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<Self>(|reg| {
|
||||
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
|
||||
reg.add_field_method_get("url", |lua, me| Url::cast(lua, me.url.clone()));
|
||||
reg.add_field_method_get("cha", |lua, me| Cha::cast(lua, me.cha));
|
||||
reg.add_field_method_get("link_to", |lua, me| {
|
||||
me.link_to.as_ref().cloned().map(|u| Url::cast(lua, u)).transpose()
|
||||
});
|
||||
yazi_plugin::file::File::register_with(reg);
|
||||
|
||||
reg.add_field_method_get("name", |lua, me| {
|
||||
me.url.file_name().map(|n| lua.create_string(n.as_encoded_bytes())).transpose()
|
||||
});
|
||||
reg.add_field_method_get("idx", |_, me| Ok(me.idx + 1));
|
||||
reg.add_method("size", |_, me, ()| {
|
||||
Ok(if me.is_dir() { me.folder().files.sizes.get(&me.url).copied() } else { Some(me.len) })
|
||||
});
|
||||
@ -57,19 +54,6 @@ impl File {
|
||||
p.next_back();
|
||||
Some(lua.create_string(p.as_path().as_os_str().as_encoded_bytes())).transpose()
|
||||
});
|
||||
reg.add_method("icon", |lua, me, ()| {
|
||||
use yazi_shared::theme::IconCache;
|
||||
|
||||
match me.icon.get() {
|
||||
IconCache::Missing => {
|
||||
let matched = THEME.icons.matches(me);
|
||||
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
|
||||
matched.map(|i| Icon::cast(lua, i)).transpose()
|
||||
}
|
||||
IconCache::Undefined => Ok(None),
|
||||
IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(),
|
||||
}
|
||||
});
|
||||
reg.add_method("style", |lua, me, ()| {
|
||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
let mime =
|
||||
|
@ -29,9 +29,7 @@ futures = "0.3.30"
|
||||
md-5 = "0.10.6"
|
||||
mlua = { version = "0.9.9", features = [ "lua54", "serialize", "macros", "async" ] }
|
||||
parking_lot = "0.12.3"
|
||||
ratatui = "0.26.3"
|
||||
serde = "1.0.203"
|
||||
serde_json = "1.0.117"
|
||||
ratatui = "0.27.0"
|
||||
shell-escape = "0.1.5"
|
||||
shell-words = "1.1.0"
|
||||
syntect = { version = "5.2.0", default-features = false, features = [ "parsing", "plist-load", "regex-onig" ] }
|
||||
|
@ -44,13 +44,18 @@ function Current:render(area)
|
||||
end
|
||||
|
||||
function Current:click(event, up)
|
||||
if up or not event.is_left then
|
||||
if up or event.is_middle then
|
||||
return
|
||||
end
|
||||
|
||||
local f = Folder:by_kind(Folder.CURRENT)
|
||||
if event.y <= #f.window and f.hovered then
|
||||
ya.manager_emit("arrow", { event.y + f.offset - f.hovered.idx })
|
||||
if event.y > #f.window or not f.hovered then
|
||||
return
|
||||
end
|
||||
|
||||
ya.manager_emit("arrow", { event.y + f.offset - f.hovered.idx })
|
||||
if event.is_right then
|
||||
ya.manager_emit("open", {})
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,9 +1,64 @@
|
||||
local M = {}
|
||||
|
||||
function M:peek()
|
||||
local _, bound = ya.preview_archive(self)
|
||||
if bound then
|
||||
ya.manager_emit("peek", { bound, only_if = self.file.url, upper_bound = true })
|
||||
local child
|
||||
if ya.target_os() == "macos" then
|
||||
child = self:try_spawn("7zz") or self:try_spawn("7z")
|
||||
else
|
||||
child = self:try_spawn("7z") or self:try_spawn("7zz")
|
||||
end
|
||||
|
||||
if not child then
|
||||
return ya.err("spawn `7z` and `7zz` both commands failed, error code: " .. tostring(self.last_error))
|
||||
end
|
||||
|
||||
local limit = self.area.h
|
||||
local i, icon, names, sizes = 0, nil, {}, {}
|
||||
repeat
|
||||
local next, event = child:read_line()
|
||||
if event ~= 0 then
|
||||
break
|
||||
end
|
||||
|
||||
local attr, size, name = next:match("^[-%d]+%s+[:%d]+%s+([.%a]+)%s+(%d+)%s+%d+%s+(.+)[\r\n]+")
|
||||
if not name then
|
||||
goto continue
|
||||
end
|
||||
|
||||
i = i + 1
|
||||
if i <= self.skip then
|
||||
goto continue
|
||||
end
|
||||
|
||||
icon = File({
|
||||
url = Url(name),
|
||||
cha = Cha { kind = attr:sub(1, 1) == "D" and 1 or 0 },
|
||||
}):icon()
|
||||
|
||||
if icon then
|
||||
names[#names + 1] = ui.Line { ui.Span(" " .. icon.text .. " "):style(icon.style), ui.Span(name) }
|
||||
else
|
||||
names[#names + 1] = ui.Line(name)
|
||||
end
|
||||
|
||||
size = tonumber(size)
|
||||
if size > 0 then
|
||||
sizes[#sizes + 1] = ui.Line(string.format(" %s ", ya.readable_size(size)))
|
||||
else
|
||||
sizes[#sizes + 1] = ui.Line("")
|
||||
end
|
||||
|
||||
::continue::
|
||||
until i >= self.skip + limit
|
||||
|
||||
child:start_kill()
|
||||
if self.skip > 0 and i < self.skip + limit then
|
||||
ya.manager_emit("peek", { math.max(0, i - limit), only_if = self.file.url, upper_bound = true })
|
||||
else
|
||||
ya.preview_widgets(self, {
|
||||
ui.Paragraph(self.area, names),
|
||||
ui.Paragraph(self.area, sizes):align(ui.Paragraph.RIGHT),
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
@ -18,4 +73,12 @@ function M:seek(units)
|
||||
end
|
||||
end
|
||||
|
||||
function M:try_spawn(name)
|
||||
local child, code = Command(name):args({ "l", "-ba", tostring(self.file.url) }):stdout(Command.PIPED):spawn()
|
||||
if not child then
|
||||
self.last_error = code
|
||||
end
|
||||
return child
|
||||
end
|
||||
|
||||
return M
|
||||
|
@ -23,11 +23,11 @@ function M:preload()
|
||||
local child, code = Command("magick"):args({
|
||||
"-density",
|
||||
"200",
|
||||
tostring(self.file.url),
|
||||
"-resize",
|
||||
string.format("%dx%d^", PREVIEW.max_width, PREVIEW.max_height),
|
||||
"-quality",
|
||||
tostring(PREVIEW.image_quality),
|
||||
tostring(self.file.url),
|
||||
"JPG:" .. tostring(cache),
|
||||
}):spawn()
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
os.setlocale("")
|
||||
package.path = BOOT.plugin_dir .. "/?.yazi/init.lua;" .. package.path
|
||||
|
||||
require("dds"):setup()
|
||||
|
@ -1,29 +0,0 @@
|
||||
use mlua::{AnyUserData, Lua, UserDataFields, UserDataRef};
|
||||
|
||||
use super::{Cast, Cha};
|
||||
use crate::url::Url;
|
||||
|
||||
pub type FileRef<'lua> = UserDataRef<'lua, yazi_shared::fs::File>;
|
||||
|
||||
pub struct File;
|
||||
|
||||
impl File {
|
||||
pub fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<yazi_shared::fs::File>(|reg| {
|
||||
reg.add_field_method_get("url", |lua, me| Url::cast(lua, me.url.clone()));
|
||||
reg.add_field_method_get("cha", |lua, me| Cha::cast(lua, me.cha));
|
||||
reg.add_field_method_get("link_to", |lua, me| {
|
||||
me.link_to.as_ref().cloned().map(|u| Url::cast(lua, u)).transpose()
|
||||
});
|
||||
|
||||
// Extension
|
||||
reg.add_field_method_get("name", |lua, me| {
|
||||
me.url.file_name().map(|n| lua.create_string(n.as_encoded_bytes())).transpose()
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<yazi_shared::fs::File>> Cast<T> for File {
|
||||
fn cast(lua: &Lua, data: T) -> mlua::Result<AnyUserData> { lua.create_any_userdata(data.into()) }
|
||||
}
|
@ -1,8 +1,6 @@
|
||||
#![allow(clippy::module_inception)]
|
||||
|
||||
mod bindings;
|
||||
mod cha;
|
||||
mod file;
|
||||
mod icon;
|
||||
mod input;
|
||||
mod mouse;
|
||||
@ -12,8 +10,6 @@ mod range;
|
||||
mod window;
|
||||
|
||||
pub use bindings::*;
|
||||
pub use cha::*;
|
||||
pub use file::*;
|
||||
pub use icon::*;
|
||||
pub use input::*;
|
||||
pub use mouse::*;
|
||||
|
@ -1,8 +1,11 @@
|
||||
use std::time::UNIX_EPOCH;
|
||||
use std::time::{Duration, SystemTime, UNIX_EPOCH};
|
||||
|
||||
use mlua::{AnyUserData, Lua, UserDataFields, UserDataMethods};
|
||||
use mlua::{AnyUserData, ExternalError, Lua, Table, UserDataFields, UserDataMethods, UserDataRef};
|
||||
use yazi_shared::fs::ChaKind;
|
||||
|
||||
use super::Cast;
|
||||
use crate::bindings::Cast;
|
||||
|
||||
pub type UrlRef<'lua> = UserDataRef<'lua, yazi_shared::fs::Cha>;
|
||||
|
||||
pub struct Cha;
|
||||
|
||||
@ -48,6 +51,39 @@ impl Cha {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
#[inline]
|
||||
fn parse_time(f: Option<f64>) -> mlua::Result<Option<SystemTime>> {
|
||||
Ok(match f {
|
||||
Some(n) if n >= 0.0 => Some(SystemTime::UNIX_EPOCH + Duration::from_secs_f64(n)),
|
||||
Some(n) => Err(format!("Invalid timestamp: {n}").into_lua_err())?,
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
lua.globals().raw_set(
|
||||
"Cha",
|
||||
lua.create_function(|lua, t: Table| {
|
||||
let kind =
|
||||
ChaKind::from_bits(t.raw_get("kind")?).ok_or_else(|| "Invalid kind".into_lua_err())?;
|
||||
|
||||
Self::cast(lua, yazi_shared::fs::Cha {
|
||||
kind,
|
||||
len: t.raw_get("len").unwrap_or_default(),
|
||||
accessed: parse_time(t.raw_get("atime").ok())?,
|
||||
created: parse_time(t.raw_get("ctime").ok())?,
|
||||
modified: parse_time(t.raw_get("mtime").ok())?,
|
||||
#[cfg(unix)]
|
||||
permissions: t.raw_get("permissions").unwrap_or_default(),
|
||||
#[cfg(unix)]
|
||||
uid: t.raw_get("uid").unwrap_or_default(),
|
||||
#[cfg(unix)]
|
||||
gid: t.raw_get("gid").unwrap_or_default(),
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<yazi_shared::fs::Cha>> Cast<T> for Cha {
|
12
yazi-plugin/src/cha/mod.rs
Normal file
12
yazi-plugin/src/cha/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![allow(clippy::module_inception)]
|
||||
|
||||
mod cha;
|
||||
|
||||
pub use cha::*;
|
||||
|
||||
pub fn pour(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
cha::Cha::register(lua)?;
|
||||
cha::Cha::install(lua)?;
|
||||
|
||||
Ok(())
|
||||
}
|
79
yazi-plugin/src/external/lsar.rs
vendored
79
yazi-plugin/src/external/lsar.rs
vendored
@ -1,79 +0,0 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::anyhow;
|
||||
use serde::Deserialize;
|
||||
use serde_json::Value;
|
||||
use tokio::process::Command;
|
||||
use yazi_shared::PeekError;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LsarAttr {
|
||||
Posix(u16),
|
||||
Windows(u16),
|
||||
Dos(u8),
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LsarFile {
|
||||
#[serde(rename = "XADFileName")]
|
||||
pub name: String,
|
||||
#[serde(rename = "XADLastModificationDate")]
|
||||
pub last_modified: String,
|
||||
#[serde(rename = "XADFileSize")]
|
||||
pub size: Option<usize>,
|
||||
#[serde(rename = "XADCompressedSize")]
|
||||
pub compressed_size: Option<usize>,
|
||||
#[serde(rename = "XADCompressionName")]
|
||||
pub compression_name: Option<String>,
|
||||
|
||||
#[serde(skip)]
|
||||
pub attributes: Option<LsarAttr>,
|
||||
}
|
||||
|
||||
#[allow(clippy::manual_map)]
|
||||
pub async fn lsar(path: &Path, skip: usize, limit: usize) -> Result<Vec<LsarFile>, PeekError> {
|
||||
let output = Command::new("lsar").arg("-j").arg(path).kill_on_drop(true).output().await?;
|
||||
if !output.status.success() {
|
||||
return Err(String::from_utf8_lossy(&output.stderr).to_string().into());
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Outer {
|
||||
#[serde(rename = "lsarContents")]
|
||||
contents: Vec<Value>,
|
||||
}
|
||||
|
||||
let output = String::from_utf8_lossy(&output.stdout);
|
||||
let contents = serde_json::from_str::<Outer>(output.trim()).map_err(|e| anyhow!(e))?.contents;
|
||||
|
||||
let mut i = 0;
|
||||
let mut files = Vec::with_capacity(limit);
|
||||
for content in contents {
|
||||
i += 1;
|
||||
if i > skip + limit {
|
||||
break;
|
||||
} else if i <= skip {
|
||||
continue;
|
||||
}
|
||||
|
||||
let attributes = if let Some(p) = content.get("XADPosixPermissions").and_then(|p| p.as_u64()) {
|
||||
Some(LsarAttr::Posix(p as u16))
|
||||
} else if let Some(a) = content.get("XADWindowsFileAttributes").and_then(|a| a.as_u64()) {
|
||||
Some(LsarAttr::Windows(a as u16))
|
||||
} else if let Some(a) = content.get("XADDOSFileAttributes").and_then(|a| a.as_u64()) {
|
||||
Some(LsarAttr::Dos(a as u8))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let mut file = serde_json::from_value::<LsarFile>(content).map_err(|e| anyhow!(e))?;
|
||||
file.attributes = attributes;
|
||||
files.push(file);
|
||||
}
|
||||
|
||||
if skip > 0 && files.len() < limit {
|
||||
Err(PeekError::Exceed(i.saturating_sub(limit)))
|
||||
} else {
|
||||
Ok(files)
|
||||
}
|
||||
}
|
2
yazi-plugin/src/external/mod.rs
vendored
2
yazi-plugin/src/external/mod.rs
vendored
@ -1,9 +1,7 @@
|
||||
mod fd;
|
||||
mod highlighter;
|
||||
mod lsar;
|
||||
mod rg;
|
||||
|
||||
pub use fd::*;
|
||||
pub use highlighter::*;
|
||||
pub use lsar::*;
|
||||
pub use rg::*;
|
||||
|
63
yazi-plugin/src/file/file.rs
Normal file
63
yazi-plugin/src/file/file.rs
Normal file
@ -0,0 +1,63 @@
|
||||
use mlua::{AnyUserData, Lua, Table, UserDataFields, UserDataMethods, UserDataRef, UserDataRegistry};
|
||||
use yazi_config::THEME;
|
||||
|
||||
use crate::{bindings::{Cast, Icon}, cha::Cha, url::Url};
|
||||
|
||||
pub type FileRef<'lua> = UserDataRef<'lua, yazi_shared::fs::File>;
|
||||
|
||||
pub struct File;
|
||||
|
||||
impl File {
|
||||
#[inline]
|
||||
pub fn register(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.register_userdata_type::<yazi_shared::fs::File>(Self::register_with)
|
||||
}
|
||||
|
||||
pub fn register_with<T>(reg: &mut UserDataRegistry<T>)
|
||||
where
|
||||
T: AsRef<yazi_shared::fs::File>,
|
||||
{
|
||||
reg.add_field_method_get("url", |lua, me| Url::cast(lua, me.as_ref().url.clone()));
|
||||
reg.add_field_method_get("cha", |lua, me| Cha::cast(lua, me.as_ref().cha));
|
||||
reg.add_field_method_get("link_to", |lua, me| {
|
||||
me.as_ref().link_to.clone().map(|u| Url::cast(lua, u)).transpose()
|
||||
});
|
||||
|
||||
// Extension
|
||||
reg.add_field_method_get("name", |lua, me| {
|
||||
me.as_ref().url.file_name().map(|n| lua.create_string(n.as_encoded_bytes())).transpose()
|
||||
});
|
||||
|
||||
reg.add_method("icon", |lua, me, ()| {
|
||||
use yazi_shared::theme::IconCache;
|
||||
|
||||
let me = me.as_ref();
|
||||
match me.icon.get() {
|
||||
IconCache::Missing => {
|
||||
let matched = THEME.icons.matches(me);
|
||||
me.icon.set(matched.map_or(IconCache::Undefined, IconCache::Icon));
|
||||
matched.map(|i| Icon::cast(lua, i)).transpose()
|
||||
}
|
||||
IconCache::Undefined => Ok(None),
|
||||
IconCache::Icon(cached) => Some(Icon::cast(lua, cached)).transpose(),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.globals().raw_set(
|
||||
"File",
|
||||
lua.create_function(|lua, t: Table| {
|
||||
Self::cast(lua, yazi_shared::fs::File {
|
||||
url: t.raw_get::<_, AnyUserData>("url")?.take()?,
|
||||
cha: t.raw_get::<_, AnyUserData>("cha")?.take()?,
|
||||
..Default::default()
|
||||
})
|
||||
})?,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<yazi_shared::fs::File>> Cast<T> for File {
|
||||
fn cast(lua: &Lua, data: T) -> mlua::Result<AnyUserData> { lua.create_any_userdata(data.into()) }
|
||||
}
|
12
yazi-plugin/src/file/mod.rs
Normal file
12
yazi-plugin/src/file/mod.rs
Normal file
@ -0,0 +1,12 @@
|
||||
#![allow(clippy::module_inception)]
|
||||
|
||||
mod file;
|
||||
|
||||
pub use file::*;
|
||||
|
||||
pub fn pour(lua: &mlua::Lua) -> mlua::Result<()> {
|
||||
file::File::register(lua)?;
|
||||
file::File::install(lua)?;
|
||||
|
||||
Ok(())
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
use mlua::{IntoLuaMulti, Lua, Value};
|
||||
use tokio::fs;
|
||||
|
||||
use crate::{bindings::{Cast, Cha}, url::UrlRef};
|
||||
use crate::{bindings::Cast, cha::Cha, url::UrlRef};
|
||||
|
||||
pub fn install(lua: &Lua) -> mlua::Result<()> {
|
||||
lua.globals().raw_set(
|
||||
|
@ -3,7 +3,7 @@ use tokio::runtime::Handle;
|
||||
use yazi_config::LAYOUT;
|
||||
|
||||
use super::slim_lua;
|
||||
use crate::{bindings::{Cast, File}, elements::Rect, loader::LOADER};
|
||||
use crate::{bindings::Cast, elements::Rect, file::File, loader::LOADER};
|
||||
|
||||
pub async fn fetch(name: &str, files: Vec<yazi_shared::fs::File>) -> mlua::Result<u8> {
|
||||
LOADER.ensure(name).await.into_lua_err()?;
|
||||
|
@ -1,14 +1,15 @@
|
||||
use mlua::Lua;
|
||||
|
||||
use crate::{bindings, elements, runtime::Runtime};
|
||||
use crate::{elements, runtime::Runtime};
|
||||
|
||||
pub fn slim_lua(name: &str) -> mlua::Result<Lua> {
|
||||
let lua = Lua::new();
|
||||
lua.set_named_registry_value("rt", Runtime::new(name))?;
|
||||
|
||||
// Base
|
||||
bindings::Cha::register(&lua)?;
|
||||
bindings::File::register(&lua)?;
|
||||
crate::bindings::Icon::register(&lua)?;
|
||||
crate::cha::pour(&lua)?;
|
||||
crate::file::pour(&lua)?;
|
||||
crate::url::pour(&lua)?;
|
||||
|
||||
crate::fs::install(&lua)?;
|
||||
|
@ -6,7 +6,7 @@ use yazi_config::LAYOUT;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use super::slim_lua;
|
||||
use crate::{bindings::{Cast, File, Window}, elements::Rect, loader::LOADER, Opt, OptCallback, LUA};
|
||||
use crate::{bindings::{Cast, Window}, elements::Rect, file::File, loader::LOADER, Opt, OptCallback, LUA};
|
||||
|
||||
pub fn peek(cmd: &Cmd, file: yazi_shared::fs::File, skip: usize) -> CancellationToken {
|
||||
let ct = CancellationToken::new();
|
||||
|
@ -3,7 +3,7 @@ use tokio::runtime::Handle;
|
||||
use yazi_config::LAYOUT;
|
||||
|
||||
use super::slim_lua;
|
||||
use crate::{bindings::{Cast, File}, elements::Rect, loader::LOADER};
|
||||
use crate::{bindings::Cast, elements::Rect, file::File, loader::LOADER};
|
||||
|
||||
pub async fn preload(name: &str, file: yazi_shared::fs::File) -> mlua::Result<u8> {
|
||||
LOADER.ensure(name).await.into_lua_err()?;
|
||||
|
@ -2,7 +2,7 @@ use mlua::TableExt;
|
||||
use yazi_config::LAYOUT;
|
||||
use yazi_shared::{emit, event::Cmd, Layer};
|
||||
|
||||
use crate::{bindings::{Cast, File}, elements::Rect, Opt, OptCallback, LUA};
|
||||
use crate::{bindings::Cast, elements::Rect, file::File, Opt, OptCallback, LUA};
|
||||
|
||||
pub fn seek_sync(cmd: &Cmd, file: yazi_shared::fs::File, units: i16) {
|
||||
let cb: OptCallback = Box::new(move |_, plugin| {
|
||||
|
@ -2,10 +2,12 @@
|
||||
|
||||
pub mod bindings;
|
||||
mod cast;
|
||||
pub mod cha;
|
||||
mod clipboard;
|
||||
mod config;
|
||||
pub mod elements;
|
||||
pub mod external;
|
||||
pub mod file;
|
||||
pub mod fs;
|
||||
pub mod isolate;
|
||||
pub mod loader;
|
||||
|
@ -21,13 +21,13 @@ fn stage_1(lua: &'static Lua) -> Result<()> {
|
||||
// Base
|
||||
lua.set_named_registry_value("rt", Runtime::default())?;
|
||||
lua.load(include_str!("../preset/ya.lua")).exec()?;
|
||||
crate::bindings::Cha::register(lua)?;
|
||||
crate::bindings::File::register(lua)?;
|
||||
crate::bindings::Icon::register(lua)?;
|
||||
crate::bindings::MouseEvent::register(lua)?;
|
||||
crate::elements::pour(lua)?;
|
||||
crate::loader::install(lua)?;
|
||||
crate::pubsub::install(lua)?;
|
||||
crate::cha::pour(lua)?;
|
||||
crate::file::pour(lua)?;
|
||||
crate::url::pour(lua)?;
|
||||
|
||||
// Components
|
||||
|
@ -3,7 +3,7 @@ use mlua::{Lua, Table};
|
||||
use yazi_config::PREVIEW;
|
||||
|
||||
use super::Utils;
|
||||
use crate::{bindings::{Cast, FileRef}, url::Url};
|
||||
use crate::{bindings::Cast, file::FileRef, url::Url};
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn cache(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
|
@ -49,6 +49,14 @@ impl Utils {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ya.raw_set(
|
||||
"input_emit",
|
||||
lua.create_function(|_, (name, args): (String, Table)| {
|
||||
emit!(Call(Cmd { name, args: Self::parse_args(args)? }, Layer::Input));
|
||||
Ok(())
|
||||
})?,
|
||||
)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ use mlua::{AnyUserData, IntoLuaMulti, Lua, Table, Value};
|
||||
use yazi_shared::{emit, event::Cmd, Layer, PeekError};
|
||||
|
||||
use super::Utils;
|
||||
use crate::{bindings::{FileRef, Window}, cast_to_renderable, elements::{Paragraph, RectRef, Renderable}, external::{self, Highlighter}};
|
||||
use crate::{bindings::Window, cast_to_renderable, elements::{Paragraph, RectRef, Renderable}, external::Highlighter, file::FileRef};
|
||||
|
||||
pub struct PreviewLock {
|
||||
pub url: yazi_shared::fs::Url,
|
||||
@ -49,29 +49,6 @@ impl Utils {
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ya.raw_set(
|
||||
"preview_archive",
|
||||
lua.create_async_function(|lua, t: Table| async move {
|
||||
let area: RectRef = t.raw_get("area")?;
|
||||
let mut lock = PreviewLock::try_from(t)?;
|
||||
|
||||
let lines: Vec<_> = match external::lsar(&lock.url, lock.skip, area.height as usize).await {
|
||||
Ok(items) => items.into_iter().map(|f| ratatui::text::Line::from(f.name)).collect(),
|
||||
Err(PeekError::Exceed(max)) => return (false, max).into_lua_multi(lua),
|
||||
Err(_) => return (false, Value::Nil).into_lua_multi(lua),
|
||||
};
|
||||
|
||||
lock.data = vec![Box::new(Paragraph {
|
||||
area: *area,
|
||||
text: ratatui::text::Text::from(lines),
|
||||
..Default::default()
|
||||
})];
|
||||
|
||||
emit!(Call(Cmd::new("preview").with_any("lock", lock), Layer::Manager));
|
||||
(true, Value::Nil).into_lua_multi(lua)
|
||||
})?,
|
||||
)?;
|
||||
|
||||
ya.raw_set(
|
||||
"preview_widgets",
|
||||
lua.create_async_function(|_, (t, widgets): (Table, Vec<AnyUserData>)| async move {
|
||||
|
@ -4,23 +4,8 @@ use super::Utils;
|
||||
|
||||
impl Utils {
|
||||
pub(super) fn target(lua: &Lua, ya: &Table) -> mlua::Result<()> {
|
||||
ya.raw_set(
|
||||
"target_family",
|
||||
lua.create_function(|_, ()| {
|
||||
#[cfg(unix)]
|
||||
{
|
||||
Ok("unix")
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
Ok("windows")
|
||||
}
|
||||
#[cfg(target_family = "wasm")]
|
||||
{
|
||||
Ok("wasm")
|
||||
}
|
||||
})?,
|
||||
)?;
|
||||
ya.raw_set("target_os", lua.create_function(|_, ()| Ok(std::env::consts::OS))?)?;
|
||||
ya.raw_set("target_family", lua.create_function(|_, ()| Ok(std::env::consts::FAMILY))?)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -33,13 +33,24 @@ impl Prework {
|
||||
let urls: Vec<_> = task.targets.iter().map(|f| f.url()).collect();
|
||||
let result = isolate::fetch(&task.plugin.name, task.targets).await;
|
||||
if let Err(e) = result {
|
||||
self.fail(task.id, format!("Fetch task failed:\n{e}"))?;
|
||||
self.fail(
|
||||
task.id,
|
||||
format!(
|
||||
"Failed to run fetcher `{}` with:\n{}\n\nError message:\n{e}",
|
||||
task.plugin.name,
|
||||
urls.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n")
|
||||
),
|
||||
)?;
|
||||
return Err(e.into());
|
||||
};
|
||||
|
||||
let code = result.unwrap();
|
||||
if code & 1 == 0 {
|
||||
error!("Fetch task `{}` returned {code}", task.plugin.name);
|
||||
error!(
|
||||
"Returned {code} when running fetcher `{}` with:\n{}",
|
||||
task.plugin.name,
|
||||
urls.iter().map(ToString::to_string).collect::<Vec<_>>().join("\n")
|
||||
);
|
||||
}
|
||||
if code >> 1 & 1 != 0 {
|
||||
let mut loaded = self.loaded.lock();
|
||||
@ -53,13 +64,16 @@ impl Prework {
|
||||
let url = task.target.url();
|
||||
let result = isolate::preload(&task.plugin.name, task.target).await;
|
||||
if let Err(e) = result {
|
||||
self.fail(task.id, format!("Preload task failed:\n{e}"))?;
|
||||
self.fail(
|
||||
task.id,
|
||||
format!("Failed to run preloader `{}` with `{url}`:\n{e}", task.plugin.name),
|
||||
)?;
|
||||
return Err(e.into());
|
||||
};
|
||||
|
||||
let code = result.unwrap();
|
||||
if code & 1 == 0 {
|
||||
error!("Preload task `{}` returned {code}", task.plugin.name);
|
||||
error!("Returned {code} when running preloader `{}` with `{url}`", task.plugin.name);
|
||||
}
|
||||
if code >> 1 & 1 != 0 {
|
||||
let mut loaded = self.loaded.lock();
|
||||
|
@ -17,7 +17,7 @@ dirs = "5.0.1"
|
||||
futures = "0.3.30"
|
||||
parking_lot = "0.12.3"
|
||||
percent-encoding = "2.3.1"
|
||||
ratatui = "0.26.3"
|
||||
ratatui = "0.27.0"
|
||||
regex = "1.10.5"
|
||||
serde = { version = "1.0.203", features = [ "derive" ] }
|
||||
shell-words = "1.1.0"
|
||||
|
@ -5,16 +5,16 @@ use bitflags::bitflags;
|
||||
bitflags! {
|
||||
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
|
||||
pub struct ChaKind: u8 {
|
||||
const DIR = 0b00000001;
|
||||
const DIR = 0b00000001;
|
||||
|
||||
const HIDDEN = 0b00000010;
|
||||
const LINK = 0b00000100;
|
||||
const ORPHAN = 0b00001000;
|
||||
const HIDDEN = 0b00000010;
|
||||
const LINK = 0b00000100;
|
||||
const ORPHAN = 0b00001000;
|
||||
|
||||
const BLOCK_DEVICE = 0b00010000;
|
||||
const CHAR_DEVICE = 0b00100000;
|
||||
const FIFO = 0b01000000;
|
||||
const SOCKET = 0b10000000;
|
||||
const BLOCK = 0b00010000;
|
||||
const CHAR = 0b00100000;
|
||||
const FIFO = 0b01000000;
|
||||
const SOCKET = 0b10000000;
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,10 +44,10 @@ impl From<Metadata> for Cha {
|
||||
{
|
||||
use std::os::unix::prelude::FileTypeExt;
|
||||
if m.file_type().is_block_device() {
|
||||
ck |= ChaKind::BLOCK_DEVICE;
|
||||
ck |= ChaKind::BLOCK;
|
||||
}
|
||||
if m.file_type().is_char_device() {
|
||||
ck |= ChaKind::CHAR_DEVICE;
|
||||
ck |= ChaKind::CHAR;
|
||||
}
|
||||
if m.file_type().is_fifo() {
|
||||
ck |= ChaKind::FIFO;
|
||||
@ -105,10 +105,10 @@ impl Cha {
|
||||
pub fn is_orphan(&self) -> bool { self.kind.contains(ChaKind::ORPHAN) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_block(&self) -> bool { self.kind.contains(ChaKind::BLOCK_DEVICE) }
|
||||
pub fn is_block(&self) -> bool { self.kind.contains(ChaKind::BLOCK) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_char(&self) -> bool { self.kind.contains(ChaKind::CHAR_DEVICE) }
|
||||
pub fn is_char(&self) -> bool { self.kind.contains(ChaKind::CHAR) }
|
||||
|
||||
#[inline]
|
||||
pub fn is_fifo(&self) -> bool { self.kind.contains(ChaKind::FIFO) }
|
||||
|
@ -20,6 +20,11 @@ impl Deref for File {
|
||||
fn deref(&self) -> &Self::Target { &self.cha }
|
||||
}
|
||||
|
||||
impl AsRef<File> for File {
|
||||
#[inline]
|
||||
fn as_ref(&self) -> &File { self }
|
||||
}
|
||||
|
||||
impl File {
|
||||
#[inline]
|
||||
pub async fn from(url: Url) -> Result<Self> {
|
||||
|
Loading…
Reference in New Issue
Block a user