refactor(panels): single-source the truncate-ellipsis helper

component_browser_panel, design_md_panel/helpers, git_panel, and
variables_panel/paint each defined their own char-aware truncate-with-ellipsis
fn (3 identical; variables used max-1 which could panic at 0). Hoist one
truncate_ellipsis into op-editor-ui::util and re-export under the original
name+visibility at each site, so the 9 git_panel call sites etc. stay
unchanged. The saturating bound also removes the variables-panel panic-at-0
latent bug.
This commit is contained in:
Kayshen-X 2026-06-19 09:48:13 +08:00
parent 1f648bd568
commit 5f3d511876
5 changed files with 24 additions and 29 deletions

View file

@ -157,10 +157,30 @@ pub fn resize_bounds(start: Rect, handle: SelectionHandle, dx: f32, dy: f32) ->
Rect::xywh(x, y, w, h)
}
/// Truncate `s` to at most `max` characters, appending a `…` ellipsis when it
/// is shortened (the ellipsis counts toward `max`). Character-aware, so
/// multibyte glyphs are never split.
pub fn truncate_ellipsis(s: &str, max: usize) -> String {
if s.chars().count() <= max {
return s.to_string();
}
let kept: String = s.chars().take(max.saturating_sub(1)).collect();
format!("{kept}…")
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn truncate_ellipsis_appends_only_when_shortened() {
assert_eq!(truncate_ellipsis("hello", 10), "hello");
assert_eq!(truncate_ellipsis("hello", 5), "hello");
assert_eq!(truncate_ellipsis("hello", 3), "he…");
// Saturating: max == 0 must not panic.
assert_eq!(truncate_ellipsis("hello", 0), "…");
}
#[test]
fn parse_hex_expands_shorthand_and_zero_pads() {
assert_eq!(

View file

@ -676,10 +676,4 @@ impl<'a> ComponentBrowserPanel<'a> {
}
}
pub(in crate::widgets) fn truncate(s: &str, max: usize) -> String {
if s.chars().count() <= max {
return s.to_string();
}
let kept: String = s.chars().take(max.saturating_sub(1)).collect();
format!("{kept}…")
}
pub(in crate::widgets) use crate::util::truncate_ellipsis as truncate;

View file

@ -9,13 +9,7 @@ pub(super) fn label_char_w(ch: char) -> f32 {
}
}
pub(super) fn truncate(s: &str, max: usize) -> String {
if s.chars().count() <= max {
return s.to_string();
}
let kept: String = s.chars().take(max.saturating_sub(1)).collect();
format!("{kept}…")
}
pub(super) use crate::util::truncate_ellipsis as truncate;
pub(super) fn hex_to_color(hex: &str) -> Color {
match op_editor_core::parse_hex_rgb(hex) {

View file

@ -919,10 +919,4 @@ impl<'a> GitPanel<'a> {
}
/// Char truncation with an ellipsis.
pub(super) fn truncate(s: &str, max: usize) -> String {
if s.chars().count() <= max {
return s.to_string();
}
let kept: String = s.chars().take(max.saturating_sub(1)).collect();
format!("{kept}…")
}
pub(super) use crate::util::truncate_ellipsis as truncate;

View file

@ -749,11 +749,4 @@ fn scalar_to_label(s: &VariableScalar) -> String {
}
}
fn truncate(s: &str, max: usize) -> String {
if s.chars().count() <= max {
return s.to_string();
}
let mut out: String = s.chars().take(max - 1).collect();
out.push('…');
out
}
use crate::util::truncate_ellipsis as truncate;