Bernardo Magri 1 месяц назад
Родитель
Сommit
b007b85a95
3 измененных файлов с 285 добавлено и 0 удалено
  1. 125 0
      include/lumacs/buffer.hpp
  2. 107 0
      include/lumacs/editor_core.hpp
  3. 53 0
      include/lumacs/lua_api.hpp

+ 125 - 0
include/lumacs/buffer.hpp

@@ -0,0 +1,125 @@
+#pragma once
+
+#include <string>
+#include <vector>
+#include <optional>
+#include <filesystem>
+#include <memory>
+
+namespace lumacs {
+
+/// Represents a cursor position in a buffer
+struct Position {
+    size_t line;
+    size_t column;
+
+    auto operator<=>(const Position&) const = default;
+};
+
+/// Represents a range in the buffer
+struct Range {
+    Position start;
+    Position end;
+
+    auto operator<=>(const Range&) const = default;
+};
+
+/// A text buffer that manages the content of a file or scratch buffer
+class Buffer {
+public:
+    /// Create an empty buffer
+    Buffer();
+
+    /// Create a buffer with a name (for scratch buffers)
+    explicit Buffer(std::string name);
+
+    /// Create a buffer from a file
+    static std::optional<Buffer> from_file(const std::filesystem::path& path);
+
+    // Disable copy, allow move
+    Buffer(const Buffer&) = delete;
+    Buffer& operator=(const Buffer&) = delete;
+    Buffer(Buffer&&) noexcept = default;
+    Buffer& operator=(Buffer&&) noexcept = default;
+
+    ~Buffer() = default;
+
+    // === Content Access ===
+
+    /// Get the number of lines in the buffer
+    [[nodiscard]] size_t line_count() const noexcept;
+
+    /// Get a line by index (0-based)
+    [[nodiscard]] const std::string& line(size_t index) const;
+
+    /// Get all lines
+    [[nodiscard]] const std::vector<std::string>& lines() const noexcept;
+
+    /// Get the entire buffer content as a single string
+    [[nodiscard]] std::string content() const;
+
+    // === Modification ===
+
+    /// Insert text at a position
+    void insert(Position pos, std::string_view text);
+
+    /// Insert a character at a position
+    void insert_char(Position pos, char c);
+
+    /// Insert a newline at a position
+    void insert_newline(Position pos);
+
+    /// Delete a range of text
+    void erase(Range range);
+
+    /// Delete a character at a position (backspace)
+    void erase_char(Position pos);
+
+    /// Replace text in a range
+    void replace(Range range, std::string_view text);
+
+    /// Clear the entire buffer
+    void clear();
+
+    // === File Operations ===
+
+    /// Save the buffer to its associated file
+    bool save();
+
+    /// Save the buffer to a specific file
+    bool save_as(const std::filesystem::path& path);
+
+    /// Check if the buffer has been modified since last save
+    [[nodiscard]] bool is_modified() const noexcept;
+
+    /// Get the file path associated with this buffer (if any)
+    [[nodiscard]] std::optional<std::filesystem::path> file_path() const noexcept;
+
+    // === Buffer Properties ===
+
+    /// Get the buffer name
+    [[nodiscard]] const std::string& name() const noexcept;
+
+    /// Set the buffer name
+    void set_name(std::string name);
+
+    /// Check if position is valid
+    [[nodiscard]] bool is_valid_position(Position pos) const noexcept;
+
+    /// Clamp a position to valid bounds
+    [[nodiscard]] Position clamp_position(Position pos) const noexcept;
+
+private:
+    std::string name_;
+    std::vector<std::string> lines_;
+    std::optional<std::filesystem::path> file_path_;
+    bool modified_;
+
+    /// Ensure the buffer has at least one line
+    void ensure_min_lines();
+
+    /// Mark the buffer as modified
+    void mark_modified();
+};
+
+} // namespace lumacs

+ 107 - 0
include/lumacs/editor_core.hpp

