organization because it was terrible before and hard to maintain. Now it should be much easier and there is still of a design decisions to figure out
190 lines
5.4 KiB
Lua
190 lines
5.4 KiB
Lua
local M = {}
|
|
|
|
---@param path string
|
|
---@return table
|
|
local function get_entries(path)
|
|
local result = {}
|
|
local handle = vim.uv.fs_scandir(path)
|
|
if not handle then return result end
|
|
while true do
|
|
local name, type = vim.uv.fs_scandir_next(handle)
|
|
if not name then break end
|
|
table.insert(result, {
|
|
name = name .. (type == "directory" and "/" or ""),
|
|
type = type,
|
|
full_path = path .. "/" .. name,
|
|
})
|
|
end
|
|
table.sort(result, function(a, b)
|
|
if a.type == "directory" and b.type ~= "directory" then return true end
|
|
if b.type == "directory" and a.type ~= "directory" then return false end
|
|
return a.name < b.name
|
|
end)
|
|
return result
|
|
end
|
|
|
|
---@param project_root string
|
|
function M.manager(project_root)
|
|
local templates = require("Polydev.templates")
|
|
local width, height = math.floor(vim.o.columns * 0.40), math.floor(vim.o.lines * 0.4)
|
|
local row, col = math.floor((vim.o.lines - height) / 3), math.floor((vim.o.columns - width) / 2)
|
|
local content_row = row + 2
|
|
local content_height = height - 3
|
|
|
|
local cwd = vim.fn.getcwd()
|
|
local current_view = {}
|
|
|
|
local content_buf = vim.api.nvim_create_buf(false, true)
|
|
local content_win = vim.api.nvim_open_win(content_buf, true, {
|
|
relative = "editor",
|
|
width = width,
|
|
height = content_height,
|
|
row = content_row,
|
|
col = col,
|
|
style = "minimal",
|
|
border = "rounded",
|
|
})
|
|
|
|
local function close_all_windows()
|
|
if vim.api.nvim_win_is_valid(content_win) then
|
|
pcall(vim.api.nvim_win_close, content_win, true)
|
|
end
|
|
end
|
|
|
|
local function update_screen()
|
|
local root = vim.fn.expand(project_root)
|
|
if vim.fn.isdirectory(root) == 0 then
|
|
vim.fn.mkdir(root, "p")
|
|
end
|
|
local entries = get_entries(cwd)
|
|
if not cwd:find(root, 1, true) then
|
|
cwd = root
|
|
entries = get_entries(cwd)
|
|
end
|
|
if cwd ~= root then
|
|
table.insert(entries, 1, {
|
|
name = "../",
|
|
type = "directory",
|
|
full_path = vim.fn.fnamemodify(cwd, ":h"),
|
|
is_up = true,
|
|
})
|
|
end
|
|
current_view = vim.deepcopy(entries)
|
|
|
|
local lines = {}
|
|
if #current_view == 0 then
|
|
table.insert(lines, "No projects found in " .. cwd)
|
|
table.insert(lines, "Press d to create a project, or a to add a folder.")
|
|
else
|
|
for i, item in ipairs(current_view) do
|
|
table.insert(lines, string.format("%-2d | %-27s | %-6s", i, item.name, item.type))
|
|
end
|
|
end
|
|
vim.api.nvim_buf_set_lines(content_buf, 0, -1, false, lines)
|
|
end
|
|
|
|
local function get_selected_entry()
|
|
local win = content_win
|
|
if not win or not vim.api.nvim_win_is_valid(win) then return end
|
|
local row = vim.api.nvim_win_get_cursor(win)[1]
|
|
return current_view[row], row
|
|
end
|
|
|
|
---@param type string
|
|
---@param callback fun(lang: string, name: string)
|
|
local function get_inputs(type, callback)
|
|
vim.ui.input({ prompt = "Enter language for new " .. type .. ": " }, function(lang)
|
|
if not lang or lang == "" then return end
|
|
vim.ui.input({ prompt = "Enter " .. type .. " name: " }, function(name)
|
|
if not name or name == "" then return end
|
|
callback(lang, name)
|
|
end)
|
|
end)
|
|
end
|
|
|
|
update_screen()
|
|
|
|
local buf = content_buf
|
|
vim.keymap.set("n", "<ESC>", function()
|
|
if vim.api.nvim_win_is_valid(content_win) then
|
|
pcall(vim.api.nvim_win_close, content_win, true)
|
|
end
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "a", function ()
|
|
vim.ui.input({ prompt = "New folder name: " }, function(input)
|
|
if input then
|
|
vim.fn.mkdir(cwd .. "/" .. input, "p")
|
|
update_screen()
|
|
end
|
|
end)
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "R", function ()
|
|
local entry = get_selected_entry()
|
|
if entry ~= nil and not entry.is_up then
|
|
vim.ui.input({ prompt = "Rename: ", default = entry.name }, function(input)
|
|
if input then
|
|
local new_path = cwd .. "/" .. input
|
|
vim.fn.rename(entry.full_path, new_path)
|
|
update_screen()
|
|
end
|
|
end)
|
|
end
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "D", function()
|
|
local entry = get_selected_entry()
|
|
if entry ~= nil and not entry.is_up then
|
|
vim.ui.input({ prompt = "Deletion of " .. entry.name .. ": (y/N) Defaults to N: " }, function(input)
|
|
if input == "y" or input == "Y" then
|
|
vim.fn.delete(entry.full_path, "rf")
|
|
update_screen()
|
|
end
|
|
end)
|
|
end
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "%", function()
|
|
get_inputs("file", function(lang, name)
|
|
local file = templates.files[lang]
|
|
if not file or not file.run then
|
|
return print("Error: No file creation method for " .. lang)
|
|
end
|
|
close_all_windows()
|
|
file.run(name)
|
|
end)
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "x", function()
|
|
get_inputs("aux file", function(lang, name)
|
|
close_all_windows()
|
|
templates.extras.run(lang, name)
|
|
end)
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "d", function()
|
|
get_inputs("project", function(lang, name)
|
|
local project = templates.projects[lang]
|
|
if not project or not project.run then
|
|
return print("Error: No project creation method for " .. lang)
|
|
end
|
|
local opts = require("Polydev.configs").get(lang)
|
|
local run_root = opts.project_root or project_root
|
|
close_all_windows()
|
|
project.run(name, run_root)
|
|
end)
|
|
end, { buffer = buf })
|
|
vim.keymap.set("n", "<CR>", function()
|
|
local entry = get_selected_entry()
|
|
if not entry then return end
|
|
|
|
if entry.type == "file" then
|
|
close_all_windows()
|
|
vim.cmd("edit " .. vim.fn.fnameescape(entry.full_path))
|
|
elseif entry.type == "directory" then
|
|
cwd = entry.full_path
|
|
vim.cmd("cd " .. cwd)
|
|
update_screen()
|
|
else
|
|
print("Error")
|
|
end
|
|
end, { buffer = buf })
|
|
end
|
|
|
|
return M
|