init.lua 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. -- Lumacs User Configuration File
  2. -- ============================================================================
  3. -- This file runs AFTER defaults.hpp, allowing you to customize and extend
  4. -- the default Emacs-like behavior. The mode system, keybindings, and commands
  5. -- are already set up - use this file to:
  6. -- 1. Load additional major modes
  7. -- 2. Load themes
  8. -- 3. Add custom keybindings
  9. -- 4. Define custom commands
  10. -- 5. Override default settings
  11. -- ============================================================================
  12. -- ============================================================================
  13. -- PACKAGE SYSTEM INITIALIZATION
  14. -- ============================================================================
  15. -- Add lua/ to package path for require() to work
  16. package.path = package.path .. ";lua/?.lua;lua/?/init.lua"
  17. -- Load the package manager
  18. local pkg = dofile("lua/core/package.lua")
  19. pkg.setup()
  20. -- Make it globally accessible
  21. lumacs.package = pkg
  22. -- Load package commands (M-x package-install, etc.)
  23. dofile("lua/core/package-commands.lua")
  24. -- Load user packages from ~/.lumacs/packages.lua
  25. local loaded, errors = pkg.load_all()
  26. if loaded > 0 or errors > 0 then
  27. print(string.format("[package] Loaded %d user packages (%d errors)", loaded, errors))
  28. end
  29. -- ============================================================================
  30. -- LOAD MAJOR MODES
  31. -- ============================================================================
  32. -- Load individual major mode definitions
  33. dofile("lua/major_modes/lua_mode.lua")
  34. dofile("lua/major_modes/c_cpp_mode.lua")
  35. -- ============================================================================
  36. -- LOAD THEMES
  37. -- ============================================================================
  38. -- Load individual theme definitions
  39. dofile("lua/themes/default.lua")
  40. dofile("lua/themes/dracula.lua")
  41. dofile("lua/themes/everforest-dark.lua")
  42. dofile("lua/themes/gruvbox-light.lua")
  43. dofile("lua/themes/nord.lua")
  44. dofile("lua/themes/solarized-dark.lua")
  45. dofile("lua/themes/catppuccin-mocha.lua")
  46. dofile("lua/themes/tokyo-night.lua")
  47. dofile("lua/themes/ayu-dark.lua")
  48. -- Load theme switching functions and keybindings
  49. dofile("lua/themes/themes_init.lua")
  50. -- ============================================================================
  51. -- LOAD PACKAGES
  52. -- ============================================================================
  53. -- which-key: Display available keybindings for prefix keys
  54. dofile("lua/packages/which-key.lua")
  55. -- doom-modeline: Doom Emacs-style modeline customization
  56. dofile("lua/packages/doom-modeline.lua")
  57. -- smartparens: Auto-pairing of brackets, quotes, etc.
  58. dofile("lua/packages/smartparens.lua")
  59. -- rainbow-delimiters: Colorize nested delimiters by depth
  60. dofile("lua/packages/rainbow-delimiters.lua")
  61. -- ido: Enhanced fuzzy completion (optional, provides utilities)
  62. dofile("lua/packages/ido.lua")
  63. -- projectile: Project management and navigation
  64. dofile("lua/packages/projectile.lua")
  65. -- company: Text completion framework
  66. dofile("lua/packages/company.lua")
  67. -- goto-line: Go to a specific line number (M-g g)
  68. dofile("lua/packages/goto-line.lua")
  69. -- recentf: Track and access recently opened files
  70. dofile("lua/packages/recentf.lua")
  71. -- bookmarks: Save and jump between named positions
  72. dofile("lua/packages/bookmarks.lua")
  73. -- visual-line: Soft word wrap mode
  74. dofile("lua/packages/visual-line.lua")
  75. -- ============================================================================
  76. -- MINOR MODES (User-defined extensions)
  77. -- ============================================================================
  78. -- Auto-save minor mode
  79. lumacs.define_minor_mode("auto-save-mode", {
  80. global = false,
  81. setup = function()
  82. editor:message("[auto-save-mode] Auto-save enabled")
  83. end,
  84. cleanup = function()
  85. editor:message("[auto-save-mode] Auto-save disabled")
  86. end
  87. })
  88. -- Line numbers minor mode (toggle control)
  89. lumacs.define_minor_mode("line-numbers-mode", {
  90. global = true,
  91. setup = function()
  92. editor.config:set("show_line_numbers", true)
  93. editor:message("[line-numbers-mode] Line numbers enabled")
  94. end,
  95. cleanup = function()
  96. editor.config:set("show_line_numbers", false)
  97. editor:message("[line-numbers-mode] Line numbers disabled")
  98. end
  99. })
  100. -- ============================================================================
  101. -- CUSTOM KEYBINDINGS (User overrides)
  102. -- ============================================================================
  103. -- Example: Custom keybinding for inserting timestamp
  104. editor:bind_key("C-c t", function()
  105. local cursor_pos = editor.cursor
  106. local timestamp = os.date("%Y-%m-%d %H:%M:%S")
  107. editor.buffer:insert(cursor_pos, timestamp)
  108. editor:message("Inserted timestamp")
  109. end)
  110. -- Example: Find TODO comments in buffer
  111. editor:bind_key("C-c o", function()
  112. local buf = editor.buffer
  113. local cursor = editor.cursor
  114. local search_start = lumacs.Position(cursor.line, cursor.column + 1)
  115. local res = buf:find("TODO", search_start)
  116. if res then
  117. editor.cursor = res.start
  118. editor:message("Found TODO at " .. res.start.line .. ":" .. res.start.column)
  119. else
  120. editor:message("No more TODOs found")
  121. end
  122. end)
  123. -- Line swapping (like VS Code Alt+Up/Down)
  124. local function swap_line_up()
  125. local buf = editor.buffer
  126. local cursor = editor.cursor
  127. if cursor.line == 0 then
  128. editor:message("Already at first line")
  129. return
  130. end
  131. local current_line = buf:line(cursor.line)
  132. local above_line = buf:line(cursor.line - 1)
  133. local delete_start = lumacs.Position(cursor.line - 1, 0)
  134. local delete_end = lumacs.Position(cursor.line, #current_line)
  135. buf:erase(lumacs.Range(delete_start, delete_end))
  136. local text = current_line .. "\n" .. above_line
  137. buf:insert(lumacs.Position(cursor.line - 1, 0), text)
  138. editor.cursor = lumacs.Position(cursor.line - 1, cursor.column)
  139. editor:message("Swapped line up")
  140. end
  141. local function swap_line_down()
  142. local buf = editor.buffer
  143. local cursor = editor.cursor
  144. if cursor.line >= buf:line_count() - 1 then
  145. editor:message("Already at last line")
  146. return
  147. end
  148. local current_line = buf:line(cursor.line)
  149. local below_line = buf:line(cursor.line + 1)
  150. local delete_start = lumacs.Position(cursor.line, 0)
  151. local delete_end = lumacs.Position(cursor.line + 1, #below_line)
  152. buf:erase(lumacs.Range(delete_start, delete_end))
  153. local text = below_line .. "\n" .. current_line
  154. buf:insert(lumacs.Position(cursor.line, 0), text)
  155. editor.cursor = lumacs.Position(cursor.line + 1, cursor.column)
  156. editor:message("Swapped line down")
  157. end
  158. editor:bind_key("M-ArrowUp", swap_line_up)
  159. editor:bind_key("M-ArrowDown", swap_line_down)
  160. -- ============================================================================
  161. -- FONT SIZE COMMANDS
  162. -- ============================================================================
  163. editor:register_command("text-scale-increase", "Increase font size", function(args)
  164. local current = editor:font_size()
  165. editor:set_font_size(current + 1)
  166. return {success = true, message = "Font size: " .. (current + 1)}
  167. end)
  168. editor:register_command("text-scale-decrease", "Decrease font size", function(args)
  169. local current = editor:font_size()
  170. editor:set_font_size(current - 1)
  171. return {success = true, message = "Font size: " .. (current - 1)}
  172. end)
  173. editor:register_command("text-scale-set", "Set font size", function(args)
  174. if #args == 0 then
  175. return {success = true, message = "Current font size: " .. editor:font_size()}
  176. end
  177. local size = tonumber(args[1])
  178. if size then
  179. editor:set_font_size(size)
  180. return {success = true, message = "Font size set to: " .. size}
  181. else
  182. return {success = false, message = "Invalid size: " .. args[1]}
  183. end
  184. end, {}, true, "s")
  185. -- Emacs-style font size keybindings (C-x C-+ and C-x C-- in Emacs)
  186. editor:bind_key("C-x +", "text-scale-increase", "Increase font size")
  187. editor:bind_key("C-x -", "text-scale-decrease", "Decrease font size")
  188. editor:bind_key("C-x =", "text-scale-set", "Show/set font size")
  189. -- ============================================================================
  190. -- CUSTOM COMMANDS
  191. -- ============================================================================
  192. -- Auto-theme based on time of day
  193. editor:register_command("auto-theme", "Automatically set theme based on time of day", function(args)
  194. local hour = tonumber(os.date("%H"))
  195. local theme_name
  196. if hour >= 6 and hour < 18 then
  197. theme_name = "gruvbox-light"
  198. elseif hour >= 18 and hour < 22 then
  199. theme_name = "everforest-dark"
  200. else
  201. theme_name = "nord"
  202. end
  203. local success, message = editor:execute_command("set-theme", {theme_name})
  204. if success then
  205. return {success = true, message = string.format("Auto-selected %s theme for %d:00", theme_name, hour)}
  206. else
  207. return {success = false, message = "Failed to auto-select theme: " .. message}
  208. end
  209. end, false)
  210. -- Theme demo command
  211. editor:register_command("theme-demo", "Demonstrate theme switching", function(args)
  212. local themes = {"solarized-dark", "nord", "gruvbox-light", "dracula"}
  213. local success, message = editor:execute_command("set-theme", {themes[1]})
  214. if success then
  215. return {success = true, message = "Theme demo - switched to " .. themes[1]}
  216. else
  217. return {success = false, message = "Demo failed: " .. message}
  218. end
  219. end, false)
  220. -- Evaluate Lua expression
  221. editor:register_command("eval-expression", "Evaluate Lua expression", function(args)
  222. if #args == 0 then
  223. return {success = false, message = "Lua expression required"}
  224. end
  225. local expr = table.concat(args, " ")
  226. local func, err = load("return " .. expr)
  227. if not func then
  228. return {success = false, message = "Parse error: " .. err}
  229. end
  230. local success, result = pcall(func)
  231. if success then
  232. return {success = true, message = tostring(result)}
  233. else
  234. return {success = false, message = "Error: " .. tostring(result)}
  235. end
  236. end, true, "s")
  237. -- ============================================================================
  238. -- CONFIGURATION OVERRIDES
  239. -- ============================================================================
  240. -- Uncomment to change defaults:
  241. -- editor.config:set("tab_width", 2)
  242. -- editor.config:set("indent_tabs_mode", true)
  243. -- editor.config:set("scroll_margin", 5)
  244. -- ============================================================================
  245. -- AUTO-ACTIVATE MAJOR MODE
  246. -- ============================================================================
  247. -- This is called after loading to ensure file-specific modes are activated
  248. lumacs.auto_activate_major_mode()
  249. -- Welcome message (override default)
  250. editor:message("Lumacs ready! C-h ? for help, M-x for commands, C-x t for themes")