]> git.lizzy.rs Git - micro.git/blob - runtime/plugins/comment/comment.lua
ce49dcaabb7becbadda52f0e5727dfa38f6319f6
[micro.git] / runtime / plugins / comment / comment.lua
1 VERSION = "1.0.0"
2
3 local util = import("micro/util")
4 local config = import("micro/config")
5 local buffer = import("micro/buffer")
6
7 local ft = {}
8
9 ft["apacheconf"] = "# %s"
10 ft["bat"] = ":: %s"
11 ft["c"] = "// %s"
12 ft["c++"] = "// %s"
13 ft["cmake"] = "# %s"
14 ft["conf"] = "# %s"
15 ft["crystal"] = "# %s"
16 ft["css"] = "/* %s */"
17 ft["d"] = "// %s"
18 ft["dart"] = "// %s"
19 ft["dockerfile"] = "# %s"
20 ft["elm"] = "-- %s"
21 ft["fish"] = "# %s"
22 ft["gdscript"] = "# %s"
23 ft["glsl"] = "// %s"
24 ft["go"] = "// %s"
25 ft["haskell"] = "-- %s"
26 ft["html"] = "<!-- %s -->"
27 ft["ini"] = "; %s"
28 ft["java"] = "// %s"
29 ft["javascript"] = "// %s"
30 ft["jinja2"] = "{# %s #}"
31 ft["julia"] = "# %s"
32 ft["kotlin"] = "// %s"
33 ft["lua"] = "-- %s"
34 ft["markdown"] = "<!-- %s -->"
35 ft["nginx"] = "# %s"
36 ft["nim"] = "# %s"
37 ft["objc"] = "// %s"
38 ft["ocaml"] = "(* %s *)"
39 ft["pascal"] = "{ %s }"
40 ft["perl"] = "# %s"
41 ft["php"] = "// %s"
42 ft["pony"] = "// %s"
43 ft["powershell"] = "# %s"
44 ft["proto"] = "// %s"
45 ft["python"] = "# %s"
46 ft["python3"] = "# %s"
47 ft["ruby"] = "# %s"
48 ft["rust"] = "// %s"
49 ft["scala"] = "// %s"
50 ft["shell"] = "# %s"
51 ft["sql"] = "-- %s"
52 ft["swift"] = "// %s"
53 ft["tex"] = "% %s"
54 ft["toml"] = "# %s"
55 ft["twig"] = "{# %s #}"
56 ft["v"] = "// %s"
57 ft["xml"] = "<!-- %s -->"
58 ft["yaml"] = "# %s"
59 ft["zig"] = "// %s"
60 ft["zscript"] = "// %s"
61 ft["zsh"] = "# %s"
62
63 function onBufferOpen(buf)
64     if buf.Settings["commenttype"] == nil then
65         if ft[buf.Settings["filetype"]] ~= nil then
66             buf.Settings["commenttype"] = ft[buf.Settings["filetype"]]
67         else
68             buf.Settings["commenttype"] = "# %s"
69         end
70     end
71 end
72
73 function isCommented(bp, lineN, commentRegex)
74     local line = bp.Buf:Line(lineN)
75     if string.match(line, commentRegex) then
76         return true
77     end
78     return false
79 end
80
81 function commentLine(bp, lineN)
82     local line = bp.Buf:Line(lineN)
83     local commentType = bp.Buf.Settings["commenttype"]
84     local sel = -bp.Cursor.CurSelection
85     local curpos = -bp.Cursor.Loc
86     local index = string.find(commentType, "%%s") - 1
87     local commentedLine = commentType:gsub("%%s", trim(line))
88     bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. commentedLine)
89     if bp.Cursor:HasSelection() then
90         bp.Cursor.CurSelection[1].Y = sel[1].Y
91         bp.Cursor.CurSelection[2].Y = sel[2].Y
92         bp.Cursor.CurSelection[1].X = sel[1].X
93         bp.Cursor.CurSelection[2].X = sel[2].X
94     else
95         bp.Cursor.X = curpos.X + index
96         bp.Cursor.Y = curpos.Y
97     end
98     bp.Cursor:Relocate()
99     bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
100 end
101
102 function uncommentLine(bp, lineN, commentRegex)
103     local line = bp.Buf:Line(lineN)
104     local commentType = bp.Buf.Settings["commenttype"]
105     local sel = -bp.Cursor.CurSelection
106     local curpos = -bp.Cursor.Loc
107     local index = string.find(commentType, "%%s") - 1
108     if string.match(line, commentRegex) then
109         uncommentedLine = string.match(line, commentRegex)
110         bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. uncommentedLine)
111         if bp.Cursor:HasSelection() then
112             bp.Cursor.CurSelection[1].Y = sel[1].Y
113             bp.Cursor.CurSelection[2].Y = sel[2].Y
114             bp.Cursor.CurSelection[1].X = sel[1].X
115             bp.Cursor.CurSelection[2].X = sel[2].X
116         else
117             bp.Cursor.X = curpos.X - index
118             bp.Cursor.Y = curpos.Y
119         end
120     end
121     bp.Cursor:Relocate()
122     bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
123 end
124
125 function toggleCommentLine(bp, lineN, commentRegex)
126     if isCommented(bp, lineN, commentRegex) then
127         uncommentLine(bp, lineN, commentRegex)
128     else
129         commentLine(bp, lineN)
130     end
131 end
132
133 function toggleCommentSelection(bp, startLine, endLine, commentRegex)
134     local allComments = true
135     for line = startLine, endLine do
136         if not isCommented(bp, line, commentRegex) then
137             allComments = false
138             break
139         end
140     end
141
142     for line = startLine, endLine do
143         if allComments then
144             uncommentLine(bp, line, commentRegex)
145         else
146             commentLine(bp, line)
147         end
148     end
149 end
150
151 function comment(bp, args)
152     local commentType = bp.Buf.Settings["commenttype"]
153     local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)"):gsub("%s+", "%s*")
154
155     if bp.Cursor:HasSelection() then
156         if bp.Cursor.CurSelection[1]:GreaterThan(-bp.Cursor.CurSelection[2]) then
157             local endLine = bp.Cursor.CurSelection[1].Y
158             if bp.Cursor.CurSelection[1].X == 0 then
159                 endLine = endLine - 1
160             end
161             toggleCommentSelection(bp, bp.Cursor.CurSelection[2].Y, endLine, commentRegex)
162         else
163             local endLine = bp.Cursor.CurSelection[2].Y
164             if bp.Cursor.CurSelection[2].X == 0 then
165                 endLine = endLine - 1
166             end
167             toggleCommentSelection(bp, bp.Cursor.CurSelection[1].Y, endLine, commentRegex)
168         end
169     else
170         toggleCommentLine(bp, bp.Cursor.Y, commentRegex)
171     end
172 end
173
174 function trim(s)
175     local trimmed = s:gsub("^%s*(.-)%s*$", "%1"):gsub("%%","%%%%")
176     return trimmed
177 end
178
179 function string.starts(String,Start)
180     return string.sub(String,1,string.len(Start))==Start
181 end
182
183 function init()
184     config.MakeCommand("comment", comment, config.NoComplete)
185     config.TryBindKey("Alt-/", "lua:comment.comment", false)
186     config.TryBindKey("CtrlUnderscore", "lua:comment.comment", false)
187     config.AddRuntimeFile("comment", config.RTHelp, "help/comment.md")
188 end