Ver Fonte

docs: Update architecture and add Lua tutorial

- Updated ARCHITECTURE.md to reflect the modular architecture, interfaces, rendering cache, and confirmed Lua API structure.
- Created documentation/LUA_TUTORIAL.md providing a comprehensive guide on extending the editor with Lua, now accurately documenting the available 'editor.buffer' API.
Bernardo Magri há 1 mês atrás
pai
commit
a440c8b426
2 ficheiros alterados com 303 adições e 63 exclusões
  1. 96 63
      documentation/ARCHITECTURE.md
  2. 207 0
      documentation/LUA_TUTORIAL.md

+ 96 - 63
documentation/ARCHITECTURE.md

@@ -2,79 +2,112 @@
 
 ## Overview
 
-Lumacs is designed as a modular, extensible editor engine inspired by Emacs. It strictly separates the core logic (buffer management, text editing, key bindings) from the user interface (GTK, TUI).
+Lumacs is a modular, extensible text editor engine inspired by Emacs, written in C++20 and scriptable via Lua 5.4. It strictly separates core logic from the user interface, allowing for multiple frontends (GTK4, TUI).
 
-## High-Level Diagram
+## High-Level Design
+
+The system follows a **Core-Manager-View** architecture. The `EditorCore` acts as the central hub but delegates actual logic to specialized Manager classes. Dependencies are managed via Dependency Injection (DI) and interfaces to prevent circular coupling.
 
 ```mermaid
 graph TD
-    User[User Input] -->|Key/Mouse| UI[UI Frontend]
-    UI -->|Key Event| Lua[Lua API]
-    Lua -->|Key Sequence| KeyBinding[KeyBindingManager]
+    User[User Input] -->|Events| UI[UI Frontend]
+    UI -->|Key Strings| LuaAPI[Lua API]
+    LuaAPI -->|Process| KeyBinding[KeyBindingManager]
     KeyBinding -->|Command Name| CommandSystem[CommandSystem]
-    CommandSystem -->|Action| EditorCore[EditorCore]
-    EditorCore -->|Modify| Buffer[Buffer]
-    EditorCore -->|Modify| Window[Window]
-    EditorCore -->|Event| UI
-    UI -->|Render| Display[Display]
+    CommandSystem -->|Execute| Core[EditorCore]
+    
+    subgraph Core Subsystems
+        Core -->|Delegate| BufferMgr[BufferManager]
+        Core -->|Delegate| WindowMgr[WindowManager]
+        Core -->|Delegate| MinibufferMgr[MinibufferManager]
+        Core -->|Delegate| MacroMgr[MacroManager]
+    end
+    
+    BufferMgr -->|Manage| Buffer[Buffer]
+    WindowMgr -->|Manage| Window[Window]
+    
+    Core -.->|Notify| IEditorNotifier
+    IEditorNotifier -.-> UI
+    
+    UI -->|Render| Renderer[Renderer (GTK/TUI)]
+    Renderer -->|Read| Buffer
 ```
 
 ## Core Components
 
 ### 1. EditorCore (`editor_core.hpp`)
