#pragma once namespace lumacs { constexpr const char* LUA_DEFAULTS = R"( -- ========================================================= -- Lumacs Embedded Defaults -- ========================================================= -- This runs BEFORE the user's init.lua. -- It establishes the core editing environment. -- 1. Sane Editor Config editor.config:set("show_line_numbers", true) editor.config:set("tab_width", 4) -- 2. Mode Infrastructure local major_modes = {} local minor_modes = {} local buffer_major_modes = {} local buffer_minor_modes = {} function define_major_mode(name, config) major_modes[name] = { name = name, file_patterns = config.file_patterns or {}, setup = config.setup or function() end, cleanup = config.cleanup or function() end, highlight = config.highlight or nil, keybindings = config.keybindings or {}, comment_syntax = config.comment_syntax or "--", } end function define_minor_mode(name, config) minor_modes[name] = { name = name, setup = config.setup or function() end, cleanup = config.cleanup or function() end, keybindings = config.keybindings or {}, global = config.global or false, } end function activate_major_mode(mode_name) local buf = editor.buffer local buf_name = buf:name() local mode = major_modes[mode_name] if not mode then return false end buffer_major_modes[buf_name] = mode_name if mode.highlight then buf:on_buffer_event(function(event_data) if event_data.event == lumacs.BufferEvent.Loaded or event_data.event == lumacs.BufferEvent.LanguageChanged then mode.highlight() end end) mode.highlight() end -- Register mode-specific keybindings -- Note: This is a simple implementation that binds globally for now. -- A proper implementation would use a keymap stack. for key, func in pairs(mode.keybindings) do editor:bind_key(key, func) end mode.setup() return true end function current_major_mode() local buf = editor.buffer local buf_name = buf:name() return buffer_major_modes[buf_name] or "fundamental-mode" end define_major_mode("fundamental-mode", {}) function auto_activate_major_mode() local buf = editor.buffer local buf_name = buf:name() for mode_name, mode in pairs(major_modes) do for _, pattern in ipairs(mode.file_patterns) do if string.match(buf_name, pattern) then activate_major_mode(mode_name) return end end end activate_major_mode("fundamental-mode") end -- 3. Basic Editing Commands & Registration -- Navigation editor:register_command("next-line", "Move cursor down", function() editor:move_down() end, true) editor:register_command("previous-line", "Move cursor up", function() editor:move_up() end, true) editor:register_command("forward-char", "Move cursor right", function() editor:move_right() end, true) editor:register_command("backward-char", "Move cursor left", function() editor:move_left() end, true) editor:register_command("forward-word", "Move forward one word", function() editor:move_forward_word() end, true) editor:register_command("backward-word", "Move backward one word", function() editor:move_backward_word() end, true) editor:register_command("move-beginning-of-line", "Go to beginning of line", function() editor:move_to_line_start() end, true) editor:register_command("move-end-of-line", "Go to end of line", function() editor:move_to_line_end() end, true) editor:register_command("beginning-of-buffer", "Go to beginning of buffer", function() editor:goto_beginning() end, true) editor:register_command("end-of-buffer", "Go to end of buffer", function() editor:goto_end() end, true) editor:register_command("scroll-up-command", "Page down", function() editor:page_down() end, true) editor:register_command("scroll-down-command", "Page up", function() editor:page_up() end, true) -- Insertion / Deletion function lumacs_insert_newline() local cursor = editor.cursor editor.buffer:insert_newline(cursor) -- Move to start of next line editor.cursor = lumacs.Position(cursor.line + 1, 0) end editor:register_command("insert-newline", "Insert newline", lumacs_insert_newline, true) function lumacs_backward_delete_char() local cursor = editor.cursor if cursor.line == 0 and cursor.column == 0 then return end editor.buffer:erase_char(cursor) -- Calculate new cursor position local new_pos = cursor if new_pos.column > 0 then new_pos = lumacs.Position(new_pos.line, new_pos.column - 1) elseif new_pos.line > 0 then local prev_line_len = #editor.buffer:line(new_pos.line - 1) new_pos = lumacs.Position(new_pos.line - 1, prev_line_len) end editor.cursor = new_pos end editor:register_command("backward-delete-char", "Delete char backward", lumacs_backward_delete_char, true) function lumacs_delete_char() local cursor = editor.cursor editor.buffer:erase_char(lumacs.Position(cursor.line, cursor.column + 1)) end editor:register_command("delete-char", "Delete char forward", lumacs_delete_char, true) function self_insert_command(args) local char_to_insert = args[1] if not char_to_insert then return end editor.buffer:insert(editor.cursor, char_to_insert) editor:move_right() end editor:register_command("self-insert-command", "Insert char", self_insert_command, true) -- Clipboard / Kill Ring editor:register_command("kill-line", "Kill rest of line", function() editor:kill_line() end, true) editor:register_command("kill-region", "Kill selected region", function() editor:kill_region() end, true) editor:register_command("copy-region-as-kill", "Copy region", function() editor:copy_region_as_kill() end, true) editor:register_command("yank", "Paste", function() editor:yank() end, true) editor:register_command("yank-pop", "Cycle paste", function() editor:yank_pop() end, true) -- Undo/Redo editor:register_command("undo", "Undo", function() editor:undo() end, true) editor:register_command("redo", "Redo", function() editor:redo() end, true) -- File/Buffer editor:register_command("save-buffer", "Save current buffer", function() if editor.buffer:save() then editor:message("Saved") else editor:message("Failed to save") end end, true) editor:register_command("find-file", "Open file", function() editor:find_file_mode() end, true, "f") editor:register_command("switch-buffer", "Switch buffer", function() editor:buffer_switch_mode() end, true, "b") editor:register_command("kill-buffer", "Kill buffer", function() editor:kill_buffer_mode() end, true, "b") editor:register_command("save-buffers-kill-terminal", "Quit", function() editor:quit() end, true) editor:register_command("execute-extended-command", "M-x", function() editor:command_mode() end, true) -- Macros editor:register_command("start-kbd-macro", "Start recording macro", function() editor:start_kbd_macro() end, true) editor:register_command("end-kbd-macro-or-call", "End recording or call macro", function() editor:end_kbd_macro_or_call() end, true) -- 4. Default Keybindings editor:bind_key("Return", "insert-newline") editor:bind_key("Backspace", "backward-delete-char") editor:bind_key("Delete", "delete-char") -- Arrow Keys editor:bind_key("ArrowUp", "previous-line") editor:bind_key("ArrowDown", "next-line") editor:bind_key("ArrowLeft", "backward-char") editor:bind_key("ArrowRight", "forward-char") -- Emacs Navigation editor:bind_key("C-f", "forward-char") editor:bind_key("C-b", "backward-char") editor:bind_key("C-n", "next-line") editor:bind_key("C-p", "previous-line") editor:bind_key("C-a", "move-beginning-of-line") editor:bind_key("C-e", "move-end-of-line") editor:bind_key("M-f", "forward-word") editor:bind_key("M-b", "backward-word") editor:bind_key("M-<", "beginning-of-buffer") editor:bind_key("M->", "end-of-buffer") editor:bind_key("C-v", "scroll-up-command") editor:bind_key("M-v", "scroll-down-command") -- File & Window Ops editor:bind_key("C-x C-c", "save-buffers-kill-terminal") editor:bind_key("C-x C-s", "save-buffer") editor:bind_key("C-x C-f", "find-file") editor:bind_key("C-x b", "switch-buffer") editor:bind_key("C-x k", "kill-buffer") editor:bind_key("C-x 0", "delete-window") -- Need to implement editor:bind_key("C-x 1", "delete-other-windows") -- Need to implement editor:bind_key("C-x 2", "split-window-below") -- Need to implement editor:bind_key("C-x 3", "split-window-right") -- Need to implement editor:bind_key("C-x o", "other-window") -- Need to implement editor:bind_key("M-x", "execute-extended-command") -- Windows Implementation editor:register_command("delete-window", "Close window", function() editor:close_window() end, true) editor:register_command("split-window-below", "Split horizontal", function() editor:split_horizontally() end, true) editor:register_command("split-window-right", "Split vertical", function() editor:split_vertically() end, true) editor:register_command("other-window", "Next window", function() editor:next_window() end, true) -- Undo/Redo editor:bind_key("C-/", "undo") editor:bind_key("C-_", "undo") editor:bind_key("C-x u", "redo") -- Mark & Kill Ring editor:bind_key("C-@", function() editor.buffer:set_mark(editor.cursor) editor:message("Mark set") end) editor:bind_key("C-w", "kill-region") editor:bind_key("M-w", "copy-region-as-kill") editor:bind_key("C-y", "yank") editor:bind_key("M-y", "yank-pop") editor:bind_key("C-k", "kill-line") -- Macros editor:bind_key("F3", "start-kbd-macro") editor:bind_key("F4", "end-kbd-macro-or-call") -- Theme Management editor:register_command("set-theme", "Set active theme", function(args) if #args == 0 then return {success = false, message = "Theme name required"} end local theme_name = args[1] local theme_manager = editor.theme_manager local available_themes = theme_manager:theme_names() -- Check if theme exists local theme_exists = false for _, name in ipairs(available_themes) do if name == theme_name then theme_exists = true break end end if not theme_exists then return {success = false, message = "Theme '" .. theme_name .. "' not found. Available: " .. table.concat(available_themes, ", ")} end theme_manager:set_active_theme(theme_name) editor:message("Switched to theme: " .. theme_name) return {success = true, message = "Switched to theme: " .. theme_name} end, true, "s") -- Auto-activate mode auto_activate_major_mode() )"; } // namespace lumacs