init.lua 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. -- recentf.lua
  2. -- Track and access recently opened files (like Emacs recentf-mode)
  3. -- ============================================================================
  4. local recentf = {}
  5. -- Configuration
  6. recentf.config = {
  7. enabled = true,
  8. max_saved = 20, -- Maximum number of recent files to track
  9. exclude_patterns = { -- Patterns to exclude from recent files
  10. "^/tmp/",
  11. "%.git/",
  12. "COMMIT_EDITMSG$",
  13. },
  14. }
  15. -- Recent files list (most recent first)
  16. recentf.list = {}
  17. -- Check if a file should be excluded
  18. local function should_exclude(filepath)
  19. if not filepath or filepath == "" then
  20. return true
  21. end
  22. -- Exclude *scratch* and other special buffers
  23. if filepath:match("^%*") then
  24. return true
  25. end
  26. for _, pattern in ipairs(recentf.config.exclude_patterns) do
  27. if filepath:match(pattern) then
  28. return true
  29. end
  30. end
  31. return false
  32. end
  33. -- Add a file to the recent list
  34. function recentf.add(filepath)
  35. if should_exclude(filepath) then
  36. return
  37. end
  38. -- Remove if already in list (to move to front)
  39. for i, f in ipairs(recentf.list) do
  40. if f == filepath then
  41. table.remove(recentf.list, i)
  42. break
  43. end
  44. end
  45. -- Add to front
  46. table.insert(recentf.list, 1, filepath)
  47. -- Trim to max size
  48. while #recentf.list > recentf.config.max_saved do
  49. table.remove(recentf.list)
  50. end
  51. end
  52. -- Get the recent files list
  53. function recentf.get_list()
  54. return recentf.list
  55. end
  56. -- Clear the recent files list
  57. function recentf.clear()
  58. recentf.list = {}
  59. end
  60. -- Open a recent file by index (1-based)
  61. function recentf.open(index)
  62. local idx = tonumber(index)
  63. if not idx or idx < 1 or idx > #recentf.list then
  64. return {success = false, message = "Invalid index: " .. tostring(index)}
  65. end
  66. local filepath = recentf.list[idx]
  67. return editor:execute_command("find-file", {filepath})
  68. end
  69. -- Format the recent files list for display
  70. function recentf.format_list()
  71. local lines = {}
  72. for i, filepath in ipairs(recentf.list) do
  73. -- Shorten home directory
  74. local display = filepath:gsub("^" .. os.getenv("HOME"), "~")
  75. table.insert(lines, string.format("%2d: %s", i, display))
  76. end
  77. return lines
  78. end
  79. -- Setup function
  80. function recentf.setup(opts)
  81. opts = opts or {}
  82. for k, v in pairs(opts) do
  83. recentf.config[k] = v
  84. end
  85. if not recentf.config.enabled then
  86. return
  87. end
  88. -- Register commands
  89. editor:register_command("recentf-open", "Open a recent file by number", function(args)
  90. if #args == 0 then
  91. -- List recent files
  92. local list = recentf.format_list()
  93. if #list == 0 then
  94. return {success = true, message = "No recent files"}
  95. end
  96. -- Show in echo area (up to 5 files)
  97. local preview = {}
  98. for i = 1, math.min(5, #list) do
  99. table.insert(preview, list[i])
  100. end
  101. local msg = table.concat(preview, " | ")
  102. if #list > 5 then
  103. msg = msg .. " ..."
  104. end
  105. return {success = true, message = msg}
  106. end
  107. return recentf.open(args[1])
  108. end, {}, true, "n")
  109. editor:register_command("recentf-list", "List all recent files", function(args)
  110. local list = recentf.format_list()
  111. if #list == 0 then
  112. return {success = true, message = "No recent files"}
  113. end
  114. -- Use echo area for multi-line display
  115. editor:set_echo_area(list)
  116. return {success = true, message = ""}
  117. end)
  118. editor:register_command("recentf-clear", "Clear the recent files list", function(args)
  119. recentf.clear()
  120. return {success = true, message = "Recent files list cleared"}
  121. end)
  122. -- Key binding (similar to Emacs)
  123. editor:bind_key("C-x C-r", "recentf-open", "Open recent file")
  124. -- Hook into find-file to track opens
  125. -- We'll expose a global function that the C++ can call
  126. lumacs.recentf_track = function(filepath)
  127. recentf.add(filepath)
  128. end
  129. print("[recentf] Package loaded")
  130. end
  131. -- Auto-setup with defaults
  132. recentf.setup()
  133. return recentf