]> git.lizzy.rs Git - micro.git/blob - runtime/plugins/autoclose/autoclose.lua
ba902fa9e797956104c7bb43ca0509b5ec37f8b1
[micro.git] / runtime / plugins / autoclose / autoclose.lua
1 function charAt(str, i)
2     return string.sub(str, i, i)
3 end
4
5 if GetOption("autoclose") == nil then
6     AddOption("autoclose", true)
7 end
8
9 local autoclosePairs = {"\"\"", "''", "()", "{}", "[]"}
10 local autoNewlinePairs = {"()", "{}", "[]"}
11
12 function onRune(r, v)
13     if not GetOption("autoclose") then
14         return
15     end
16
17     for i = 1, #autoclosePairs do
18         if r == charAt(autoclosePairs[i], 2) then
19             local curLine = v.Buf:Line(v.Cursor.Y)
20
21             if charAt(curLine, v.Cursor.X+1) == charAt(autoclosePairs[i], 2) then
22                 v:Backspace(false)
23                 v:CursorRight(false)
24                 break
25             end
26
27             if v.Cursor.X > 1 and (IsWordChar(charAt(curLine, v.Cursor.X-1)) or charAt(curLine, v.Cursor.X-1) == charAt(autoclosePairs[i], 1)) then
28                 break
29             end
30         end
31         if r == charAt(autoclosePairs[i], 1) then
32             local curLine = v.Buf:Line(v.Cursor.Y)
33
34             if v.Cursor.X == #curLine or not IsWordChar(charAt(curLine, v.Cursor.X+1)) then
35                 -- the '-' here is to derefence the pointer to v.Cursor.Loc which is automatically made
36                 -- when converting go structs to lua
37                 -- It needs to be dereferenced because the function expects a non pointer struct
38                 v.Buf:Insert(-v.Cursor.Loc, charAt(autoclosePairs[i], 2))
39                 break
40             end
41         end
42     end
43 end
44
45 function preInsertNewline(v)
46     if not GetOption("autoclose") then
47         return
48     end
49
50     local curLine = v.Buf:Line(v.Cursor.Y)
51     local curRune = charAt(curLine, v.Cursor.X)
52     local nextRune = charAt(curLine, v.Cursor.X+1)
53     local ws = GetLeadingWhitespace(curLine)
54
55     for i = 1, #autoNewlinePairs do
56         if curRune == charAt(autoNewlinePairs[i], 1) then
57             if nextRune == charAt(autoNewlinePairs[i], 2) then
58                 v:InsertNewline(false)
59                 v:InsertTab(false)
60                 v.Buf:Insert(-v.Cursor.Loc, "\n" .. ws)
61                 return false
62             end
63         end
64     end
65
66     return true
67 end
68
69 function preBackspace(v)
70     if not GetOption("autoclose") then
71         return
72     end
73
74     for i = 1, #autoclosePairs do
75         local curLine = v.Buf:Line(v.Cursor.Y)
76         if charAt(curLine, v.Cursor.X+1) == charAt(autoclosePairs[i], 2) and charAt(curLine, v.Cursor.X) == charAt(autoclosePairs[i], 1) then
77             v:Delete(false)
78         end
79     end
80
81     return true
82 end