diff --git a/yazi-config/preset/theme.toml b/yazi-config/preset/theme.toml index cf807289..40fc269c 100644 --- a/yazi-config/preset/theme.toml +++ b/yazi-config/preset/theme.toml @@ -10,12 +10,12 @@ cwd = { fg = "cyan" } # Hovered -hovered = { fg = "black", bg = "lightblue" } +hovered = { reversed = true } preview_hovered = { underline = true } # Find -find_keyword = { fg = "yellow", italic = true } -find_position = { fg = "magenta", bg = "reset", italic = true } +find_keyword = { fg = "yellow", bold = true, italic = true, underline = true } +find_position = { fg = "magenta", bg = "reset", bold = true, italic = true } # Marker marker_copied = { fg = "lightgreen", bg = "lightgreen" } diff --git a/yazi-core/src/tab/finder.rs b/yazi-core/src/tab/finder.rs index e8145823..72239ce9 100644 --- a/yazi-core/src/tab/finder.rs +++ b/yazi-core/src/tab/finder.rs @@ -66,10 +66,5 @@ impl Finder { pub fn matched(&self) -> &BTreeMap { &self.matched } #[inline] - pub fn matched_idx(&self, url: &Url) -> Option { - if let Some((_, &idx)) = self.matched.iter().find(|(u, _)| *u == url) { - return Some(idx); - } - None - } + pub fn matched_idx(&self, url: &Url) -> Option { self.matched.get(url).copied() } } diff --git a/yazi-fm/src/lives/file.rs b/yazi-fm/src/lives/file.rs index cffebf27..e987ff01 100644 --- a/yazi-fm/src/lives/file.rs +++ b/yazi-fm/src/lives/file.rs @@ -95,6 +95,7 @@ impl File { }) }); reg.add_method("is_selected", |_, me, ()| Ok(me.tab().selected.contains(&me.url))); + reg.add_method("in_current", |_, me, ()| Ok(me.folder().cwd == me.tab().current.cwd)); reg.add_method("found", |lua, me, ()| { let cx = lua.named_registry_value::("cx")?; let Some(finder) = &cx.manager.active().finder else { @@ -113,7 +114,9 @@ impl File { let Some(finder) = &cx.manager.active().finder else { return Ok(None); }; - + if me.folder().cwd != me.tab().current.cwd { + return Ok(None); + } let Some(h) = me.name().and_then(|n| finder.filter.highlighted(n)) else { return Ok(None); }; diff --git a/yazi-plugin/preset/components/current.lua b/yazi-plugin/preset/components/current.lua index 6c457df7..434ee475 100644 --- a/yazi-plugin/preset/components/current.lua +++ b/yazi-plugin/preset/components/current.lua @@ -12,19 +12,12 @@ function Current:render(area) local items, markers = {}, {} for i, f in ipairs(files) do - local name = Folder:highlighted_name(f) - - -- Highlight hovered file - local item = ui.ListItem(ui.Line { Folder:icon(f), table.unpack(name) }) - if f:is_hovered() then - item = item:style(THEME.manager.hovered) - else - item = item:style(f:style()) - end - items[#items + 1] = item + local style = f:style() + items[#items + 1] = ui.ListItem(ui.Line(File:full(f))) + :style(f:is_hovered() and style:patch(THEME.manager.hovered) or style) -- Yanked/marked/selected files - local marker = Folder:marker(f) + local marker = File:marker(f) if marker ~= 0 then markers[#markers + 1] = { i, marker } end diff --git a/yazi-plugin/preset/components/file.lua b/yazi-plugin/preset/components/file.lua new file mode 100644 index 00000000..402d45ad --- /dev/null +++ b/yazi-plugin/preset/components/file.lua @@ -0,0 +1,88 @@ +File = {} + +function File:icon(file) + local icon = file:icon() + if not icon then + return {} + elseif file:is_hovered() then + return { ui.Span(" " .. icon.text .. " ") } + else + return { ui.Span(" " .. icon.text .. " "):style(icon.style) } + end +end + +function File:prefix(file) + local prefix = file:prefix() or "" + return prefix == "" and {} or { ui.Span(prefix .. "/") } +end + +function File:highlights(file) + local name = file.name:gsub("\r", "?", 1) + local highlights = file:highlights() + if not highlights or #highlights == 0 then + return { ui.Span(name) } + end + + local spans, last = {}, 0 + for _, r in ipairs(highlights) do + if r[1] > last then + spans[#spans + 1] = ui.Span(name:sub(last + 1, r[1])) + end + spans[#spans + 1] = ui.Span(name:sub(r[1] + 1, r[2])):style(THEME.manager.find_keyword) + last = r[2] + end + if last < #name then + spans[#spans + 1] = ui.Span(name:sub(last + 1)) + end + return spans +end + +function File:found(file) + if not file:is_hovered() then + return {} + end + + local found = file:found() + if not found then + return {} + end + + return { + ui.Span(" "), + ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position), + } +end + +function File:symlink(file) + if not MANAGER.show_symlink then + return {} + end + + local to = file.link_to + return to and { ui.Span(" -> " .. tostring(to)):italic() } or {} +end + +function File:full(file) + return ya.flat { + self:icon(file), + self:prefix(file), + self:highlights(file), + self:found(file), + self:symlink(file), + } +end + +function File: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 diff --git a/yazi-plugin/preset/components/folder.lua b/yazi-plugin/preset/components/folder.lua index b4c0ef34..aaaa7df5 100644 --- a/yazi-plugin/preset/components/folder.lua +++ b/yazi-plugin/preset/components/folder.lua @@ -4,69 +4,6 @@ Folder = { PREVIEW = 2, } -function Folder:by_kind(kind) - if kind == self.PARENT then - return cx.active.parent - elseif kind == self.CURRENT then - return cx.active.current - elseif kind == self.PREVIEW then - return cx.active.preview.folder - end -end - -function Folder:icon(file) - local icon = file:icon() - return icon and ui.Span(" " .. icon.text .. " "):style(icon.style) or ui.Span("") -end - -function Folder:highlight_ranges(s, ranges) - if not ranges or #ranges == 0 then - return { ui.Span(s) } - end - - local spans = {} - local last = 0 - for _, r in ipairs(ranges) do - if r[1] > last then - spans[#spans + 1] = ui.Span(s:sub(last + 1, r[1])) - end - spans[#spans + 1] = ui.Span(s:sub(r[1] + 1, r[2])):style(THEME.manager.find_keyword) - last = r[2] - end - if last < #s then - spans[#spans + 1] = ui.Span(s:sub(last + 1)) - end - return spans -end - -function Folder:highlighted_name(file) - -- Complete prefix when searching across directories - local prefix = file:prefix() or "" - if prefix ~= "" then - prefix = prefix .. "/" - end - - -- Range highlighting for filenames - local highlights = file:highlights() - local spans = self:highlight_ranges(prefix .. file.name, highlights) - - -- Show symlink target - if MANAGER.show_symlink and file.link_to ~= nil then - spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic() - end - - if not highlights or not file:is_hovered() then - return spans - end - - local found = file:found() - if found ~= nil then - spans[#spans + 1] = ui.Span(" ") - spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position) - end - return spans -end - function Folder:linemode(area, files) local mode = cx.active.conf.linemode if mode == "none" then @@ -92,21 +29,6 @@ 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 {} @@ -150,3 +72,13 @@ function Folder:markers(area, markers) append(last) return elements end + +function Folder:by_kind(kind) + if kind == self.PARENT then + return cx.active.parent + elseif kind == self.CURRENT then + return cx.active.current + elseif kind == self.PREVIEW then + return cx.active.preview.folder + end +end diff --git a/yazi-plugin/preset/components/parent.lua b/yazi-plugin/preset/components/parent.lua index be5d5e5e..40e9f99b 100644 --- a/yazi-plugin/preset/components/parent.lua +++ b/yazi-plugin/preset/components/parent.lua @@ -12,17 +12,12 @@ function Parent:render(area) local items, markers = {}, {} for i, f in ipairs(folder.window) do - -- Highlight hovered file - local item = ui.ListItem(ui.Line { Folder:icon(f), ui.Span(f.name) }) - if f:is_hovered() then - item = item:style(THEME.manager.hovered) - else - item = item:style(f:style()) - end - items[#items + 1] = item + local style = f:style() + items[#items + 1] = ui.ListItem(ui.Line(File:full(f))) + :style(f:is_hovered() and style:patch(THEME.manager.hovered) or style) -- Yanked/marked/selected files - local marker = Folder:marker(f) + local marker = File:marker(f) if marker ~= 0 then markers[#markers + 1] = { i, marker } end diff --git a/yazi-plugin/preset/plugins/folder.lua b/yazi-plugin/preset/plugins/folder.lua index a5460205..4cd127db 100644 --- a/yazi-plugin/preset/plugins/folder.lua +++ b/yazi-plugin/preset/plugins/folder.lua @@ -13,17 +13,12 @@ function M:peek() local items, markers = {}, {} for i, f in ipairs(folder.window) do - -- Highlight hovered file - local item = ui.ListItem(ui.Line { Folder:icon(f), ui.Span(f.name) }) - if f:is_hovered() then - item = item:style(THEME.manager.preview_hovered) - else - item = item:style(f:style()) - end - items[#items + 1] = item + local style = f:style() + items[#items + 1] = ui.ListItem(ui.Line(File:full(f))) + :style(f:is_hovered() and style:patch(THEME.manager.preview_hovered) or style) -- Yanked/marked/selected files - local marker = Folder:marker(f) + local marker = File:marker(f) if marker ~= 0 then markers[#markers + 1] = { i, marker } end diff --git a/yazi-plugin/src/elements/style.rs b/yazi-plugin/src/elements/style.rs index 3bf3b7bf..fa5c2068 100644 --- a/yazi-plugin/src/elements/style.rs +++ b/yazi-plugin/src/elements/style.rs @@ -1,4 +1,4 @@ -use mlua::{AnyUserData, Lua, Table, UserData, UserDataMethods}; +use mlua::{AnyUserData, ExternalError, Lua, Table, UserData, UserDataMethods, Value}; use yazi_config::theme::Color; #[derive(Clone, Copy, Default)] @@ -80,5 +80,16 @@ impl UserData for Style { ud.borrow_mut::()?.0.add_modifier = ratatui::style::Modifier::empty(); Ok(ud) }); + methods.add_function("patch", |_, (ud, value): (AnyUserData, Value)| { + { + let mut me = ud.borrow_mut::()?; + me.0 = me.0.patch(match value { + Value::Table(tb) => Style::from(tb).0, + Value::UserData(ud) => ud.borrow::