Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 34 additions & 5 deletions src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -618,11 +618,22 @@ impl PagerState {
let row_in_line = selection.absolute_row.saturating_sub(line_start_row);
let cols_avail = self.wrapped_cols_available();
let wrapped_rows = textwrap::wrap(line, cols_avail.max(1));
let preceding_chars = wrapped_rows
.iter()
.take(row_in_line)
.map(|row| row.chars().count())
.sum::<usize>();
// Wrapping drops the whitespace at each break, so the preceding rows' lengths do not add up
// to this row's position in `line`. Find each row in order to get its real starting offset.
let mut row_start = 0;
for (idx, row) in wrapped_rows.iter().enumerate() {
let row = row.trim_end();
if let Some(found) = line.get(row_start..).and_then(|rest| rest.find(row)) {
row_start += found;
}
if idx == row_in_line {
break;
}
row_start += row.len();
}
let preceding_chars = line
.get(..row_start)
.map_or(0, |prefix| prefix.chars().count());

preceding_chars.saturating_add(selection.col)
}
Expand Down Expand Up @@ -777,6 +788,24 @@ mod tests {
assert_eq!(ps.extract_selection().as_deref(), Some("cdefghi\njklm"));
}

#[test]
fn extract_selection_across_wrapped_rows_with_spaces() {
let mut ps = PagerState::new().unwrap();
ps.cols = 6;
ps.screen.orig_text = "hello world foo\n".to_string();
ps.reformat_display();
ps.selection_anchor = Some(Selection {
absolute_row: 1,
col: 0,
});
ps.selection = Some(Selection {
absolute_row: 2,
col: 2,
});

assert_eq!(ps.extract_selection().as_deref(), Some("world foo"));
}

#[test]
fn format_prompt_truncates_long_message_to_available_width() {
let mut ps = PagerState::new().unwrap();
Expand Down