Browse Source

Complete Phase 2: Enhance buffer management and safety

- Add Buffer::clear() exposed to Lua
- Update C-x C-b to properly refresh buffer list content
- Add modified buffer warning to C-x k (kill-buffer) with ConfirmKill mode
- Add tests for Buffer::clear
Bernardo Magri 1 month ago
parent
commit
272a379be5
4 changed files with 62 additions and 32 deletions
  1. 18 31
      init.lua
  2. 1 0
      src/lua_api.cpp
  3. 31 1
      src/main_ncurses.cpp
  4. 12 0
      tests/test_buffer.cpp

+ 18 - 31
init.lua

@@ -742,15 +742,17 @@ bind_key("C-x C-b", function()
     table.insert(lines, "Buffer List:")
     table.insert(lines, "------------")
     table.insert(lines, "")
+    table.insert(lines, string.format("%-3s %-20s %-10s %s", "Mod", "Name", "Size", "File"))
+    table.insert(lines, string.format("%-3s %-20s %-10s %s", "---", "----", "----", "----"))
 
     for i, info in ipairs(buffer_info) do
-        local modified = info.modified and "[+]" or "   "
+        local modified = info.modified and " * " or "   "
         local filepath = ""
         if info.filepath then
             filepath = tostring(info.filepath)
         end
 
-        local line = string.format("%s %-20s %5d lines   %s",
+        local line = string.format("%s %-20s %-10d %s",
             modified,
             info.name,
             info.size,
@@ -759,38 +761,23 @@ bind_key("C-x C-b", function()
         table.insert(lines, line)
     end
 
-    -- Create a new buffer for the list
     local list_text = table.concat(lines, "\n")
-
-    -- For now, just show in message (full buffer list implementation would create a special buffer)
-    -- This is a simple version that shows the list in a new buffer
-    local current_buf_name = editor.buffer:name()
-
-    -- Try to find or create the *Buffer List* buffer
-    local list_buf = editor:get_buffer_by_name("*Buffer List*")
-    if not list_buf then
-        -- Create a new buffer for buffer list
-        editor:new_buffer("*Buffer List*")
-        local buf = editor.buffer
-
-        -- Clear buffer and insert list
-        buf:clear_styles()
-        -- Insert the formatted text
-        local cursor = editor.cursor
-        buf:insert(cursor, list_text)
-
-        message(string.format("Buffer list (%d buffers)", #buffer_info))
+    local list_buf_name = "*Buffer List*"
+    
+    -- Switch to or create buffer
+    local list_buf = editor:get_buffer_by_name(list_buf_name)
+    if list_buf then
+        editor:switch_buffer_in_window(list_buf_name)
     else
-        -- Switch to existing buffer list
-        editor:switch_buffer_in_window("*Buffer List*")
-
-        -- Update the content
-        local buf = editor.buffer
-        -- Clear and reinsert (simple approach)
-        -- In a full implementation, we'd replace the content properly
-
-        message("Showing buffer list")
+        editor:new_buffer(list_buf_name)
     end
+    
+    local buf = editor.buffer
+    buf:clear()
+    buf:insert(lumacs.Position(0,0), list_text)
+    editor:goto_beginning()
+    
+    message(string.format("Buffer list (%d buffers)", #buffer_info))
 end)
 
 -- Test control keys (ncurses versions)

+ 1 - 0
src/lua_api.cpp

@@ -230,6 +230,7 @@ void LuaApi::register_types() {
         "erase_char", &Buffer::erase_char,
         "replace", &Buffer::replace,
         "find", &Buffer::find,
+        "clear", &Buffer::clear,
         "save", &Buffer::save,
         // Styling methods
         "set_style", &Buffer::set_style,

+ 31 - 1
src/main_ncurses.cpp

@@ -135,7 +135,8 @@ private:
         Command,       // Minibuffer entry
         FindFile,      // Find file prompt
         BufferSwitch,  // Buffer switching with completion
-        KillBuffer     // Kill buffer with completion
+        KillBuffer,    // Kill buffer with completion
+        ConfirmKill    // Confirm killing modified buffer
     };
     
     std::unique_ptr<EditorCore> core_;
@@ -280,6 +281,26 @@ private:
     }
 
     bool handle_input(int ch) {
+        // Handle confirmation mode
+        if (mode_ == Mode::ConfirmKill) {
+            if (ch == 'y' || ch == 'Y') {
+                if (core_->close_buffer(command_buffer_)) {
+                    message_line_ = "Closed modified buffer: " + command_buffer_;
+                } else {
+                    message_line_ = "Failed to close buffer";
+                }
+                mode_ = Mode::Normal;
+                command_buffer_.clear();
+                reset_completion();
+            } else if (ch == 'n' || ch == 'N' || ch == 27) { // n or ESC
+                mode_ = Mode::Normal;
+                message_line_ = "Cancelled kill buffer";
+                command_buffer_.clear();
+                reset_completion();
+            }
+            return true;
+        }
+
         // Handle minibuffer/command mode
         if (mode_ == Mode::Command || mode_ == Mode::FindFile ||
             mode_ == Mode::BufferSwitch || mode_ == Mode::KillBuffer) {
@@ -333,6 +354,14 @@ private:
                         message_line_ = "Buffer not found: " + command_buffer_;
                     }
                 } else if (mode_ == Mode::KillBuffer) {
+                    // Check for modification
+                    auto buf = core_->get_buffer_by_name(command_buffer_);
+                    if (buf && buf->is_modified()) {
+                        mode_ = Mode::ConfirmKill;
+                        message_line_ = "Buffer modified! Kill anyway? (y/n)";
+                        return true;
+                    }
+
                     if (core_->close_buffer(command_buffer_)) {
                         message_line_ = "Closed buffer: " + command_buffer_;
                     } else {
@@ -818,6 +847,7 @@ private:
         else if (mode_ == Mode::FindFile) status += " [FILE]";
         else if (mode_ == Mode::BufferSwitch) status += " [BUFFER]";
         else if (mode_ == Mode::KillBuffer) status += " [KILL]";
+        else if (mode_ == Mode::ConfirmKill) status += " [CONFIRM]";
 
         mvprintw(status_y, 0, "%s", status.c_str());
         attroff(A_REVERSE);

+ 12 - 0
tests/test_buffer.cpp

@@ -52,6 +52,18 @@ TEST(Buffer_Find_MultiLine) {
     ASSERT_EQ(static_cast<size_t>(0), res->start.column);
 }
 
+TEST(Buffer_Clear) {
+    Buffer b("test");
+    b.insert({0, 0}, "Hello World\nLine 2");
+    ASSERT_EQ(static_cast<size_t>(2), b.line_count());
+    
+    b.clear();
+    
+    ASSERT_EQ(static_cast<size_t>(1), b.line_count());
+    ASSERT_EQ(std::string(""), b.content());
+    ASSERT_TRUE(b.is_modified());
+}
+
 int main() {
     return TestRunner::instance().run_all();
 }