Skip to content

Commit d933021

Browse files
committed
feat: add support for backspacing through the parentheses
1 parent bf7b5c8 commit d933021

File tree

3 files changed

+226
-6
lines changed

3 files changed

+226
-6
lines changed

lua/auto-fix-return/fix.lua

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,27 @@ end
4949
---@return FixedDefinition
5050
function M.build_fixed_definition(line, cursor_col)
5151
-- Strip the parens off, we will add them back if we need to
52-
local value = string.gsub(line, "^%(", "")
53-
value = string.gsub(value, "%)$", "")
52+
local temp, count_left = string.gsub(line, "^%(", "")
53+
local value, count_right = string.gsub(temp, "%)$", "")
54+
55+
-- In the case that we ONLY remove the one paren then it is most likely
56+
-- that the user is performing a backspace of the entire return on either parentheses,
57+
-- E.G.
58+
-- func Foo() (int, error)|<bs> {}
59+
-- ->
60+
-- func Foo() (int, error| {}
61+
-- ->
62+
-- func Foo() (int, error|) {}
63+
--
64+
-- in this case when we rebuild the return type and add back the removed paren we would also set the cursor
65+
-- back to its original position effectively removing the users ability to backspace.
66+
--
67+
-- If we detect that case mark it here and simply do not modify the cursor at the end
68+
local needs_cursor_moved = true
69+
if count_left ~= count_right then
70+
needs_cursor_moved = false
71+
end
72+
5473
-- If there are any commas in the return definition we know we will need parenthesis
5574
local returns = vim.split(value, ",")
5675

@@ -92,7 +111,6 @@ function M.build_fixed_definition(line, cursor_col)
92111

93112
-- This technically does not handle a case like `func foo() chan<- int a b c` but as this will never be syntactically valid go code we can ignore it
94113
if c == " " and not (curr_word:find("^chan") ~= nil or curr_word:find("chan$") ~= nil or curr_word:find("^func")) then
95-
-- vim.print(curr_word)
96114
-- Peek ahead to find the next non-space character
97115
-- so that we can ignore whitespace in return definitions like `interface {}`
98116
-- we then do a stack approach to ensure we only add a return definition if we have validated
@@ -131,12 +149,16 @@ function M.build_fixed_definition(line, cursor_col)
131149

132150
-- If returns just equals one we know we have a single return and do
133151
-- not need parenthesis
134-
-- Here we also need to set the offset for the CURSOR to be placed after we do the text replacement
152+
-- Here we also need to possibly set the offset for the CURSOR to be placed after we do the text replacement
135153
if #returns == 1 then
136-
final_cursor_col = final_cursor_col - 1
154+
if needs_cursor_moved then
155+
final_cursor_col = final_cursor_col - 1
156+
end
137157
new_line = value
138158
else
139-
final_cursor_col = final_cursor_col + 1
159+
if needs_cursor_moved then
160+
final_cursor_col = final_cursor_col + 1
161+
end
140162
new_line = "(" .. value .. ")"
141163
end
142164

@@ -186,6 +208,7 @@ function M.parse_return()
186208
return
187209
end
188210

211+
189212
-- Here we rebuild the entire return statement to a syntactically correct version
190213
-- splitting on commas to decide if there is a parameter list or a single value
191214
local fixed_def = M.build_fixed_definition(line, cursor_col)

lua/auto-fix-return/parsers/declaration.lua

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ function M.parse_declaration(cursor_row)
5959
(ERROR)? @outside_error_end
6060
)
6161
62+
;; For the following code
63+
;; func Foo() (string, int| {}
64+
;; There is no 'result' node parsed, the error token contains the entire thing
65+
;; so we need to special case this input
66+
(
67+
(function_declaration
68+
name: (_)
69+
parameters: (_)
70+
(ERROR)? @result
71+
!result
72+
body: (_)
73+
) @func
74+
)
75+
6276
;; The following code
6377
;;
6478
;; func (b *Bar) Foo() i,
@@ -89,6 +103,20 @@ function M.parse_declaration(cursor_row)
89103
;; with the final error token for the , outside of the method_declaration
90104
(ERROR)? @outside_error_end
91105
)
106+
;; For the following code
107+
;; func (b *Bar) Foo() (string, int| {}
108+
;; There is no 'result' node parsed, the error token contains the entire thing
109+
;; so we need to special case this input
110+
(
111+
(method_declaration
112+
name: (_)
113+
parameters: (_)
114+
(ERROR)? @result
115+
!result
116+
body: (_)
117+
) @func
118+
)
119+
92120
;; For methods that are created above existing valid declarations treesitter
93121
;; parses the tree with the error token outside the function declaration and no result field
94122
;; so we need to handle that here

lua/test/declaration_test_spec.lua

Lines changed: 169 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -590,6 +590,48 @@ describe("test functions with body defined", function()
590590
end
591591
)
592592

593+
describe(
594+
"when a multi return only has one starting parentheses",
595+
function()
596+
local winid = 0
597+
before_each(function()
598+
winid = utils.set_test_window_value("func Foo() (i,k| {}")
599+
vim.cmd("AutoFixReturn")
600+
end)
601+
602+
it("should add parentheses around the return type", function()
603+
local lines = utils.get_win_lines(winid)
604+
eq("func Foo() (i,k) {}", lines[1])
605+
end)
606+
607+
it("should set the cursor to inside the parens", function()
608+
local char = utils.get_cursor_char(winid)
609+
eq("k", char)
610+
end)
611+
end
612+
)
613+
614+
describe(
615+
"when a multi return only has one ending parentheses",
616+
function()
617+
local winid = 0
618+
before_each(function()
619+
winid = utils.set_test_window_value("func Foo() i|,k) {}")
620+
vim.cmd("AutoFixReturn")
621+
end)
622+
623+
it("should add parentheses around the return type", function()
624+
local lines = utils.get_win_lines(winid)
625+
eq("func Foo() (i,k) {}", lines[1])
626+
end)
627+
628+
it("should set the cursor to inside the parens", function()
629+
local char = utils.get_cursor_char(winid)
630+
eq("(", char)
631+
end)
632+
end
633+
)
634+
593635
describe("when a multi return is started with cursor at the end of the second type", function()
594636
local winid = 0
595637
before_each(function()
@@ -1026,6 +1068,48 @@ describe("test functions without a body defined", function()
10261068
end)
10271069
end)
10281070

1071+
describe(
1072+
"when a multi return only has one starting parentheses",
1073+
function()
1074+
local winid = 0
1075+
before_each(function()
1076+
winid = utils.set_test_window_value("func Foo() (i,k|")
1077+
vim.cmd("AutoFixReturn")
1078+
end)
1079+
1080+
it("should add parentheses around the return type", function()
1081+
local lines = utils.get_win_lines(winid)
1082+
eq("func Foo() (i,k)", lines[1])
1083+
end)
1084+
1085+
it("should set the cursor to inside the parens", function()
1086+
local char = utils.get_cursor_char(winid)
1087+
eq("k", char)
1088+
end)
1089+
end
1090+
)
1091+
1092+
describe(
1093+
"when a multi return only has one ending parentheses",
1094+
function()
1095+
local winid = 0
1096+
before_each(function()
1097+
winid = utils.set_test_window_value("func Foo() i|,k) {}")
1098+
vim.cmd("AutoFixReturn")
1099+
end)
1100+
1101+
it("should add parentheses around the return type", function()
1102+
local lines = utils.get_win_lines(winid)
1103+
eq("func Foo() (i,k) {}", lines[1])
1104+
end)
1105+
1106+
it("should set the cursor to inside the parens", function()
1107+
local char = utils.get_cursor_char(winid)
1108+
eq("(", char)
1109+
end)
1110+
end
1111+
)
1112+
10291113
describe("when a multi closure return with cursor at the end of the second type", function()
10301114
local winid = 0
10311115
before_each(function()
@@ -2279,6 +2363,49 @@ describe("test methods with body defined", function()
22792363
eq("F", char)
22802364
end)
22812365
end)
2366+
2367+
describe(
2368+
"when a multi return only has one starting parentheses",
2369+
function()
2370+
local winid = 0
2371+
before_each(function()
2372+
winid = utils.set_test_window_value("func (b *Bar) Foo() (i,k| {}")
2373+
vim.cmd("AutoFixReturn")
2374+
end)
2375+
2376+
it("should add parentheses around the return type", function()
2377+
local lines = utils.get_win_lines(winid)
2378+
eq("func (b *Bar) Foo() (i,k) {}", lines[1])
2379+
end)
2380+
2381+
it("should set the cursor to inside the parens", function()
2382+
local char = utils.get_cursor_char(winid)
2383+
eq("k", char)
2384+
end)
2385+
end
2386+
)
2387+
2388+
describe(
2389+
"when a multi return only has one ending parentheses",
2390+
function()
2391+
local winid = 0
2392+
before_each(function()
2393+
winid = utils.set_test_window_value("func Foo() i|,k) {}")
2394+
vim.cmd("AutoFixReturn")
2395+
end)
2396+
2397+
it("should add parentheses around the return type", function()
2398+
local lines = utils.get_win_lines(winid)
2399+
eq("func Foo() (i,k) {}", lines[1])
2400+
end)
2401+
2402+
it("should set the cursor to inside the parens", function()
2403+
local char = utils.get_cursor_char(winid)
2404+
eq("(", char)
2405+
end)
2406+
end
2407+
)
2408+
22822409

22832410
describe(
22842411
"when a multi inline interface return is started with cursor at the end of the comma",
@@ -2784,6 +2911,48 @@ describe("test methods without a body defined", function()
27842911
end
27852912
)
27862913

2914+
describe(
2915+
"when a multi return only has one starting parentheses",
2916+
function()
2917+
local winid = 0
2918+
before_each(function()
2919+
winid = utils.set_test_window_value("func (b *Bar) Foo() (i,k|")
2920+
vim.cmd("AutoFixReturn")
2921+
end)
2922+
2923+
it("should add parentheses around the return type", function()
2924+
local lines = utils.get_win_lines(winid)
2925+
eq("func (b *Bar) Foo() (i,k)", lines[1])
2926+
end)
2927+
2928+
it("should set the cursor to inside the parens", function()
2929+
local char = utils.get_cursor_char(winid)
2930+
eq("k", char)
2931+
end)
2932+
end
2933+
)
2934+
2935+
describe(
2936+
"when a multi return only has one ending parentheses",
2937+
function()
2938+
local winid = 0
2939+
before_each(function()
2940+
winid = utils.set_test_window_value("func Foo() i|,k) {}")
2941+
vim.cmd("AutoFixReturn")
2942+
end)
2943+
2944+
it("should add parentheses around the return type", function()
2945+
local lines = utils.get_win_lines(winid)
2946+
eq("func Foo() (i,k) {}", lines[1])
2947+
end)
2948+
2949+
it("should set the cursor to inside the parens", function()
2950+
local char = utils.get_cursor_char(winid)
2951+
eq("(", char)
2952+
end)
2953+
end
2954+
)
2955+
27872956
describe(
27882957
"when a multi send only channel return is started with cursor at the end of the second type",
27892958
function()

0 commit comments

Comments
 (0)