Skip to content

Commit e6882ab

Browse files
remi-dupredjc
authored andcommitted
Implement measure_text_width with no allocation
I implemented that while working on optimizing something I don't remember, it might still be useful.
1 parent 89cc237 commit e6882ab

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ test:
1414
@cargo test
1515
@cargo test --all-features
1616
@cargo test --no-default-features
17+
@cargo test --no-default-features --features ansi-parsing
18+
@cargo test --no-default-features --features unicode-width
1719

1820
check-minver:
1921
@echo "MINVER CHECK"

src/utils.rs

+30-9
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,7 @@ use once_cell::sync::Lazy;
99
use crate::term::{wants_emoji, Term};
1010

1111
#[cfg(feature = "ansi-parsing")]
12-
use crate::ansi::{strip_ansi_codes, AnsiCodeIterator};
13-
14-
#[cfg(not(feature = "ansi-parsing"))]
15-
fn strip_ansi_codes(s: &str) -> &str {
16-
s
17-
}
12+
use crate::ansi::AnsiCodeIterator;
1813

1914
fn default_colors_enabled(out: &Term) -> bool {
2015
(out.features().colors_supported()
@@ -71,7 +66,19 @@ pub fn set_colors_enabled_stderr(val: bool) {
7166

7267
/// Measure the width of a string in terminal characters.
7368
pub fn measure_text_width(s: &str) -> usize {
74-
str_width(&strip_ansi_codes(s))
69+
#[cfg(feature = "ansi-parsing")]
70+
{
71+
AnsiCodeIterator::new(s)
72+
.filter_map(|(s, is_ansi)| match is_ansi {
73+
false => Some(str_width(s)),
74+
true => None,
75+
})
76+
.sum()
77+
}
78+
#[cfg(not(feature = "ansi-parsing"))]
79+
{
80+
str_width(s)
81+
}
7582
}
7683

7784
/// A terminal color.
@@ -937,16 +944,30 @@ fn test_text_width() {
937944
.bold()
938945
.force_styling(true)
939946
.to_string();
947+
940948
assert_eq!(
941949
measure_text_width(&s),
942950
if cfg!(feature = "ansi-parsing") {
943951
3
944-
} else if cfg!(feature = "unicode-width") {
945-
17
946952
} else {
947953
21
948954
}
949955
);
956+
957+
let s = style("🐶 <3").red().force_styling(true).to_string();
958+
959+
assert_eq!(
960+
measure_text_width(&s),
961+
match (
962+
cfg!(feature = "ansi-parsing"),
963+
cfg!(feature = "unicode-width")
964+
) {
965+
(true, true) => 5, // "🐶 <3"
966+
(true, false) => 4, // "🐶 <3", no unicode-aware width
967+
(false, true) => 14, // full string
968+
(false, false) => 13, // full string, no unicode-aware width
969+
}
970+
);
950971
}
951972

952973
#[test]

0 commit comments

Comments
 (0)