Merge
This commit is contained in:
@ -1,50 +1,54 @@
|
|||||||
{
|
{
|
||||||
"CopilotChat.nvim": { "branch": "main", "commit": "a7138a0ee04d8af42c262554eccee168bbf1454f" },
|
"LazyVim": { "branch": "main", "commit": "28db03f958d58dfff3c647ce28fdc1cb88ac158d" },
|
||||||
"LazyVim": { "branch": "main", "commit": "0329bc0e508eb48f7cee7fe57975c364584f8738" },
|
"SchemaStore.nvim": { "branch": "main", "commit": "fb5f164a28f8fd5a052da512436d4173e06cf71e" },
|
||||||
"SchemaStore.nvim": { "branch": "main", "commit": "4341619da06779ae310ee9c3d6d70edfefed7152" },
|
|
||||||
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
|
"bufferline.nvim": { "branch": "main", "commit": "655133c3b4c3e5e05ec549b9f8cc2894ac6f51b3" },
|
||||||
"catppuccin": { "branch": "main", "commit": "8c4125e3c746976ba025dc5d908fa22c6aa09486" },
|
"catppuccin": { "branch": "main", "commit": "ce8d176faa4643e026e597ae3c31db59b63cef09" },
|
||||||
"cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" },
|
"cmp-buffer": { "branch": "main", "commit": "b74fab3656eea9de20a9b8116afa3cfc4ec09657" },
|
||||||
"cmp-nvim-lsp": { "branch": "main", "commit": "bd5a7d6db125d4654b50eeae9f5217f24bb22fd3" },
|
"cmp-nvim-lsp": { "branch": "main", "commit": "cbc7b02bb99fae35cb42f514762b89b5126651ef" },
|
||||||
"cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" },
|
"cmp-path": { "branch": "main", "commit": "c642487086dbd9a93160e1679a1327be111cbc25" },
|
||||||
"codeium.nvim": { "branch": "main", "commit": "821b570b526dbb05b57aa4ded578b709a704a38a" },
|
"conform.nvim": { "branch": "master", "commit": "8314f4c9e205e7f30b62147069729f9a1227d8bf" },
|
||||||
"conform.nvim": { "branch": "master", "commit": "9fd3d5e0b689ec1bf400c53cbbec72c6fdf24081" },
|
"flash.nvim": { "branch": "main", "commit": "fcea7ff883235d9024dc41e638f164a450c14ca2" },
|
||||||
"flash.nvim": { "branch": "main", "commit": "3be9bf7e85550045ec576379a0c45aac144d0438" },
|
|
||||||
"friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
|
"friendly-snippets": { "branch": "main", "commit": "572f5660cf05f8cd8834e096d7b4c921ba18e175" },
|
||||||
"gitsigns.nvim": { "branch": "main", "commit": "20ad4419564d6e22b189f6738116b38871082332" },
|
"gitsigns.nvim": { "branch": "main", "commit": "6bd29494e3f79ff08be1d35bc1926ed23c22ed9a" },
|
||||||
"grug-far.nvim": { "branch": "main", "commit": "3e72397465f774b01aa38e4fe8e6eecf23d766d9" },
|
"grug-far.nvim": { "branch": "main", "commit": "74eef260e1142264ab994fb9c88e4f420e9486d7" },
|
||||||
"lazy.nvim": { "branch": "main", "commit": "db067881fff0fd4be8c00e5bde7492e0e1c77a2f" },
|
"lazy.nvim": { "branch": "main", "commit": "85c7ff3711b730b4030d03144f6db6375044ae82" },
|
||||||
"lazydev.nvim": { "branch": "main", "commit": "01bc2aacd51cf9021eb19d048e70ce3dd09f7f93" },
|
"lazydev.nvim": { "branch": "main", "commit": "5231c62aa83c2f8dc8e7ba957aa77098cda1257d" },
|
||||||
"lualine.nvim": { "branch": "master", "commit": "3946f0122255bc377d14a59b27b609fb3ab25768" },
|
"lualine.nvim": { "branch": "master", "commit": "47f91c416daef12db467145e16bed5bbfe00add8" },
|
||||||
"markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" },
|
"markdown-preview.nvim": { "branch": "master", "commit": "a923f5fc5ba36a3b17e289dc35dc17f66d0548ee" },
|
||||||
"mason-lspconfig.nvim": { "branch": "main", "commit": "83db0174efbac2d69fd45afef269b47dfedadbe1" },
|
"mason-lspconfig.nvim": { "branch": "main", "commit": "4cfe411526a7a99c18281135e8b4765ae6330d15" },
|
||||||
"mason.nvim": { "branch": "main", "commit": "ad7146aa61dcaeb54fa900144d768f040090bff0" },
|
"mason-nvim-dap.nvim": { "branch": "main", "commit": "9a10e096703966335bd5c46c8c875d5b0690dade" },
|
||||||
"mini.ai": { "branch": "main", "commit": "11c57180bc9084089206e211ac7aa598bedc9673" },
|
"mason.nvim": { "branch": "main", "commit": "57e5a8addb8c71fb063ee4acda466c7cf6ad2800" },
|
||||||
"mini.icons": { "branch": "main", "commit": "284798619aed9f4c1ac1b9417b9a5e3b4b85ef3a" },
|
"mini.ai": { "branch": "main", "commit": "bfb26d9072670c3aaefab0f53024b2f3729c8083" },
|
||||||
"mini.pairs": { "branch": "main", "commit": "b9aada8c0e59f2b938e98fbf4eae0799eba96ad9" },
|
"mini.icons": { "branch": "main", "commit": "efc85e42262cd0c9e1fdbf806c25cb0be6de115c" },
|
||||||
"neo-tree.nvim": { "branch": "main", "commit": "0d0b29a529216d41173c9c5c8a8f484db5b891ba" },
|
"mini.pairs": { "branch": "main", "commit": "d5a29b6254dad07757832db505ea5aeab9aad43a" },
|
||||||
"noice.nvim": { "branch": "main", "commit": "c86aea584d98be7ee1167ce4d4ef946fbd7f3ae0" },
|
"neo-tree.nvim": { "branch": "main", "commit": "4925f31285940af2805f5bfe52dcffa2037ecab2" },
|
||||||
|
"noice.nvim": { "branch": "main", "commit": "7bfd942445fb63089b59f97ca487d605e715f155" },
|
||||||
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
|
"nui.nvim": { "branch": "main", "commit": "de740991c12411b663994b2860f1a4fd0937c130" },
|
||||||
"nvim-cmp": { "branch": "main", "commit": "a7bcf1d88069fc67c9ace8a62ba480b8fe879025" },
|
"nvim-cmp": { "branch": "main", "commit": "85bbfad83f804f11688d1ab9486b459e699292d6" },
|
||||||
"nvim-jdtls": { "branch": "master", "commit": "380ac148f989e1291aac002dc959ecc68c5243d0" },
|
"nvim-dap": { "branch": "master", "commit": "7bb46cc612bb127d7b0e3e9ed695267d830824ec" },
|
||||||
"nvim-lint": { "branch": "master", "commit": "9da1fb942dd0668d5182f9c8dee801b9c190e2bb" },
|
"nvim-dap-go": { "branch": "main", "commit": "b4421153ead5d726603b02743ea40cf26a51ed5f" },
|
||||||
"nvim-lspconfig": { "branch": "master", "commit": "a9b2fb560c4ab22c10728fd5149dbd7b62aa4f69" },
|
"nvim-dap-ui": { "branch": "master", "commit": "cf91d5e2d07c72903d052f5207511bf7ecdb7122" },
|
||||||
|
"nvim-dap-virtual-text": { "branch": "master", "commit": "fbdb48c2ed45f4a8293d0d483f7730d24467ccb6" },
|
||||||
|
"nvim-jdtls": { "branch": "master", "commit": "f73731b543f5971e0da9665eb1d7ceffe1fde71f" },
|
||||||
|
"nvim-lint": { "branch": "master", "commit": "1f19dacd945a7b1a57f29f32b2d7168384df3d36" },
|
||||||
|
"nvim-lspconfig": { "branch": "master", "commit": "ac04ec3c2af08e9821b4eb64ede86072b9b213bf" },
|
||||||
|
"nvim-nio": { "branch": "master", "commit": "21f5324bfac14e22ba26553caf69ec76ae8a7662" },
|
||||||
"nvim-snippets": { "branch": "main", "commit": "56b4052f71220144689caaa2e5b66222ba5661eb" },
|
"nvim-snippets": { "branch": "main", "commit": "56b4052f71220144689caaa2e5b66222ba5661eb" },
|
||||||
"nvim-treesitter": { "branch": "main", "commit": "98fe644cb3b5ba390d1bc3f89299f93c70020803" },
|
"nvim-treesitter": { "branch": "main", "commit": "737088f8571293f6a1ef8cd6c858d5daf9a38162" },
|
||||||
"nvim-treesitter-context": { "branch": "master", "commit": "ec308c7827b5f8cb2dd0ad303a059c945dd21969" },
|
"nvim-treesitter-context": { "branch": "master", "commit": "64dd4cf3f6fd0ab17622c5ce15c91fc539c3f24a" },
|
||||||
"nvim-treesitter-textobjects": { "branch": "main", "commit": "1b2d85d3de6114c4bcea89ffb2cd1ce9e3a19931" },
|
"nvim-treesitter-textobjects": { "branch": "main", "commit": "ecd03f5811eb5c66d2fa420b79121b866feecd82" },
|
||||||
"nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" },
|
"nvim-ts-autotag": { "branch": "main", "commit": "c4ca798ab95b316a768d51eaaaee48f64a4a46bc" },
|
||||||
"persistence.nvim": { "branch": "main", "commit": "51eef57272742b773468949f6bd0503ec3f83874" },
|
"persistence.nvim": { "branch": "main", "commit": "b20b2a7887bd39c1a356980b45e03250f3dce49c" },
|
||||||
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
"plenary.nvim": { "branch": "master", "commit": "b9fd5226c2f76c951fc8ed5923d85e4de065e509" },
|
||||||
"render-markdown.nvim": { "branch": "main", "commit": "bfd67f1402b97ac619cb538f4bbaed12a7fa89aa" },
|
"render-markdown.nvim": { "branch": "main", "commit": "07d088bf8bdadd159eb807b90eaee86a4778383f" },
|
||||||
"snacks.nvim": { "branch": "main", "commit": "f75eaf1e18cea03605e626eca2a1b9c4345071d4" },
|
"snacks.nvim": { "branch": "main", "commit": "fe7cfe9800a182274d0f868a74b7263b8c0c020b" },
|
||||||
"tailwindcss-colorizer-cmp.nvim": { "branch": "main", "commit": "3d3cd95e4a4135c250faf83dd5ed61b8e5502b86" },
|
"tailwindcss-colorizer-cmp.nvim": { "branch": "main", "commit": "3d3cd95e4a4135c250faf83dd5ed61b8e5502b86" },
|
||||||
"todo-comments.nvim": { "branch": "main", "commit": "19d461ddd543e938eb22505fb03fa878800270b6" },
|
"todo-comments.nvim": { "branch": "main", "commit": "31e3c38ce9b29781e4422fc0322eb0a21f4e8668" },
|
||||||
"tokyonight.nvim": { "branch": "main", "commit": "4fe1b0c44f5d6ee769cdfbdffc7ccb703f53feda" },
|
"tokyonight.nvim": { "branch": "main", "commit": "5da1b76e64daf4c5d410f06bcb6b9cb640da7dfd" },
|
||||||
"trouble.nvim": { "branch": "main", "commit": "76030c5542c5d132aeeb467ca0ab370f3f79a697" },
|
"trouble.nvim": { "branch": "main", "commit": "bd67efe408d4816e25e8491cc5ad4088e708a69a" },
|
||||||
"ts-comments.nvim": { "branch": "main", "commit": "217ab9cc137fceb6659b53790bd25e608219abe1" },
|
"ts-comments.nvim": { "branch": "main", "commit": "123a9fb12e7229342f807ec9e6de478b1102b041" },
|
||||||
"vim-dadbod": { "branch": "master", "commit": "e95afed23712f969f83b4857a24cf9d59114c2e6" },
|
"vim-dadbod": { "branch": "master", "commit": "e95afed23712f969f83b4857a24cf9d59114c2e6" },
|
||||||
"vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" },
|
"vim-dadbod-completion": { "branch": "master", "commit": "a8dac0b3cf6132c80dc9b18bef36d4cf7a9e1fe6" },
|
||||||
"vim-dadbod-ui": { "branch": "master", "commit": "5a83ee1fdafcdedb03222bb46f7cfd70646025ee" },
|
"vim-dadbod-ui": { "branch": "master", "commit": "48c4f271da13d380592f4907e2d1d5558044e4e5" },
|
||||||
"which-key.nvim": { "branch": "main", "commit": "b4177e3eaf15fe5eb8357ebac2286d488be1ed00" }
|
"which-key.nvim": { "branch": "main", "commit": "3aab2147e74890957785941f0c1ad87d0a44c15a" }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,7 @@
|
|||||||
{
|
{
|
||||||
"extras": [
|
"extras": [
|
||||||
"lazyvim.plugins.extras.ai.codeium",
|
|
||||||
"lazyvim.plugins.extras.ai.copilot-chat",
|
|
||||||
"lazyvim.plugins.extras.coding.nvim-cmp",
|
"lazyvim.plugins.extras.coding.nvim-cmp",
|
||||||
|
"lazyvim.plugins.extras.dap.core",
|
||||||
"lazyvim.plugins.extras.editor.neo-tree",
|
"lazyvim.plugins.extras.editor.neo-tree",
|
||||||
"lazyvim.plugins.extras.lang.docker",
|
"lazyvim.plugins.extras.lang.docker",
|
||||||
"lazyvim.plugins.extras.lang.go",
|
"lazyvim.plugins.extras.lang.go",
|
||||||
|
|||||||
15
lua/plugins/go-helper.lua
Normal file
15
lua/plugins/go-helper.lua
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
return {
|
||||||
|
{
|
||||||
|
"go-helper",
|
||||||
|
dir = vim.fn.stdpath("config") .. "/lua/scripts",
|
||||||
|
ft = "go",
|
||||||
|
keys = {
|
||||||
|
{ "<leader>cei", "<cmd>GoExtractInterface<cr>", desc = "Extract Interface", ft = "go" },
|
||||||
|
{ "<leader>cec", "<cmd>GoGenerateConstructor<cr>", desc = "Generate Constructor", ft = "go" },
|
||||||
|
},
|
||||||
|
config = function()
|
||||||
|
require("scripts.go-extract-interface").setup()
|
||||||
|
require("scripts.go-gen-constructor").setup()
|
||||||
|
end,
|
||||||
|
},
|
||||||
|
}
|
||||||
@ -9,6 +9,7 @@ return {
|
|||||||
filtered_items = {
|
filtered_items = {
|
||||||
hide_by_pattern = {
|
hide_by_pattern = {
|
||||||
"*_test.go",
|
"*_test.go",
|
||||||
|
"test",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
group_empty_dirs = true,
|
group_empty_dirs = true,
|
||||||
|
|||||||
131
lua/scripts/go-extract-interface.lua
Normal file
131
lua/scripts/go-extract-interface.lua
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Parse method signature from a line
|
||||||
|
local function parse_method(line)
|
||||||
|
-- Match: func (receiver) MethodName(params) (returns)
|
||||||
|
local pattern = "^func%s+%([^)]+%)%s+([%w_]+)%s*(%b())%s*(.*)"
|
||||||
|
local name, params, returns = line:match(pattern)
|
||||||
|
|
||||||
|
if name then
|
||||||
|
-- Clean up returns (remove leading spaces and parentheses if single return)
|
||||||
|
returns = returns:gsub("^%s+", "")
|
||||||
|
if returns:match("^%b()") then
|
||||||
|
returns = " " .. returns
|
||||||
|
elseif returns ~= "" then
|
||||||
|
returns = " " .. returns
|
||||||
|
end
|
||||||
|
|
||||||
|
return name .. params .. returns
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find all methods for a given struct type
|
||||||
|
local function find_struct_methods(struct_name, bufnr)
|
||||||
|
local methods = {}
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
|
||||||
|
-- Pattern to match methods with the struct as receiver
|
||||||
|
-- Matches both pointer and value receivers
|
||||||
|
local patterns = {
|
||||||
|
"^func%s+%(%s*%w+%s+%*?" .. struct_name .. "%s*%)", -- Standard pattern
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
for _, pattern in ipairs(patterns) do
|
||||||
|
if line:match(pattern) then
|
||||||
|
local method_sig = parse_method(line)
|
||||||
|
if method_sig then
|
||||||
|
table.insert(methods, method_sig)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return methods
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get struct name under cursor
|
||||||
|
local function get_struct_name()
|
||||||
|
local line = vim.api.nvim_get_current_line()
|
||||||
|
|
||||||
|
-- Try to match: type StructName struct
|
||||||
|
local struct_name = line:match("^type%s+([%w_]+)%s+struct")
|
||||||
|
|
||||||
|
if not struct_name then
|
||||||
|
-- Try to match if cursor is on struct keyword
|
||||||
|
struct_name = line:match("type%s+([%w_]+)%s+struct")
|
||||||
|
end
|
||||||
|
|
||||||
|
return struct_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate interface from methods
|
||||||
|
local function generate_interface(struct_name, methods)
|
||||||
|
if #methods == 0 then
|
||||||
|
return nil, "No methods found for struct " .. struct_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Create interface name (conventionally, I + StructName or StructName + er)
|
||||||
|
local interface_name = "I" .. struct_name
|
||||||
|
|
||||||
|
local lines = {
|
||||||
|
"type " .. interface_name .. " interface {",
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, method in ipairs(methods) do
|
||||||
|
local method_without_bracket = method:gsub("{$", "")
|
||||||
|
local cleaned_method = method_without_bracket:gsub("%s+$", "")
|
||||||
|
table.insert(lines, "\t" .. cleaned_method)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(lines, "}")
|
||||||
|
|
||||||
|
return lines, nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main function to extract interface
|
||||||
|
function M.extract_interface()
|
||||||
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
|
||||||
|
-- Check if we're in a Go file
|
||||||
|
local filetype = vim.bo[bufnr].filetype
|
||||||
|
if filetype ~= "go" then
|
||||||
|
vim.notify("This command only works in Go files", vim.log.levels.ERROR)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get struct name under cursor
|
||||||
|
local struct_name = get_struct_name()
|
||||||
|
if not struct_name then
|
||||||
|
vim.notify("Cursor is not on a struct definition", vim.log.levels.ERROR)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find all methods for this struct
|
||||||
|
local methods = find_struct_methods(struct_name, bufnr)
|
||||||
|
|
||||||
|
-- Generate interface
|
||||||
|
local interface_lines, err = generate_interface(struct_name, methods)
|
||||||
|
if err then
|
||||||
|
vim.notify(err, vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Insert interface above the struct definition
|
||||||
|
local cursor_line = vim.api.nvim_win_get_cursor(0)[1]
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, cursor_line - 1, cursor_line - 1, false, interface_lines)
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, cursor_line, cursor_line, false, { "" }) -- Empty line
|
||||||
|
|
||||||
|
vim.notify("Interface extracted: " .. #methods .. " methods found", vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setup function for lazy.nvim
|
||||||
|
function M.setup()
|
||||||
|
-- Create command
|
||||||
|
vim.api.nvim_create_user_command("GoExtractInterface", M.extract_interface, {
|
||||||
|
desc = "Extract interface from Go struct under cursor",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
346
lua/scripts/go-gen-constructor.lua
Normal file
346
lua/scripts/go-gen-constructor.lua
Normal file
@ -0,0 +1,346 @@
|
|||||||
|
local M = {}
|
||||||
|
|
||||||
|
-- Get the struct name from the current line
|
||||||
|
local function get_struct_name()
|
||||||
|
local line = vim.api.nvim_get_current_line()
|
||||||
|
|
||||||
|
-- Try to match: type StructName struct
|
||||||
|
local struct_name = line:match("^type%s+([%w_]+)%s+struct")
|
||||||
|
|
||||||
|
-- If not found, try to match if cursor is on struct definition
|
||||||
|
if not struct_name then
|
||||||
|
struct_name = line:match("type%s+([%w_]+)%s+struct")
|
||||||
|
end
|
||||||
|
|
||||||
|
return struct_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check if constructor already exists and find its location
|
||||||
|
local function find_existing_constructor(constructor_name, bufnr)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
-- Look for function definition with constructor name
|
||||||
|
if line:match("^func%s+" .. constructor_name .. "%s*%(") then
|
||||||
|
local start_line = i
|
||||||
|
local end_line = i
|
||||||
|
|
||||||
|
-- Find the end of the function (matching braces)
|
||||||
|
local bracket_count = 0
|
||||||
|
for j = i, #lines do
|
||||||
|
for char in lines[j]:gmatch(".") do
|
||||||
|
if char == "{" then
|
||||||
|
bracket_count = bracket_count + 1
|
||||||
|
elseif char == "}" then
|
||||||
|
bracket_count = bracket_count - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if bracket_count == 0 and lines[j]:match("}") then
|
||||||
|
end_line = j
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return { start_line = start_line, end_line = end_line, line = line }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Extract return type from existing constructor
|
||||||
|
local function extract_return_type_from_existing(constructor_line)
|
||||||
|
-- Match: func ConstructorName(params) ReturnType {
|
||||||
|
local return_type = constructor_line:match("%)%s*([%w%.]+)%s*{")
|
||||||
|
return return_type
|
||||||
|
end
|
||||||
|
|
||||||
|
local function remove_existing_constructor(constructor_name, bufnr)
|
||||||
|
local location = find_existing_constructor(constructor_name, bufnr)
|
||||||
|
if location then
|
||||||
|
-- Remove the constructor
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, location.start_line - 1, location.end_line, false, {})
|
||||||
|
return location
|
||||||
|
end
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find interface that the struct should implement
|
||||||
|
local function find_interface_for_struct(struct_name, bufnr)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
|
||||||
|
-- Look for interfaces defined in the file
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
-- Match interface definition
|
||||||
|
local interface_name = line:match("^type%s+([%w_]+)%s+interface")
|
||||||
|
if interface_name then
|
||||||
|
-- Check if this interface has methods that match our struct
|
||||||
|
-- Simple check: if interface name contains struct name or vice versa
|
||||||
|
if
|
||||||
|
string.find(interface_name, struct_name)
|
||||||
|
or string.find(struct_name, interface_name)
|
||||||
|
or string.lower(struct_name) == string.lower(interface_name)
|
||||||
|
then
|
||||||
|
return interface_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- If no matching interface found, check if struct has an interface with same name + "er" or "Service"
|
||||||
|
local possible_interfaces = {
|
||||||
|
string.gsub(struct_name, "Service$", "Service"),
|
||||||
|
struct_name .. "er",
|
||||||
|
"I" .. struct_name,
|
||||||
|
string.gsub(struct_name, "^%l", string.upper),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, interface_name in ipairs(possible_interfaces) do
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
if line:match("^type%s+" .. interface_name .. "%s+interface") then
|
||||||
|
return interface_name
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nil
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Parse struct fields
|
||||||
|
local function parse_struct_fields(struct_name, bufnr)
|
||||||
|
local fields = {}
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
local in_struct = false
|
||||||
|
local bracket_count = 0
|
||||||
|
local start_line = 0
|
||||||
|
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
-- Find the struct definition
|
||||||
|
if line:match("^type%s+" .. struct_name .. "%s+struct") then
|
||||||
|
in_struct = true
|
||||||
|
start_line = i
|
||||||
|
-- Check if opening brace is on same line
|
||||||
|
if line:match("{") then
|
||||||
|
bracket_count = 1
|
||||||
|
end
|
||||||
|
if line:match("}") then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
elseif in_struct then
|
||||||
|
-- Count brackets to know when we're done
|
||||||
|
if not line:match("^%s*//") then -- Skip comment lines for bracket counting
|
||||||
|
for char in line:gmatch(".") do
|
||||||
|
if char == "{" then
|
||||||
|
bracket_count = bracket_count + 1
|
||||||
|
elseif char == "}" then
|
||||||
|
bracket_count = bracket_count - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Parse field if we're inside the struct and it's not the closing brace
|
||||||
|
if bracket_count > 0 and i > start_line then
|
||||||
|
-- Remove comments and trim
|
||||||
|
local clean_line = line:gsub("//.*$", ""):gsub("^%s*(.-)%s*$", "%1")
|
||||||
|
|
||||||
|
-- Skip empty lines and closing braces
|
||||||
|
if clean_line ~= "" and not clean_line:match("^}") and not clean_line:match("^{") then
|
||||||
|
-- Extract field name and type
|
||||||
|
-- Handle multiple fields with same type: field1, field2 Type
|
||||||
|
local field_part = clean_line
|
||||||
|
|
||||||
|
-- Check if line contains a type declaration
|
||||||
|
if field_part:match("[%w_]+%s+[%w%.%*%[%]]+$") then
|
||||||
|
-- Split by last space to get type and field names
|
||||||
|
local last_space = field_part:match("^.*()%s[%w%.%*%[%]]+$")
|
||||||
|
if last_space then
|
||||||
|
local type_part = field_part:sub(last_space + 1)
|
||||||
|
local fields_part = field_part:sub(1, last_space - 1)
|
||||||
|
|
||||||
|
-- Split multiple field names by comma
|
||||||
|
for field_name in fields_part:gmatch("([%w_]+),?%s*") do
|
||||||
|
if field_name ~= "" then
|
||||||
|
table.insert(fields, {
|
||||||
|
name = field_name,
|
||||||
|
type = type_part,
|
||||||
|
line = clean_line,
|
||||||
|
})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Stop parsing when we exit the struct
|
||||||
|
if bracket_count == 0 then
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return fields
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Generate constructor function
|
||||||
|
local function generate_constructor(struct_name, interface_name, fields, existing_constructor)
|
||||||
|
local constructor_name = "New" .. struct_name
|
||||||
|
if string.match(struct_name, "^[a-z]") and interface_name then
|
||||||
|
constructor_name = "New" .. interface_name
|
||||||
|
else
|
||||||
|
constructor_name = "New" .. string.upper(string.sub(struct_name, 1, 1)) .. string.sub(struct_name, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
local lines = {}
|
||||||
|
|
||||||
|
-- Function signature
|
||||||
|
local return_type
|
||||||
|
if existing_constructor and existing_constructor.line then
|
||||||
|
return_type = extract_return_type_from_existing(existing_constructor.line)
|
||||||
|
end
|
||||||
|
|
||||||
|
if not return_type then
|
||||||
|
return_type = interface_name or struct_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build parameters
|
||||||
|
local params = {}
|
||||||
|
local field_params = {}
|
||||||
|
for _, field in ipairs(fields) do
|
||||||
|
local param_name = field.name
|
||||||
|
local param_type = field.type
|
||||||
|
|
||||||
|
table.insert(params, param_name .. " " .. param_type)
|
||||||
|
field_params[param_name] = param_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Build function signature
|
||||||
|
local func_sig = "func " .. constructor_name .. "("
|
||||||
|
if #params > 0 then
|
||||||
|
func_sig = func_sig .. table.concat(params, ", ")
|
||||||
|
end
|
||||||
|
func_sig = func_sig .. ") " .. return_type .. " {"
|
||||||
|
table.insert(lines, func_sig)
|
||||||
|
|
||||||
|
-- Function body
|
||||||
|
table.insert(lines, "\treturn &" .. struct_name .. "{")
|
||||||
|
|
||||||
|
-- Field assignments
|
||||||
|
local field_assignments = {}
|
||||||
|
for _, field in ipairs(fields) do
|
||||||
|
local value = field_params[field.name] or field.name
|
||||||
|
table.insert(field_assignments, "\t\t" .. field.name .. ": " .. value .. ",")
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, assignment in ipairs(field_assignments) do
|
||||||
|
table.insert(lines, assignment)
|
||||||
|
end
|
||||||
|
|
||||||
|
table.insert(lines, "\t}")
|
||||||
|
table.insert(lines, "}")
|
||||||
|
|
||||||
|
return lines, constructor_name
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Main function to generate constructor
|
||||||
|
function M.generate_constructor()
|
||||||
|
local bufnr = vim.api.nvim_get_current_buf()
|
||||||
|
|
||||||
|
-- Check if we're in a Go file
|
||||||
|
local filetype = vim.bo[bufnr].filetype
|
||||||
|
if filetype ~= "go" then
|
||||||
|
vim.notify("This command only works in Go files", vim.log.levels.ERROR)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get struct name under cursor
|
||||||
|
local struct_name = get_struct_name()
|
||||||
|
if not struct_name then
|
||||||
|
vim.notify("Cursor is not on a struct definition", vim.log.levels.ERROR)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Find interface if exists
|
||||||
|
local interface_name = find_interface_for_struct(struct_name, bufnr)
|
||||||
|
|
||||||
|
-- Parse struct fields
|
||||||
|
local fields = parse_struct_fields(struct_name, bufnr)
|
||||||
|
|
||||||
|
if #fields == 0 then
|
||||||
|
vim.notify("No fields found in struct " .. struct_name, vim.log.levels.WARN)
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Check for existing constructor and remove it (but save its info)
|
||||||
|
local constructor_name = "New" .. struct_name
|
||||||
|
if string.match(struct_name, "^[a-z]") and interface_name then
|
||||||
|
constructor_name = "New" .. interface_name
|
||||||
|
else
|
||||||
|
constructor_name = "New" .. string.upper(string.sub(struct_name, 1, 1)) .. string.sub(struct_name, 2)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Remove existing constructor if it exists
|
||||||
|
local removed = remove_existing_constructor(constructor_name, bufnr)
|
||||||
|
|
||||||
|
-- Generate constructor
|
||||||
|
local constructor_lines = generate_constructor(struct_name, interface_name, fields, removed)
|
||||||
|
|
||||||
|
-- Find where to insert the constructor (after the struct)
|
||||||
|
local lines = vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
|
||||||
|
local insert_line = 0
|
||||||
|
|
||||||
|
for i, line in ipairs(lines) do
|
||||||
|
if line:match("^type%s+" .. struct_name .. "%s+struct") then
|
||||||
|
-- Find the end of the struct
|
||||||
|
local bracket_count = 0
|
||||||
|
for j = i, #lines do
|
||||||
|
local current_line = lines[j]
|
||||||
|
-- Skip comment lines for bracket counting
|
||||||
|
if not current_line:match("^%s*//") then
|
||||||
|
for char in current_line:gmatch(".") do
|
||||||
|
if char == "{" then
|
||||||
|
bracket_count = bracket_count + 1
|
||||||
|
elseif char == "}" then
|
||||||
|
bracket_count = bracket_count - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if bracket_count == 0 then
|
||||||
|
insert_line = j
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if insert_line > 0 then
|
||||||
|
-- Check if we need to add an empty line
|
||||||
|
if insert_line < #lines and lines[insert_line + 1] and lines[insert_line + 1]:match("^%s*$") then
|
||||||
|
-- Next line is already empty, insert after it
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, insert_line + 1, insert_line + 1, false, constructor_lines)
|
||||||
|
else
|
||||||
|
-- Add an empty line before constructor
|
||||||
|
table.insert(constructor_lines, 1, "")
|
||||||
|
vim.api.nvim_buf_set_lines(bufnr, insert_line, insert_line, false, constructor_lines)
|
||||||
|
end
|
||||||
|
|
||||||
|
if removed then
|
||||||
|
vim.notify("Replaced existing constructor: " .. constructor_name, vim.log.levels.INFO)
|
||||||
|
else
|
||||||
|
vim.notify("Generated constructor: " .. constructor_name, vim.log.levels.INFO)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
vim.notify("Could not find where to insert constructor", vim.log.levels.ERROR)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Setup function
|
||||||
|
function M.setup()
|
||||||
|
-- Create command
|
||||||
|
vim.api.nvim_create_user_command("GoGenerateConstructor", M.generate_constructor, {
|
||||||
|
desc = "Generate constructor for Go struct under cursor",
|
||||||
|
})
|
||||||
|
end
|
||||||
|
|
||||||
|
return M
|
||||||
Reference in New Issue
Block a user