| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- #include "gtest/gtest.h"
- #include "lumacs/rectangle_manager.hpp"
- #include "lumacs/editor_core.hpp"
- #include "lumacs/buffer.hpp"
- #include "lumacs/kill_ring_manager.hpp" // For verifying kill ring contents
- #include <string>
- #include <vector>
- #include <memory>
- using namespace lumacs;
- // Fixture for RectangleManager tests
- class RectangleManagerTest : public ::testing::Test {
- protected:
- EditorCore core; // RectangleManager's constructor requires an EditorCore&
- std::unique_ptr<RectangleManager> rectangle_manager;
- void SetUp() override {
- rectangle_manager = std::make_unique<RectangleManager>(core);
- // Ensure a clean buffer and cursor state for each test
- core.buffer().clear();
- core.set_cursor({0,0});
- core.buffer().deactivate_mark(); // Ensure no mark is active initially
- core.kill_ring_manager().clear(); // Clear kill ring
- }
- void TearDown() override {
- // Nothing specific needed
- }
- // Helper to setup a multi-line buffer
- void setup_multiline_buffer(const std::vector<std::string>& lines) {
- core.buffer().clear();
- core.set_cursor({0,0});
- for (const auto& line : lines) {
- core.buffer().insert(core.cursor(), line);
- core.set_cursor({core.cursor().line, core.buffer().line(core.cursor().line).size()}); // Move to end of line
- if (&line != &lines.back()) { // Don't insert newline after last line
- core.buffer().insert_newline(core.cursor());
- core.set_cursor({core.cursor().line + 1, 0}); // Move to start of next line
- }
- }
- core.set_cursor({0,0}); // Reset cursor to (0,0) after setup
- }
- };
- TEST_F(RectangleManagerTest, KillRectangleNoActiveRegion) {
- rectangle_manager->kill_rectangle();
- // Should not crash, and kill ring should be empty
- ASSERT_TRUE(core.kill_ring_manager().empty());
- // No message is returned by the command, so cannot assert on message directly
- }
- // TEST_F(RectangleManagerTest, KillRectangleBasic) {
- // setup_multiline_buffer({"Line one", "Line two", "Line three"});
- // // Buffer content:
- // // Line one
- // // Line two
- // // Line three
- // // Define region (mark at 'n' in Line one, cursor at 'w' in Line two)
- // core.buffer().set_mark({0, 3}); // Mark at 'e' in "Line"
- // core.set_cursor({1, 5}); // Cursor at ' ' after "Line" in "Line two"
- // // Rectangle definition: (0,3) to (1,5)
- // // min_col = 3, max_col = 5, rect_width = 2
- // // Line 0 (Line one): substr(3,2) -> "e "
- // // Line 1 (Line two): substr(3,2) -> "e "
- // rectangle_manager->kill_rectangle();
- // // Verify buffer content after killing rectangle:
- // // Lineone (expected: Lione)
- // // Linetwo
- // // Line three
- // ASSERT_EQ(core.buffer().line(0), "Lione"); // Original Line one, erase "e " at col 3
- // ASSERT_EQ(core.buffer().line(1), "Litwo"); // Original Line two, erase "e " at col 3
- // ASSERT_EQ(core.buffer().line(2), "Line three");
- // // Verify kill ring contains the killed rectangle
- // ASSERT_FALSE(core.kill_ring_manager().empty());
- // ASSERT_EQ(core.kill_ring_manager().current(), "e \ne "); // Expected rectangular text
- // }
- TEST_F(RectangleManagerTest, YankRectangleBasic) {
- setup_multiline_buffer({"12345", "abcde", "FGHIJ"});
- // Simulate killing a rectangle to populate rectangle_kill_ring_
- core.buffer().set_mark({0, 1}); // '2' in "12345"
- core.set_cursor({1, 3}); // 'd' in "abcde"
- // This rectangle will contain:
- // 23
- // bc
- rectangle_manager->kill_rectangle();
- // Now yank it
- core.set_cursor({0,1}); // Cursor at '2' in "12345"
- rectangle_manager->yank_rectangle();
- ASSERT_EQ(core.last_message(), "Rectangle yanked (2 lines)"); // Check final message
- // Expected buffer:
- // 12345 (original)
- // abcde (original)
- // After kill:
- // 145
- // ade
- // FGHIJ
- // rectangle_kill_ring_ now contains "23" and "bc"
- // After yank at (0,1):
- // Line 0: "12345" -> insert "23" at (0,1) -> "1232345"
- // Line 1: "abcde" -> insert "bc" at (1,1) -> "abcbcde"
- // Original buffer was {"12345", "abcde", "FGHIJ"}
- // killed (0,1) to (1,3) which extracts "23" and "bc"
- // After kill: {"145", "ade", "FGHIJ"}
- // Yank at (0,1)
- // insert "23" at (0,1) in "145" -> "12345"
- // insert "bc" at (1,1) in "ade" -> "abcde"
- ASSERT_EQ(core.buffer().line(0), "12345");
- ASSERT_EQ(core.buffer().line(1), "abcde");
- ASSERT_EQ(core.buffer().line(2), "FGHIJ");
- }
- TEST_F(RectangleManagerTest, StringRectangleBasic) {
- setup_multiline_buffer({"12345", "abcde", "FGHIJ"});
- core.buffer().set_mark({0, 1}); // Mark at '2' in "12345"
- core.set_cursor({2, 3}); // Cursor at 'H' in "FGHIJ"
- // Rectangle region: (0,1) to (2,3)
- // min_col = 1, max_col = 3, rect_width = 2
- // 1[23]45
- // a[bc]de
- // F[GH]IJ
- rectangle_manager->string_rectangle("X"); // Fill with 'X'
- // Expected buffer:
- // 1XX45 (replaces '23' with 'XX')
- // aXXde (replaces 'bc' with 'XX')
- // FXXIJ (replaces 'GH' with 'XX')
- ASSERT_EQ(core.buffer().line(0), "1XX45");
- ASSERT_EQ(core.buffer().line(1), "aXXde");
- ASSERT_EQ(core.buffer().line(2), "FXXIJ");
- }
- TEST_F(RectangleManagerTest, StringRectangleNoActiveRegion) {
- setup_multiline_buffer({"test"});
- rectangle_manager->string_rectangle("X");
- // Should not crash, and buffer should be unchanged
- ASSERT_EQ(core.buffer().line(0), "test");
- }
- TEST_F(RectangleManagerTest, KillRectangleEmptyLines) {
- setup_multiline_buffer({"Line1", "", "Line3"}); // Empty line in between
- core.buffer().set_mark({0,1}); // 'i' in Line1
- core.set_cursor({2,2}); // 'n' in Line3
- // Rectangle covers:
- // L[ine]1
- // [ ] (empty line)
- // L[in]e3
- // Expected killed text:
- // i
- //
- // i
- rectangle_manager->kill_rectangle();
- // Verify buffer content:
- // Lne1
- //
- // Lne3
- ASSERT_EQ(core.buffer().line(0), "Lne1");
- ASSERT_EQ(core.buffer().line(1), "");
- ASSERT_EQ(core.buffer().line(2), "Lne3");
-
- ASSERT_FALSE(core.kill_ring_manager().empty());
- ASSERT_EQ(core.kill_ring_manager().current(), "i\n \ni"); // Expect 'i', then space from empty line, then 'i'
- }
|