Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for multi-cursor comments to the comment plugin (V1.1.0) #3543

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 58 additions & 54 deletions runtime/plugins/comment/comment.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
VERSION = "1.0.0"
VERSION = "1.1.0"

local util = import("micro/util")
local config = import("micro/config")
Expand Down Expand Up @@ -78,66 +78,31 @@ end
function isCommented(bp, lineN, commentRegex)
local line = bp.Buf:Line(lineN)
local regex = commentRegex:gsub("%s+", "%s*")
if string.match(line, regex) then
return true
end
return false
return string.match(line, regex)
end

function commentLine(bp, lineN, indentLen)
updateCommentType(bp.Buf)

local line = bp.Buf:Line(lineN)
local commentType = bp.Buf.Settings["commenttype"]
local sel = -bp.Cursor.CurSelection
local curpos = -bp.Cursor.Loc
local index = string.find(commentType, "%%s") - 1
local indent = string.sub(line, 1, indentLen)
local trimmedLine = string.sub(line, indentLen + 1)
trimmedLine = trimmedLine:gsub("%%", "%%%%")
local commentedLine = commentType:gsub("%%s", trimmedLine)
bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), indent .. commentedLine)
if bp.Cursor:HasSelection() then
bp.Cursor.CurSelection[1].Y = sel[1].Y
bp.Cursor.CurSelection[2].Y = sel[2].Y
bp.Cursor.CurSelection[1].X = sel[1].X
bp.Cursor.CurSelection[2].X = sel[2].X
else
bp.Cursor.X = curpos.X + index
bp.Cursor.Y = curpos.Y
end
bp.Cursor:Relocate()
bp.Cursor:StoreVisualX()
end

function uncommentLine(bp, lineN, commentRegex)
updateCommentType(bp.Buf)

local line = bp.Buf:Line(lineN)
local commentType = bp.Buf.Settings["commenttype"]
local sel = -bp.Cursor.CurSelection
local curpos = -bp.Cursor.Loc
local index = string.find(commentType, "%%s") - 1
if not string.match(line, commentRegex) then
commentRegex = commentRegex:gsub("%s+", "%s*")
end
if string.match(line, commentRegex) then
uncommentedLine = string.match(line, commentRegex)
bp.Buf:Replace(buffer.Loc(0, lineN), buffer.Loc(#line, lineN), util.GetLeadingWhitespace(line) .. uncommentedLine)
if bp.Cursor:HasSelection() then
bp.Cursor.CurSelection[1].Y = sel[1].Y
bp.Cursor.CurSelection[2].Y = sel[2].Y
bp.Cursor.CurSelection[1].X = sel[1].X
bp.Cursor.CurSelection[2].X = sel[2].X
else
bp.Cursor.X = curpos.X - index
bp.Cursor.Y = curpos.Y
end
end
bp.Cursor:Relocate()
bp.Cursor:StoreVisualX()
end

-- unused
function toggleCommentLine(bp, lineN, commentRegex)
if isCommented(bp, lineN, commentRegex) then
uncommentLine(bp, lineN, commentRegex)
Expand All @@ -146,9 +111,9 @@ function toggleCommentLine(bp, lineN, commentRegex)
end
end

function toggleCommentSelection(bp, startLine, endLine, commentRegex)
function toggleCommentSelection(bp, lines, commentRegex)
local allComments = true
for line = startLine, endLine do
for line,_ in pairs(lines) do
if not isCommented(bp, line, commentRegex) then
allComments = false
break
Expand All @@ -158,21 +123,22 @@ function toggleCommentSelection(bp, startLine, endLine, commentRegex)
-- NOTE: we assume that the indentation is either tabs only or spaces only
local indentMin = -1
if not allComments then
for line = startLine, endLine do
for line,_ in pairs(lines) do
local indentLen = #util.GetLeadingWhitespace(bp.Buf:Line(line))
if indentMin == -1 or indentLen < indentMin then
indentMin = indentLen
end
end
end

for line = startLine, endLine do
for line,_ in pairs(lines) do
if allComments then
uncommentLine(bp, line, commentRegex)
else
commentLine(bp, line, indentMin)
end
end
return not allComments
end

function comment(bp, args)
Expand All @@ -181,22 +147,60 @@ function comment(bp, args)
local commentType = bp.Buf.Settings["commenttype"]
local commentRegex = "^%s*" .. commentType:gsub("%%","%%%%"):gsub("%$","%$"):gsub("%)","%)"):gsub("%(","%("):gsub("%?","%?"):gsub("%*", "%*"):gsub("%-", "%-"):gsub("%.", "%."):gsub("%+", "%+"):gsub("%]", "%]"):gsub("%[", "%["):gsub("%%%%s", "(.*)")

if bp.Cursor:HasSelection() then
if bp.Cursor.CurSelection[1]:GreaterThan(-bp.Cursor.CurSelection[2]) then
local endLine = bp.Cursor.CurSelection[1].Y
if bp.Cursor.CurSelection[1].X == 0 then
endLine = endLine - 1
local lines = {}
local curData = {}
-- gather cursor data and lines to (un)comment
for i = 1,#bp.Buf:getCursors() do
local cursor = bp.Buf:getCursor(i-1)
local hasSelection = cursor:HasSelection()
local excludedEnd = nil
if hasSelection then
local startSel = 1
local endSel = 2
if cursor.CurSelection[startSel]:GreaterThan(-cursor.CurSelection[endSel]) then
startSel = 2
endSel = 1
end
local fromLineNo = cursor.CurSelection[startSel].Y
local toLineNo = cursor.CurSelection[endSel].Y

-- don't indent the line after when selection ends in a newline
if cursor.CurSelection[endSel].X == 0 then
excludedEnd = endSel
toLineNo = toLineNo - 1
end

for lineN = fromLineNo,toLineNo do
lines[lineN] = true
end
toggleCommentSelection(bp, bp.Cursor.CurSelection[2].Y, endLine, commentRegex)
else
local endLine = bp.Cursor.CurSelection[2].Y
if bp.Cursor.CurSelection[2].X == 0 then
endLine = endLine - 1
lines[cursor.Y] = true
end
table.insert(curData, {
sel = -cursor.CurSelection,
curpos = -cursor.Loc,
cursor = cursor,
hasSelection = hasSelection,
excludedEnd = excludedEnd,
})
end
-- (un)comment selected lines
local commented = toggleCommentSelection(bp, lines, commentRegex)
-- restore cursors
local displacement = (string.find(commentType, "%%s") - 1) * (commented and 1 or -1)
for i=1,#curData do
local cursor = curData[i].cursor
if curData[i].hasSelection then
for j=1,2 do
cursor.CurSelection[j].Y = curData[i].sel[j].Y
cursor.CurSelection[j].X = curData[i].sel[j].X + (j == curData[i].excludedEnd and 0 or displacement)
end
toggleCommentSelection(bp, bp.Cursor.CurSelection[1].Y, endLine, commentRegex)
else
cursor.Y = curData[i].curpos.Y
cursor.X = curData[i].curpos.X + displacement
end
else
toggleCommentLine(bp, bp.Cursor.Y, commentRegex)
cursor:Relocate()
cursor:StoreVisualX()
end
end

Expand Down
4 changes: 2 additions & 2 deletions runtime/plugins/comment/help/comment.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@ the binding:
> comment
```

If you have a selection, the plugin will comment all the lines
selected.
If you have a selection of text, or multiple cursors, the plugin
will comment all the selected lines.

The comment type will be auto detected based on the filetype,
but it is only available for certain filetypes:
Expand Down