mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
feat: add new file marked state (#682)
This commit is contained in:
parent
95d2358100
commit
52d91c0e42
12 changed files with 84 additions and 76 deletions
|
|
@ -58,29 +58,29 @@ keymap = [
|
|||
{ on = [ "<C-r>" ], exec = "select_all --state=none", desc = "Inverse selection of all files" },
|
||||
|
||||
# Operation
|
||||
{ on = [ "o" ], exec = "open", desc = "Open the selected files" },
|
||||
{ on = [ "O" ], exec = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = [ "<Enter>" ], exec = "open", desc = "Open the selected files" },
|
||||
{ on = [ "<C-Enter>" ], exec = "open --interactive", desc = "Open the selected files interactively" },
|
||||
{ on = [ "y" ], exec = [ "yank", "escape --visual --select" ], desc = "Copy the selected files" },
|
||||
{ on = [ "Y" ], exec = [ "unyank", "escape --visual --select" ], desc = "Cancel the yank status of files" },
|
||||
{ on = [ "x" ], exec = [ "yank --cut", "escape --visual --select" ], desc = "Cut the selected files" },
|
||||
{ on = [ "p" ], exec = "paste", desc = "Paste the files" },
|
||||
{ on = [ "P" ], exec = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||
{ on = [ "-" ], exec = "link", desc = "Symlink the absolute path of files" },
|
||||
{ on = [ "_" ], exec = "link --relative", desc = "Symlink the relative path of files" },
|
||||
{ on = [ "d" ], exec = [ "remove", "escape --visual --select" ], desc = "Move the files to the trash" },
|
||||
{ on = [ "D" ], exec = [ "remove --permanently", "escape --visual --select" ], desc = "Permanently delete the files" },
|
||||
{ on = [ "a" ], exec = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
{ on = [ "r" ], exec = "rename --cursor=before_ext", desc = "Rename a file or directory" },
|
||||
{ on = [ ";" ], exec = "shell", desc = "Run a shell command" },
|
||||
{ on = [ ":" ], exec = "shell --block", desc = "Run a shell command (block the UI until the command finishes)" },
|
||||
{ on = [ "." ], exec = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||
{ on = [ "s" ], exec = "search fd", desc = "Search files by name using fd" },
|
||||
{ on = [ "S" ], exec = "search rg", desc = "Search files by content using ripgrep" },
|
||||
{ on = [ "<C-s>" ], exec = "search none", desc = "Cancel the ongoing search" },
|
||||
{ on = [ "z" ], exec = "jump zoxide", desc = "Jump to a directory using zoxide" },
|
||||
{ on = [ "Z" ], exec = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
||||
{ on = [ "o" ], exec = [ "escape --visual", "open" ], desc = "Open the selected files" },
|
||||
{ on = [ "O" ], exec = [ "escape --visual", "open --interactive" ], desc = "Open the selected files interactively" },
|
||||
{ on = [ "<Enter>" ], exec = [ "escape --visual", "open" ], desc = "Open the selected files" },
|
||||
{ on = [ "<C-Enter>" ], exec = [ "escape --visual", "open --interactive" ], desc = "Open the selected files interactively" },
|
||||
{ on = [ "y" ], exec = [ "escape --visual", "yank" ], desc = "Copy the selected files" },
|
||||
{ on = [ "Y" ], exec = "unyank", desc = "Cancel the yank status of files" },
|
||||
{ on = [ "x" ], exec = [ "escape --visual", "yank --cut" ], desc = "Cut the selected files" },
|
||||
{ on = [ "p" ], exec = "paste", desc = "Paste the files" },
|
||||
{ on = [ "P" ], exec = "paste --force", desc = "Paste the files (overwrite if the destination exists)" },
|
||||
{ on = [ "-" ], exec = "link", desc = "Symlink the absolute path of files" },
|
||||
{ on = [ "_" ], exec = "link --relative", desc = "Symlink the relative path of files" },
|
||||
{ on = [ "d" ], exec = [ "escape --visual", "remove" ], desc = "Move the files to the trash" },
|
||||
{ on = [ "D" ], exec = [ "escape --visual", "remove --permanently" ], desc = "Permanently delete the files" },
|
||||
{ on = [ "a" ], exec = "create", desc = "Create a file or directory (ends with / for directories)" },
|
||||
{ on = [ "r" ], exec = [ "escape --visual", "rename --cursor=before_ext" ], desc = "Rename a file or directory" },
|
||||
{ on = [ ";" ], exec = [ "escape --visual", "shell" ], desc = "Run a shell command" },
|
||||
{ on = [ ":" ], exec = [ "escape --visual", "shell --block" ], desc = "Run a shell command (block the UI until the command finishes)" },
|
||||
{ on = [ "." ], exec = "hidden toggle", desc = "Toggle the visibility of hidden files" },
|
||||
{ on = [ "s" ], exec = "search fd", desc = "Search files by name using fd" },
|
||||
{ on = [ "S" ], exec = "search rg", desc = "Search files by content using ripgrep" },
|
||||
{ on = [ "<C-s>" ], exec = "search none", desc = "Cancel the ongoing search" },
|
||||
{ on = [ "z" ], exec = "jump zoxide", desc = "Jump to a directory using zoxide" },
|
||||
{ on = [ "Z" ], exec = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" },
|
||||
|
||||
# Linemode
|
||||
{ on = [ "m", "s" ], exec = "linemode size", desc = "Set linemode to size" },
|
||||
|
|
@ -89,10 +89,10 @@ keymap = [
|
|||
{ on = [ "m", "n" ], exec = "linemode none", desc = "Set linemode to none" },
|
||||
|
||||
# Copy
|
||||
{ on = [ "c", "c" ], exec = "copy path", desc = "Copy the absolute path" },
|
||||
{ on = [ "c", "d" ], exec = "copy dirname", desc = "Copy the path of the parent directory" },
|
||||
{ on = [ "c", "f" ], exec = "copy filename", desc = "Copy the name of the file" },
|
||||
{ on = [ "c", "n" ], exec = "copy name_without_ext", desc = "Copy the name of the file without the extension" },
|
||||
{ on = [ "c", "c" ], exec = [ "escape --visual", "copy path" ], desc = "Copy the absolute path" },
|
||||
{ on = [ "c", "d" ], exec = [ "escape --visual", "copy dirname" ], desc = "Copy the path of the parent directory" },
|
||||
{ on = [ "c", "f" ], exec = [ "escape --visual", "copy filename" ], desc = "Copy the name of the file" },
|
||||
{ on = [ "c", "n" ], exec = [ "escape --visual", "copy name_without_ext" ], desc = "Copy the name of the file without the extension" },
|
||||
|
||||
# Filter
|
||||
{ on = [ "f" ], exec = "filter --smart", desc = "Filter the files" },
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@ find_keyword = { fg = "yellow", italic = true }
|
|||
find_position = { fg = "magenta", bg = "reset", italic = true }
|
||||
|
||||
# Marker
|
||||
marker_selected = { fg = "lightgreen", bg = "lightgreen" }
|
||||
marker_copied = { fg = "lightyellow", bg = "lightyellow" }
|
||||
marker_copied = { fg = "lightgreen", bg = "lightgreen" }
|
||||
marker_cut = { fg = "lightred", bg = "lightred" }
|
||||
marker_marked = { fg = "lightyellow", bg = "lightyellow" }
|
||||
marker_selected = { fg = "lightblue", bg = "lightblue" }
|
||||
|
||||
# Tab
|
||||
tab_active = { fg = "black", bg = "lightblue" }
|
||||
|
|
|
|||
|
|
@ -20,9 +20,10 @@ pub struct Manager {
|
|||
find_position: Style,
|
||||
|
||||
// Marker
|
||||
marker_selected: Style,
|
||||
marker_copied: Style,
|
||||
marker_cut: Style,
|
||||
marker_marked: Style,
|
||||
marker_selected: Style,
|
||||
|
||||
// Tab
|
||||
tab_active: Style,
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use std::collections::HashSet;
|
||||
|
||||
use yazi_shared::{event::Cmd, render};
|
||||
|
||||
use crate::manager::{Manager, Yanked};
|
||||
|
|
@ -12,10 +14,13 @@ impl From<Cmd> for Opt {
|
|||
|
||||
impl Manager {
|
||||
pub fn yank(&mut self, opt: impl Into<Opt>) {
|
||||
let opt = opt.into() as Opt;
|
||||
let selected: HashSet<_> = self.selected_or_hovered().into_iter().cloned().collect();
|
||||
if selected.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
self.yanked =
|
||||
Yanked { cut: opt.cut, urls: self.selected_or_hovered().into_iter().cloned().collect() };
|
||||
self.yanked = Yanked { cut: opt.into().cut, urls: selected };
|
||||
self.active_mut().escape_select();
|
||||
render!();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,10 +29,10 @@ impl From<Cmd> for Opt {
|
|||
|
||||
impl Tab {
|
||||
#[inline]
|
||||
fn escape_find(&mut self) -> bool { self.finder.take().is_some() }
|
||||
pub fn escape_find(&mut self) -> bool { self.finder.take().is_some() }
|
||||
|
||||
#[inline]
|
||||
fn escape_visual(&mut self) -> bool {
|
||||
pub fn escape_visual(&mut self) -> bool {
|
||||
let Some((_, indices)) = self.mode.visual() else {
|
||||
return false;
|
||||
};
|
||||
|
|
@ -52,7 +52,7 @@ impl Tab {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_select(&mut self) -> bool {
|
||||
pub fn escape_select(&mut self) -> bool {
|
||||
if self.selected.is_empty() {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -65,14 +65,14 @@ impl Tab {
|
|||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_filter(&mut self) -> bool {
|
||||
pub fn escape_filter(&mut self) -> bool {
|
||||
let b = self.current.files.filter().is_some();
|
||||
self.filter_do(super::filter::Opt::default());
|
||||
b
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn escape_search(&mut self) -> bool {
|
||||
pub fn escape_search(&mut self) -> bool {
|
||||
let b = self.current.cwd.is_search();
|
||||
self.search_stop();
|
||||
b
|
||||
|
|
|
|||
|
|
@ -26,15 +26,6 @@ impl Mode {
|
|||
Mode::Unset(start, indices) => Some((*start, indices)),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn pending(&self, idx: usize, state: bool) -> bool {
|
||||
match self {
|
||||
Mode::Normal => state,
|
||||
Mode::Select(_, indices) => state || indices.contains(&idx),
|
||||
Mode::Unset(_, indices) => state && !indices.contains(&idx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Mode {
|
||||
|
|
|
|||
|
|
@ -84,19 +84,19 @@ impl File {
|
|||
1u8
|
||||
})
|
||||
});
|
||||
reg.add_method("is_selected", |lua, me, ()| {
|
||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
let selected = me.tab().selected.contains(&me.url);
|
||||
reg.add_method("is_marked", |_, me, ()| {
|
||||
use yazi_core::tab::Mode::*;
|
||||
if !me.tab().mode.is_visual() || me.folder().cwd != me.tab().current.cwd {
|
||||
return Ok(0u8);
|
||||
}
|
||||
|
||||
#[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)
|
||||
Ok(match &me.tab().mode {
|
||||
Select(_, indices) if indices.contains(&me.idx) => 1u8,
|
||||
Unset(_, indices) if indices.contains(&me.idx) => 2u8,
|
||||
_ => 0u8,
|
||||
})
|
||||
});
|
||||
reg.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains(&me.url)));
|
||||
reg.add_method("found", |lua, me, ()| {
|
||||
let cx = lua.named_registry_value::<CtxRef>("cx")?;
|
||||
let Some(finder) = &cx.manager.active().finder else {
|
||||
|
|
|
|||
|
|
@ -25,7 +25,6 @@ impl Mode {
|
|||
reg.add_field_method_get("is_select", |_, me| Ok(me.is_select()));
|
||||
reg.add_field_method_get("is_unset", |_, me| Ok(me.is_unset()));
|
||||
reg.add_field_method_get("is_visual", |_, me| Ok(me.is_visual()));
|
||||
reg.add_method("pending", |_, me, (idx, state): (usize, bool)| Ok(me.pending(idx, state)));
|
||||
|
||||
reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string()));
|
||||
})
|
||||
|
|
|
|||
|
|
@ -23,12 +23,10 @@ function Current:render(area)
|
|||
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 }
|
||||
-- Yanked/marked/selected files
|
||||
local marker = Folder:marker(f)
|
||||
if marker ~= 0 then
|
||||
markers[#markers + 1] = { i, marker }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -92,6 +92,21 @@ function Folder:linemode(area, files)
|
|||
return ui.Paragraph(area, lines):align(ui.Paragraph.RIGHT)
|
||||
end
|
||||
|
||||
function Folder:marker(file)
|
||||
local yanked = file:is_yanked()
|
||||
if yanked ~= 0 then
|
||||
return yanked -- 1: copied, 2: cut
|
||||
end
|
||||
|
||||
local marked = file:is_marked()
|
||||
if marked == 1 then
|
||||
return 3 -- 3: marked
|
||||
elseif marked == 0 and file:is_selected() then
|
||||
return 4 -- 4: selected
|
||||
end
|
||||
return 0
|
||||
end
|
||||
|
||||
function Folder:markers(area, markers)
|
||||
if #markers == 0 or area.w * area.h == 0 then
|
||||
return {}
|
||||
|
|
@ -115,6 +130,8 @@ function Folder:markers(area, markers)
|
|||
elseif last[3] == 2 then
|
||||
bar = bar:style(THEME.manager.marker_cut)
|
||||
elseif last[3] == 3 then
|
||||
bar = bar:style(THEME.manager.marker_marked)
|
||||
elseif last[3] == 4 then
|
||||
bar = bar:style(THEME.manager.marker_selected)
|
||||
end
|
||||
elements[#elements + 1] = bar
|
||||
|
|
|
|||
|
|
@ -21,12 +21,10 @@ function Parent:render(area)
|
|||
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 }
|
||||
-- Yanked/marked/selected files
|
||||
local marker = Folder:marker(f)
|
||||
if marker ~= 0 then
|
||||
markers[#markers + 1] = { i, marker }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -22,12 +22,10 @@ function M:peek()
|
|||
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 }
|
||||
-- Yanked/marked/selected files
|
||||
local marker = Folder:marker(f)
|
||||
if marker ~= 0 then
|
||||
markers[#markers + 1] = { i, marker }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue