Last active
July 24, 2024 04:04
-
-
Save Jay-Madden/9a6479f6c31999927306ca6d5590637f to your computer and use it in GitHub Desktop.
Quick and dirty neovim autocmd to add or remove the wrapping parenthesis around golang multi returns whenever they go from single return to multireturn
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local function wrap_golang_multi_return() | |
-- If its not a go buffer dont bother doing any more work | |
if vim.bo.filetype ~= "go" then | |
return | |
end | |
local cursor_pos = vim.api.nvim_win_get_cursor(0) | |
local line_num, line_col = cursor_pos[1], cursor_pos[2] | |
local curr_buf = vim.api.nvim_get_current_buf() | |
local line = vim.api.nvim_buf_get_lines(curr_buf, line_num - 1, line_num, false)[1] | |
local P, R, S, C, Cs = vim.lpeg.P, vim.lpeg.R, vim.lpeg.S, vim.lpeg.C, vim.lpeg.Cs | |
local letter = R("az", "AZ") + S("_") | |
local digit = R("09") | |
local whitespace = S(" \t\n") | |
local repeat_whitespace = whitespace ^ 0 | |
local alphanumeric = letter + digit | |
local identifier = alphanumeric ^ 1 | |
local symbol = S("., &*-[]|") | |
local open_paren = P("(") | |
local close_paren = P(")") | |
local open_bracket = P("[") | |
local close_bracket = P("]") | |
local open_brace = P("{") | |
local close_brace = P("}") | |
local func_keyword = P("func") | |
local arguments = alphanumeric + symbol + whitespace | |
local function_argument_list = open_paren * arguments ^ 0 * close_paren | |
-- We are just gonna ignore that nested generics happen | |
local generic_argument_list = open_bracket * (arguments - close_bracket) ^ 0 * close_bracket | |
local reciever = open_paren | |
* alphanumeric ^ 1 | |
* repeat_whitespace | |
* P("*") ^ -1 | |
* identifier | |
* repeat_whitespace | |
* close_paren | |
-- | |
-- The signature can be malformed, in fact it likely as this happens while we are typing | |
local return_signature = open_paren ^ 0 * (identifier + symbol) ^ 1 * close_paren ^ 0 | |
local return_signature_capture = vim.lpeg.Cs((return_signature / function(match) | |
if match == nil then | |
return | |
end | |
local function gsub(s, patt, repl) | |
patt = vim.lpeg.P(patt) | |
patt = vim.lpeg.Cs((patt / repl + 1) ^ 0) | |
return vim.lpeg.match(patt, s) | |
end | |
-- Strip the parens off, we will add them back if we need to | |
local value = gsub(match, "(", "") | |
value = gsub(value, ")", "") | |
-- Disable the type error, lpeg match will work as a string | |
---@diagnostic disable-next-line: param-type-mismatch | |
local returns = vim.split(value, ",") | |
if #returns == 1 then | |
--line_col = line_col - 1 | |
return value | |
else | |
--line_col = line_col + 1 | |
return "(" .. value .. ")" | |
end | |
end)) | |
local anonymous_function = C(func_keyword * function_argument_list * repeat_whitespace) | |
* return_signature_capture * C(repeat_whitespace * open_brace ^ 0 * repeat_whitespace) | |
local named_function = C( | |
func_keyword | |
* repeat_whitespace | |
* reciever ^ 0 | |
* repeat_whitespace | |
* identifier | |
* generic_argument_list ^ 0 | |
* repeat_whitespace | |
* function_argument_list | |
* repeat_whitespace | |
) * return_signature_capture * C(repeat_whitespace * open_brace ^ 0 * repeat_whitespace) | |
local full_function = anonymous_function + named_function | |
-- We want to ignore the start of the line incase it is a lambda | |
local full_line = Cs(((P(1) - func_keyword) ^ 0 * full_function)) | |
local match = vim.lpeg.match(full_line, line) | |
if match == nil then | |
return | |
end | |
-- Disable the type error, lpeg match will work as a string | |
---@diagnostic disable-next-line: param-type-mismatch | |
vim.api.nvim_set_current_line(match) | |
-- When we add parenthesis we need to bump the cursor one block to the right to account for the paren on the left. | |
-- we bump the column number in the match handler and execute it here | |
vim.api.nvim_win_set_cursor(0, { line_num, line_col }) | |
end | |
vim.api.nvim_create_autocmd( | |
{ "TextChanged", "TextChangedI" }, | |
{ callback = wrap_golang_multi_return } | |
) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment