buffer_manager.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #include "lumacs/buffer_manager.hpp"
  2. #include "lumacs/editor_core.hpp" // For EditorCore access
  3. #include <algorithm>
  4. #include <iostream> // TODO: Replace with proper logging
  5. namespace lumacs {
  6. BufferManager::BufferManager(EditorCore& core) : core_(core) {
  7. }
  8. std::shared_ptr<Buffer> BufferManager::create_buffer_no_window(std::string name) {
  9. // Check if a buffer with this name already exists
  10. auto existing_buf = get_buffer_by_name(name);
  11. if (existing_buf) {
  12. return existing_buf;
  13. }
  14. auto new_buf = std::make_shared<Buffer>(std::move(name));
  15. buffers_.push_back(new_buf);
  16. return new_buf;
  17. }
  18. void BufferManager::new_buffer(std::string name) {
  19. auto new_buf = create_buffer_no_window(std::move(name));
  20. // Set this new buffer in the active window
  21. if (core_.active_window()) {
  22. core_.active_window()->set_buffer(new_buf);
  23. } else {
  24. // This case should ideally not happen if EditorCore initializes properly
  25. // For robustness, create a default window if none exists
  26. std::cerr << "[ERROR] No active window to set new buffer. This should not happen." << std::endl;
  27. }
  28. core_.emit_event(EditorEvent::BufferModified);
  29. core_.emit_event(EditorEvent::CursorMoved);
  30. core_.emit_event(EditorEvent::ViewportChanged);
  31. }
  32. bool BufferManager::load_file(const std::filesystem::path& path) {
  33. std::filesystem::path abs_path = std::filesystem::absolute(path);
  34. // Check if already open
  35. for (const auto& buf : buffers_) {
  36. if (buf->file_path() && std::filesystem::equivalent(*buf->file_path(), abs_path)) {
  37. if (core_.active_window()) {
  38. core_.active_window()->set_buffer(buf);
  39. }
  40. core_.emit_event(EditorEvent::BufferModified);
  41. core_.emit_event(EditorEvent::CursorMoved);
  42. core_.emit_event(EditorEvent::ViewportChanged);
  43. return true;
  44. }
  45. }
  46. auto new_buffer_opt = Buffer::from_file(abs_path);
  47. if (!new_buffer_opt) {
  48. return false;
  49. }
  50. auto new_buffer = std::make_shared<Buffer>(std::move(*new_buffer_opt));
  51. buffers_.push_back(new_buffer);
  52. if (core_.active_window()) {
  53. core_.active_window()->set_buffer(new_buffer);
  54. }
  55. core_.emit_event(EditorEvent::BufferModified);
  56. core_.emit_event(EditorEvent::CursorMoved);
  57. core_.emit_event(EditorEvent::ViewportChanged);
  58. return true;
  59. }
  60. bool BufferManager::switch_buffer_in_window(const std::string& name) {
  61. auto buf = get_buffer_by_name(name);
  62. if (!buf) {
  63. return false;
  64. }
  65. if (core_.active_window()) {
  66. core_.active_window()->set_buffer(buf);
  67. }
  68. core_.emit_event(EditorEvent::BufferModified);
  69. core_.emit_event(EditorEvent::CursorMoved);
  70. core_.emit_event(EditorEvent::ViewportChanged);
  71. return true;
  72. }
  73. bool BufferManager::close_buffer(const std::string& name) {
  74. auto buf_to_close = get_buffer_by_name(name);
  75. if (!buf_to_close) {
  76. return false;
  77. }
  78. // Cannot close buffer if it's the only one
  79. if (buffers_.size() <= 1) {
  80. core_.set_message("Cannot close last buffer");
  81. return false;
  82. }
  83. // Check if buffer is displayed in any window and switch it
  84. std::vector<std::shared_ptr<Window>> windows;
  85. // Need a way for BufferManager to access all windows.
  86. // EditorCore should provide this functionality.
  87. core_.collect_windows(core_.root_layout().get(), windows); // Assuming EditorCore has this helper
  88. for (const auto& win : windows) {
  89. if (win->buffer_ptr() == buf_to_close) {
  90. // Find another buffer to switch to
  91. auto other_buf_it = std::find_if(buffers_.begin(), buffers_.end(),
  92. [&](const std::shared_ptr<Buffer>& b) { return b != buf_to_close; });
  93. if (other_buf_it != buffers_.end()) {
  94. win->set_buffer(*other_buf_it);
  95. } else {
  96. // This scenario should be prevented by the buffers_.size() <= 1 check
  97. std::cerr << "[ERROR] No other buffer found to switch to after closing." << std::endl;
  98. return false;
  99. }
  100. }
  101. }
  102. // Remove buffer from list
  103. buffers_.remove(buf_to_close);
  104. core_.emit_event(EditorEvent::BufferModified);
  105. core_.emit_event(EditorEvent::CursorMoved);
  106. core_.emit_event(EditorEvent::ViewportChanged);
  107. return true;
  108. }
  109. std::shared_ptr<Buffer> BufferManager::active_buffer() {
  110. if (core_.active_window()) {
  111. return core_.active_window()->buffer_ptr();
  112. }
  113. return nullptr; // Should not happen in a well-initialized editor
  114. }
  115. std::shared_ptr<Buffer> BufferManager::get_buffer_by_name(const std::string& name) const {
  116. for (const auto& buf : buffers_) {
  117. if (buf->name() == name) {
  118. return buf;
  119. }
  120. }
  121. return nullptr;
  122. }
  123. std::vector<std::string> BufferManager::get_buffer_names() const {
  124. std::vector<std::string> names;
  125. names.reserve(buffers_.size());
  126. for (const auto& buf : buffers_) {
  127. names.push_back(buf->name());
  128. }
  129. return names;
  130. }
  131. std::vector<BufferManager::BufferInfo> BufferManager::get_all_buffer_info() const {
  132. std::vector<BufferInfo> info;
  133. info.reserve(buffers_.size());
  134. for (const auto& buf : buffers_) {
  135. BufferInfo bi;
  136. bi.name = buf->name();
  137. bi.size = buf->line_count();
  138. bi.modified = buf->is_modified();
  139. bi.mode = "fundamental-mode"; // TODO: Get actual mode from buffer
  140. bi.filepath = buf->file_path();
  141. info.push_back(bi);
  142. }
  143. return info;
  144. }
  145. } // namespace lumacs