adding functionalities on the buffer
This commit is contained in:
275
lua/ideaDrop/ui/sidebar.lua
Normal file
275
lua/ideaDrop/ui/sidebar.lua
Normal file
@@ -0,0 +1,275 @@
|
||||
-- ideaDrop/ui/sidebar.lua
|
||||
local config = require("ideaDrop.core.config")
|
||||
local tree = require("ideaDrop.ui.tree")
|
||||
|
||||
---@class Sidebar
|
||||
---@field open fun(file: string|nil, filename: string|nil, use_buffer: boolean|nil): nil
|
||||
---@field open_in_buffer fun(file: string|nil, filename: string|nil): nil
|
||||
---@field open_right_side fun(file: string|nil, filename: string|nil): nil
|
||||
---@field toggle_tree fun(): nil
|
||||
---@field get_current_file fun(): string|nil
|
||||
---@field save_idea fun(lines: string[], file: string|nil): nil
|
||||
local M = {}
|
||||
|
||||
-- Global variables to track the right-side buffer and window
|
||||
local right_side_buf = nil
|
||||
local right_side_win = nil
|
||||
local current_file = nil
|
||||
|
||||
---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)
|
||||
---@param use_buffer boolean|nil If true, opens in current buffer instead of floating window
|
||||
---@return nil
|
||||
function M.open(file, filename, use_buffer)
|
||||
if use_buffer then
|
||||
M.open_in_buffer(file, filename)
|
||||
return
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
---Opens the idea file in the current buffer
|
||||
---@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_in_buffer(file, filename)
|
||||
-- Create default path if none provided
|
||||
if not file then
|
||||
local idea_path = config.options.idea_dir
|
||||
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
|
||||
|
||||
-- Open the file in the current buffer
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(file))
|
||||
|
||||
-- If it's a new file, add template content
|
||||
if vim.fn.filereadable(file) == 0 then
|
||||
local template_lines = {
|
||||
"# " .. (filename or "Idea for " .. os.date("%Y-%m-%d")),
|
||||
"",
|
||||
"- ",
|
||||
}
|
||||
vim.api.nvim_buf_set_lines(0, 0, -1, false, template_lines)
|
||||
end
|
||||
|
||||
-- Set up autosave on buffer write
|
||||
vim.api.nvim_create_autocmd("BufWritePost", {
|
||||
buffer = 0,
|
||||
callback = function()
|
||||
vim.notify("💾 Idea saved to " .. file, vim.log.levels.INFO)
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
---Opens the idea file in a persistent right-side buffer
|
||||
---@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_right_side(file, filename)
|
||||
-- Create default path if none provided
|
||||
if not file then
|
||||
local idea_path = config.options.idea_dir
|
||||
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
|
||||
|
||||
current_file = file
|
||||
|
||||
-- Create buffer if it doesn't exist
|
||||
if not right_side_buf or not vim.api.nvim_buf_is_valid(right_side_buf) then
|
||||
right_side_buf = vim.api.nvim_create_buf(false, false)
|
||||
vim.api.nvim_buf_set_option(right_side_buf, "filetype", "markdown")
|
||||
vim.api.nvim_buf_set_option(right_side_buf, "buftype", "acwrite")
|
||||
vim.api.nvim_buf_set_option(right_side_buf, "bufhidden", "hide")
|
||||
|
||||
-- Set up autosave for the right-side buffer
|
||||
vim.api.nvim_create_autocmd("BufWriteCmd", {
|
||||
buffer = right_side_buf,
|
||||
callback = function()
|
||||
local lines = vim.api.nvim_buf_get_lines(right_side_buf, 0, -1, false)
|
||||
M.save_idea(lines, current_file)
|
||||
-- Prevent the default write behavior
|
||||
vim.api.nvim_command("setlocal nomodified")
|
||||
end,
|
||||
})
|
||||
|
||||
-- Set up key mappings for the right-side buffer
|
||||
vim.api.nvim_buf_set_keymap(right_side_buf, "n", "<C-t>", "", {
|
||||
callback = function()
|
||||
M.toggle_tree()
|
||||
end,
|
||||
noremap = true,
|
||||
silent = true,
|
||||
})
|
||||
|
||||
vim.api.nvim_buf_set_keymap(right_side_buf, "n", "<C-r>", "", {
|
||||
callback = function()
|
||||
M.refresh_current_file()
|
||||
end,
|
||||
noremap = true,
|
||||
silent = true,
|
||||
})
|
||||
end
|
||||
|
||||
-- Load file content or create new file template
|
||||
if vim.fn.filereadable(file) == 1 then
|
||||
local content = vim.fn.readfile(file)
|
||||
vim.api.nvim_buf_set_lines(right_side_buf, 0, -1, false, content)
|
||||
else
|
||||
vim.api.nvim_buf_set_lines(right_side_buf, 0, -1, false, {
|
||||
"# " .. (filename or "Idea for " .. os.date("%Y-%m-%d")),
|
||||
"",
|
||||
"- ",
|
||||
})
|
||||
end
|
||||
|
||||
-- Set the buffer name to show the current file
|
||||
vim.api.nvim_buf_set_name(right_side_buf, "ideaDrop://" .. (filename or os.date("%Y-%m-%d")))
|
||||
|
||||
-- Create or update the right-side window
|
||||
if not right_side_win or not vim.api.nvim_win_is_valid(right_side_win) then
|
||||
-- Calculate window dimensions (30% of screen width, full height)
|
||||
local width = math.floor(vim.o.columns * 0.3)
|
||||
local height = vim.o.lines - 2 -- Full height minus status line
|
||||
|
||||
-- Create the right-side window
|
||||
right_side_win = vim.api.nvim_open_win(right_side_buf, false, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = height,
|
||||
row = 0,
|
||||
col = vim.o.columns - width,
|
||||
border = "single",
|
||||
style = "minimal",
|
||||
})
|
||||
|
||||
-- Set window options
|
||||
vim.api.nvim_win_set_option(right_side_win, "wrap", true)
|
||||
vim.api.nvim_win_set_option(right_side_win, "number", true)
|
||||
vim.api.nvim_win_set_option(right_side_win, "relativenumber", false)
|
||||
vim.api.nvim_win_set_option(right_side_win, "cursorline", true)
|
||||
vim.api.nvim_win_set_option(right_side_win, "winhl", "Normal:Normal,FloatBorder:FloatBorder")
|
||||
|
||||
-- Set up autosave on window close
|
||||
vim.api.nvim_create_autocmd("WinClosed", {
|
||||
pattern = tostring(right_side_win),
|
||||
once = true,
|
||||
callback = function()
|
||||
local lines = vim.api.nvim_buf_get_lines(right_side_buf, 0, -1, false)
|
||||
M.save_idea(lines, current_file)
|
||||
right_side_win = nil
|
||||
end,
|
||||
})
|
||||
else
|
||||
-- Window exists, just switch to it
|
||||
vim.api.nvim_set_current_win(right_side_win)
|
||||
end
|
||||
|
||||
-- Focus on the right-side window
|
||||
vim.api.nvim_set_current_win(right_side_win)
|
||||
end
|
||||
|
||||
---Toggles the tree view
|
||||
---@return nil
|
||||
function M.toggle_tree()
|
||||
tree.open_tree_window(function(selected_file)
|
||||
-- Callback when a file is selected from the tree
|
||||
if selected_file then
|
||||
local filename = vim.fn.fnamemodify(selected_file, ":t")
|
||||
M.open_right_side(selected_file, filename)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
---Refreshes the current file in the right-side buffer
|
||||
---@return nil
|
||||
function M.refresh_current_file()
|
||||
if current_file and right_side_buf and vim.api.nvim_buf_is_valid(right_side_buf) then
|
||||
if vim.fn.filereadable(current_file) == 1 then
|
||||
local content = vim.fn.readfile(current_file)
|
||||
vim.api.nvim_buf_set_lines(right_side_buf, 0, -1, false, content)
|
||||
vim.notify("🔄 File refreshed", vim.log.levels.INFO)
|
||||
end
|
||||
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
|
||||
|
||||
---Gets the current file path from the right-side buffer
|
||||
---@return string|nil Current file path or nil if no file is open
|
||||
function M.get_current_file()
|
||||
return current_file
|
||||
end
|
||||
|
||||
return M
|
||||
138
lua/ideaDrop/ui/tree.lua
Normal file
138
lua/ideaDrop/ui/tree.lua
Normal file
@@ -0,0 +1,138 @@
|
||||
-- ideaDrop/ui/tree.lua
|
||||
local config = require("ideaDrop.core.config")
|
||||
|
||||
---@class Tree
|
||||
---@field open_tree_window fun(callback: fun(file_path: string): nil): nil
|
||||
local M = {}
|
||||
|
||||
-- Tree state
|
||||
local tree_callback = nil
|
||||
local original_cwd = nil
|
||||
|
||||
---Opens nvim-tree focused on the idea directory
|
||||
---@param callback fun(file_path: string): nil Callback function when a file is selected
|
||||
---@return nil
|
||||
function M.open_tree_window(callback)
|
||||
tree_callback = callback
|
||||
|
||||
-- Check if nvim-tree is available
|
||||
local has_nvim_tree, nvim_tree = pcall(require, "nvim-tree")
|
||||
if not has_nvim_tree then
|
||||
vim.notify("❌ nvim-tree is not installed. Please install nvim-tree to use this feature.", vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
-- Store original working directory
|
||||
original_cwd = vim.fn.getcwd()
|
||||
|
||||
-- Change to idea directory
|
||||
local idea_path = config.options.idea_dir
|
||||
if vim.fn.isdirectory(idea_path) == 1 then
|
||||
vim.cmd("cd " .. vim.fn.fnameescape(idea_path))
|
||||
else
|
||||
vim.notify("❌ Idea directory not found: " .. idea_path, vim.log.levels.ERROR)
|
||||
return
|
||||
end
|
||||
|
||||
-- Set up nvim-tree to open on the left side
|
||||
nvim_tree.setup({
|
||||
view = {
|
||||
side = "left",
|
||||
width = 30,
|
||||
},
|
||||
actions = {
|
||||
open_file = {
|
||||
quit_on_open = false,
|
||||
},
|
||||
},
|
||||
on_attach = function(bufnr)
|
||||
-- Override the default file opening behavior
|
||||
local api = require("nvim-tree.api")
|
||||
|
||||
-- Map Enter to custom handler
|
||||
vim.keymap.set("n", "<CR>", function()
|
||||
local node = api.tree.get_node_under_cursor()
|
||||
if node and node.type == "file" then
|
||||
-- Call our callback with the selected file
|
||||
if tree_callback then
|
||||
tree_callback(node.absolute_path)
|
||||
end
|
||||
-- Close nvim-tree
|
||||
api.tree.close()
|
||||
-- Restore original working directory
|
||||
if original_cwd then
|
||||
vim.cmd("cd " .. vim.fn.fnameescape(original_cwd))
|
||||
end
|
||||
else
|
||||
-- Default behavior for directories
|
||||
api.node.open.edit()
|
||||
end
|
||||
end, { buffer = bufnr, noremap = true, silent = true })
|
||||
|
||||
-- Map 'q' to close tree and restore directory
|
||||
vim.keymap.set("n", "q", function()
|
||||
api.tree.close()
|
||||
if original_cwd then
|
||||
vim.cmd("cd " .. vim.fn.fnameescape(original_cwd))
|
||||
end
|
||||
end, { buffer = bufnr, noremap = true, silent = true })
|
||||
|
||||
-- Keep other default mappings
|
||||
vim.keymap.set("n", "<C-]>", api.tree.change_root_to_node, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-e>", api.node.open.replace_tree_buffer, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-k>", api.node.show_info_popup, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-r>", api.fs.rename_sub, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-t>", api.node.open.tab, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-v>", api.node.open.vertical, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<C-x>", api.node.open.horizontal, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<BS>", api.node.navigate.parent_close, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<Tab>", api.node.open.preview, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", ">", api.node.navigate.sibling.next, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<", api.node.navigate.sibling.prev, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", ".", api.node.run.cmd, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "-", api.tree.change_root_to_parent, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "a", api.fs.create, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "bmv", api.marks.bulk.move, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "B", api.tree.toggle_no_buffer_filter, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "c", api.fs.copy.node, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "C", api.tree.toggle_git_clean_filter, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "[c", api.node.navigate.git.prev, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "]c", api.node.navigate.git.next, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "d", api.fs.remove, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "D", api.fs.trash, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "E", api.tree.expand_all, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "e", api.fs.rename_basename, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "]e", api.node.navigate.diagnostics.next, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "[e", api.node.navigate.diagnostics.prev, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "F", api.live_filter.clear, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "f", api.live_filter.start, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "g?", api.tree.toggle_help, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "gy", api.fs.copy.absolute_path, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "H", api.tree.toggle_hidden_filter, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "I", api.tree.toggle_gitignore_filter, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "J", api.node.navigate.sibling.last, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "K", api.node.navigate.sibling.first, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "m", api.marks.toggle, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "o", api.node.open.edit, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "O", api.node.open.no_window_picker, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "P", api.node.navigate.parent, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "r", api.fs.rename, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "R", api.tree.reload, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "s", api.node.run.system, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "S", api.tree.search_node, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "U", api.tree.toggle_custom_filter, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "W", api.tree.collapse_all, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "x", api.fs.cut, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "y", api.fs.copy.filename, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "Y", api.fs.copy.relative_path, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<2-LeftMouse>", api.node.open.edit, { buffer = bufnr, noremap = true, silent = true })
|
||||
vim.keymap.set("n", "<2-RightMouse>", api.tree.change_root_to_node, { buffer = bufnr, noremap = true, silent = true })
|
||||
end,
|
||||
})
|
||||
|
||||
-- Open nvim-tree using the correct API
|
||||
local api = require("nvim-tree.api")
|
||||
api.tree.open()
|
||||
end
|
||||
|
||||
return M
|
||||
Reference in New Issue
Block a user