From 4bcac5d09b54150b15f376cb798831e10dd6a479 Mon Sep 17 00:00:00 2001 From: Andrew Haynes Date: Thu, 15 Oct 2026 02:07:14 -0400 Subject: [PATCH] REFACTOR: I spent all day on it but I am heavily refactoring the API and 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 --- README.md | 10 +- lua/Polydev/configs.lua | 83 ----- lua/Polydev/init.lua | 51 ---- lua/Polydev/languages.lua | 226 -------------- lua/Polydev/utils.lua | 114 ------- lua/vern/actions/python.lua | 42 +++ lua/vern/attach/init.lua | 25 ++ lua/vern/attach/python.lua | 43 +++ lua/vern/configs/default.lua | 15 + lua/vern/configs/python.lua | 43 +++ lua/{Polydev => vern}/health.lua | 0 lua/vern/init.lua | 20 ++ lua/vern/languages.lua | 389 ++++++++++++++++++++++++ lua/{Polydev => vern}/presets.lua | 0 lua/vern/providers/python/uv.lua | 3 + lua/vern/scratchpad | 23 ++ lua/{Polydev => vern}/templates.lua | 0 lua/vern/templates/extras/gitignore.lua | 31 ++ lua/vern/templates/python/__init__.lua | 13 + lua/vern/templates/python/main.lua | 15 + lua/vern/templates/python/module.lua | 13 + lua/vern/templates/python/pyproject.lua | 25 ++ lua/{Polydev => vern}/ui.lua | 0 lua/vern/utils.lua | 149 +++++++++ plugin/Polydev.lua | 1 - plugin/vern.lua | 1 + stylua.toml | 20 ++ 27 files changed, 875 insertions(+), 480 deletions(-) delete mode 100644 lua/Polydev/configs.lua delete mode 100644 lua/Polydev/init.lua delete mode 100644 lua/Polydev/languages.lua delete mode 100644 lua/Polydev/utils.lua create mode 100644 lua/vern/actions/python.lua create mode 100644 lua/vern/attach/init.lua create mode 100644 lua/vern/attach/python.lua create mode 100644 lua/vern/configs/default.lua create mode 100644 lua/vern/configs/python.lua rename lua/{Polydev => vern}/health.lua (100%) create mode 100644 lua/vern/init.lua create mode 100644 lua/vern/languages.lua rename lua/{Polydev => vern}/presets.lua (100%) create mode 100644 lua/vern/providers/python/uv.lua create mode 100644 lua/vern/scratchpad rename lua/{Polydev => vern}/templates.lua (100%) create mode 100644 lua/vern/templates/extras/gitignore.lua create mode 100644 lua/vern/templates/python/__init__.lua create mode 100644 lua/vern/templates/python/main.lua create mode 100644 lua/vern/templates/python/module.lua create mode 100644 lua/vern/templates/python/pyproject.lua rename lua/{Polydev => vern}/ui.lua (100%) create mode 100644 lua/vern/utils.lua delete mode 100644 plugin/Polydev.lua create mode 100644 plugin/vern.lua create mode 100644 stylua.toml diff --git a/README.md b/README.md index b14bcf6..7e747cf 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -

Polydev

+

Vern.nvim

-

A multi-language project managing plugin for file creation, building, and running code—all within neovim. Whether you're coding in C/C++ Java, Python, Lua, Rust, and more, Polydev provides seamless integration to boost your productivity inside Neovim.

+

Vern.nvim or Vernacular.nvim is a multi lingual project manager. It creates new projects and files from templates, builds and runs code and can run language specific functions within Neovim

