Initial commit: ideaDrop.nvim plugin with sidebar and idea saving

This commit is contained in:
Carlos
2025-06-14 20:39:13 -04:00
commit fef0bb9266
11 changed files with 484 additions and 0 deletions

24
lua/ideaDrop/config.lua Normal file
View File

@@ -0,0 +1,24 @@
-- ideaDrop/config.lua
---@class Config
---@field options IdeaDropOptions
---@field setup fun(user_opts: IdeaDropOptions|nil): nil
---@class IdeaDropOptions
---@field idea_dir string Directory where idea files will be stored
local M = {}
---Default configuration options
M.options = {
idea_dir = vim.fn.stdpath("data") .. "/ideaDrop" -- default path
}
---Setup function to merge user options with defaults
---@param user_opts IdeaDropOptions|nil User configuration options
---@return nil
function M.setup(user_opts)
M.options = vim.tbl_deep_extend("force", M.options, user_opts or {})
end
return M

53
lua/ideaDrop/init.lua Normal file
View File

@@ -0,0 +1,53 @@
-- ideaDrop.nvim/init.lua
local config = require("ideaDrop.config")
local sidebar = require("ideaDrop.sidebar")
local list = require("ideaDrop.list")
local M = {}
---@class IdeaDrop
---@field setup fun(user_opts: IdeaDropConfig): nil
---@class IdeaDropConfig
---@field idea_dir string Directory where idea files will be stored
---Setup function for ideaDrop.nvim
---@param user_opts IdeaDropConfig|nil User configuration options
---@return nil
function M.setup(user_opts)
config.setup(user_opts)
vim.api.nvim_create_user_command("Idea", function(opts)
local arg = opts.args
local idea_dir = config.options.idea_dir
if arg == "listAll" then
list.list_all()
elseif arg ~= "" then
-- Ensure directory exists (even for nested folders)
local filename = arg:match("%.md$") and arg or (arg .. ".md")
local full_path = idea_dir .. "/" .. filename
-- Create parent folders if needed
local folder = vim.fn.fnamemodify(full_path, ":h")
if vim.fn.isdirectory(folder) == 0 then
vim.fn.mkdir(folder, "p")
end
sidebar.open(full_path, filename)
else
-- Default to today's idea file
local path = string.format("%s/%s.md", idea_dir, os.date("%Y-%m-%d"))
sidebar.open(path)
end
end, {
nargs = "?",
complete = function()
return { "listAll" }
end,
desc = "Open today's idea, a named idea, or list all",
})
vim.notify("ideaDrop loaded!", vim.log.levels.INFO)
end
return M

16
lua/ideaDrop/keymaps.lua Normal file
View File

@@ -0,0 +1,16 @@
-- ideaDrop/keymaps.lua
---@class Keymaps
---@field setup fun(): nil
local M = {}
---Sets up default keymaps for ideaDrop
---Currently only sets up a demo keymap
---@return nil
function M.setup()
-- Demo keymap for idea capture
vim.keymap.set("n", "<leader>id", function()
vim.notify("💡 Idea captured!")
end, { desc = "Drop idea (demo)" })
end
return M

30
lua/ideaDrop/list.lua Normal file
View File

@@ -0,0 +1,30 @@
-- ideaDrop/list.lua
local config = require("ideaDrop.config")
local sidebar = require("ideaDrop.sidebar")
---@class List
---@field list_all fun(): nil
local M = {}
---Lists all idea files and allows user to select one to open
---@return nil
function M.list_all()
local path = config.options.idea_dir
-- Find all .md files recursively
local files = vim.fn.glob(path .. "**/*.md", false, true)
if #files == 0 then
vim.notify("📂 No idea files found", vim.log.levels.INFO)
return
end
-- Present file selection UI
vim.ui.select(files, { prompt = "📂 Select an idea file to open:" }, function(choice)
if choice then
sidebar.open(choice) -- Open the selected file in sidebar
end
end)
end
return M

82
lua/ideaDrop/sidebar.lua Normal file
View File

@@ -0,0 +1,82 @@
local config = require("ideaDrop.config")
---@class Sidebar
---@field open fun(file: string|nil, filename: string|nil): nil
---@field save_idea fun(lines: string[], file: string|nil): nil
local M = {}
---Opens a floating sidebar window with the specified file
---@param file string|nil Path to the file to open
---@param filename string|nil Name of the file (used for new files)
---@return nil
function M.open(file, filename)
-- Create a new buffer
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_buf_set_option(buf, "filetype", "markdown")
-- Calculate window dimensions (30% of screen width, 80% of screen height)
local width = math.floor(vim.o.columns * 0.3)
local height = math.floor(vim.o.lines * 0.8)
-- Create and configure the floating window
local win = vim.api.nvim_open_win(buf, true, {
relative = "editor",
width = width,
height = height,
row = 1,
col = 1,
border = "rounded",
style = "minimal",
})
-- Load file content or create new file template
if file and vim.fn.filereadable(file) == 1 then
local content = vim.fn.readfile(file)
vim.api.nvim_buf_set_lines(buf, 0, -1, false, content)
else
vim.api.nvim_buf_set_lines(buf, 0, -1, false, {
"# " .. (filename or "Idea for " .. os.date("%Y-%m-%d")),
"",
"- ",
})
end
-- Set up autosave on window close
vim.api.nvim_create_autocmd("WinClosed", {
pattern = tostring(win),
once = true,
callback = function()
local lines = vim.api.nvim_buf_get_lines(buf, 0, -1, false)
M.save_idea(lines, file)
end,
})
end
---Saves the idea content to a file
---@param lines string[] Array of lines to save
---@param file string|nil Path where to save the file
---@return nil
function M.save_idea(lines, file)
local idea_path = config.options.idea_dir
-- Create default path if none provided
if not file then
if vim.fn.isdirectory(idea_path) == 0 then
vim.fn.mkdir(idea_path, "p")
end
file = string.format("%s/%s.md", idea_path, os.date("%Y-%m-%d"))
end
-- Write content to file
local f, err = io.open(file, "w")
if not f then
vim.notify("❌ Failed to write idea: " .. tostring(err), vim.log.levels.ERROR)
return
end
f:write(table.concat(lines, "\n") .. "\n")
f:close()
vim.notify("💾 Idea saved to " .. file, vim.log.levels.INFO)
end
return M

0
lua/ideaDrop/utils.lua Normal file
View File