diff --git a/data/core/commands/doc.lua b/data/core/commands/doc.lua index 3ff66841..d5c37c9a 100644 --- a/data/core/commands/doc.lua +++ b/data/core/commands/doc.lua @@ -4,11 +4,7 @@ local common = require "core.common" local config = require "core.config" local translate = require "core.doc.translate" local DocView = require "core.docview" - - -local function dv() - return core.active_view -end +local tokenizer = require "core.tokenizer" local function doc() @@ -433,15 +429,28 @@ local commands = { end, ["doc:toggle-block-comments"] = function(dv) - local comment = dv.doc.syntax.block_comment - if not comment then - if dv.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 + local current_syntax = dv.doc.syntax + if line1 > 1 then + -- Use the previous line state, as it will be the state + -- of the beginning of the current line + local state = dv.doc.highlighter:get_line(line1 - 1).state + local syntaxes = tokenizer.extract_subsyntaxes(dv.doc.syntax, state) + -- Go through all the syntaxes until the first with `block_comment` defined + for _, s in pairs(syntaxes) do + if s.block_comment then + current_syntax = s + break + end + end + end + local comment = current_syntax.block_comment + if not comment then + if dv.doc.syntax.comment then + command.perform "doc:toggle-line-comments" + end + return + end -- if nothing is selected, toggle the whole line if line1 == line2 and col1 == col2 then col1 = 1 @@ -452,9 +461,23 @@ local commands = { end, ["doc:toggle-line-comments"] = function(dv) - local comment = dv.doc.syntax.comment or dv.doc.syntax.block_comment - if comment then - for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do + for idx, line1, col1, line2, col2 in doc_multiline_selections(true) do + local current_syntax = dv.doc.syntax + if line1 > 1 then + -- Use the previous line state, as it will be the state + -- of the beginning of the current line + local state = dv.doc.highlighter:get_line(line1 - 1).state + local syntaxes = tokenizer.extract_subsyntaxes(dv.doc.syntax, state) + -- Go through all the syntaxes until the first with comments defined + for _, s in pairs(syntaxes) do + if s.comment or s.block_comment then + current_syntax = s + break + end + end + end + local comment = current_syntax.comment or current_syntax.block_comment + if comment then dv.doc:set_selections(idx, line_comment(comment, line1, col1, line2, col2)) end end diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua index dd1f2e2c..5ecdf325 100644 --- a/data/core/tokenizer.lua +++ b/data/core/tokenizer.lua @@ -100,6 +100,21 @@ local function retrieve_syntax_state(incoming_syntax, state) return current_syntax, subsyntax_info, current_pattern_idx, current_level end +---Return the list of syntaxes used in the specified state. +---@param base_syntax table @The initial base syntax (the syntax of the file) +---@param state string @The state of the tokenizer to extract from +---@return table @Array of syntaxes starting from the innermost one +function tokenizer.extract_subsyntaxes(base_syntax, state) + local current_syntax + local t = {} + repeat + current_syntax = retrieve_syntax_state(base_syntax, state) + table.insert(t, current_syntax) + state = string.sub(state, 2) + until #state == 0 + return t +end + local function report_bad_pattern(log_fn, syntax, pattern_idx, msg, ...) if not bad_patterns[syntax] then bad_patterns[syntax] = { } @@ -121,7 +136,7 @@ function tokenizer.tokenize(incoming_syntax, text, state) return { "normal", text } end - state = state or "" + state = state or string.char(0) -- incoming_syntax : the parent syntax of the file. -- state : a string of bytes representing syntax state (see above)