@@ -0,0 +1,107 @@
+#pragma once
+
+#include "lumacs/buffer.hpp"
+#include <memory>
+#include <functional>
+#include <vector>
+
+namespace lumacs {
+
+/// Viewport information for rendering
+struct Viewport {
+    int scroll_offset = 0;
+    int height = 20;
+    int width = 80;
+};
+
+/// Editor state change events
+enum class EditorEvent {
+    BufferModified,
+    CursorMoved,
+    ViewportChanged,
+    Quit
+};
+
+/// Core editor logic, independent of UI framework
+class EditorCore {
+public:
+    EditorCore();
+    ~EditorCore() = default;
+
+    // Disable copy, allow move
+    EditorCore(const EditorCore&) = delete;
+    EditorCore& operator=(const EditorCore&) = delete;
+    EditorCore(EditorCore&&) noexcept = default;
+    EditorCore& operator=(EditorCore&&) noexcept = default;
+
+    // === Buffer Management ===
+
+    /// Get the current buffer
+    [[nodiscard]] const Buffer& buffer() const noexcept { return *buffer_; }
+    [[nodiscard]] Buffer& buffer() noexcept { return *buffer_; }
+
+    /// Load a file into the buffer
+    bool load_file(const std::filesystem::path& path);
+
+    /// Create a new empty buffer
+    void new_buffer(std::string name = "*scratch*");
+
+    // === Cursor Management ===
+
+    /// Get the current cursor position
+    [[nodiscard]] Position cursor() const noexcept { return cursor_; }
+
+    /// Set the cursor position (will be clamped to valid bounds)
+    void set_cursor(Position pos);
+
+    // === Cursor Movement ===
+
+    void move_up();
+    void move_down();
+    void move_left();
+    void move_right();
+    void move_to_line_start();
+    void move_to_line_end();
+
+    // === Viewport Management ===
+
+    /// Get the current viewport
+    [[nodiscard]] const Viewport& viewport() const noexcept { return viewport_; }
+
+    /// Update viewport dimensions (typically called on window resize)
+    void set_viewport_size(int width, int height);
+
+    /// Adjust scroll to ensure cursor is visible
+    void adjust_scroll();
+
+    /// Get the range of visible lines [start, end)
+    [[nodiscard]] std::pair<size_t, size_t> visible_line_range() const;
+
+    // === Event Callbacks ===
+
+    using EventCallback = std::function<void(EditorEvent)>;
+
+    /// Register a callback for editor events
+    void on_event(EventCallback callback) {
+        event_callbacks_.push_back(std::move(callback));
+    }
+
+    // === Actions ===
+
+    void request_quit() {
+        emit_event(EditorEvent::Quit);
+    }
+
+private:
+    std::unique_ptr<Buffer> buffer_;
+    Position cursor_;
+    Viewport viewport_;
+    std::vector<EventCallback> event_callbacks_;
+
+    static constexpr int SCROLL_MARGIN = 3;
+
+    void clamp_cursor();
+    void emit_event(EditorEvent event);
+};
+
+} // namespace lumacs

+ 53 - 0
include/lumacs/lua_api.hpp

@@ -0,0 +1,53 @@
+#pragma once
+
+#include "lumacs/editor_core.hpp"
+#include <sol/sol.hpp>
+#include <functional>
+#include <map>
+#include <string>
+
+namespace lumacs {
+
+/// Lua scripting API for Lumacs
+class LuaApi {
+public:
+    explicit LuaApi(EditorCore& core);
+    ~LuaApi() = default;
+
+    /// Get the Lua state
+    [[nodiscard]] sol::state& state() { return lua_; }
+
+    /// Load and execute a Lua file
+    bool load_file(const std::filesystem::path& path);
+
+    /// Execute Lua code
+    bool execute(std::string_view code);
+
+    /// Load init.lua from standard locations
+    bool load_init_file();
+
+    /// Bind a key to a Lua function
+    void bind_key(std::string key, sol::function callback);
+
+    /// Check if a key has a binding
+    [[nodiscard]] bool has_key_binding(const std::string& key) const;
+
+    /// Execute key binding if it exists
+    bool execute_key_binding(const std::string& key);
+
+    /// Get all key bindings (for debugging)
+    [[nodiscard]] std::map<std::string, sol::function> key_bindings() const {
+        return key_bindings_;
+    }
+
+private:
+    sol::state lua_;
+    EditorCore& core_;
+    std::map<std::string, sol::function> key_bindings_;
+
+    void setup_api();
+    void register_types();
+    void register_functions();
+};
+
+} // namespace lumacs