Repository: zyedidia/micro
File: runtime/plugins/comment/comment.lua (Lua)

Code before:
ft["perl"] = "# %s"
ft["php"] = "// %s"
ft["pony"] = "// %s"
ft["powershell"] = "# %s"
ft["proto"] = "// %s"
ft["python"] = "# %s"
ft["python3"] = "# %s"
ft["ruby"] = "# %s"
ft["rust"] = "// %s"
ft["scala"] = "// %s"
ft["shell"] = "# %s"
ft["sql"] = "-- %s"
ft["swift"] = "// %s"
ft["tex"] = "% %s"
ft["toml"] = "# %s"
ft["twig"] = "{# %s #}"
ft["v"] = "// %s"
ft["xml"] = "<!-- %s -->"
ft["yaml"] = "# %s"
ft["zig"] = "// %s"
ft["zscript"] = "// %s"
ft["zsh"] = "# %s"

function updateCommentType(buf)
    -- NOTE: Don't use SetOptionNative() to set "comment.type",
    -- otherwise "comment.type" can't be reset by a "filetype" change.
    if buf.Settings["comment.type"] == "" then
        if ft[buf.Settings["filetype"]] ~= nil then
            buf.Settings["comment.type"] = ft[buf.Settings["filetype"]]
        else
            buf.Settings["comment.type"] = "# %s"
        end
    end
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
end

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

    local line = bp.Buf:Line(lineN)
    local commentType = bp.Buf.Settings["comment.type"]
    local sel = -bp.Cursor.CurSelection
    local curpos = -bp.Cursor.Loc

Review comment (suggestion):
It is not nearly obvious *why* can't it be reset by a "filetype" change if we use `SetOptionNative()` (it took me some time to figure it out, for instance). We should explain it better, e.g. "Don't use SetOptionNative() to set "comment.type", otherwise "comment.type" will be marked as locally overridden and will not be updated when "filetype" changes."

Or actually it seems better to:
1. use `DoSetOptionNative()` instead of setting the option directly
2. add documentation to both `SetOptionNative()` and `DoSetOptionNative()`, so that everyone knows what is the difference between them and when to use each of them, and then we don't need this comment here.

...Another option would be to somehow extend `RegisterCommonOption()` to allow registering default per-filetype values of an option, not just its default global value, at init time, - so that `updateCommentType()` would not be needed at all.

Code after:
ft["pascal"] = "{ %s }"
ft["perl"] = "# %s"
ft["php"] = "// %s"
ft["pony"] = "// %s"
ft["powershell"] = "# %s"
ft["proto"] = "// %s"
ft["python"] = "# %s"
ft["python3"] = "# %s"
ft["ruby"] = "# %s"
ft["rust"] = "// %s"
ft["scala"] = "// %s"
ft["shell"] = "# %s"
ft["sql"] = "-- %s"
ft["swift"] = "// %s"
ft["tex"] = "% %s"
ft["toml"] = "# %s"
ft["twig"] = "{# %s #}"
ft["v"] = "// %s"
ft["xml"] = "<!-- %s -->"
ft["yaml"] = "# %s"
ft["zig"] = "// %s"
ft["zscript"] = "// %s"
ft["zsh"] = "# %s"

function updateCommentType(buf)
    -- NOTE: Using DoSetOptionNative to avoid LocalSettings[option] = true
    -- so that "comment.type" can be reset by a "filetype" change to default.
    if (buf.Settings["comment.type"] == "") then
        -- NOTE: This won't get triggered if a filetype is change via `setlocal filetype`
        -- since it is not registered with `RegisterGlobalOption()``
        if buf.Settings["commenttype"] ~= nil then
            buf:DoSetOptionNative("comment.type", buf.Settings["commenttype"])
        else
            if (ft[buf.Settings["filetype"]] ~= nil) then
                buf:DoSetOptionNative("comment.type", ft[buf.Settings["filetype"]])
            else
                buf:DoSetOptionNative("comment.type", "# %s")
            end
        end
    end
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
end