|
|
@@ -16,41 +16,31 @@
|
|
|
namespace lumacs {
|
|
|
|
|
|
EditorCore::EditorCore() :
|
|
|
- // root_node_(), // Managed by WindowManager
|
|
|
- // active_window_(), // Managed by WindowManager
|
|
|
last_message_(),
|
|
|
message_clear_time_(),
|
|
|
event_callbacks_(),
|
|
|
- // kill_ring_(), // Managed by KillRingManager
|
|
|
last_yank_start_(),
|
|
|
last_yank_end_(),
|
|
|
- // registers_(), // Managed by RegisterManager
|
|
|
- // current_macro_(), // Managed by MacroManager
|
|
|
- // last_macro_(), // Managed by MacroManager
|
|
|
- // recording_macro_(false), // Managed by MacroManager
|
|
|
- // rectangle_kill_ring_(), // Managed by RectangleManager
|
|
|
theme_manager_(),
|
|
|
config_(),
|
|
|
- // Subsystem initializations - order matters for dependencies
|
|
|
- lua_api_(std::make_unique<LuaApi>()), // LuaApi is a dependency for PluginManager and MinibufferManager
|
|
|
- completion_system_(std::make_unique<CompletionSystem>(*this)), // CompletionSystem is a dependency for MinibufferManager
|
|
|
- minibuffer_manager_(std::make_unique<MinibufferManager>(*this, *lua_api_, *completion_system_)), // MinibufferManager is a dependency for CommandSystem
|
|
|
- command_system_(std::make_unique<CommandSystem>(*this, *minibuffer_manager_)), // CommandSystem is a dependency for KeyBindingManager
|
|
|
- keybinding_manager_(std::make_unique<KeyBindingManager>(*command_system_)), // KeyBindingManager needs CommandSystem
|
|
|
- plugin_manager_(std::make_unique<PluginManager>(*this, *lua_api_)), // PluginManager needs EditorCore and LuaApi
|
|
|
- buffer_manager_(std::make_unique<BufferManager>(*this)), // BufferManager needs EditorCore
|
|
|
- window_manager_(std::make_unique<WindowManager>(*this)), // WindowManager needs EditorCore and BufferManager (implicitly via EditorCore)
|
|
|
- kill_ring_manager_(std::make_unique<KillRingManager>()), // KillRingManager is simple, no dependencies here
|
|
|
- register_manager_(std::make_unique<RegisterManager>()), // RegisterManager is simple
|
|
|
- macro_manager_(std::make_unique<MacroManager>(*this)), // MacroManager needs EditorCore
|
|
|
- rectangle_manager_(std::make_unique<RectangleManager>(*this)) // RectangleManager needs EditorCore
|
|
|
+ modeline_manager_member_(), // Direct member
|
|
|
+ // Subsystem initializations - order matters for dependencies based on member declaration order in .hpp
|
|
|
+ // Corrected Order based on dependencies and declaration order:
|
|
|
+ lua_api_(std::make_unique<LuaApi>()),
|
|
|
+ completion_system_(std::make_unique<CompletionSystem>(*this)),
|
|
|
+ minibuffer_manager_(std::make_unique<MinibufferManager>(*this, *lua_api_, *completion_system_)),
|
|
|
+ command_system_(std::make_unique<CommandSystem>(*this, *minibuffer_manager_)),
|
|
|
+ keybinding_manager_(std::make_unique<KeyBindingManager>(command_system_.get())), // Pass raw pointer
|
|
|
+ plugin_manager_(std::make_unique<PluginManager>(*this, *lua_api_)),
|
|
|
+ buffer_manager_(std::make_unique<BufferManager>(*this)),
|
|
|
+ window_manager_(std::make_unique<WindowManager>(*this)),
|
|
|
+ kill_ring_manager_(std::make_unique<KillRingManager>()),
|
|
|
+ register_manager_(std::make_unique<RegisterManager>()),
|
|
|
+ macro_manager_(std::make_unique<MacroManager>(*this)),
|
|
|
+ rectangle_manager_(std::make_unique<RectangleManager>(*this))
|
|
|
{
|
|
|
// LuaApi needs core_ pointer to be valid, so set it after constructor body starts
|
|
|
lua_api_->set_core(*this);
|
|
|
-
|
|
|
- // Initial buffer and window creation is now managed by BufferManager and WindowManager.
|
|
|
- // The WindowManager constructor will create the initial window and assign it a buffer
|
|
|
- // using the BufferManager.
|
|
|
|
|
|
// Initialize themes
|
|
|
theme_manager_.create_default_themes();
|
|
|
@@ -62,83 +52,39 @@ EditorCore::EditorCore() :
|
|
|
|
|
|
EditorCore::~EditorCore() = default;
|
|
|
|
|
|
-// === Window Management (Delegated to WindowManager) ===
|
|
|
-
|
|
|
-// These are still in EditorCore because they are part of the ICommandTarget interface
|
|
|
-// but their implementation delegates to WindowManager.
|
|
|
-
|
|
|
-/*
|
|
|
-// Helper to recursively replace a window in the tree (Moved to WindowManager)
|
|
|
-bool replace_window_node(...) { ... }
|
|
|
-
|
|
|
-// Recursive parent finder (Moved to WindowManager)
|
|
|
-LayoutNode* find_parent_of_node(...) { ... }
|
|
|
-
|
|
|
-// Recursive leaf finder (Moved to WindowManager)
|
|
|
-LayoutNode* find_node_with_window(...) { ... }
|
|
|
-*/
|
|
|
-
|
|
|
-void EditorCore::split_horizontally() {
|
|
|
- window_manager_->split_horizontally();
|
|
|
-}
|
|
|
-
|
|
|
-void EditorCore::split_vertically() {
|
|
|
- window_manager_->split_vertically();
|
|
|
-}
|
|
|
-
|
|
|
-void EditorCore::close_active_window() {
|
|
|
- window_manager_->close_active_window();
|
|
|
-}
|
|
|
-
|
|
|
-void EditorCore::collect_windows(LayoutNode* node, std::vector<std::shared_ptr<Window>>& windows) {
|
|
|
- window_manager_->collect_windows(node, windows);
|
|
|
-}
|
|
|
-
|
|
|
-void EditorCore::next_window() {
|
|
|
- window_manager_->next_window();
|
|
|
-}
|
|
|
-
|
|
|
-void EditorCore::next_window_safe() {
|
|
|
- next_window();
|
|
|
-}
|
|
|
-
|
|
|
-bool EditorCore::set_active_window(std::shared_ptr<Window> window) {
|
|
|
- return window_manager_->set_active_window(window);
|
|
|
-}
|
|
|
-
|
|
|
// === Cursor Proxies ===
|
|
|
|
|
|
Position EditorCore::cursor() const noexcept {
|
|
|
- return active_window()->cursor(); // Uses delegated active_window()
|
|
|
+ return window_manager_->active_window()->cursor();
|
|
|
}
|
|
|
|
|
|
void EditorCore::set_cursor(Position pos) {
|
|
|
- active_window()->set_cursor(pos); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(pos);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
|
|
|
void EditorCore::move_up() {
|
|
|
- active_window()->move_up();
|
|
|
+ window_manager_->active_window()->move_up();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
void EditorCore::move_down() {
|
|
|
- active_window()->move_down();
|
|
|
+ window_manager_->active_window()->move_down();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
void EditorCore::move_left() {
|
|
|
- active_window()->move_left();
|
|
|
+ window_manager_->active_window()->move_left();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
void EditorCore::move_right() {
|
|
|
- active_window()->move_right();
|
|
|
+ window_manager_->active_window()->move_right();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
void EditorCore::move_to_line_start() {
|
|
|
- active_window()->move_to_line_start();
|
|
|
+ window_manager_->active_window()->move_to_line_start();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
void EditorCore::move_to_line_end() {
|
|
|
- active_window()->move_to_line_end();
|
|
|
+ window_manager_->active_window()->move_to_line_end();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
|
|
|
@@ -149,20 +95,20 @@ static bool is_word_char(char c) {
|
|
|
}
|
|
|
|
|
|
void EditorCore::move_forward_word() {
|
|
|
- auto new_pos = calculate_forward_word_pos(active_window()->cursor());
|
|
|
- active_window()->set_cursor(new_pos);
|
|
|
+ auto new_pos = calculate_forward_word_pos(window_manager_->active_window()->cursor());
|
|
|
+ window_manager_->active_window()->set_cursor(new_pos);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
|
|
|
void EditorCore::move_backward_word() {
|
|
|
- auto new_pos = calculate_backward_word_pos(active_window()->cursor());
|
|
|
- active_window()->set_cursor(new_pos);
|
|
|
+ auto new_pos = calculate_backward_word_pos(window_manager_->active_window()->cursor());
|
|
|
+ window_manager_->active_window()->set_cursor(new_pos);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
|
|
|
Position EditorCore::calculate_forward_word_pos(Position start_pos) {
|
|
|
// Delegates to active buffer
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
auto cursor = start_pos;
|
|
|
|
|
|
// Check if we are at the end of buffer
|
|
|
@@ -204,7 +150,7 @@ Position EditorCore::calculate_forward_word_pos(Position start_pos) {
|
|
|
|
|
|
Position EditorCore::calculate_backward_word_pos(Position start_pos) {
|
|
|
// Delegates to active buffer
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
auto cursor = start_pos;
|
|
|
|
|
|
// Skip whitespace and punctuation backwards
|
|
|
@@ -237,8 +183,8 @@ Position EditorCore::calculate_backward_word_pos(Position start_pos) {
|
|
|
}
|
|
|
|
|
|
void EditorCore::page_up() {
|
|
|
- auto& viewport = active_window()->viewport(); // Uses delegated active_window()
|
|
|
- auto cursor = active_window()->cursor(); // Uses delegated active_window()
|
|
|
+ auto& viewport = window_manager_->active_window()->viewport();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
|
|
|
// Move up by viewport height (minus 2 for overlap)
|
|
|
int page_size = std::max(1, viewport.height - 2);
|
|
|
@@ -250,20 +196,20 @@ void EditorCore::page_up() {
|
|
|
}
|
|
|
|
|
|
// Keep column position if possible
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
const auto& line = buf.line(cursor.line);
|
|
|
cursor.column = std::min(cursor.column, line.size());
|
|
|
|
|
|
- active_window()->set_cursor(cursor); // Uses delegated active_window()
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(cursor);
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
void EditorCore::page_down() {
|
|
|
- auto& viewport = active_window()->viewport(); // Uses delegated active_window()
|
|
|
- auto cursor = active_window()->cursor(); // Uses delegated active_window()
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& viewport = window_manager_->active_window()->viewport();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
|
|
|
// Move down by viewport height (minus 2 for overlap)
|
|
|
int page_size = std::max(1, viewport.height - 2);
|
|
|
@@ -274,39 +220,39 @@ void EditorCore::page_down() {
|
|
|
const auto& line = buf.line(cursor.line);
|
|
|
cursor.column = std::min(cursor.column, line.size());
|
|
|
|
|
|
- active_window()->set_cursor(cursor); // Uses delegated active_window()
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(cursor);
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
void EditorCore::goto_beginning() {
|
|
|
Position pos = {0, 0};
|
|
|
- active_window()->set_cursor(pos); // Uses delegated active_window()
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(pos);
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
void EditorCore::goto_end() {
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
size_t last_line = buf.line_count() > 0 ? buf.line_count() - 1 : 0;
|
|
|
size_t last_col = buf.line(last_line).size();
|
|
|
Position pos = {last_line, last_col};
|
|
|
|
|
|
- active_window()->set_cursor(pos); // Uses delegated active_window()
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(pos);
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
void EditorCore::goto_line(size_t line) {
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
line = std::min(line, buf.line_count() > 0 ? buf.line_count() - 1 : 0); // Clamp to max line index
|
|
|
Position pos = {line, 0};
|
|
|
|
|
|
- active_window()->set_cursor(pos); // Uses delegated active_window()
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(pos);
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
@@ -314,32 +260,32 @@ void EditorCore::goto_line(size_t line) {
|
|
|
// === Viewport Management (Proxies to active window) ===
|
|
|
|
|
|
const Viewport& EditorCore::viewport() const noexcept {
|
|
|
- return active_window()->viewport(); // Uses delegated active_window()
|
|
|
+ return window_manager_->active_window()->viewport();
|
|
|
}
|
|
|
|
|
|
void EditorCore::set_viewport_size(int width, int height) {
|
|
|
- active_window()->set_viewport_size(width, height); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_viewport_size(width, height);
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
void EditorCore::adjust_scroll() {
|
|
|
- active_window()->adjust_scroll(); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->adjust_scroll();
|
|
|
emit_event(EditorEvent::ViewportChanged);
|
|
|
}
|
|
|
|
|
|
std::pair<size_t, size_t> EditorCore::visible_line_range() const {
|
|
|
- return active_window()->visible_line_range(); // Uses delegated active_window()
|
|
|
+ return window_manager_->active_window()->visible_line_range();
|
|
|
}
|
|
|
|
|
|
// === Undo/Redo ===
|
|
|
|
|
|
bool EditorCore::undo() {
|
|
|
- auto& buf = buffer();
|
|
|
- buf.save_undo_state(active_window()->cursor()); // Uses delegated active_window()
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ buf.save_undo_state(window_manager_->active_window()->cursor());
|
|
|
|
|
|
- Position new_cursor = active_window()->cursor(); // Uses delegated active_window()
|
|
|
+ Position new_cursor = window_manager_->active_window()->cursor();
|
|
|
if (buf.undo(new_cursor)) {
|
|
|
- active_window()->set_cursor(new_cursor); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(new_cursor);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
return true;
|
|
|
@@ -348,10 +294,10 @@ bool EditorCore::undo() {
|
|
|
}
|
|
|
|
|
|
bool EditorCore::redo() {
|
|
|
- auto& buf = buffer();
|
|
|
- Position new_cursor = active_window()->cursor(); // Uses delegated active_window()
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ Position new_cursor = window_manager_->active_window()->cursor();
|
|
|
if (buf.redo(new_cursor)) {
|
|
|
- active_window()->set_cursor(new_cursor); // Uses delegated active_window()
|
|
|
+ window_manager_->active_window()->set_cursor(new_cursor);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
return true;
|
|
|
@@ -360,56 +306,52 @@ bool EditorCore::redo() {
|
|
|
}
|
|
|
|
|
|
bool EditorCore::can_undo() const {
|
|
|
- return buffer().can_undo();
|
|
|
+ return buffer_manager_->active_buffer()->can_undo();
|
|
|
}
|
|
|
|
|
|
bool EditorCore::can_redo() const {
|
|
|
- return buffer().can_redo();
|
|
|
+ return buffer_manager_->active_buffer()->can_redo();
|
|
|
}
|
|
|
|
|
|
// === Kill Ring (Delegated to KillRingManager) ===
|
|
|
|
|
|
void EditorCore::kill_line() {
|
|
|
- auto& buf = buffer();
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
- const auto& line = buf.line(cursor.line);
|
|
|
-
|
|
|
- // If at end of line, kill the newline (join with next line)
|
|
|
- if (cursor.column >= line.size()) {
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
+ const auto& line_text = buf.line(cursor.line);
|
|
|
+
|
|
|
+ Range range_to_kill;
|
|
|
+ std::string killed_text;
|
|
|
+
|
|
|
+ if (cursor.column == 0 && cursor.line < buf.line_count() - 1) {
|
|
|
+ // Kill whole line including newline
|
|
|
+ range_to_kill = {{cursor.line, 0}, {cursor.line + 1, 0}};
|
|
|
+ } else if (cursor.column < line_text.size()) {
|
|
|
+ // Kill from cursor to end of line
|
|
|
+ range_to_kill = {cursor, {cursor.line, line_text.size()}};
|
|
|
+ } else { // Cursor is at or past end of line
|
|
|
if (cursor.line < buf.line_count() - 1) {
|
|
|
- // Kill the newline character
|
|
|
- Position start = {cursor.line, line.size()};
|
|
|
- Position end = {cursor.line + 1, 0};
|
|
|
- Range range = {start, end};
|
|
|
-
|
|
|
- kill_ring_manager_->push("\n"); // Delegate to manager
|
|
|
-
|
|
|
- buf.erase(range);
|
|
|
- emit_event(EditorEvent::BufferModified);
|
|
|
-
|
|
|
- std::cerr << "[DEBUG] Killed newline at end of line " << cursor.line << std::endl;
|
|
|
+ // Kill only the newline (join with next line)
|
|
|
+ range_to_kill = {{cursor.line, line_text.size()}, {cursor.line + 1, 0}};
|
|
|
+ } else {
|
|
|
+ // At end of last line, nothing to kill
|
|
|
+ return;
|
|
|
}
|
|
|
- return;
|
|
|
}
|
|
|
|
|
|
- // Kill from cursor to end of line
|
|
|
- Position start = cursor;
|
|
|
- Position end = {cursor.line, line.size()};
|
|
|
- Range range = {start, end};
|
|
|
-
|
|
|
- std::string killed_text = buf.get_text_in_range(range);
|
|
|
+ killed_text = buf.get_text_in_range(range_to_kill); // Get text BEFORE erase
|
|
|
if (!killed_text.empty()) {
|
|
|
- kill_ring_manager_->push(killed_text); // Delegate to manager
|
|
|
- buf.erase(range);
|
|
|
+ kill_ring_manager_->push(killed_text);
|
|
|
+ buf.erase(range_to_kill);
|
|
|
+ // Cursor position does not change after kill-line; it remains at the beginning of the killed region.
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
-
|
|
|
- std::cerr << "[DEBUG] Killed text: '" << killed_text << "'" << std::endl;
|
|
|
+ emit_event(EditorEvent::CursorMoved);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
void EditorCore::kill_region() {
|
|
|
- auto& buf = buffer();
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
|
|
|
auto region = buf.get_region(cursor);
|
|
|
if (!region.has_value()) {
|
|
|
@@ -423,7 +365,7 @@ void EditorCore::kill_region() {
|
|
|
buf.deactivate_mark();
|
|
|
|
|
|
// Move cursor to start of killed region
|
|
|
- active_window()->set_cursor(region.value().start);
|
|
|
+ window_manager_->active_window()->set_cursor(region.value().start);
|
|
|
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
@@ -433,13 +375,13 @@ void EditorCore::kill_region() {
|
|
|
}
|
|
|
|
|
|
void EditorCore::kill_word() {
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
auto end_pos = calculate_forward_word_pos(cursor);
|
|
|
|
|
|
if (cursor == end_pos) return;
|
|
|
|
|
|
Range range = {cursor, end_pos};
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
std::string text = buf.get_text_in_range(range);
|
|
|
|
|
|
if (!text.empty()) {
|
|
|
@@ -451,19 +393,19 @@ void EditorCore::kill_word() {
|
|
|
}
|
|
|
|
|
|
void EditorCore::backward_kill_word() {
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
auto start_pos = calculate_backward_word_pos(cursor);
|
|
|
|
|
|
if (cursor == start_pos) return;
|
|
|
|
|
|
Range range = {start_pos, cursor};
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
std::string text = buf.get_text_in_range(range);
|
|
|
|
|
|
if (!text.empty()) {
|
|
|
kill_ring_manager_->push(text); // Delegate to manager
|
|
|
buf.erase(range);
|
|
|
- active_window()->set_cursor(start_pos);
|
|
|
+ window_manager_->active_window()->set_cursor(start_pos);
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
std::cerr << "[DEBUG] Backward killed word: '" << text << "'" << std::endl;
|
|
|
@@ -472,8 +414,8 @@ void EditorCore::backward_kill_word() {
|
|
|
|
|
|
|
|
|
void EditorCore::copy_region_as_kill() {
|
|
|
- auto& buf = buffer();
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
|
|
|
auto region = buf.get_region(cursor);
|
|
|
if (!region.has_value()) {
|
|
|
@@ -502,8 +444,8 @@ void EditorCore::yank() {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- auto& buf = buffer();
|
|
|
- auto cursor = active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ auto cursor = window_manager_->active_window()->cursor();
|
|
|
|
|
|
// Save yank start position
|
|
|
last_yank_start_ = cursor;
|
|
|
@@ -528,7 +470,7 @@ void EditorCore::yank() {
|
|
|
}
|
|
|
|
|
|
last_yank_end_ = new_cursor;
|
|
|
- active_window()->set_cursor(new_cursor);
|
|
|
+ window_manager_->active_window()->set_cursor(new_cursor);
|
|
|
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
@@ -548,7 +490,7 @@ void EditorCore::yank_pop() {
|
|
|
}
|
|
|
|
|
|
// Delete the previously yanked text
|
|
|
- auto& buf = buffer();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
Range yank_range = {last_yank_start_.value(), last_yank_end_.value()};
|
|
|
buf.erase(yank_range);
|
|
|
|
|
|
@@ -557,7 +499,7 @@ void EditorCore::yank_pop() {
|
|
|
|
|
|
// Restore cursor to yank start
|
|
|
auto cursor = last_yank_start_.value();
|
|
|
- active_window()->set_cursor(cursor);
|
|
|
+ window_manager_->active_window()->set_cursor(cursor);
|
|
|
|
|
|
// Insert new text
|
|
|
buf.insert(cursor, text);
|
|
|
@@ -575,7 +517,7 @@ void EditorCore::yank_pop() {
|
|
|
}
|
|
|
|
|
|
last_yank_end_ = new_cursor;
|
|
|
- active_window()->set_cursor(new_cursor);
|
|
|
+ window_manager_->active_window()->set_cursor(new_cursor);
|
|
|
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
@@ -609,8 +551,8 @@ bool EditorCore::insert_register(char register_name) {
|
|
|
}
|
|
|
std::string text = text_opt.value();
|
|
|
|
|
|
- auto& buf = buffer();
|
|
|
- Position cursor = active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ Position cursor = window_manager_->active_window()->cursor();
|
|
|
buf.insert(cursor, text);
|
|
|
|
|
|
// Move cursor to end of inserted text
|
|
|
@@ -623,7 +565,7 @@ bool EditorCore::insert_register(char register_name) {
|
|
|
cursor.column += text.size();
|
|
|
}
|
|
|
|
|
|
- active_window()->set_cursor(cursor);
|
|
|
+ window_manager_->active_window()->set_cursor(cursor);
|
|
|
emit_event(EditorEvent::BufferModified);
|
|
|
emit_event(EditorEvent::CursorMoved);
|
|
|
|
|
|
@@ -632,8 +574,8 @@ bool EditorCore::insert_register(char register_name) {
|
|
|
}
|
|
|
|
|
|
void EditorCore::copy_region_to_register(char register_name) {
|
|
|
- auto& buf = buffer();
|
|
|
- Position cursor = active_window()->cursor();
|
|
|
+ auto& buf = *buffer_manager_->active_buffer();
|
|
|
+ Position cursor = window_manager_->active_window()->cursor();
|
|
|
|
|
|
auto region = buf.get_region(cursor);
|
|
|
if (!region) {
|
|
|
@@ -677,6 +619,48 @@ void EditorCore::string_rectangle(const std::string& text) {
|
|
|
rectangle_manager_->string_rectangle(text);
|
|
|
}
|
|
|
|
|
|
+// === Helper Implementation ===
|
|
|
+
|
|
|
+void EditorCore::collect_windows(LayoutNode* node, std::vector<std::shared_ptr<Window>>& windows) {
|
|
|
+ if (!node) return;
|
|
|
+ if (node->type == LayoutNode::Type::Leaf && node->window) {
|
|
|
+ windows.push_back(node->window);
|
|
|
+ } else {
|
|
|
+ collect_windows(node->child1.get(), windows);
|
|
|
+ collect_windows(node->child2.get(), windows);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void EditorCore::set_message(std::string msg) {
|
|
|
+ last_message_ = std::move(msg);
|
|
|
+ message_clear_time_ = std::chrono::steady_clock::now() + std::chrono::seconds(3);
|
|
|
+ emit_event(EditorEvent::Message);
|
|
|
+}
|
|
|
+
|
|
|
+void EditorCore::check_and_clear_message() {
|
|
|
+ if (message_clear_time_.has_value() && std::chrono::steady_clock::now() > message_clear_time_.value()) {
|
|
|
+ last_message_.clear();
|
|
|
+ message_clear_time_.reset();
|
|
|
+ emit_event(EditorEvent::TransientMessageCleared);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void EditorCore::request_quit() {
|
|
|
+ emit_event(EditorEvent::Quit);
|
|
|
+}
|
|
|
+
|
|
|
+bool EditorCore::is_recording_macro() const noexcept {
|
|
|
+ return macro_manager_->is_recording_macro();
|
|
|
+}
|
|
|
+
|
|
|
+void EditorCore::enter_command_mode() { emit_event(EditorEvent::CommandMode); }
|
|
|
+void EditorCore::enter_buffer_switch_mode() { emit_event(EditorEvent::BufferSwitchMode); }
|
|
|
+void EditorCore::enter_kill_buffer_mode() { emit_event(EditorEvent::KillBufferMode); }
|
|
|
+void EditorCore::enter_find_file_mode() { emit_event(EditorEvent::FindFileMode); }
|
|
|
+void EditorCore::enter_theme_selection_mode() { emit_event(EditorEvent::ThemeSelectionMode); }
|
|
|
+void EditorCore::enter_isearch_mode() { emit_event(EditorEvent::ISearchMode); }
|
|
|
+void EditorCore::enter_isearch_backward_mode() { emit_event(EditorEvent::ISearchBackwardMode); }
|
|
|
+
|
|
|
// === Private ===
|
|
|
|
|
|
void EditorCore::emit_event(EditorEvent event) {
|
|
|
@@ -685,4 +669,4 @@ void EditorCore::emit_event(EditorEvent event) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-} // namespace lumacs
|
|
|
+} // namespace lumacs
|