-The central hub of the application. It orchestrates all subsystems and holds the state of the editor.
-- **Responsibilities**: Buffer management, Window layout (splits), Global Kill Ring, Event dispatching.
-- **Dependencies**: `Buffer`, `Window`, `CommandSystem`, `LuaApi`, `ThemeManager`.
-
-### 2. Buffer (`buffer.hpp`)
-Represents a text file or scratch space.
-- **Data**: List of strings (lines), file path, modification flag.
-- **Features**: Gap buffer (conceptually), Styling attributes (syntax highlighting), Undo/Redo stack, Mark/Region.
-
-### 3. Window (`window.hpp`)
-A view into a Buffer.
-- **Data**: Reference to a Buffer, Cursor position, Viewport (scroll offset).
-- **Logic**: Cursor clamping, Scrolling logic.
-
-### 4. Command System (`command_system.hpp`)
-Registry of executable commands.
-- **Features**: Command registration, Execution by name, Argument parsing, Autocompletion providers.
-- **Lua Integration**: Commands can be defined in C++ or Lua.
-
-### 5. Lua API (`lua_api.hpp`)
-Bridge to the Lua 5.4 scripting environment.
-- **Role**: `init.lua` loading, Key binding definitions, Exposing Core API to scripts.
-
-### 6. Modeline Framework (`modeline.hpp`)
-Generates the status line for each window.
-- **Design**: Modular segments (`ModelineSegment`) managed by `ModelineManager`.
+The application root.
+- **Role**: Owner of all Manager subsystems.
+- **Interfaces**: Implements `IEditorNotifier` (events) and `IWindowManager` (layout access).
+- **State**: Holds the global editor configuration and theme manager.
+
+### 2. Managers (The Logic Layer)
+Functionality is partitioned into specialized managers:
+- **`BufferManager`**: Creates, loads, and manages the lifecycle of `Buffer` objects.
+- **`WindowManager`**: Manages the window layout tree (`LayoutNode`), splits, and focus.
+- **`CommandSystem`**: Registry of commands (C++ and Lua). Handles execution and interactive argument reading.
+- **`KeyBindingManager`**: Trie-based key sequence resolution. Maps `C-x C-f` -> `find-file`.
+- **`MinibufferManager`**: Handles the command line / prompt area logic, including completion and interactive search (ISearch).
+- **`MacroManager`**: Records and plays back keyboard macros.
+- **`PluginManager`**: Discovers and loads Lua plugins.
+
+### 3. Data Structures
+- **`Buffer`**: Stores text as a list of strings (Gap Buffer concept abstract). Manages syntax highlighting (`StyledRange`), undo/redo stack, and mark/region.
+- **`Window`**: A view into a buffer. Tracks cursor position (`Position`) and scroll viewport (`Viewport`).
+- **`LayoutNode`**: A node in the binary tree representing window splits.
+
+### 4. Interfaces & Decoupling
+To avoid circular dependencies (e.g., `BufferManager` needing `EditorCore` needing `BufferManager`), we use interfaces:
+- **`IEditorNotifier`**: Allows subsystems to emit events (`BufferModified`, `Message`) without knowing about `EditorCore`.
+- **`IWindowManager`**: Allows `BufferManager` to query window state without depending on the concrete `WindowManager`.
+- **`ICommandTarget`**: Abstract interface for objects that can receive commands.
+- **`IEditorView`**: Abstract base for UI frontends.
+
+### 5. Lua Integration (`lua_api.cpp`)
+- **Binding**: Uses `sol2` to bind C++ classes (`EditorCore`, `Buffer`, `Window`, `Config`, `Theme`) to Lua.
+- **Extension**: `init.lua` implements the "Standard Library" of the editor (Major Modes, default keybindings).
 
 ## User Interface (Frontends)
 
-The UI interacts with the core via the `IEditorView` interface (`ui_interface.hpp`).
-
-### GTK Frontend (`gtk_editor.cpp`)
-- Uses GTK4 and Cairo for rendering.
-- Pango for text layout and font handling.
-- Supports window splits using `Gtk::Paned`.
-
-### TUI Frontend (`tui_editor.cpp`)
-- Uses Ncurses.
-- Fallback for terminal environments.
-
-## Event Loop
-
-1.  **Input**: UI captures input (e.g., `Gtk::EventControllerKey`).
-2.  **Processing**: Input is passed to `LuaApi::process_key`.
-3.  **Binding**: `KeyBindingManager` resolves the sequence to a command.
-4.  **Execution**: `CommandSystem` executes the command.
-5.  **State Change**: Command modifies `Buffer` or `EditorCore` state.
-6.  **Notification**: `EditorCore` emits `EditorEvent` (e.g., `BufferModified`).
-7.  **Rendering**: UI observes the event and requests a redraw.
-
-## Design Patterns
-
-- **Observer**: `IEditorView` observes `EditorCore`.
-- **Factory**: UI creation via factory functions.
-- **Command**: Encapsulated actions in `CommandSystem`.
-- **Composite**: Window layout tree (`LayoutNode`).
+### GTK4 Frontend (`src/ui/`)
+- **`GtkEditor`**: The main application window. Handles input events and forwards them to Core.
+- **`GtkRenderer`**: High-performance text renderer using **Cairo** and **Pango**.
+    - **Caching**: Implements a line-based cache (`Cairo::ImageSurface`) to minimize Pango layout re-computation.
+    - **Layers**: Background -> Cached Text -> Syntax Highlighting -> Selection -> Cursor.
+- **`GtkCompletionPopup`**: A `Gtk::Popover` widget for showing autocompletion candidates.
+
+### TUI Frontend
+- **`TuiEditor`**: Ncurses-based fallback. Renders text grid and handles terminal input sequences.
+
+## Event Flow (The "Golden Path")
+
+1.  **Input**: User presses a key (e.g., `C-f`).
+2.  **Capture**: `GtkEditor` captures the event via `Gtk::EventControllerKey` (Phase: Capture).
+3.  **Normalization**: Key is converted to a string `"C-f"`.
+4.  **Processing**: Passed to `KeyBindingManager::process_key`.
+5.  **Resolution**: Trie traversal finds command `"forward-char"`.
+6.  **Recording**: If macro recording is active, `KeyBindingManager` notifies `MacroManager`.
+7.  **Execution**: `CommandSystem` executes the C++ lambda for `forward-char`.
+8.  **Update**: `EditorCore::move_right` modifies the `Window` cursor.
+9.  **Notification**: `EditorCore` emits `EditorEvent::CursorMoved`.
+10. **Render**: `GtkEditor` receives event, queues redraw. `GtkRenderer` updates the screen.
+
+## Styling System
+
+- **Themes**: JSON-like structures (in C++ or Lua) defining colors for semantic tags (`ThemeElement`).
+- **Faces**: Specific style attributes (foreground, background, bold, italic).
+- **Application**:
+    1.  `Buffer` stores `StyledRange` (semantic tag + range).
+    2.  `GtkRenderer` queries the active `Theme` to map tags to Pango attributes.
+    3.  Pango renders the text with attributes.
+
+## Build System
+
+- **CMake**: Manages build configuration.
+- **Dependencies**:
+    - `gtkmm-4.0` (UI)
+    - `lua` (Scripting)
+    - `sol2` (Bindings)
+    - `spdlog` (Logging)
+    - `ncurses` (TUI)
+    - `gtest` (Testing)

