mirror of
https://github.com/sxyazi/yazi.git
synced 2024-12-18 22:31:35 +03:00
feat: highlight matching words on finding (#211)
This commit is contained in:
parent
782f88b965
commit
f9eeac611f
@ -50,7 +50,7 @@ impl<'a> Folder<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn file_style(&self, file: &File) -> Style {
|
fn item_style(&self, file: &File) -> Style {
|
||||||
let mimetype = &self.cx.manager.mimetype;
|
let mimetype = &self.cx.manager.mimetype;
|
||||||
THEME
|
THEME
|
||||||
.filetypes
|
.filetypes
|
||||||
@ -59,6 +59,25 @@ impl<'a> Folder<'a> {
|
|||||||
.map(|x| x.style.get())
|
.map(|x| x.style.get())
|
||||||
.unwrap_or_else(Style::new)
|
.unwrap_or_else(Style::new)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn highlighted_item<'b>(&'b self, file: &'b File) -> Vec<Span> {
|
||||||
|
let short = short_path(file.url(), &self.folder.cwd);
|
||||||
|
|
||||||
|
let v = self.is_find.then_some(()).and_then(|_| {
|
||||||
|
let finder = self.cx.manager.active().finder()?;
|
||||||
|
let (head, body, tail) = finder.explode(short.name)?;
|
||||||
|
|
||||||
|
// TODO: to be configured by THEME?
|
||||||
|
let style = Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC);
|
||||||
|
Some(vec![
|
||||||
|
Span::raw(short.prefix.join(head.as_ref()).display().to_string()),
|
||||||
|
Span::styled(body, style),
|
||||||
|
Span::raw(tail),
|
||||||
|
])
|
||||||
|
});
|
||||||
|
|
||||||
|
v.unwrap_or_else(|| vec![Span::raw(format!("{}", short))])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Widget for Folder<'a> {
|
impl<'a> Widget for Folder<'a> {
|
||||||
@ -96,13 +115,12 @@ impl<'a> Widget for Folder<'a> {
|
|||||||
} else if hovered {
|
} else if hovered {
|
||||||
THEME.selection.hovered.get()
|
THEME.selection.hovered.get()
|
||||||
} else {
|
} else {
|
||||||
self.file_style(f)
|
self.item_style(f)
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut spans = Vec::with_capacity(10);
|
let mut spans = Vec::with_capacity(10);
|
||||||
|
|
||||||
spans.push(Span::raw(format!(" {} ", Self::icon(f))));
|
spans.push(Span::raw(format!(" {} ", Self::icon(f))));
|
||||||
spans.push(Span::raw(short_path(f.url(), &self.folder.cwd)));
|
spans.extend(self.highlighted_item(f));
|
||||||
|
|
||||||
if let Some(link_to) = f.link_to() {
|
if let Some(link_to) = f.link_to() {
|
||||||
if MANAGER.show_symlink {
|
if MANAGER.show_symlink {
|
||||||
@ -116,14 +134,14 @@ impl<'a> Widget for Folder<'a> {
|
|||||||
.and_then(|finder| finder.matched_idx(f.url()))
|
.and_then(|finder| finder.matched_idx(f.url()))
|
||||||
{
|
{
|
||||||
let len = active.finder().unwrap().matched().len();
|
let len = active.finder().unwrap().matched().len();
|
||||||
let style = Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC);
|
|
||||||
spans.push(Span::styled(
|
spans.push(Span::styled(
|
||||||
format!(
|
format!(
|
||||||
" [{}/{}]",
|
" [{}/{}]",
|
||||||
if idx > 99 { ">99".to_string() } else { (idx + 1).to_string() },
|
if idx > 99 { ">99".to_string() } else { (idx + 1).to_string() },
|
||||||
if len > 99 { ">99".to_string() } else { len.to_string() }
|
if len > 99 { ">99".to_string() } else { len.to_string() }
|
||||||
),
|
),
|
||||||
style,
|
// TODO: to be configured by THEME?
|
||||||
|
Style::new().fg(Color::Rgb(255, 255, 50)).add_modifier(Modifier::ITALIC),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{collections::BTreeMap, ffi::OsStr};
|
use std::{borrow::Cow, collections::BTreeMap, ffi::OsStr};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use regex::bytes::Regex;
|
use regex::bytes::Regex;
|
||||||
@ -108,6 +108,26 @@ impl Finder {
|
|||||||
self.query.is_match(name.as_bytes())
|
self.query.is_match(name.as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Explode the name into three parts: head, body, tail.
|
||||||
|
#[inline]
|
||||||
|
pub fn explode<'a>(&self, name: &'a OsStr) -> Option<(Cow<'a, str>, Cow<'a, str>, Cow<'a, str>)> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let b = { name.to_string_lossy().as_bytes() };
|
||||||
|
|
||||||
|
#[cfg(not(target_os = "windows"))]
|
||||||
|
let b = {
|
||||||
|
use std::os::unix::ffi::OsStrExt;
|
||||||
|
name.as_bytes()
|
||||||
|
};
|
||||||
|
|
||||||
|
let range = self.query.find(b).map(|m| m.range())?;
|
||||||
|
Some((
|
||||||
|
String::from_utf8_lossy(&b[..range.start]),
|
||||||
|
String::from_utf8_lossy(&b[range.start..range.end]),
|
||||||
|
String::from_utf8_lossy(&b[range.end..]),
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Finder {
|
impl Finder {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use std::{borrow::Cow, env, path::{Component, Path, PathBuf}};
|
use std::{borrow::Cow, env, ffi::OsStr, fmt::Display, path::{Component, Path, PathBuf}};
|
||||||
|
|
||||||
use tokio::fs;
|
use tokio::fs;
|
||||||
|
|
||||||
@ -23,11 +23,28 @@ pub fn expand_url(mut u: Url) -> Url {
|
|||||||
u
|
u
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn short_path(p: &Path, base: &Path) -> String {
|
pub struct ShortPath<'a> {
|
||||||
if let Ok(p) = p.strip_prefix(base) {
|
pub prefix: &'a Path,
|
||||||
return p.display().to_string();
|
pub name: &'a OsStr,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for ShortPath<'_> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
if self.prefix == Path::new("") {
|
||||||
|
return write!(f, "{}", self.name.to_string_lossy());
|
||||||
|
}
|
||||||
|
write!(f, "{}/{}", self.prefix.display(), self.name.to_string_lossy())
|
||||||
}
|
}
|
||||||
p.display().to_string()
|
}
|
||||||
|
|
||||||
|
pub fn short_path<'a>(p: &'a Path, base: &Path) -> ShortPath<'a> {
|
||||||
|
let p = p.strip_prefix(base).unwrap_or(p);
|
||||||
|
let mut parts = p.components();
|
||||||
|
let name = parts.next_back().and_then(|p| match p {
|
||||||
|
Component::Normal(p) => Some(p),
|
||||||
|
_ => None,
|
||||||
|
});
|
||||||
|
ShortPath { prefix: parts.as_path(), name: name.unwrap_or_default() }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readable_path(p: &Path) -> String {
|
pub fn readable_path(p: &Path) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user