]> git.lizzy.rs Git - micro.git/blob - runtime/plugins/comment/comment.lua
Update comment filetype when commenting
[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 updateCommentType(buf)
64     if ft[buf.Settings["filetype"]] ~= nil and ft[buf.Settings["filetype"]] ~= nil then
65         buf.Settings["commenttype"] = ft[buf.Settings["filetype"]]
66     elseif buf.Settings["commenttype"] == nil then
67         buf.Settings["commenttype"] = "# %s"
68     end
69 end
70
71 function isCommented(bp, lineN, commentRegex)
72     local line = bp.Buf:Line(lineN)
73     if string.match(line, commentRegex) then
74         return true
75     end
76     return false
77 end
78
79 function commentLine(bp, lineN)
80     updateCommentType(bp.Buf)
81
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     updateCommentType(bp.Buf)
104
105     local line = bp.Buf:Line(lineN)
106     local commentType = bp.Buf.Settings["commenttype"]
107     local sel = -bp.Cursor.CurSelection
108     local curpos = -bp.Cursor.Loc
109     local index = string.find(commentType, "%%s") - 1
110     if string.match(line, commentRegex) then
111         uncommentedLine = string.match(line, commentRegex)
112         bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. uncommentedLine)
113         if bp.Cursor:HasSelection() then
114             bp.Cursor.CurSelection[1].Y = sel[1].Y
115             bp.Cursor.CurSelection[2].Y = sel[2].Y
116             bp.Cursor.CurSelection[1].X = sel[1].X
117             bp.Cursor.CurSelection[2].X = sel[2].X
118         else
119             bp.Cursor.X = curpos.X - index
120             bp.Cursor.Y = curpos.Y
121         end
122     end
123     bp.Cursor:Relocate()
124     bp.Cursor.LastVisualX = bp.Cursor:GetVisualX()
125 end
126
127 function toggleCommentLine(bp, lineN, commentRegex)
128     if isCommented(bp, lineN, commentRegex) then
129         uncommentLine(bp, lineN, commentRegex)
130     else
131         commentLine(bp, lineN)
132     end
133 end
134
135 function toggleCommentSelection(bp, startLine, endLine, commentRegex)
136     local allComments = true
137     for line = startLine, endLine do
138         if not isCommented(bp, line, commentRegex) then
139             allComments = false
140             break
141         end
142     end
143
144     for line = startLine, endLine do
145         if allComments then
146             uncommentLine(bp, line, commentRegex)
147         else
148             commentLine(bp, line)
149         end
150     end
151 end
152
153 function comment(bp, args)
154     updateCommentType(bp.Buf)
155
156     local commentType = bp.Buf.Settings["commenttype"]
157     local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)"):gsub("%s+", "%s*")
158
159     if bp.Cursor:HasSelection() then
160         if bp.Cursor.CurSelection[1]:GreaterThan(-bp.Cursor.CurSelection[2]) then
161             local endLine = bp.Cursor.CurSelection[1].Y
162             if bp.Cursor.CurSelection[1].X == 0 then
163                 endLine = endLine - 1
164             end
165             toggleCommentSelection(bp, bp.Cursor.CurSelection[2].Y, endLine, commentRegex)
166         else
167             local endLine = bp.Cursor.CurSelection[2].Y
168             if bp.Cursor.CurSelection[2].X == 0 then
169                 endLine = endLine - 1
170             end
171             toggleCommentSelection(bp, bp.Cursor.CurSelection[1].Y, endLine, commentRegex)
172         end
173     else
174         toggleCommentLine(bp, bp.Cursor.Y, commentRegex)
175     end
176 end
177
178 function trim(s)
179     local trimmed = s:gsub("^%s*(.-)%s*$", "%1"):gsub("%%","%%%%")
180     return trimmed
181 end
182
183 function string.starts(String,Start)
184     return string.sub(String,1,string.len(Start))==Start
185 end
186
187 function init()
188     config.MakeCommand("comment", comment, config.NoComplete)
189     config.TryBindKey("Alt-/", "lua:comment.comment", false)
190     config.TryBindKey("CtrlUnderscore", "lua:comment.comment", false)
191     config.AddRuntimeFile("comment", config.RTHelp, "help/comment.md")
192 end