Skip to content
Merged
Show file tree
Hide file tree
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
25 changes: 18 additions & 7 deletions src/wrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -301,17 +301,28 @@ pub fn wrap_text(lines: &[String], width: usize) -> Vec<String> {
indent = line.chars().take_while(|c| c.is_whitespace()).collect();
}
let trimmed_end = line.trim_end();
let hard_break = line.ends_with(" ")
|| trimmed_end.ends_with("<br>")
|| trimmed_end.ends_with("<br/>")
|| trimmed_end.ends_with("<br />");
let text = trimmed_end
let text_without_html_breaks = trimmed_end
.trim_end_matches("<br>")
.trim_end_matches("<br/>")
.trim_end_matches("<br />")
.trim_end_matches(' ')
.trim_end_matches("<br />");

let is_trailing_spaces = line.ends_with(" ");
let is_html_br = trimmed_end != text_without_html_breaks;
let backslash_count = line
.trim_end()
.chars()
.rev()
.take_while(|&c| c == '\\')
.count();
let is_backslash_escape = backslash_count % 2 == 1;

let hard_break = is_trailing_spaces || is_html_br || is_backslash_escape;

let text = text_without_html_breaks
.trim_start()
.trim_end_matches(' ')
.to_string();

buf.push((text, hard_break));
}

Expand Down
4 changes: 4 additions & 0 deletions tests/data/hard_linebreak_expected.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Scenarios live under `tests/features/`. Step implementations in `tests` share \
a common `World` struct that uses `figment::Jail` for isolation. Each scenario
demonstration example \
executes asynchronously with `tokio`.
3 changes: 3 additions & 0 deletions tests/data/hard_linebreak_input.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Scenarios live under `tests/features/`. Step implementations in `tests` share \
a common `World` struct that uses `figment::Jail` for isolation. Each scenario demonstration example \
executes asynchronously with `tokio`.
29 changes: 29 additions & 0 deletions tests/integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,35 @@ fn test_preserve_hard_line_breaks() {
assert_eq!(output[1], "Line two follows.");
}

#[test]
fn test_wrap_hard_linebreak_backslash() {
let input: Vec<String> = include_lines!("data/hard_linebreak_input.txt");
let expected: Vec<String> = include_lines!("data/hard_linebreak_expected.txt");
assert_eq!(process_stream(&input), expected);
}
Comment thread
leynos marked this conversation as resolved.

#[test]
fn test_wrap_hard_linebreak_backslash_edge_cases() {
let input = lines_vec!(
"This line ends with two backslashes: \\\\",
"This line ends with a single backslash: \\",
" \\ ",
"\\",
"Text before \\ and after",
" \\",
"",
);
let expected = lines_vec!(
"This line ends with two backslashes: \\\\ This line ends with a single backslash:",
"\\",
"\\",
"\\",
"Text before \\ and after \\",
"",
);
Comment on lines +806 to +822
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion (testing): Consider adding a test case for a line ending with an odd number of backslashes greater than one.

Please add a test case with a line ending in three backslashes to ensure correct handling of odd numbers of trailing backslashes.

Suggested change
let input = lines_vec!(
"This line ends with two backslashes: \\\\",
"This line ends with a single backslash: \\",
" \\ ",
"\\",
"Text before \\ and after",
" \\",
"",
);
let expected = lines_vec!(
"This line ends with two backslashes: \\\\ This line ends with a single backslash:",
"\\",
"\\",
"\\",
"Text before \\ and after \\",
"",
);
let input = lines_vec!(
"This line ends with two backslashes: \\\\",
"This line ends with a single backslash: \\",
"This line ends with three backslashes: \\\\\\",
" \\ ",
"\\",
"Text before \\ and after",
" \\",
"",
);
let expected = lines_vec!(
"This line ends with two backslashes: \\\\ This line ends with a single backslash:",
"This line ends with three backslashes: \\\\\\",
"\\",
"\\",
"\\",
"Text before \\ and after \\",
"",
);

assert_eq!(process_stream(&input), expected);
Comment on lines +815 to +823
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Verification agent

🧩 Analysis chain

Verify the expected test outputs match the implementation.

The expected outputs suggest specific behaviour for backslash line breaks. Ensure these expectations align with the actual implementation in src/wrap.rs.


🏁 Script executed:

#!/bin/bash
# Description: Verify the backslash line break behaviour matches test expectations
# Expected: Lines with odd trailing backslashes should create hard breaks

# Test the actual behaviour with the edge case inputs
echo "Testing backslash line break behaviour..."

# Check if the wrap_text function properly handles these cases
ast-grep --pattern 'fn wrap_text($_, $_) -> $_ {
  $$$
}'