+ 207 - 0
documentation/LUA_TUTORIAL.md

@@ -0,0 +1,207 @@
+# Extending Lumacs with Lua
+
+Lumacs is designed to be deeply extensible via Lua 5.4. Almost every aspect of the editor, from keybindings to major modes, is configured using the Lua API.
+
+## The `editor` Object
+
+The global `editor` object is your gateway to the Lumacs core. It represents the editor application state.
+
+### Core Properties
+- `editor.buffer`: The currently active **Buffer** object (see [Buffer Operations](#buffer-operations)).
+- `editor.cursor`: The current cursor position (`Position`).
+- `editor.config`: The configuration object.
+- `editor.active_theme`: The currently active theme object.
+- `editor.theme_manager`: The manager for loading/selecting themes.
+
+### Core Methods
+- `editor:message(msg)`: Display a message in the minibuffer.
+- `editor:quit()`: Exit the editor.
+- `editor:load_file(path)`: Open a file in a new buffer.
+- `editor:new_buffer(name)`: Create a new scratch buffer.
+- `editor:switch_buffer_in_window(name)`: Switch the current window to a named buffer.
+- `editor:close_buffer(name)`: Close a buffer.
+- `editor:split_horizontally()` / `editor:split_vertically()`: Split the active window.
+- `editor:close_window()`: Close the active window.
+- `editor:next_window()`: Cycle focus to the next window.
+
+## Buffer Operations
+
+The `Buffer` object (accessed via `editor.buffer`) allows you to manipulate text.
+
+```lua
+local buf = editor.buffer
+
+-- Get info
+print(buf:name())
+print(buf:line_count())
+print(buf:filepath()) -- Returns path string or nil if not saved
+print(buf:is_modified())
+
+-- Content Access
+local line_text = buf:line(0) -- Get text of line 0 (0-indexed)
+local full_text = buf:content()
+
+-- Modification
+-- Positions are 0-indexed (line, col)
+local pos = lumacs.Position(0, 0) 
+buf:insert(pos, "Hello World\n")
+
+-- Ranges
+local start_pos = lumacs.Position(0, 0)
+local end_pos = lumacs.Position(0, 5)
+local range = lumacs.Range(start_pos, end_pos)
+buf:erase(range)
+
+-- Styling (Syntax Highlighting)
+-- Apply a 'Keyword' face to the first word
+local attr = lumacs.TextAttribute(lumacs.ColorType.Keyword, 0)
+buf:set_style(range, attr)
+buf:clear_styles()
+```
+
+## Keybindings
+
+You can bind keys to Lua functions or named commands.
+
+### Binding to a Function
+```lua
+editor:bind_key("C-c t", function()
+    editor:message("You pressed Ctrl-c t")
+end, "Test command")
+```
+
+### Binding to a Command
+```lua
+-- Bind F5 to the existing 'save-buffer' command
+editor:bind_key("F5", function()
+    editor:execute_command("save-buffer")
+end)
+```
+
+**Key Syntax:**
+- `C-x`: Control + x
+- `M-x`: Meta (Alt) + x
+- `S-x`: Shift + x
+- `Return`, `Space`, `Backspace`, `Tab`, `Escape`
+- `ArrowUp`, `ArrowDown`, `PageUp`, `PageDown`
+- Function keys: `F1` ... `F12`
+
+## Creating Commands
+
+Commands can be registered and then executed by name (e.g., via `M-x`).
+
+```lua
+-- Register a command named 'hello-world'
+editor:register_command(
+    "hello-world",              -- Command Name
+    "Prints hello",             -- Documentation
+    function(args)              -- Function
+        -- args is a table of strings passed to the command
+        local name = args[1] or "World"
+        editor.buffer:insert(editor.cursor, "Hello " .. name)
+    end,
+    true,                       -- Interactive? (Can show up in M-x)
+    "s"                         -- Interactive Spec (Optional: 's' prompts for string)
+)
+```
+
+## Major Modes
+
+Lumacs uses a "Major Mode" system (implemented in `init.lua`) to configure the editor for specific file types. A Major Mode defines syntax highlighting, keybindings, and setup hooks.
+
+### Defining a Mode
+
+```lua
+define_major_mode("my-lang-mode", {
+    file_patterns = {"%.mylang$"},
+    comment_syntax = "//",
+    
+    -- Setup: Runs when mode is activated
+    setup = function()
+        editor:message("MyLang Mode Active")
+    end,
+
+    -- Syntax Highlighting Logic
+    highlight = function()
+        local buf = editor.buffer
+        buf:clear_styles()
+        
+        -- Scan buffer line by line
+        for i = 0, buf:line_count() - 1 do
+            local line = buf:line(i)
+            
+            -- Find keywords (simple example)
+            if string.find(line, "function") then
+                -- Calculate range and apply style...
+                -- (See init.lua 'lua-mode' for a full regex loop example)
+            end
+        end
+    end,
+
+    -- Mode-specific keybindings
+    keybindings = {
+        ["C-c C-c"] = function() editor:message("Compiling...") end
+    }
+})
+```
+
+## Theming
+
+Themes control the colors of the UI and syntax highlighting.
+
+### Creating a Theme
+Themes are defined by setting colors for `ThemeElement`s.
+
+```lua
+-- Define a new theme function
+function setup_my_theme()
+    local tm = editor.theme_manager
+    
+    -- Set faces for specific semantic tags
+    editor:define_face("default", lumacs.FaceAttributes({
+        foreground = lumacs.Color(200, 200, 200),
+        background = lumacs.Color(20, 20, 20)
+    }))
+    
+    editor:define_face("font-lock-keyword-face", lumacs.FaceAttributes({
+        foreground = lumacs.Color(255, 100, 100), -- Red keywords
+        weight = lumacs.FontWeight.Bold
+    }))
+end
+```
+
+## Configuration
+
+Access editor configuration via `editor.config`.
+
+```lua
+-- Set line number width
+editor.config:set("line_number_width", 4)
+
+-- Toggle line numbers
+local current = editor.config:get_bool("show_line_numbers", true)
+editor.config:set("show_line_numbers", not current)
+```
+
+## Minibuffer and Interaction
+
+You can prompt the user for input using the Minibuffer.
+
+```lua
+-- Prompt for a string via command mode logic
+editor:command_mode() 
+-- Or use register_command interactive specs for simpler prompts.
+```
+
+## Directory Structure
+
+- `~/.config/lumacs/init.lua`: Main user configuration file.
+- `~/.config/lumacs/themes/`: Place custom theme Lua files here (if supported by loader).
+- `~/.config/lumacs/plugins/`: Place plugins here.
+
+## Troubleshooting
+
+- **Logs**: Check `lumacs.log` or stdout/stderr for Lua errors.
+- **MobDebug**: Lumacs supports remote debugging via MobDebug. Ensure `mobdebug.lua` is in your path and set `debug_lua = true` in config.
+
+```