diff --git a/aider/tools/insert_block.py b/aider/tools/insert_block.py index 9105dc7e998..57211742735 100644 --- a/aider/tools/insert_block.py +++ b/aider/tools/insert_block.py @@ -176,6 +176,10 @@ def execute( new_lines = lines[:insertion_line_idx] + content_lines + lines[insertion_line_idx:] new_content = "\n".join(new_lines) + # Restore trailing newline if original file had one + if original_content.endswith("\n"): + new_content += "\n" + if original_content == new_content: coder.io.tool_warning("No changes made: insertion would not change file") return "Warning: No changes made (insertion would not change file)" diff --git a/tests/tools/test_insert_block.py b/tests/tools/test_insert_block.py index 33955bb6509..54d3483f675 100644 --- a/tests/tools/test_insert_block.py +++ b/tests/tools/test_insert_block.py @@ -115,3 +115,35 @@ def test_mutually_exclusive_parameters_raise(coder_with_file): assert result.startswith("Error: Must specify exactly one of") assert file_path.read_text().startswith("first line") coder.io.tool_error.assert_called() + + +def test_trailing_newline_preservation(coder_with_file): + coder, file_path = coder_with_file + insert_block.Tool.execute( + coder, + file_path="example.txt", + content="inserted line", + position="top", + ) + + content = file_path.read_text() + assert content.endswith("\n"), "File should preserve trailing newline" + coder.io.tool_error.assert_not_called() + + +def test_no_trailing_newline_preservation(coder_with_file): + coder, file_path = coder_with_file + + content_without_trailing_newline = "first line\nsecond line" + file_path.write_text(content_without_trailing_newline) + + insert_block.Tool.execute( + coder, + file_path="example.txt", + content="inserted line", + position="top", + ) + + content = file_path.read_text() + assert not content.endswith("\n"), "File should preserve lack of trailing newline" + coder.io.tool_error.assert_not_called()