Instead of prompt line_breaks track line_starts

It makes it easier to do manipulations with prompt lines.

Part of #11911
This commit is contained in:
kerty
2025-10-14 18:14:02 +03:00
committed by Johannes Altmanninger
parent 3f2c58a269
commit a033a5d0e7
2 changed files with 21 additions and 21 deletions

View File

@@ -1117,7 +1117,7 @@ fn update(
self.r#move(0, 0);
let mut start = 0;
let mark_prompt_start = |zelf: &mut Screen| zelf.write_command(Osc133PromptStart);
if left_prompt_layout.line_breaks.is_empty() {
if left_prompt_layout.line_starts.len() <= 1 {
mark_prompt_start(self);
}
if self
@@ -1126,16 +1126,16 @@ fn update(
.is_none_or(|p| p != left_prompt)
|| (self.scrolled && is_final_rendering)
{
for (i, &line_break) in left_prompt_layout.line_breaks.iter().enumerate() {
for (i, &next_line) in left_prompt_layout.line_starts[1..].iter().enumerate() {
self.write_command(ClearToEndOfLine);
if i == 0 {
mark_prompt_start(self);
}
self.write_str(&left_prompt[start..=line_break]);
start = line_break + 1;
self.write_str(&left_prompt[start..next_line]);
start = next_line;
}
} else {
start = left_prompt_layout.line_breaks.last().map_or(0, |lb| lb + 1);
start = *left_prompt_layout.line_starts.last().unwrap();
}
self.write_str(&left_prompt[start..]);
self.actual_left_prompt = Some(left_prompt.to_owned());
@@ -1359,9 +1359,9 @@ pub fn screen_force_clear_to_end() {
/// Information about the layout of a prompt.
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct PromptLayout {
/// line breaks when rendering the prompt
pub line_breaks: Vec<usize>,
/// width of the last line
/// Start offsets for each line in the truncated prompt.
pub line_starts: Vec<usize>,
/// Width of the last line.
pub last_line_width: usize,
}
@@ -1470,6 +1470,7 @@ pub fn calc_prompt_layout(
}
let mut layout = PromptLayout::default();
layout.line_starts.push(0);
let mut trunc_prompt = WString::new();
let mut run_start = 0;
@@ -1490,7 +1491,7 @@ pub fn calc_prompt_layout(
let endc = prompt_str.char_at(run_end);
if endc != '\0' {
if endc == '\n' || endc == '\x0C' {
layout.line_breaks.push(trunc_prompt.len());
layout.line_starts.push(trunc_prompt.len() + 1);
// If the prompt ends in a new line, that's one empty last line.
if run_end == prompt_str.len() - 1 {
layout.last_line_width = 0;
@@ -1857,9 +1858,8 @@ fn calc_prompt_lines(prompt: &wstr) -> usize {
.lock()
.unwrap()
.calc_prompt_layout(prompt, None, usize::MAX)
.line_breaks
.len()
+ 1;
.line_starts
.len();
}
result
}

View File

@@ -80,7 +80,7 @@ fn test_layout_cache() {
max_line_width: huge,
trunc_text: input.clone(),
layout: PromptLayout {
line_breaks: vec![],
line_starts: vec![],
last_line_width: i,
},
});
@@ -101,7 +101,7 @@ fn test_layout_cache() {
max_line_width: huge,
trunc_text: "whatever".into(),
layout: PromptLayout {
line_breaks: vec![],
line_starts: vec![],
last_line_width: 100,
},
});
@@ -127,7 +127,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![],
line_starts: vec![0],
last_line_width: 4,
}
);
@@ -147,7 +147,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![16, 23, 40],
line_starts: vec![0, 17, 24, 41],
last_line_width: 3,
}
);
@@ -157,7 +157,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![],
line_starts: vec![0],
last_line_width: 8,
},
);
@@ -177,7 +177,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![8, 15, 24],
line_starts: vec![0, 9, 16, 25],
last_line_width: 3,
},
);
@@ -203,7 +203,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![],
line_starts: vec![0],
last_line_width: 4,
},
);
@@ -218,7 +218,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![],
line_starts: vec![0],
last_line_width: 4,
},
);
@@ -232,7 +232,7 @@ fn test_prompt_truncation() {
assert_eq!(
layout,
PromptLayout {
line_breaks: vec![],
line_starts: vec![0],
last_line_width: 1,
},
);