Skip to content

Commit

Permalink
reflow: consider newlines to be word separators
Browse files Browse the repository at this point in the history
  • Loading branch information
Vince Mutolo committed Apr 16, 2022
1 parent 78b18f9 commit a3127d4
Showing 1 changed file with 43 additions and 7 deletions.
50 changes: 43 additions & 7 deletions helix-core/src/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ pub fn reflow_hard_wrap(text: RopeSlice, max_line_len: usize) -> String {
for piece in flow_pieces {
match piece {
Piece::NoReflow(piece) => {
// Get rid of spaces at the ends of lines.
match new_flow.pop() {
Some(c) if c == ' ' => (),
Some(c) => new_flow.push(c),
None => unreachable!(),
}
new_flow.push('\n');
new_flow.push_str(piece);
current_line_len = 0;
Expand All @@ -31,8 +37,19 @@ pub fn reflow_hard_wrap(text: RopeSlice, max_line_len: usize) -> String {
use unicode_segmentation::UnicodeSegmentation;
let piece_len = UnicodeSegmentation::graphemes(piece, true).count();

if piece.is_empty() {
continue;
}

let piece_will_fit = current_line_len + piece_len <= max_line_len;
if !piece_will_fit && !new_flow.is_empty() {
// Get rid of spaces at the ends of lines.
match new_flow.pop() {
Some(c) if c == ' ' => (),
Some(c) => new_flow.push(c),
None => unreachable!(),
}

new_flow.push('\n');
current_line_len = 0;
}
Expand All @@ -43,11 +60,22 @@ pub fn reflow_hard_wrap(text: RopeSlice, max_line_len: usize) -> String {

new_flow.push_str(piece);

if !piece.chars().rev().next().unwrap().is_whitespace() {
new_flow.push(' ');
}

current_line_len += piece_len;
}
}
}

// Get rid of the space at the very end.
match new_flow.pop() {
Some(c) if c == ' ' => (),
Some(c) => new_flow.push(c),
None => (),
}

if ends_with_newline {
new_flow.push('\n');
}
Expand Down Expand Up @@ -184,6 +212,14 @@ mod tests {

#[test]
fn reflow_basic_to_one_line() {
let text = "hello my name\nis helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 100);
assert_eq!(reflow, "hello my name is helix");
}

#[test]
fn reflow_basic_to_one_line_with_trailing_space() {
let text = "hello my name \nis helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 100);
Expand All @@ -195,39 +231,39 @@ mod tests {
let text = "hello my name is helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 10);
assert_eq!(reflow, "hello my \nname is \nhelix");
assert_eq!(reflow, "hello my\nname is\nhelix");
}

#[test]
fn reflow_with_blank_empty_line() {
let text = "hello\n\nmy name is helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 10);
assert_eq!(reflow, "hello\n\nmy name \nis helix");
assert_eq!(reflow, "hello\n\nmy name\nis helix");
}

#[test]
fn reflow_with_blank_whitespace_line() {
let text = "hello\n \nmy name is helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 10);
assert_eq!(reflow, "hello\n \nmy name \nis helix");
assert_eq!(reflow, "hello\n \nmy name\nis helix");
}

#[test]
fn reflow_end_with_blank_line() {
let text = "hello my name is helix\n";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 10);
assert_eq!(reflow, "hello my \nname is \nhelix\n");
assert_eq!(reflow, "hello my\nname is\nhelix\n");
}

#[test]
fn reflow_with_blank_lines_and_prefix() {
let text = " hello\n\nmy name is helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 10);
assert_eq!(reflow, " hello\n\nmy name \nis helix");
assert_eq!(reflow, " hello\n\nmy name\nis helix");
}

#[test]
Expand Down Expand Up @@ -259,13 +295,13 @@ mod tests {
let text = "hello my name is helix";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 0);
assert_eq!(reflow, "hello \nmy \nname \nis \nhelix");
assert_eq!(reflow, "hello\nmy\nname\nis\nhelix");
}

#[test]
fn reflow_comment_after_blank_line() {
let text = Rope::from("// Text indented. \n\n// Still indented.");
let expected_reflow = "// Text indented. \n\n// Still indented.";
let expected_reflow = "// Text indented.\n\n// Still indented.";
let text = Rope::from(text);
let reflow = reflow_hard_wrap(text.slice(..), 80);
assert_eq!(reflow, expected_reflow);
Expand Down

0 comments on commit a3127d4

Please sign in to comment.