LUA_TUTORIAL.md 5.9 KB

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

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

editor:bind_key("C-c t", function()
    editor:message("You pressed Ctrl-c t")
end, "Test command")

Binding to a Command

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

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

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

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

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

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