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