feat: add new file marked state (#682)

This commit is contained in:
三咲雅 · Misaki Masa 2024-02-15 20:24:20 +08:00 committed by GitHub
parent 95d2358100
commit 52d91c0e42
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 84 additions and 76 deletions

View file

@ -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" },

View file

@ -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" }

View file

@ -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,

View file

@ -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!();
} }
} }

View file

@ -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

View file

@ -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 {

View file

@ -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 {

View file

@ -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()));
}) })

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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