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 4 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
98 changes: 43 additions & 55 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 All @@ -19,6 +19,7 @@ ft["dart"] = "// %s"
ft["dockerfile"] = "# %s"
ft["elm"] = "-- %s"
ft["fish"] = "# %s"
ft["freest"] = "-- %s"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems unrelated to the content of this PR. What's freest? Micro doesn't have built-in support for a file type called "freest". If it gets special treatment in the comment plugin it should probably have a file type (syntax file under micro/runtime/syntax/) as well. Whether or not it's popular enough to warrant built-in support could be a separate PR and discussion.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the end of a selection happens to be on the new empty line it would be commented as well.

I agree that what you commented should be the correct behavior. In the last commit I added a fix for this. I added an exception to not comment the last line of a selection, if it is an empty line.

Regarding FreeST, you're right. I removed the changes. May add full language support in another PR at some point ;)

ft["gdscript"] = "# %s"
ft["glsl"] = "// %s"
ft["go"] = "// %s"
Expand Down Expand Up @@ -78,66 +79,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 +112,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 +124,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 +148,43 @@ 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 = 0,#bp.Buf:getCursors()-1 do
local cursor = bp.Buf:getCursor(i)
local hasSelection = cursor:HasSelection()
table.insert(curData, {
sel = -cursor.CurSelection,
curpos = -cursor.Loc,
cursor = cursor,
hasSelection = hasSelection
})
if hasSelection then
for lineN = cursor.CurSelection[1].Y, cursor.CurSelection[2].Y 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
end
toggleCommentSelection(bp, bp.Cursor.CurSelection[1].Y, endLine, commentRegex)
lines[cursor.Y] = true
end
else
toggleCommentLine(bp, bp.Cursor.Y, commentRegex)
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
cursor.CurSelection[1].Y = curData[i].sel[1].Y
cursor.CurSelection[2].Y = curData[i].sel[2].Y
cursor.CurSelection[1].X = curData[i].sel[1].X + displacement
cursor.CurSelection[2].X = curData[i].sel[2].X + displacement
else
cursor.Y = curData[i].curpos.Y
cursor.X = curData[i].curpos.X + displacement
end
cursor:Relocate()
cursor:StoreVisualX()
end
end

Expand Down
5 changes: 3 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 All @@ -38,6 +38,7 @@ but it is only available for certain filetypes:
* dockerfile: `# %s`
* elm: `-- %s`
* fish: `# %s`
* freest: `-- %s`
* gdscript: `# %s`
* glsl: `// %s`
* go: `// %s`
Expand Down