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