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