ARCHITECTURE.md 6.3 KB

Lumacs Architecture

Overview

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 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.

graph TD
    User[User Input] -->|Events| UI[UI Frontend]
    UI -->|Key Strings| LuaAPI[Lua API]
    LuaAPI -->|Process| KeyBinding[KeyBindingManager]
    KeyBinding -->|Command Name| CommandSystem[CommandSystem]
    CommandSystem -->|Execute| Core[EditorCore]
    
    %% Gave subgraph a unique ID 'CoreSystem' and a label string
    subgraph CoreSystem ["Core Subsystems"]
        Core -->|Delegate| BufferMgr[BufferManager]
        Core -->|Delegate| WindowMgr[WindowManager]
        Core -->|Delegate| MinibufferMgr[MinibufferManager]
        Core -->|Delegate| MacroMgr[MacroManager]
        Core -->|Delegate| PluginMgr[PluginManager]
        Core -->|Delegate| ThemeMgr[ThemeManager]
    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 application root.

  • Role: Owner of all Manager subsystems.
  • Interfaces: Implements IEditorNotifier (events) and IWindowManager (layout access) and ICommandTarget.
  • State: Holds the global editor configuration and delegates functionality to managers.

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.
  • ThemeManager: Manages color themes and face definitions.
  • KillRingManager: Manages the kill ring (clipboard history).
  • RegisterManager: Manages text registers.
  • RectangleManager: Handles rectangular edit operations.

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.
  • Initialization Cascade:
    1. Baked-in Defaults (src/defaults.hpp): Loads essential keybindings and mode infrastructure from binary memory. Ensures the editor is always functional.
    2. User Config (init.lua): Loads the user's configuration file (if found), overriding defaults.
  • Extension: init.lua (and the embedded defaults) implements the "Standard Library" of the editor (Major Modes, default keybindings).

User Interface (Frontends)

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 LuaApi::process_key which delegates 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 delegates to method (e.g., move_right), which updates 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)