fix: icon rules mixing (#2755)

This commit is contained in:
三咲雅 · Misaki Masa 2025-05-14 16:31:21 +08:00 committed by GitHub
parent 5a4e6e4068
commit 9a0ef6bb20
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 103 additions and 24 deletions

View file

@ -101,13 +101,13 @@ impl Icon {
self.prepend_globs.0.into_iter().chain(self.globs.0).chain(self.append_globs.0).collect(), self.prepend_globs.0.into_iter().chain(self.globs.0).chain(self.append_globs.0).collect(),
), ),
dirs: StrIcons( dirs: StrIcons(
self.prepend_dirs.0.into_iter().chain(self.dirs.0).chain(self.append_dirs.0).collect(), self.append_dirs.0.into_iter().chain(self.dirs.0).chain(self.prepend_dirs.0).collect(),
), ),
files: StrIcons( files: StrIcons(
self.prepend_files.0.into_iter().chain(self.files.0).chain(self.append_files.0).collect(), self.append_files.0.into_iter().chain(self.files.0).chain(self.prepend_files.0).collect(),
), ),
exts: StrIcons( exts: StrIcons(
self.prepend_exts.0.into_iter().chain(self.exts.0).chain(self.append_exts.0).collect(), self.append_exts.0.into_iter().chain(self.exts.0).chain(self.prepend_exts.0).collect(),
), ),
conds: CondIcons( conds: CondIcons(
self.prepend_conds.0.into_iter().chain(self.conds.0).chain(self.append_conds.0).collect(), self.prepend_conds.0.into_iter().chain(self.conds.0).chain(self.append_conds.0).collect(),

View file

@ -25,17 +25,20 @@ impl Utils {
} }
pub(super) fn truncate(lua: &Lua) -> mlua::Result<Function> { pub(super) fn truncate(lua: &Lua) -> mlua::Result<Function> {
fn idx_and_width(it: impl Iterator<Item = (usize, char)>, max: usize) -> (usize, usize) { fn traverse(
let mut width = 0; it: impl Iterator<Item = (usize, char)>,
max: usize,
) -> (Option<usize>, usize, bool) {
let (mut adv, mut last) = (0, 0);
let idx = it let idx = it
.take_while(|(_, c)| { .take_while(|&(_, c)| {
width += c.width().unwrap_or(0); last = adv;
width <= max adv += c.width().unwrap_or(0);
adv <= max
}) })
.map(|(i, _)| i) .map(|(i, _)| i)
.last() .last();
.unwrap(); (idx, last, adv > max)
(idx, width)
} }
lua.create_function(|lua, (s, t): (mlua::String, Table)| { lua.create_function(|lua, (s, t): (mlua::String, Table)| {
@ -53,25 +56,28 @@ impl Utils {
let lossy = String::from_utf8_lossy(&b); let lossy = String::from_utf8_lossy(&b);
let rtl = t.raw_get("rtl").unwrap_or(false); let rtl = t.raw_get("rtl").unwrap_or(false);
let (idx, width) = if rtl { let (idx, width, remain) = if rtl {
idx_and_width(lossy.char_indices().rev(), max) traverse(lossy.char_indices().rev(), max)
} else { } else {
idx_and_width(lossy.char_indices(), max) traverse(lossy.char_indices(), max)
}; };
if width <= max { let Some(idx) = idx else { return lua.create_string("") };
return Ok(s); if !remain {
} else if rtl && idx == 0 {
return Ok(s);
} else if !rtl && lossy[idx..].chars().nth(1).is_none() {
return Ok(s); return Ok(s);
} }
let result: Vec<_> = if rtl { let result: Vec<_> = match (rtl, width == max) {
let i = lossy[idx..].char_indices().nth(1).map(|(i, _)| idx + i).unwrap_or(lossy.len()); (false, false) => {
"".bytes().chain(lossy[i..].bytes()).collect() let len = lossy[idx..].chars().next().map_or(0, |c| c.len_utf8());
} else { lossy[..idx + len].bytes().chain("".bytes()).collect()
lossy[..idx].bytes().chain("".bytes()).collect() }
(false, true) => lossy[..idx].bytes().chain("".bytes()).collect(),
(true, false) => "".bytes().chain(lossy[idx..].bytes()).collect(),
(true, true) => {
let len = lossy[idx..].chars().next().map_or(0, |c| c.len_utf8());
"".bytes().chain(lossy[idx + len..].bytes()).collect()
}
}; };
lua.create_string(result) lua.create_string(result)
}) })
@ -88,3 +94,76 @@ impl Utils {
}) })
} }
} }
#[cfg(test)]
mod tests {
use mlua::Value;
use super::*;
fn truncate(s: &str, max: usize, rtl: bool) -> String {
let lua = Lua::new();
let t = lua
.create_table_from([("max", Value::Integer(max as i64)), ("rtl", Value::Boolean(rtl))])
.unwrap();
Utils::truncate(&lua).unwrap().call((s, t)).unwrap()
}
#[test]
fn test_truncate() {
assert_eq!(truncate("你好world", 0, false), "");
assert_eq!(truncate("你好world", 1, false), "");
assert_eq!(truncate("你好world", 2, false), "");
assert_eq!(truncate("你好,世界", 3, false), "你…");
assert_eq!(truncate("你好,世界", 4, false), "你…");
assert_eq!(truncate("你好,世界", 5, false), "你好…");
assert_eq!(truncate("Hello, world", 5, false), "Hell…");
assert_eq!(truncate("Ni好世界", 3, false), "Ni…");
}
#[test]
fn test_truncate_rtl() {
assert_eq!(truncate("world你好", 0, true), "");
assert_eq!(truncate("world你好", 1, true), "");
assert_eq!(truncate("world你好", 2, true), "");
assert_eq!(truncate("你好,世界", 3, true), "…界");
assert_eq!(truncate("你好,世界", 4, true), "…界");
assert_eq!(truncate("你好,世界", 5, true), "…世界");
assert_eq!(truncate("Hello, world", 5, true), "…orld");
assert_eq!(truncate("你好Shi界", 3, true), "…界");
}
#[test]
fn test_truncate_oboe() {
assert_eq!(truncate("Hello, world", 11, false), "Hello, wor…");
assert_eq!(truncate("你好,世界", 9, false), "你好,世…");
assert_eq!(truncate("你好世Jie", 9, false), "你好,世…");
assert_eq!(truncate("Hello, world", 11, true), "…llo, world");
assert_eq!(truncate("你好,世界", 9, true), "…好,世界");
assert_eq!(truncate("Ni好世界", 9, true), "…好,世界");
}
#[test]
fn test_truncate_exact() {
assert_eq!(truncate("Hello, world", 12, false), "Hello, world");
assert_eq!(truncate("你好,世界", 10, false), "你好,世界");
assert_eq!(truncate("Hello, world", 12, true), "Hello, world");
assert_eq!(truncate("你好,世界", 10, true), "你好,世界");
}
#[test]
fn test_truncate_overflow() {
assert_eq!(truncate("Hello, world", 13, false), "Hello, world");
assert_eq!(truncate("你好,世界", 11, false), "你好,世界");
assert_eq!(truncate("Hello, world", 13, true), "Hello, world");
assert_eq!(truncate("你好,世界", 11, true), "你好,世界");
}
}