@@ -19,13 +19,13 @@ * Integrated terminal for flexible command execution * Lightweight, fast project manager UI * Minimal configuration with extensibility in mind -* Built-in diagnostics with `:checkhealth Polydev` +* Built-in diagnostics with `:checkhealth Vern.nvim` > 📚 [View the full documentation](https://git.moomancer.xyz/DarthMooMancer/polydev/wiki/Home$0) for setup, configuration, and usage details. ## Supported Languages -Polydev currently supports the following languages: +Vern.nvim currently supports the following languages: * Java * Python @@ -52,4 +52,4 @@ Contributions are welcome and appreciated. * Submit a pull request if you'd like to contribute directly. If you have an idea or use case you'd like to see supported, let’s discuss it. -Your feedback and contributions are key to making Polydev even better! Thank you for being part of the journey. 🙏 +Your feedback and contributions are key to making Vern.nvim even better! Thank you for being part of the journey. 🙏 diff --git a/lua/Polydev/configs.lua b/lua/Polydev/configs.lua deleted file mode 100644 index c313e23..0000000 --- a/lua/Polydev/configs.lua +++ /dev/null @@ -1,83 +0,0 @@ -local M = {} - -M.user_config = {} - ----@param user_opts table -function M.setup(user_opts) - user_opts = user_opts or {} - local project_root = (user_opts.globals and user_opts.globals.project_root) or "~/personal/Projects" - local defaults = { - rust = { - project_root = project_root .. "/Rust", - keybinds = { - ["pr"] = "RustRun", - }, - }, - javascript = { - project_root = project_root .. "/Javascript", - keybinds = { - ["pr"] = "JavascriptRun", - }, - }, - java = { - project_root = project_root .. "/Java", - keybinds = { - ["pr"] = "JavaRun", - }, - }, - lua = { - project_root = project_root .. "/Lua", - keybinds = { - ["pr"] = "LuaRun", - }, - }, - c = { - project_root = project_root .. "/C", - keybinds = { - ["pr"] = "CRun", - }, - }, - cpp = { - project_root = project_root .. "/CPP", - keybinds = { - ["pr"] = "CppRun", - }, - }, - python = { - project_root = project_root .. "/Python", - keybinds = { - ["pr"] = "PythonRun", - ["pb"] = "PythonPip", - }, - }, - html = { - project_root = project_root .. "/Html", - }, - globals = { - project_root = project_root, - keybinds = { - ["po"] = "PolydevOpen", - }, - }, - terminal = { - mode = "split", - win = { - type = "horizontal", anchor = "bottom", size = "20" - }, - border = { - enabled = true, - type = "rounded", - }, - }, - } - - M.user_config = vim.tbl_deep_extend("force", defaults, user_opts) -end - ----@param lang string ----@return table -function M.get(lang) - return M.user_config[lang] or {} -end - -return M diff --git a/lua/Polydev/init.lua b/lua/Polydev/init.lua deleted file mode 100644 index ebd8bc9..0000000 --- a/lua/Polydev/init.lua +++ /dev/null @@ -1,51 +0,0 @@ -local M = {} - -function M.setup(opts) - opts = opts or {} - local config = require("Polydev.configs") - if config == nil then - return -1 - end - config.setup(opts) - require("Polydev.utils").setup(opts) - - vim.api.nvim_create_user_command("PolydevOpen", function() require("Polydev.ui").manager(config.get("globals").project_root) end, {}) - - local keys = vim.tbl_deep_extend("force", {}, config.get("globals").keybinds, opts.keybinds or {}) - for key, _ in pairs(keys) do - vim.keymap.set("n", key, ":PolydevOpen") - end - - vim.api.nvim_create_autocmd("FileType", { - pattern = "*", - callback = function() - local filetype = vim.bo.filetype - require("Polydev.languages").load_language_module(filetype, opts) - end, - }) - vim.api.nvim_create_autocmd("ColorScheme", { - callback = function() - 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 - -return M diff --git a/lua/Polydev/languages.lua b/lua/Polydev/languages.lua deleted file mode 100644 index b770acd..0000000 --- a/lua/Polydev/languages.lua +++ /dev/null @@ -1,226 +0,0 @@ -local utils = require("Polydev.utils") -local configs = require("Polydev.configs") -local M = {} - -local loaded_languages = {} - ----@param lang string ----@param opts? table ----@return boolean -function M.load_language_module(lang, opts) - if loaded_languages[lang] then return true end - - local ok, mod = pcall(require, "Polydev.languages") - if not ok or type(mod.languages) ~= "table" then return false end - - local lang_mod = mod.languages[lang] - if type(lang_mod) ~= "table" or type(lang_mod.setup) ~= "function" then return false end - - lang_mod:setup(opts and opts[lang] or {}) - loaded_languages[lang] = lang_mod - return true -end - -M.languages = { - javascript = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("javascript"), user_opts or {}) - vim.api.nvim_create_user_command("JavascriptRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":JavascriptRun", { silent = true }) - end - end, - run = function() - local root = utils.get_project_root() - - local cmd = string.format("node " .. root .. "/main.js") - local output = vim.fn.system(cmd) - - if not vim.v.shell_error == 0 then - 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, - vim.list_extend({ "Error during compilation:" }, - vim.split(output, "\n", { trimempty = true })) - ) - vim.api.nvim_set_option_value("modifiable", false, { buf = term_buf }) - else - utils.terminal({ "node " .. root .. "/main.js" }) - end - end - }, - java = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("java"), user_opts or {}) - vim.api.nvim_create_user_command("JavaRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":JavaRun", { silent = true }) - end - end, - run = function() - local root = utils.get_project_root() - - local cmd = string.format("javac -d %s %s", root .. "/build", root .. "/src/*.java") - local output = vim.fn.system(cmd) - - if not vim.v.shell_error == 0 then - 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, - vim.list_extend({ "Error during compilation:" }, - vim.split(output, "\n", { trimempty = true })) - ) - vim.api.nvim_set_option_value("modifiable", false, { buf = term_buf }) - else - utils.terminal({ "java -cp " .. root, "build" .. " Main" }) - end - end - }, - c = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("c"), user_opts or {}) - vim.api.nvim_create_user_command("CRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":CRun", { silent = true }) - end - end, - run = function() - local root = utils.get_project_root() - local build_dir = root .. "/build" - - local cmd = "cd '" .. build_dir .. "' && cmake --build ." - local output = vim.fn.system(cmd) - local success = vim.v.shell_error == 0 - - if not success then - 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, - vim.list_extend({ "Error during compilation:" }, - vim.split(output, "\n", { trimempty = true })) - ) - vim.api.nvim_set_option_value("modifiable", false, { buf = term_buf }) - end - if success then - local run_cmd = "cd '" .. build_dir .. "' && ./" .. utils.get_project_name() - utils.terminal({ run_cmd }) - end - end - }, - cpp = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("cpp"), user_opts or {}) - vim.api.nvim_create_user_command("CppRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":CppRun", { silent = true }) - end - end, - run = function() - local root = utils.get_project_root() - local build_dir = root .. "/build" - - local cmd = "cd '" .. build_dir .. "' && cmake --build ." - local output = vim.fn.system(cmd) - local success = vim.v.shell_error == 0 - - if not success then - 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, - vim.list_extend({ "Error during compilation:" }, - vim.split(output, "\n", { trimempty = true })) - ) - vim.api.nvim_set_option_value("modifiable", false, { buf = term_buf }) - end - if success then - local run_cmd = "cd '" .. build_dir .. "' && ./" .. utils.get_project_name() - utils.terminal({ run_cmd }) - end - end - }, - html = { - setup = function(user_opts) - vim.tbl_deep_extend("force", {}, configs.get("html"), user_opts or {}) - end - }, - rust = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("rust"), user_opts or {}) - vim.api.nvim_create_user_command("RustRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":RustRun", { silent = true }) - end - end, - run = function() - local root = utils.get_project_root() - if not root then return print("Error: Project root not found.") end - - local cmd = { "cargo build" } - local output = vim.fn.system(table.concat(cmd)) - - if not vim.v.shell_error == 0 then - 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, - vim.list_extend({ "Error during compilation:" }, - vim.split(output, "\n", { trimempty = true })) - ) - vim.api.nvim_set_option_value("modifiable", false, { buf = term_buf }) - else - utils.terminal({ "cargo run" }) - end - end - }, - python = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("python"), user_opts or {}) - vim.api.nvim_create_user_command("PythonPip", function() self:install_dependency() end, {}) - vim.api.nvim_create_user_command("PythonRun", function() self:run() end, {}) - for key, command in pairs(opts.keybinds) do - if command == "PythonRun" then - vim.keymap.set("n", key, ":PythonRun", { silent = true }) - end - if command == "PythonPip" then - vim.keymap.set("n", key, ":PythonPip", { silent = true }) - end - end - - local root = utils.get_project_root() - if root then - local venv_path = root .. "/venv/bin/activate" - if vim.fn.filereadable(venv_path) == 1 then - vim.env.VIRTUAL_ENV = venv_path - vim.env.PATH = root .. "/venv/bin:" .. vim.env.PATH - end - end - end, - install_dependency = function() - vim.ui.input({ prompt = "Enter pip module: " }, function(pip_module) - if not pip_module or pip_module == "" then return print("Pip canceled") end - utils.terminal({ "pip install " .. pip_module }) - end) - end, - run = function() - utils.terminal({ "python3 " .. utils.get_project_root(), "main.py" }) - end - }, - lua = { - setup = function(self, user_opts) - local opts = vim.tbl_deep_extend("force", {}, configs.get("lua"), user_opts or {}) - vim.api.nvim_create_user_command("LuaRun", function() self:run() end, {}) - for key, _ in pairs(opts.keybinds) do - vim.keymap.set("n", key, ":LuaRun", { silent = true }) - end - end, - run = function() - local init_lua_path = utils.get_project_root() .. - "/lua/" .. utils.get_project_name() .. "/init.lua" - if vim.fn.filereadable(init_lua_path) == 1 then - utils.terminal({ "lua " .. init_lua_path }) - end - end - }, -} - -return M diff --git a/lua/Polydev/utils.lua b/lua/Polydev/utils.lua deleted file mode 100644 index 793b11d..0000000 --- a/lua/Polydev/utils.lua +++ /dev/null @@ -1,114 +0,0 @@ -local M = {} -M.opts = {} - -function M.setup(opts) - M.opts = vim.tbl_deep_extend("force", {}, require("Polydev.configs").get("terminal"), opts or {}) -end - -function M.exists(path) - return (io.open(path, "r") ~= nil) -end - ----@return string -function M.get_project_root() - local plugin_dir = vim.fn.fnamemodify(debug.getinfo(1, "S").source:sub(2), ":h:h:h") - - local dir = vim.fn.system(plugin_dir .. "/bash_scripts/walkup.sh"):gsub("%s+$", "") - return dir -end - ----@return string -function M.get_project_name() - return vim.fn.fnamemodify(M.get_project_root(), ":t") -end - ----@param path_segments table ----@param content string -function M.write_file(path_segments, content) - local path = table.concat(path_segments, "/") - local file = assert(io.open(path, "w"), "Error creating file: " .. path) - file:write(content) - file:close() - vim.cmd("edit " .. path) -end - ----@param path string ----@param gitignore_lines table -function M.init_git(path, gitignore_lines) - vim.fn.mkdir(path, "p") - vim.fn.system({ "git", "-C", path, "init" }) - - if gitignore_lines and #gitignore_lines > 0 then - local contents = table.concat(gitignore_lines, "\n") - M.write_file({ path, ".gitignore" }, contents) - end -end - ----@param cmd table ----@return integer, integer? -function M.terminal(cmd) - if M.opts.mode == "floating" then - local opts = require("Polydev.presets").getPresets(M.opts.win.anchor) - - local ui = vim.api.nvim_list_uis()[1] - local width, height, row, col - - if opts ~= nil then - 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)) - height = math.max(1, math.floor(ui.height * 0.9)) - row = math.floor((ui.height - height) / 2) - col = math.floor((ui.width - width) / 2) - end - local buf = vim.api.nvim_create_buf(false, true) - local win = vim.api.nvim_open_win(buf, true, { - relative = "editor", - width = width, - height = height, - row = row, - col = col, - style = "minimal", - border = M.opts.border.enabled and M.opts.border.type, - }) - vim.api.nvim_set_option_value("winhighlight", "Normal:PolydevNormal,FloatBorder:PolydevBorder", - { win = win }) - vim.fn.jobstart(table.concat(cmd, "/"), { term = true }) - vim.api.nvim_buf_set_keymap(buf, "n", "", "i:q", { noremap = true, silent = true }) - return buf, win - end - if M.opts.mode == "split" then - if M.opts.win.type == "vertical" then - if M.opts.win.anchor == "right" then - vim.cmd("set splitright") - end - end - if M.opts.win.type == "horizontal" then - if M.opts.win.anchor == "bottom" then - vim.cmd("set splitbelow") - end - end - - if M.opts.win.type == "vertical" then - vim.cmd(M.opts.win.size .. " vsplit") - end - if M.opts.win.type == "horizontal" then - vim.cmd(M.opts.win.size .. " split") - end - local buf = vim.api.nvim_create_buf(false, true) - local win = vim.api.nvim_get_current_win() - - vim.api.nvim_win_set_buf(0, buf) - - vim.fn.jobstart(table.concat(cmd, "/"), { term = true }) - vim.api.nvim_buf_set_keymap(buf, "n", "", "i:q", { noremap = true, silent = true }) - return buf, win - end - return 0 -end - -return M diff --git a/lua/vern/actions/python.lua b/lua/vern/actions/python.lua new file mode 100644 index 0000000..33bc89d --- /dev/null +++ b/lua/vern/actions/python.lua @@ -0,0 +1,42 @@ +local M = {} + +local utils = require("vern.utils") +M.default_target_file = "main.py" + +--- Goal is to add providers for uv and venv so its available to more users +---@param opts? table Takes a table for the runtime +function M.run(opts) + opts = opts or {} + local root = utils.get_project_root() or "." + local project_name = vim.fs.basename(root) + + local pattern = vim.tbl_get( + opts, + "templates", + "project", + "executable", + "target" + ) or "src/%s/main.py" + local rel_path = pattern:find("%%s") + and string.format(pattern, project_name) + or pattern + local full_path = root .. "/" .. rel_path + utils.terminal({ "python3 " .. full_path }, opts) +end + +---@param cmd_args? table Takes a table for the runtime +function M.pip_install(opts, cmd_args) + if cmd_args and cmd_args.args and cmd_args ~= "" then + utils.terminal({ "pip install " .. cmd_args.args }) + return + end + vim.ui.input({ prompt = "Enter pip module: " }, function(pip_module) + if not pip_module or pip_module == "" then + vim.notify("Pip Cancelled", vim.log.levels.WARN) + return + end + utils.terminal({ "pip install " .. pip_module }, opts or {}) + end) +end + +return M diff --git a/lua/vern/attach/init.lua b/lua/vern/attach/init.lua new file mode 100644 index 0000000..a6bdcd6 --- /dev/null +++ b/lua/vern/attach/init.lua @@ -0,0 +1,25 @@ +local M = {} + +function M.buf(bufnr, user_opts) + bufnr = (bufnr == nil or bufnr == 0) and vim.api.nvim_get_current_buf() + or bufnr + local ft = vim.bo[bufnr].filetype + if not ft or ft == "" then + return + end + + user_opts = user_opts or {} + + local default = require("vern.configs.default") + + local lang_opts = (user_opts or {})[ft] or {} + local final_opts = + vim.tbl_deep_extend("force", {}, default, user_opts, lang_opts) + final_opts[ft] = nil + local ok, lang_attach = pcall(require, "vern.attach." .. ft) --- like a try / catch block in c++ + if ok and type(lang_attach) == "function" then + lang_attach(bufnr, final_opts) + end +end + +return M diff --git a/lua/vern/attach/python.lua b/lua/vern/attach/python.lua new file mode 100644 index 0000000..b1a1f08 --- /dev/null +++ b/lua/vern/attach/python.lua @@ -0,0 +1,43 @@ +local actions = require("vern.actions.python") +local config = require("vern.configs.python") + +return function(bufnr, user_opts) + local opts = vim.tbl_deep_extend("force", {}, config, user_opts or {}) + vim.api.nvim_buf_create_user_command(bufnr, "Pythonrun", function() + if actions.run then + actions.run(opts) + end + end, { desc = "Run python project" }) + + vim.api.nvim_buf_create_user_command(bufnr, "Pythonpip", function(cmd_args) + if actions.pip_install then + actions.pip_install(opts, cmd_args) + end + end, { nargs = "*", desc = "Install python packages" }) + + for key, def in pairs(opts.keybinds or {}) do + if type(def.action) == "function" then + vim.keymap.set("n", key, function() + def.action(opts) + end, { + buffer = bufnr, + silent = true, + desc = def.desc, + }) + end + end + + local root = require("vern.utils").get_project_root() + if root then + local venv_dir = nil + if vim.uv.fs_stat(root .. "/venv/bin/python") then + venv_dir = root .. "/venv" + elseif vim.uv.fs_stat(root .. "/.venv/bin/python") then + venv_dir = root .. "/.venv" + end + if venv_dir then + vim.env.VIRTUAL_ENV = venv_dir + vim.env.PATH = venv_dir .. "/bin:" .. vim.env.PATH + end + end +end diff --git a/lua/vern/configs/default.lua b/lua/vern/configs/default.lua new file mode 100644 index 0000000..8bd048c --- /dev/null +++ b/lua/vern/configs/default.lua @@ -0,0 +1,15 @@ +return { + workspace_root = "~/personal/Projects", + terminal = { + mode = "split", + win = { + type = "horizontal", + anchor = "bottom", + size = "20", + }, + border = { + enabled = true, + type = "rounded", + }, + }, +} diff --git a/lua/vern/configs/python.lua b/lua/vern/configs/python.lua new file mode 100644 index 0000000..1d64bc9 --- /dev/null +++ b/lua/vern/configs/python.lua @@ -0,0 +1,43 @@ +local actions = require("vern.actions.python") + +return { + root = "Python", --- later will concat the project_root to the front + keybinds = { + ["pr"] = { + desc = "Executes python code", + action = actions.run, + }, + ["pb"] = { + desc = "Asks for what python package to install", + action = actions.pip_install, + }, + }, + templates = { + project = { + ["executable"] = { + template = "vern.templates.python.main", + target = "src/%s/main.py", + }, + ["init"] = { + template = "vern.templates.python.__init__", + target = "src/%s/__init__.py", + }, + ["manifest"] = { + template = "vern.templates.python.pyproject", + target = "pyproject.toml", + }, + }, + file = { + ["module"] = { + template = "vern.templates.python.module", + target = "src/%s.py", + }, + }, + extras = { + ["gitignore"] = { + template = "vern.templates.extras.gitignore", + target = ".gitignore", + }, + }, + }, +} diff --git a/lua/Polydev/health.lua b/lua/vern/health.lua similarity index 100% rename from lua/Polydev/health.lua rename to lua/vern/health.lua diff --git a/lua/vern/init.lua b/lua/vern/init.lua new file mode 100644 index 0000000..6614192 --- /dev/null +++ b/lua/vern/init.lua @@ -0,0 +1,20 @@ +local M = {} + +M.user_opts = {} + +function M.setup(opts) + M.user_opts = opts or {} + local group = + vim.api.nvim_create_augroup("VernAutocommands", { clear = true }) + + vim.api.nvim_create_autocmd("FileType", { + group = group, + pattern = "*", + callback = function(args) + require("vern.attach").buf(args.buf, M.user_opts) + end, + desc = "Attach languages to buffer", + }) +end + +return M diff --git a/lua/vern/languages.lua b/lua/vern/languages.lua new file mode 100644 index 0000000..6f6b24f --- /dev/null +++ b/lua/vern/languages.lua @@ -0,0 +1,389 @@ +local utils = require("Polydev.utils") +local configs = require("Polydev.configs") +local M = {} + +local loaded_languages = {} + +---@param lang string +---@param opts? table +---@return boolean +function M.load_language_module(lang, opts) + if loaded_languages[lang] then + return true + end + + local ok, mod = pcall(require, "Polydev.languages") + if not ok or type(mod.languages) ~= "table" then + return false + end + + local lang_mod = mod.languages[lang] + if type(lang_mod) ~= "table" or type(lang_mod.setup) ~= "function" then + return false + end + + lang_mod:setup(opts and opts[lang] or {}) + loaded_languages[lang] = lang_mod + return true +end + +M.languages = { + javascript = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("javascript"), + user_opts or {} + ) + vim.api.nvim_create_user_command("JavascriptRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set( + "n", + key, + ":JavascriptRun", + { silent = true } + ) + end + end, + run = function() + local root = utils.get_project_root() + + local cmd = string.format("node " .. root .. "/main.js") + local output = vim.fn.system(cmd) + + if not vim.v.shell_error == 0 then + 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, + vim.list_extend( + { "Error during compilation:" }, + vim.split(output, "\n", { trimempty = true }) + ) + ) + vim.api.nvim_set_option_value( + "modifiable", + false, + { buf = term_buf } + ) + else + utils.terminal({ "node " .. root .. "/main.js" }) + end + end, + }, + java = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("java"), + user_opts or {} + ) + vim.api.nvim_create_user_command("JavaRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set("n", key, ":JavaRun", { silent = true }) + end + end, + run = function() + local root = utils.get_project_root() + + local cmd = string.format( + "javac -d %s %s", + root .. "/build", + root .. "/src/*.java" + ) + local output = vim.fn.system(cmd) + + if not vim.v.shell_error == 0 then + 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, + vim.list_extend( + { "Error during compilation:" }, + vim.split(output, "\n", { trimempty = true }) + ) + ) + vim.api.nvim_set_option_value( + "modifiable", + false, + { buf = term_buf } + ) + else + utils.terminal({ "java -cp " .. root, "build" .. " Main" }) + end + end, + }, + c = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("c"), + user_opts or {} + ) + vim.api.nvim_create_user_command("CRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set("n", key, ":CRun", { silent = true }) + end + end, + run = function() + local root = utils.get_project_root() + local build_dir = root .. "/build" + + local cmd = "cd '" .. build_dir .. "' && cmake --build ." + local output = vim.fn.system(cmd) + local success = vim.v.shell_error == 0 + + if not success then + 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, + vim.list_extend( + { "Error during compilation:" }, + vim.split(output, "\n", { trimempty = true }) + ) + ) + vim.api.nvim_set_option_value( + "modifiable", + false, + { buf = term_buf } + ) + end + if success then + local run_cmd = "cd '" + .. build_dir + .. "' && ./" + .. utils.get_project_name() + utils.terminal({ run_cmd }) + end + end, + }, + cpp = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("cpp"), + user_opts or {} + ) + vim.api.nvim_create_user_command("CppRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set("n", key, ":CppRun", { silent = true }) + end + end, + run = function() + local root = utils.get_project_root() + local build_dir = root .. "/build" + + local cmd = "cd '" .. build_dir .. "' && cmake --build ." + local output = vim.fn.system(cmd) + local success = vim.v.shell_error == 0 + + if not success then + 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, + vim.list_extend( + { "Error during compilation:" }, + vim.split(output, "\n", { trimempty = true }) + ) + ) + vim.api.nvim_set_option_value( + "modifiable", + false, + { buf = term_buf } + ) + end + if success then + local run_cmd = "cd '" + .. build_dir + .. "' && ./" + .. utils.get_project_name() + utils.terminal({ run_cmd }) + end + end, + }, + html = { + setup = function(user_opts) + vim.tbl_deep_extend( + "force", + {}, + configs.get("html"), + user_opts or {} + ) + end, + }, + rust = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("rust"), + user_opts or {} + ) + vim.api.nvim_create_user_command("RustRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set("n", key, ":RustRun", { silent = true }) + end + end, + run = function() + local root = utils.get_project_root() + if not root then + return print("Error: Project root not found.") + end + + local cmd = { "cargo build" } + local output = vim.fn.system(table.concat(cmd)) + + if not vim.v.shell_error == 0 then + 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, + vim.list_extend( + { "Error during compilation:" }, + vim.split(output, "\n", { trimempty = true }) + ) + ) + vim.api.nvim_set_option_value( + "modifiable", + false, + { buf = term_buf } + ) + else + utils.terminal({ "cargo run" }) + end + end, + }, + python = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("python"), + user_opts or {} + ) + vim.api.nvim_create_user_command("PythonPip", function() + self:install_dependency() + end, {}) + vim.api.nvim_create_user_command("PythonRun", function() + self:run() + end, {}) + for key, command in pairs(opts.keybinds) do + if command == "PythonRun" then + vim.keymap.set( + "n", + key, + ":PythonRun", + { silent = true } + ) + end + if command == "PythonPip" then + vim.keymap.set( + "n", + key, + ":PythonPip", + { silent = true } + ) + end + end + + local root = utils.get_project_root() + if root then + local venv_path = root .. "/venv/bin/activate" + if vim.fn.filereadable(venv_path) == 1 then + vim.env.VIRTUAL_ENV = venv_path + vim.env.PATH = root .. "/venv/bin:" .. vim.env.PATH + end + end + end, + install_dependency = function() + vim.ui.input({ prompt = "Enter pip module: " }, function(pip_module) + if not pip_module or pip_module == "" then + return print("Pip canceled") + end + utils.terminal({ "pip install " .. pip_module }) + end) + end, + run = function() + utils.terminal({ "python3 " .. utils.get_project_root(), "main.py" }) + end, + }, + lua = { + setup = function(self, user_opts) + local opts = vim.tbl_deep_extend( + "force", + {}, + configs.get("lua"), + user_opts or {} + ) + vim.api.nvim_create_user_command("LuaRun", function() + self:run() + end, {}) + for key, _ in pairs(opts.keybinds) do + vim.keymap.set("n", key, ":LuaRun", { silent = true }) + end + end, + run = function() + local init_lua_path = utils.get_project_root() + .. "/lua/" + .. utils.get_project_name() + .. "/init.lua" + if vim.fn.filereadable(init_lua_path) == 1 then + utils.terminal({ "lua " .. init_lua_path }) + end + end, + }, +} + +return M diff --git a/lua/Polydev/presets.lua b/lua/vern/presets.lua similarity index 100% rename from lua/Polydev/presets.lua rename to lua/vern/presets.lua diff --git a/lua/vern/providers/python/uv.lua b/lua/vern/providers/python/uv.lua new file mode 100644 index 0000000..5044d6f --- /dev/null +++ b/lua/vern/providers/python/uv.lua @@ -0,0 +1,3 @@ +local M = {} + +return M diff --git a/lua/vern/scratchpad b/lua/vern/scratchpad new file mode 100644 index 0000000..64f1556 --- /dev/null +++ b/lua/vern/scratchpad @@ -0,0 +1,23 @@ +Configs and setups currently for each file type + +Configs: + project_root = the location on the file system for projects + keybinds = Custom keybinds for each file type + +Templates: + projects: + run = creates project + files: + run = creates file + extras: + run = creates auxiliary files for specific languages like c + +Languages: + file type: + setup = loads on filetype and loads functions + Run = builds if needed then executes the main file + +Use a polydevrc.json or something named like that but in json for user specific +settings per project like changing where the executable for a project is like +how I have been doing manually in CMAKE for c projects to test + diff --git a/lua/Polydev/templates.lua b/lua/vern/templates.lua similarity index 100% rename from lua/Polydev/templates.lua rename to lua/vern/templates.lua diff --git a/lua/vern/templates/extras/gitignore.lua b/lua/vern/templates/extras/gitignore.lua new file mode 100644 index 0000000..c71d152 --- /dev/null +++ b/lua/vern/templates/extras/gitignore.lua @@ -0,0 +1,31 @@ +local M = {} + +---@param opts table +M.template = function(opts) + local base = [=[ +.DS_Store + +.vscode/ +.idea/ + +.env +.env.* + +]=] + local lang_block = { + python = [=[ +__pycache__/ +build/ +dist/ +.venv/ +env/ +venv/ +.pytest_cache/ + ]=], + } + + local extra = (opts and opts and lang_block[opts.lang]) or "" + return base .. extra +end + +return M diff --git a/lua/vern/templates/python/__init__.lua b/lua/vern/templates/python/__init__.lua new file mode 100644 index 0000000..b9eac27 --- /dev/null +++ b/lua/vern/templates/python/__init__.lua @@ -0,0 +1,13 @@ +local M = {} + +---@param opts table +M.template = function(opts) + local template = [=[ +# %s + +__all__: list[str] = [] +]=] + return string.format(template, opts.project_name) +end + +return M diff --git a/lua/vern/templates/python/main.lua b/lua/vern/templates/python/main.lua new file mode 100644 index 0000000..41c2d19 --- /dev/null +++ b/lua/vern/templates/python/main.lua @@ -0,0 +1,15 @@ +local M = {} + +---@param opts table +M.template = function(opts) + local template = [=[ +def main() -> None: + printf("Hello from %s!") + +if __name__ == "__main__": + main() +]=] + return string.format(template, opts.project_name) +end + +return M diff --git a/lua/vern/templates/python/module.lua b/lua/vern/templates/python/module.lua new file mode 100644 index 0000000..752af9c --- /dev/null +++ b/lua/vern/templates/python/module.lua @@ -0,0 +1,13 @@ +local M = {} + +---@param opts table +M.template = function(opts) + local template = [=[ +""" +%s module +""" +]=] + return string.format(template, opts.project_name) +end + +return M diff --git a/lua/vern/templates/python/pyproject.lua b/lua/vern/templates/python/pyproject.lua new file mode 100644 index 0000000..20a3f44 --- /dev/null +++ b/lua/vern/templates/python/pyproject.lua @@ -0,0 +1,25 @@ +local M = {} + +---@param opts table +M.template = function(opts) + local n = opts.project_name + local template = [=[ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "%s" +version = "0.1.0" +description = "Project %s" +readme = "README.md" +requires-python = ">=3.10" +dependencies = [] + +[project.scripts] +%s = "%s.main:main" +]=] + return string.format(template, n, n, n, n) +end + +return M diff --git a/lua/Polydev/ui.lua b/lua/vern/ui.lua similarity index 100% rename from lua/Polydev/ui.lua rename to lua/vern/ui.lua diff --git a/lua/vern/utils.lua b/lua/vern/utils.lua new file mode 100644 index 0000000..97d47c3 --- /dev/null +++ b/lua/vern/utils.lua @@ -0,0 +1,149 @@ +local M = {} + +---@param bufnr? integer Default is 0 (current buffer) +---@return string|nil +function M.get_project_root(bufnr) + bufnr = bufnr or 0 + local root_markers = { + ".git", + "pyproject.toml", + "setup.py", + "Makefile", + "CMakeLists", + "Cargo.toml", + } + return vim.fs.root(bufnr, root_markers) or vim.uv.cwd() +end +--- +---@param cmd table +---@return integer, integer? +function M.terminal(cmd, opts) + opts = opts or {} + if opts.terminal.mode == "floating" then + local ui = vim.api.nvim_list_uis()[1] + local width, height, row, col + + if opts.terminal ~= nil then + width = math.max( + 1, + math.floor(ui.width * 0.9) + - opts.terminal.left + - opts.terminal.right + ) + height = math.max( + 1, + math.floor(ui.height * 0.9) + - opts.terminal.top + - opts.terminal.bottom + ) + row = math.floor((ui.height - height) / 2) + opts.terminal.top + col = math.floor((ui.width - width) / 2) + opts.terminal.left + end + if opts.terminal == nil then + width = math.max(1, math.floor(ui.width * 0.9)) + height = math.max(1, math.floor(ui.height * 0.9)) + row = math.floor((ui.height - height) / 2) + col = math.floor((ui.width - width) / 2) + end + local buf = vim.api.nvim_create_buf(false, true) + local win = vim.api.nvim_open_win(buf, true, { + relative = "editor", + width = width, + height = height, + row = row, + col = col, + style = "minimal", + border = opts.terminal.border.enabled and opts.terminal.border.type, + }) + vim.api.nvim_set_option_value( + "winhighlight", + "Normal:PolydevNormal,FloatBorder:PolydevBorder", + { win = win } + ) + vim.fn.jobstart(table.concat(cmd, "/"), { term = true }) + vim.api.nvim_buf_set_keymap( + buf, + "n", + "", + "i:q", + { noremap = true, silent = true } + ) + return buf, win + end + if opts.terminal.mode == "split" then + if opts.terminal.win.type == "vertical" then + if opts.terminal.win.anchor == "right" then + vim.cmd("set splitright") + end + end + if opts.terminal.win.type == "horizontal" then + if opts.terminal.win.anchor == "bottom" then + vim.cmd("set splitbelow") + end + end + + if opts.terminal.win.type == "vertical" then + vim.cmd(opts.terminal.win.size .. " vsplit") + end + if opts.terminal.win.type == "horizontal" then + vim.cmd(opts.terminal.win.size .. " split") + end + local buf = vim.api.nvim_create_buf(false, true) + local win = vim.api.nvim_get_current_win() + + vim.api.nvim_win_set_buf(0, buf) + + vim.fn.jobstart(table.concat(cmd, "/"), { term = true }) + vim.api.nvim_buf_set_keymap( + buf, + "n", + "", + "i:q", + { noremap = true, silent = true } + ) + return buf, win + end + return 0 +end + +return M + +-- M.opts = {} +-- +-- function M.setup(opts) +-- M.opts = vim.tbl_deep_extend("force", {}, require("Polydev.configs").get("terminal"), opts or {}) +-- end +-- +-- function M.exists(path) +-- return (io.open(path, "r") ~= nil) +-- end +-- +-- +-- ---@return string +-- function M.get_project_name() +-- return vim.fn.fnamemodify(M.get_project_root(), ":t") +-- end +-- +-- ---@param path_segments table +-- ---@param content string +-- function M.write_file(path_segments, content) +-- local path = table.concat(path_segments, "/") +-- local file = assert(io.open(path, "w"), "Error creating file: " .. path) +-- file:write(content) +-- file:close() +-- vim.cmd("edit " .. path) +-- end +-- +-- ---@param path string +-- ---@param gitignore_lines table +-- function M.init_git(path, gitignore_lines) +-- vim.fn.mkdir(path, "p") +-- vim.fn.system({ "git", "-C", path, "init" }) +-- +-- if gitignore_lines and #gitignore_lines > 0 then +-- local contents = table.concat(gitignore_lines, "\n") +-- M.write_file({ path, ".gitignore" }, contents) +-- end +-- end +---- +-- return M diff --git a/plugin/Polydev.lua b/plugin/Polydev.lua deleted file mode 100644 index d9ee380..0000000 --- a/plugin/Polydev.lua +++ /dev/null @@ -1 +0,0 @@ -require("Polydev").setup() diff --git a/plugin/vern.lua b/plugin/vern.lua new file mode 100644 index 0000000..c4f770e --- /dev/null +++ b/plugin/vern.lua @@ -0,0 +1 @@ +require("vern").setup() diff --git a/stylua.toml b/stylua.toml new file mode 100644 index 0000000..13bf097 --- /dev/null +++ b/stylua.toml @@ -0,0 +1,20 @@ +# stylua.toml + +# How many characters per line before wrapping +column_width = 80 + +# Indentation style: "Tabs" or "Spaces" +line_endings = "Unix" +indent_type = "Spaces" +indent_width = 4 + +# Quote styling: "AutoPreferDouble", "AutoPreferSingle", "ForceDouble", "ForceSingle" +quote_style = "AutoPreferDouble" + +# Call parentheses: "Always", "NoSingleString", "None", "Input" +# "None" removes parens when a single string/table literal is passed: fn "arg" / fn { ... } +# "Always" keeps them strictly standard: fn("arg") / fn({ ... }) +call_parentheses = "Always" + +# Sorting and formatting behavior +collapse_simple_statement = "Never"