diff --git a/lua/godotdev/init.lua b/lua/godotdev/init.lua new file mode 100644 index 0000000..33a37d7 --- /dev/null +++ b/lua/godotdev/init.lua @@ -0,0 +1,2 @@ +-- lua/godotdev/init.lua +return require("godotdev.setup") diff --git a/lua/godotdev/keymaps.lua b/lua/godotdev/keymaps.lua new file mode 100644 index 0000000..04694b5 --- /dev/null +++ b/lua/godotdev/keymaps.lua @@ -0,0 +1,60 @@ +local M = {} + +function M.attach(bufnr) + local opts = { buffer = bufnr } + + local has_telescope, telescope_builtin = pcall(require, "telescope.builtin") + + local function map(mode, lhs, rhs, desc) + vim.keymap.set(mode, lhs, rhs, vim.tbl_extend("force", opts, { desc = desc })) + end + + -- Definitions / Declarations + map("n", "gd", has_telescope and telescope_builtin.lsp_definitions or vim.lsp.buf.definition, "LSP: Go to definition") + map("n", "gD", vim.lsp.buf.declaration, "LSP: Go to declaration") + map( + "n", + "gy", + has_telescope and telescope_builtin.lsp_type_definitions or vim.lsp.buf.type_definition, + "LSP: Type definition" + ) + map( + "n", + "gi", + has_telescope and telescope_builtin.lsp_implementations or vim.lsp.buf.implementation, + "LSP: Go to implementation" + ) + map("n", "gr", has_telescope and telescope_builtin.lsp_references or vim.lsp.buf.references, "LSP: List references") + + -- Info + map("n", "K", vim.lsp.buf.hover, "LSP: Hover documentation") + map("n", "", vim.lsp.buf.signature_help, "LSP: Signature help") + + -- Symbols + map( + "n", + "ds", + has_telescope and telescope_builtin.lsp_document_symbols or vim.lsp.buf.document_symbol, + "LSP: Document symbols" + ) + map( + "n", + "ws", + has_telescope and telescope_builtin.lsp_dynamic_workspace_symbols or vim.lsp.buf.workspace_symbol, + "LSP: Workspace symbols" + ) + + -- Actions + map("n", "rn", vim.lsp.buf.rename, "LSP: Rename symbol") + map({ "n", "v" }, "ca", vim.lsp.buf.code_action, "LSP: Code action") + map("n", "f", function() + vim.lsp.buf.format({ async = true }) + end, "LSP: Format buffer") + + -- Diagnostics + map("n", "gl", vim.diagnostic.open_float, "LSP: Show diagnostics") + map("n", "[d", vim.diagnostic.goto_prev, "LSP: Previous diagnostic") + map("n", "]d", vim.diagnostic.goto_next, "LSP: Next diagnostic") +end + +return M diff --git a/lua/godotdev/lsp.lua b/lua/godotdev/lsp.lua new file mode 100644 index 0000000..4670609 --- /dev/null +++ b/lua/godotdev/lsp.lua @@ -0,0 +1,29 @@ +local M = {} + +M.setup = function(config) + config = config or {} + local lspconfig = require("lspconfig") + local utils = require("godotdev.utils") + local keymaps = require("godotdev.keymaps") + + local host = config.editor_host or "127.0.0.1" + local port = config.editor_port or 6005 + + local capabilities = vim.lsp.protocol.make_client_capabilities() + capabilities.textDocument.typeDefinition = nil -- suppress unsupported typeDefinition + + lspconfig.gdscript.setup({ + name = "godot_editor", + cmd = vim.lsp.rpc.connect(host, port), + filetypes = { "gd", "gdscript" }, + root_dir = lspconfig.util.root_pattern("project.godot"), + capabilities = capabilities, + on_attach = function(client, bufnr) + -- suppress known Godot unsupported messages + utils.suppress_lsp_messages(client, { "Method not found: godot/reloadScript" }) + keymaps.attach(bufnr) + end, + }) +end + +return M diff --git a/lua/godotdev/setup.lua b/lua/godotdev/setup.lua new file mode 100644 index 0000000..83138c9 --- /dev/null +++ b/lua/godotdev/setup.lua @@ -0,0 +1,14 @@ +local M = {} + +M.opts = { + editor_host = "127.0.0.1", + editor_port = 6005, +} + +function M.setup(opts) + M.opts = vim.tbl_extend("force", M.opts, opts or {}) + require("godotdev.lsp").setup({ editor_host = M.opts.editor_host, editor_port = M.opts.editor_port }) + require("godotdev.health").setup({ port = M.opts.editor_port }) +end + +return M diff --git a/lua/godotdev/utils.lua b/lua/godotdev/utils.lua new file mode 100644 index 0000000..2fd1abe --- /dev/null +++ b/lua/godotdev/utils.lua @@ -0,0 +1,24 @@ +local M = {} + +--- Suppress specific LSP messages +-- @param client vim.lsp.Client +-- @param patterns table List of string patterns to ignore in client messages +function M.suppress_lsp_messages(client, patterns) + local orig_handler = vim.lsp.handlers["window/showMessage"] + vim.lsp.handlers["window/showMessage"] = function(err, method, params, client_id) + local lsp_client = vim.lsp.get_client_by_id(client_id) + if lsp_client and lsp_client.name == client.name then + if params and params.message then + for _, pat in ipairs(patterns) do + if params.message:match(pat) then + return -- silently ignore this message + end + end + end + end + -- fallback to original handler for all other messages + orig_handler(err, method, params, client_id) + end +end + +return M diff --git a/plugin/dev-reload.lua b/plugin/dev-reload.lua new file mode 100644 index 0000000..3f65b8d --- /dev/null +++ b/plugin/dev-reload.lua @@ -0,0 +1,39 @@ +local plugin_name = "godotdev.nvim" +local plugin_path = vim.fn.expand("~/Repositories/" .. plugin_name) + +vim.api.nvim_create_autocmd("BufWritePost", { + pattern = plugin_path .. "/**/*.lua", + callback = function(args) + -- Clear all godotdev modules so they reload + for name, _ in pairs(package.loaded) do + if name:match("^godotdev") then + package.loaded[name] = nil + end + end + + -- Re-require plugin + local ok, mod = pcall(require, "godotdev") + if not ok then + vim.notify("Failed to reload godotdev.nvim: " .. mod, vim.log.levels.ERROR) + return + end + + -- Run setup (if available) + if mod.setup then + pcall(mod.setup, {}) + end + + -- Reattach keymaps + lsp + local ok_keymaps, keymaps = pcall(require, "godotdev.keymaps") + if ok_keymaps and keymaps.attach and vim.api.nvim_get_current_buf() then + keymaps.attach(vim.api.nvim_get_current_buf()) + end + + local ok_lsp, lsp = pcall(require, "godotdev.lsp") + if ok_lsp and lsp.setup then + lsp.setup({}) + end + + vim.notify("Reloaded " .. plugin_name .. " (after saving " .. args.file .. ")", vim.log.levels.INFO) + end, +})