Length of output: 152


🏁 Script executed:

#!/bin/bash
# Locate process_stream implementation
rg -n "fn process_stream" 

# Locate wrap_text implementation
rg -n "fn wrap_text" || echo "No direct wrap_text; searching usage"
rg -n "wrap_text"

# Find the wrap.rs file
WRAP_FILE=$(find src -name wrap.rs | head -n1)
echo "wrap.rs found at: $WRAP_FILE"

# Display the first 200 lines of wrap.rs for context
sed -n '1,200p' "$WRAP_FILE"

Length of output: 8807


🏁 Script executed:

#!/bin/bash
# Display integration test around backslash behaviour
echo "=== Integration Test Snippet ==="
sed -n '780,860p' tests/integration.rs

# Display process_stream_inner implementation to inspect hard-break logic
echo -e "\n=== process.rs (lines 1–200) ==="
sed -n '1,200p' src/process.rs

Length of output: 5645


🏁 Script executed:

#!/bin/bash
echo "=== wrap_text definition ==="
sed -n '200,360p' src/wrap.rs

echo -e "\n=== hard_break detection ==="
grep -n "hard_break" -n src/wrap.rs

Length of output: 5434


Update backslash edge-case test expected outputs

Adjust the test_wrap_hard_linebreak_backslash_edge_cases expectations to match the actual process_stream behaviour in wrap.rs:

• File: tests/integration.rs
• Test: test_wrap_hard_linebreak_backslash_edge_cases
• Replace the expected vector with this diff:

-let expected = lines_vec!(
-    "This line ends with two backslashes: \\\\ This line ends with a single backslash:",
-    "\\",
-    "\\",
-    "\\",
-    "Text before \\ and after \\",
-    "",
-);
+let expected = lines_vec!(
+    "This line ends with two backslashes: \\\\ This line ends with a single backslash:\\",
+    "\\",
+    "\\",
+    "Text before \\ and after \\",
+    "",
+);

This removes the extra lone backslash line and preserves the trailing backslash on the first combined line.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
let expected = lines_vec!(
"This line ends with two backslashes: \\\\ This line ends with a single backslash:",
"\\",
"\\",
"\\",
"Text before \\ and after \\",
"",
);
assert_eq!(process_stream(&input), expected);
let expected = lines_vec!(
- "This line ends with two backslashes: \\\\ This line ends with a single backslash:",
- "\\",
- "\\",
- "\\",
- "Text before \\ and after \\",
- "",
+ "This line ends with two backslashes: \\\\ This line ends with a single backslash:\\",
+ "\\",
+ "\\",
+ "Text before \\ and after \\",
+ "",
);
assert_eq!(process_stream(&input), expected);
🤖 Prompt for AI Agents
In tests/integration.rs around lines 815 to 823, the expected output in the
test_wrap_hard_linebreak_backslash_edge_cases test does not match the actual
behavior of process_stream in wrap.rs. Update the expected vector by removing
the extra lone backslash lines and ensure the trailing backslash is preserved on
the first combined line, so the expected output aligns with the real output of
process_stream.

}

#[test]
/// Tests that `process_stream` preserves complex table formatting without modification.
///
Expand Down