feat(ui): removed nui dependency and now have tabbed ui for current project and recent folders and files
chore(all): just cleaned up and removed some redundant code
This commit is contained in:
@@ -59,9 +59,9 @@ function M.setup(user_opts)
|
||||
},
|
||||
},
|
||||
terminal = {
|
||||
mode = "split", -- floating or split
|
||||
mode = "split",
|
||||
win = {
|
||||
type = "horizontal", anchor = "bottom", size = "20" -- type: "vertical" or "horizonal" -- anchor: "below" or "right" or "center" or "corner" -- size: amount of cols or rows based on percentage without percente symbol
|
||||
type = "horizontal", anchor = "bottom", size = "20"
|
||||
},
|
||||
border = {
|
||||
enabled = true,
|
||||
@@ -70,14 +70,9 @@ function M.setup(user_opts)
|
||||
},
|
||||
}
|
||||
|
||||
-- First merge global and terminal
|
||||
M.user_config = vim.tbl_deep_extend("force", {}, defaults, user_opts or {})
|
||||
local langs = default_languages(M.user_config.globals.project_root)
|
||||
|
||||
-- Now use the final resolved project_root from user_config
|
||||
local root = M.user_config.globals.project_root
|
||||
local langs = default_languages(root)
|
||||
|
||||
-- Inject languages into the config, respecting user overrides
|
||||
for lang, conf in pairs(langs) do
|
||||
M.user_config[lang] = vim.tbl_deep_extend("force", conf, M.user_config[lang] or {})
|
||||
end
|
||||
|
||||
+20
-1
@@ -21,7 +21,26 @@ function M.setup(opts)
|
||||
})
|
||||
vim.api.nvim_create_autocmd("ColorScheme", {
|
||||
callback = function()
|
||||
require("Polydev.styles").setup_highlights()
|
||||
local function define(name, o)
|
||||
if vim.fn.hlexists(name) == 0 then
|
||||
vim.api.nvim_set_hl(0, name, o)
|
||||
end
|
||||
end
|
||||
|
||||
define("PolydevNormal", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "NormalFloat", link = true }).fg,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
|
||||
define("PolydevBorder", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "FloatBorder", link = true }).fg,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
|
||||
define("PolydevTitle", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "FloatTitle", link = true }).fg, bold = true,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
end,
|
||||
})
|
||||
end
|
||||
|
||||
@@ -95,7 +95,7 @@ M.languages = {
|
||||
local success = vim.v.shell_error == 0
|
||||
|
||||
if not success then
|
||||
local term_buf, term_win = utils.terminal({ cmd })
|
||||
local term_buf = utils.terminal({ cmd })
|
||||
|
||||
vim.api.nvim_set_option_value("modifiable", true, { buf = term_buf })
|
||||
vim.api.nvim_buf_set_lines(term_buf, 0, -1, false,
|
||||
|
||||
+8
-19
@@ -1,28 +1,17 @@
|
||||
local M = {}
|
||||
|
||||
---@class padding
|
||||
---@field left_padding integer
|
||||
---@field right_padding integer
|
||||
---@field top_padding integer
|
||||
---@field bottom_padding integer
|
||||
|
||||
---@class preset_list
|
||||
---@field right padding
|
||||
---@field corner padding
|
||||
|
||||
---@type preset_list
|
||||
local presets = {
|
||||
right = {
|
||||
left_padding = 100,
|
||||
right_padding = 0,
|
||||
top_padding = 0,
|
||||
bottom_padding = 0,
|
||||
left = 100,
|
||||
right = 0,
|
||||
top = 0,
|
||||
bottom = 0,
|
||||
},
|
||||
corner = {
|
||||
left_padding = 100,
|
||||
right_padding = 0,
|
||||
top_padding = 25,
|
||||
bottom_padding = 0,
|
||||
left = 100,
|
||||
right = 0,
|
||||
top = 25,
|
||||
bottom = 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
local M = {}
|
||||
|
||||
function M.setup_highlights()
|
||||
local function define(name, opts)
|
||||
if vim.fn.hlexists(name) == 0 then
|
||||
vim.api.nvim_set_hl(0, name, opts)
|
||||
end
|
||||
end
|
||||
|
||||
define("PolydevNormal", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "NormalFloat", link = true }).fg,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
|
||||
define("PolydevBorder", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "Function", link = true }).fg,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
|
||||
define("PolydevTitle", {
|
||||
fg = vim.api.nvim_get_hl(0, { name = "FloatTitle", link = true }).fg, bold = true,
|
||||
bg = vim.api.nvim_get_hl(0, { name = "Normal", link = true }).bg,
|
||||
})
|
||||
end
|
||||
|
||||
return M
|
||||
+164
-168
@@ -7,196 +7,192 @@ local function get_entries(path)
|
||||
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)
|
||||
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 Popup = require("nui.popup")
|
||||
local Layout = require("nui.layout")
|
||||
local cwd = vim.fn.expand(vim.fn.getcwd())
|
||||
local entries = get_entries(cwd)
|
||||
local current_view = vim.deepcopy(entries)
|
||||
local ui = vim.api.nvim_list_uis()[1]
|
||||
local width, height = math.floor(ui.width * 0.8), math.floor(ui.height * 0.9)
|
||||
local row, col = math.floor((ui.height - height) / 2), math.floor((ui.width - width) / 2)
|
||||
local content_row = row + 2
|
||||
local content_height = height - 3
|
||||
|
||||
local popup = Popup({
|
||||
enter = true,
|
||||
focusable = true,
|
||||
border = {
|
||||
style = "rounded", -- "double", "none", "rounded", "shadow", "single" or "solid".
|
||||
text = { top = " Results ", top_align = "center" },
|
||||
},
|
||||
position = "50%",
|
||||
buf_options = { modifiable = true, readonly = false },
|
||||
win_options = {
|
||||
winhighlight = "Normal:PolydevNormal,FloatBorder:PolydevBorder,FloatTitle:PolydevTitle",
|
||||
}
|
||||
local tabs = { "Projects", "Recents" }
|
||||
local selected = 1
|
||||
local selected_tab = tabs[selected]
|
||||
|
||||
local cwd = vim.fn.getcwd()
|
||||
local current_view = {}
|
||||
|
||||
local tab_buf = vim.api.nvim_create_buf(false, true)
|
||||
local tab_win = vim.api.nvim_open_win(tab_buf, false, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = 1,
|
||||
row = row,
|
||||
col = col,
|
||||
style = "minimal",
|
||||
border = "rounded",
|
||||
})
|
||||
local layout = Layout(
|
||||
{
|
||||
position = "50%",
|
||||
size = { width = "80%", height = "90%" },
|
||||
},
|
||||
Layout.Box({ Layout.Box(popup, { grow = 1 }) }, { dir = "row" })
|
||||
)
|
||||
layout:mount()
|
||||
|
||||
---@return table, integer
|
||||
local function get_selected_entry()
|
||||
local row = vim.api.nvim_win_get_cursor(popup.winid)[1] - 1
|
||||
return current_view[row], row
|
||||
end
|
||||
local content_bufs = {
|
||||
Projects = vim.api.nvim_create_buf(false, true),
|
||||
Recents = vim.api.nvim_create_buf(false, true),
|
||||
}
|
||||
|
||||
local content_wins = {
|
||||
Projects = vim.api.nvim_open_win(content_bufs.Projects, true, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = content_height,
|
||||
row = content_row,
|
||||
col = col,
|
||||
style = "minimal",
|
||||
border = "rounded",
|
||||
}),
|
||||
Recents = nil,
|
||||
}
|
||||
|
||||
---@return string, string
|
||||
local function get_inputs()
|
||||
local l, n
|
||||
vim.ui.input({ prompt = "Enter language for new file: " }, function(lang)
|
||||
vim.ui.input({ prompt = "Enter file name: " }, function(name)
|
||||
if not lang or lang == "" then return end
|
||||
if not name or name == "" then return end
|
||||
l, n = lang, name
|
||||
end)
|
||||
end)
|
||||
return l, n
|
||||
local function update_tab_bar()
|
||||
local line = {}
|
||||
for i, tab in ipairs(tabs) do
|
||||
local label = (i == selected and "[ " .. tab .. " ]") or (" " .. tab .. " ")
|
||||
table.insert(line, label)
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(tab_buf, 0, -1, false, { table.concat(line, " ") })
|
||||
end
|
||||
|
||||
local function update_screen()
|
||||
entries = get_entries(cwd)
|
||||
local root = vim.fn.expand(project_root)
|
||||
if selected_tab == "Projects" then
|
||||
local entries = get_entries(cwd)
|
||||
local root = vim.fn.expand(project_root)
|
||||
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)
|
||||
|
||||
if not cwd:find(root, 1, true) then
|
||||
cwd = root
|
||||
entries = get_entries(cwd)
|
||||
end
|
||||
local lines = {}
|
||||
for i, item in ipairs(current_view) do
|
||||
table.insert(lines, string.format("%-2d | %-27s | %-6s", i, item.name, item.type))
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(content_bufs.Projects, 0, -1, false, lines)
|
||||
|
||||
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)
|
||||
elseif selected_tab == "Recents" then
|
||||
local oldfiles = vim.v.oldfiles
|
||||
local valid = {}
|
||||
for _, file in ipairs(oldfiles) do
|
||||
if vim.fn.filereadable(file) == 1 then
|
||||
table.insert(valid, file)
|
||||
end
|
||||
end
|
||||
current_view = vim.tbl_map(function(f)
|
||||
return { name = vim.fn.fnamemodify(f, ":t"), full_path = f, type = "file" }
|
||||
end, valid)
|
||||
|
||||
if not popup.bufnr then return end
|
||||
vim.api.nvim_buf_set_lines(popup.bufnr, 0, -1, false, {})
|
||||
for i, item in ipairs(current_view) do
|
||||
local line = string.format("%-2d | %-27s | %-6s", i, item.name, item.type)
|
||||
vim.api.nvim_buf_set_lines(popup.bufnr, -1, -1, false, { line })
|
||||
end
|
||||
local lines = {}
|
||||
for i, item in ipairs(current_view) do
|
||||
table.insert(lines, string.format("%-2d | %-40s", i, item.full_path))
|
||||
end
|
||||
vim.api.nvim_buf_set_lines(content_bufs.Recents, 0, -1, false, lines)
|
||||
end
|
||||
end
|
||||
|
||||
popup:map("n", "<ESC>", function() popup:unmount() end)
|
||||
local function get_selected_entry()
|
||||
local win = content_wins[selected_tab]
|
||||
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
|
||||
|
||||
popup:map("n", "a", function()
|
||||
vim.ui.input({ prompt = "New folder name: " }, function(input)
|
||||
if input then
|
||||
vim.fn.mkdir(cwd .. "/" .. input, "p")
|
||||
local function switch_tab(index)
|
||||
if content_wins[selected_tab] and vim.api.nvim_win_is_valid(content_wins[selected_tab]) then
|
||||
vim.api.nvim_win_hide(content_wins[selected_tab])
|
||||
end
|
||||
|
||||
selected = ((index - 1) % #tabs) + 1
|
||||
selected_tab = tabs[selected]
|
||||
|
||||
if not content_wins[selected_tab] or not vim.api.nvim_win_is_valid(content_wins[selected_tab]) then
|
||||
content_wins[selected_tab] = vim.api.nvim_open_win(content_bufs[selected_tab], true, {
|
||||
relative = "editor",
|
||||
width = width,
|
||||
height = content_height,
|
||||
row = content_row,
|
||||
col = col,
|
||||
style = "minimal",
|
||||
border = "rounded",
|
||||
})
|
||||
else
|
||||
vim.api.nvim_set_current_win(content_wins[selected_tab])
|
||||
end
|
||||
|
||||
update_tab_bar()
|
||||
update_screen()
|
||||
end
|
||||
|
||||
update_tab_bar()
|
||||
update_screen()
|
||||
|
||||
-- Shared mappings
|
||||
for _, buf in pairs(content_bufs) do
|
||||
vim.keymap.set("n", "<Tab>", function() switch_tab(selected + 1) end, { buffer = buf })
|
||||
vim.keymap.set("n", "gT", function() switch_tab(selected - 1) end, { buffer = buf })
|
||||
vim.keymap.set("n", "<ESC>", function()
|
||||
for _, win in pairs(content_wins) do
|
||||
if win and vim.api.nvim_win_is_valid(win) then
|
||||
pcall(vim.api.nvim_win_close, win, true)
|
||||
end
|
||||
end
|
||||
pcall(vim.api.nvim_win_close, tab_win, true)
|
||||
end, { buffer = buf })
|
||||
end
|
||||
|
||||
-- Open file
|
||||
for tab, buf in pairs(content_bufs) do
|
||||
vim.keymap.set("n", "<CR>", function()
|
||||
local entry = get_selected_entry()
|
||||
if not entry then return end
|
||||
|
||||
if entry.type == "file" then
|
||||
for _, win in pairs(content_wins) do
|
||||
if win and vim.api.nvim_win_is_valid(win) then
|
||||
pcall(vim.api.nvim_win_close, win, true)
|
||||
end
|
||||
end
|
||||
pcall(vim.api.nvim_win_close, tab_win, true)
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(entry.full_path))
|
||||
|
||||
elseif entry.type == "directory" then
|
||||
cwd = entry.full_path
|
||||
vim.cmd("cd " .. cwd)
|
||||
update_screen()
|
||||
end
|
||||
end)
|
||||
end)
|
||||
end, { buffer = buf })
|
||||
|
||||
popup:map("n", "R", function()
|
||||
local entry = get_selected_entry()
|
||||
if 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)
|
||||
|
||||
popup:map("n", "<CR>", function()
|
||||
local entry = get_selected_entry()
|
||||
if entry.type == "directory" then
|
||||
cwd = entry.full_path
|
||||
vim.cmd("cd " .. cwd)
|
||||
update_screen()
|
||||
end
|
||||
if entry.type == "file" then
|
||||
popup:unmount()
|
||||
vim.cmd("edit " .. vim.fn.fnameescape(entry.full_path))
|
||||
end
|
||||
end)
|
||||
|
||||
popup:map("n", "D", function()
|
||||
local entry = get_selected_entry()
|
||||
if 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)
|
||||
|
||||
popup:map("n", "%", function()
|
||||
local lang, name = get_inputs()
|
||||
if lang == nil or lang == "" then return print("Error: Can't have a blank name for lang") end
|
||||
if templates.files[lang].run then
|
||||
popup:unmount()
|
||||
if name ~= nil and name ~= "" then
|
||||
templates.files[lang].run(name)
|
||||
end
|
||||
else
|
||||
print("Error: No File creation method for " .. lang)
|
||||
end
|
||||
end)
|
||||
|
||||
popup:map("n", "x", function()
|
||||
local lang, name = get_inputs()
|
||||
if lang == nil or lang == "" then return print("Error: Can't have a blank name for lang") end
|
||||
if templates.extras.run then
|
||||
popup:unmount()
|
||||
if name ~= nil and name ~= "" then
|
||||
templates.extras.run(lang, name)
|
||||
end
|
||||
else
|
||||
print("Error: No File creation method for " .. lang)
|
||||
end
|
||||
end)
|
||||
|
||||
popup:map("n", "d", function()
|
||||
local lang, name = get_inputs()
|
||||
local opts = {}
|
||||
opts = vim.tbl_deep_extend("force", {}, require("Polydev.configs").get(lang), opts or {})
|
||||
if lang == nil or lang == "" then return print("Error: Can't have a blank name for lang") end
|
||||
if templates.projects[lang].run then
|
||||
popup:unmount()
|
||||
if name ~= nil and name ~= "" then
|
||||
templates.projects[lang].run(name, opts.project_root)
|
||||
end
|
||||
else
|
||||
print("Error: No project creation method for " .. lang)
|
||||
end
|
||||
end)
|
||||
|
||||
popup:mount()
|
||||
update_screen()
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
||||
@@ -15,8 +15,7 @@ end
|
||||
|
||||
---@return string
|
||||
function M.get_project_name()
|
||||
local root = M.get_project_root()
|
||||
return vim.fn.fnamemodify(root, ":t")
|
||||
return vim.fn.fnamemodify(M.get_project_root(), ":t")
|
||||
end
|
||||
|
||||
---@param path_segments table
|
||||
@@ -36,9 +35,8 @@ function M.init_git(path, gitignore_lines)
|
||||
vim.fn.system({ "git", "-C", path, "init" })
|
||||
|
||||
if gitignore_lines and #gitignore_lines > 0 then
|
||||
local gitignore_path = { path, ".gitignore" }
|
||||
local contents = table.concat(gitignore_lines, "\n")
|
||||
M.write_file(gitignore_path, contents)
|
||||
M.write_file({ path, ".gitignore" }, contents)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -55,10 +53,10 @@ function M.terminal(cmd)
|
||||
local col
|
||||
|
||||
if opts ~= nil then
|
||||
width = math.max(1, math.floor(ui.width * 0.9) - opts.left_padding - opts.right_padding)
|
||||
height = math.max(1, math.floor(ui.height * 0.9) - opts.top_padding - opts.bottom_padding)
|
||||
row = math.floor((ui.height - height) / 2) + opts.top_padding
|
||||
col = math.floor((ui.width - width) / 2) + opts.left_padding
|
||||
width = math.max(1, math.floor(ui.width * 0.9) - opts.left - opts.right)
|
||||
height = math.max(1, math.floor(ui.height * 0.9) - opts.top - opts.bottom)
|
||||
row = math.floor((ui.height - height) / 2) + opts.top
|
||||
col = math.floor((ui.width - width) / 2) + opts.left
|
||||
end
|
||||
if opts == nil then
|
||||
width = math.max(1, math.floor(ui.width * 0.9))
|
||||
|
||||
Reference in New Issue
Block a user