From ee8a9a70d39944d26669104b9eb0a7a5e4bd98e1 Mon Sep 17 00:00:00 2001 From: Henry Date: Fri, 29 Mar 2024 10:16:53 -0400 Subject: [PATCH] Add Command GenConstructor --- README.md | 8 ++++++ lua/gopher/api.lua | 1 + lua/gopher/gen_constructor.lua | 51 ++++++++++++++++++++++++++++++++++ plugin/gopher.vim | 5 ++++ 4 files changed, 65 insertions(+) create mode 100644 lua/gopher/gen_constructor.lua diff --git a/README.md b/README.md index 88d6bfb..0171959 100644 --- a/README.md +++ b/README.md @@ -154,6 +154,14 @@ Notice: [nvim-dap](https://github.com/mfussenegger/nvim-dap) is required require"gopher.dap".setup() ``` +11. Generate `constructor` from a `struct` + +Set cursor on a struct name and execute: + +```vim +:GenConstructor +``` + ## Contributing PRs are always welcome. See [CONTRIBUTING.md](./CONTRIBUTING.md) diff --git a/lua/gopher/api.lua b/lua/gopher/api.lua index 6e854af..1d0c688 100644 --- a/lua/gopher/api.lua +++ b/lua/gopher/api.lua @@ -12,6 +12,7 @@ API.comment = require "gopher.comment" API.test_add = tests.func_test API.test_exported = tests.all_exported_tests API.tests_all = tests.all_tests +API.gen_constructor = require "gopher.gen_constructor" API.get = function(...) cmd("get", ...) diff --git a/lua/gopher/gen_constructor.lua b/lua/gopher/gen_constructor.lua new file mode 100644 index 0000000..81ef477 --- /dev/null +++ b/lua/gopher/gen_constructor.lua @@ -0,0 +1,51 @@ +local u = require "gopher._utils" + +return function (cmd_args) + local parser = vim.treesitter.get_parser() + if not parser then + u.notify("no parser not available", "error") + return + end + + -- When the command is runned on the 'struct name' the current node will be + -- the node referring directly to the 'struct name', therefore, to get the + -- node that refers to the entire struct we have to get the parent. + local current_node = vim.treesitter.get_node():parent() + if not current_node then + u.notify("no node found at cursor", "error") + return + end + + if current_node:type() ~= 'type_spec' then + u.notify("not struct node under cursor","error") + return + end + + -- TODO: allow to pass a funcName as an argument + -- local struct_name = (fn_args.args ~= nil and fn_args.args ~= "") and fn_args.args:gsub('"', '') or vim.treesitter.get_node_text(current_node:child(0), 1) + local struct_name = vim.treesitter.get_node_text(current_node:child(0), 1) + local struct_type_node = current_node:child(1):child(1) + + local args = {} + local struct_initialization = {} + for field in struct_type_node:iter_children() do + if field:type() == 'field_declaration' then + local field_type_node = field:child(1) + local field_name_node = field:child(0) + if field_type_node and field_name_node then + local field_type = vim.treesitter.get_node_text(field_type_node, 1) + local field_name = vim.treesitter.get_node_text(field_name_node, 1) + local field_name_lower = string.lower(field_name) + table.insert(args, field_name_lower .. " " .. field_type) + table.insert(struct_initialization, field_name .. ": " .. field_name_lower) + end + end + end + + local constructor_code = string.format( + "\nfunc New%s(%s) *%s {\n\treturn &%s{%s}\n}\n", + struct_name:gsub("^%l", string.upper), table.concat(args, ', '), struct_name, struct_name, table.concat(struct_initialization, ', ') + ) + + vim.fn.append(current_node:end_() + 1, vim.split(constructor_code, '\n')) +end diff --git a/plugin/gopher.vim b/plugin/gopher.vim index e797966..c16206c 100644 --- a/plugin/gopher.vim +++ b/plugin/gopher.vim @@ -11,3 +11,8 @@ command! -nargs=* GoGenerate :lua require"gopher.api".generate() command! GoCmt :lua require"gopher.api".comment() command! GoIfErr :lua require"gopher.api".iferr() command! GoInstallDeps :lua require"gopher.api".install_deps() +command! GoGenConstructor :lua require"gopher.api".gen_constructor(f-args) + + +" TODO: Use this format to remove vimscript in the future" +" vim.api.nvim_create_user_command('GenerateConstructor', generate_constructor, {})