diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 8e2078f3..54b84921 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -97,6 +97,67 @@ local function set_cursor(x, y, snap_type) core.blink_reset() end +local function line_comment(comment, line1, line2) + local comment_text = comment .. " " + local uncomment = true + local start_offset = math.huge + for line = line1, line2 do + local text = doc().lines[line] + local s = text:find("%S") + local cs, ce = text:find(comment_text, s, true) + if s and cs ~= s then + uncomment = false + start_offset = math.min(start_offset, s) + end + end + for line = line1, line2 do + local text = doc().lines[line] + local s = text:find("%S") + if uncomment then + local cs, ce = text:find(comment_text, s, true) + if ce then + doc():remove(line, cs, line, ce + 1) + end + elseif s then + doc():insert(line, start_offset, comment_text) + end + end +end + +local function block_comment(comment, line1, col1, line2, col2) + -- automatically skip spaces + local word_start = doc():get_text(line1, col1, line1, math.huge):find("%S") + local word_end = doc():get_text(line2, 1, line2, col2):find("%s*$") + col1 = col1 + (word_start and (word_start - 1) or 0) + col2 = word_end and word_end or col2 + + local block_start = doc():get_text(line1, col1, line1, col1 + #comment[1]) + local block_end = doc():get_text(line2, col2 - #comment[2], line2, col2) + + if block_start == comment[1] and block_end == comment[2] then + -- remove up to 1 whitespace after the comment + local start_len, stop_len = #comment[1], #comment[2] + if doc():get_text(line1, col1 + #comment[1], line1, col1 + #comment[1] + 1):find("%s$") then + start_len = start_len + 1 + end + if doc():get_text(line2, col2 - #comment[2] - 1, line2, col2):find("^%s") then + stop_len = stop_len + 1 + end + + doc():remove(line1, col1, line1, col1 + start_len) + col2 = col2 - (line1 == line2 and start_len or 0) + doc():remove(line2, col2 - stop_len, line2, col2) + + return line1, col1, line2, col2 - stop_len + else + doc():insert(line1, col1, comment[1] .. " ") + col2 = col2 + (line1 == line2 and (#comment[1] + 1) or 0) + doc():insert(line2, col2, " " .. comment[2]) + + return line1, col1, line2, col2 + #comment[2] + 1 + end +end + local selection_commands = { ["doc:select-none"] = function() local line, col = doc():get_selection() @@ -292,34 +353,43 @@ local commands = { end end, + ["doc:toggle-block-comments"] = function() + local comment = doc().syntax.block_comment + if not comment then + if doc().syntax.comment then + command.perform "doc:toggle-line-comments" + end + return + end + + for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do + -- if nothing is selected, toggle the whole line + if line1 == line2 and col1 == col2 then + col1 = 1 + col2 = #doc().lines[line2] + end + + line1, col1, line2, col2 = block_comment(comment, line1, col1, line2, col2) + doc():set_selections(idx, line1, col1, line2, col2) + end + end, + ["doc:toggle-line-comments"] = function() local comment = doc().syntax.comment - if not comment then return end - local indentation = doc():get_indent_string() - local comment_text = comment .. " " - for idx, line1, _, line2 in doc_multiline_selections(true) do - local uncomment = true - local start_offset = math.huge - for line = line1, line2 do - local text = doc().lines[line] - local s = text:find("%S") - local cs, ce = text:find(comment_text, s, true) - if s and cs ~= s then - uncomment = false - start_offset = math.min(start_offset, s) - end - end - for line = line1, line2 do - local text = doc().lines[line] - local s = text:find("%S") - if uncomment then - local cs, ce = text:find(comment_text, s, true) - if ce then - doc():remove(line, cs, line, ce + 1) - end - elseif s then - doc():insert(line, start_offset, comment_text) + local block = false + if not comment then + comment = doc().syntax.block_comment + if not comment then return end + block = true + end + + for _, line1, _, line2 in doc_multiline_selections(true) do + if block then + for line = line1, line2 do + block_comment(comment, line, 1, line, #doc().lines[line]) end + else + line_comment(comment, line1, line2) end end end, diff --git a/data/core/keymap.lua b/data/core/keymap.lua index 404cff39..6716fca9 100644 --- a/data/core/keymap.lua +++ b/data/core/keymap.lua @@ -215,6 +215,7 @@ keymap.add_direct { ["ctrl+l"] = "doc:select-lines", ["ctrl+shift+l"] = { "find-replace:select-add-all", "doc:select-word" }, ["ctrl+/"] = "doc:toggle-line-comments", + ["ctrl+shift+/"] = "doc:toggle-block-comments", ["ctrl+up"] = "doc:move-lines-up", ["ctrl+down"] = "doc:move-lines-down", ["ctrl+shift+d"] = "doc:duplicate-lines", diff --git a/data/plugins/language_c.lua b/data/plugins/language_c.lua index 88cc7c5a..c4d3b07b 100644 --- a/data/plugins/language_c.lua +++ b/data/plugins/language_c.lua @@ -5,6 +5,7 @@ syntax.add { name = "C", files = { "%.c$", "%.h$", "%.inl$" }, comment = "//", + block_comment = { "/*", "*/" }, patterns = { { pattern = "//.-\n", type = "comment" }, { pattern = { "/%*", "%*/" }, type = "comment" }, diff --git a/data/plugins/language_cpp.lua b/data/plugins/language_cpp.lua index a945fd1f..2b3a104f 100644 --- a/data/plugins/language_cpp.lua +++ b/data/plugins/language_cpp.lua @@ -10,6 +10,7 @@ syntax.add { "%.c++$", "%.hh$", "%.H$", "%.hxx$", "%.hpp$", "%.h++$" }, comment = "//", + block_comment = { "/*", "*/" }, patterns = { { pattern = "//.-\n", type = "comment" }, { pattern = { "/%*", "%*/" }, type = "comment" }, diff --git a/data/plugins/language_css.lua b/data/plugins/language_css.lua index 395e375c..96c3eb8d 100644 --- a/data/plugins/language_css.lua +++ b/data/plugins/language_css.lua @@ -4,6 +4,7 @@ local syntax = require "core.syntax" syntax.add { name = "CSS", files = { "%.css$" }, + block_comment = { "/*", "*/" }, patterns = { { pattern = "\\.", type = "normal" }, { pattern = "//.-\n", type = "comment" }, diff --git a/data/plugins/language_html.lua b/data/plugins/language_html.lua index 1f4515bc..ff61fa7f 100644 --- a/data/plugins/language_html.lua +++ b/data/plugins/language_html.lua @@ -4,28 +4,29 @@ local syntax = require "core.syntax" syntax.add { name = "HTML", files = { "%.html?$" }, + block_comment = { "" }, patterns = { - { - pattern = { + { + pattern = { "<%s*[sS][cC][rR][iI][pP][tT]%s+[tT][yY][pP][eE]%s*=%s*" .. "['\"]%a+/[jJ][aA][vV][aA][sS][cC][rR][iI][pP][tT]['\"]%s*>", - "<%s*/[sS][cC][rR][iI][pP][tT]>" - }, - syntax = ".js", - type = "function" - }, - { - pattern = { - "<%s*[sS][cC][rR][iI][pP][tT]%s*>", - "<%s*/%s*[sS][cC][rR][iI][pP][tT]>" + "<%s*/[sS][cC][rR][iI][pP][tT]>" }, syntax = ".js", type = "function" }, - { - pattern = { - "<%s*[sS][tT][yY][lL][eE][^>]*>", - "<%s*/%s*[sS][tT][yY][lL][eE]%s*>" + { + pattern = { + "<%s*[sS][cC][rR][iI][pP][tT]%s*>", + "<%s*/%s*[sS][cC][rR][iI][pP][tT]>" + }, + syntax = ".js", + type = "function" + }, + { + pattern = { + "<%s*[sS][tT][yY][lL][eE][^>]*>", + "<%s*/%s*[sS][tT][yY][lL][eE]%s*>" }, syntax = ".css", type = "function" diff --git a/data/plugins/language_js.lua b/data/plugins/language_js.lua index 94ab8499..2e6d5d87 100644 --- a/data/plugins/language_js.lua +++ b/data/plugins/language_js.lua @@ -5,6 +5,7 @@ syntax.add { name = "JavaScript", files = { "%.js$", "%.json$", "%.cson$" }, comment = "//", + block_comment = { "/*", "*/" }, patterns = { { pattern = "//.-\n", type = "comment" }, { pattern = { "/%*", "%*/" }, type = "comment" }, diff --git a/data/plugins/language_lua.lua b/data/plugins/language_lua.lua index 5c770d43..993e53c8 100644 --- a/data/plugins/language_lua.lua +++ b/data/plugins/language_lua.lua @@ -6,6 +6,7 @@ syntax.add { files = "%.lua$", headers = "^#!.*[ /]lua", comment = "--", + block_comment = { "--[[", "]]" }, patterns = { { pattern = { '"', '"', '\\' }, type = "string" }, { pattern = { "'", "'", '\\' }, type = "string" }, diff --git a/data/plugins/language_xml.lua b/data/plugins/language_xml.lua index c858d3cf..297b6d73 100644 --- a/data/plugins/language_xml.lua +++ b/data/plugins/language_xml.lua @@ -5,6 +5,7 @@ syntax.add { name = "XML", files = { "%.xml$" }, headers = "<%?xml", + block_comment = { "" }, patterns = { { pattern = { "" }, type = "comment" }, { pattern = { '%f[^>][^<]', '%f[<]' }, type = "normal" },