diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 5d63cdd3..c9560f33 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -3825,6 +3825,29 @@ pub enum CommentContinuation { Disabled, } +fn continued_line_comment_token<'a>( + doc: &'a Document, + loader: &'a helix_core::syntax::Loader, + text: RopeSlice, + line_num: usize, + byte_pos: usize, +) -> Option<&'a str> { + if let Some(syntax) = doc.syntax() { + let mut token = None; + for layer in syntax.layers_for_byte_range(byte_pos as u32, byte_pos as u32) { + let config = loader.language(syntax.layer(layer).language).config(); + if let Some(tokens) = config.comment_tokens.as_ref() { + token = comment::get_comment_token(text, tokens, line_num).or(token); + } + } + token + } else { + doc.language_config() + .and_then(|config| config.comment_tokens.as_ref()) + .and_then(|tokens| comment::get_comment_token(text, tokens, line_num)) + } +} + fn open(cx: &mut Context, open: Open, comment_continuation: CommentContinuation) { let count = cx.count(); enter_insert_mode(cx); @@ -3860,9 +3883,9 @@ fn open(cx: &mut Context, open: Open, comment_continuation: CommentContinuation) text.line(curr_line_num) .first_non_whitespace_char() .map(|c| text.char_to_byte(text.line_to_char(curr_line_num) + c)) - .and_then(|byte| doc.language_config_at(&loader, byte)) - .and_then(|config| config.comment_tokens.as_ref()) - .and_then(|tokens| comment::get_comment_token(text, tokens, curr_line_num)) + .and_then(|byte| { + continued_line_comment_token(doc, &loader, text, curr_line_num, byte) + }) } else { None }; @@ -4489,9 +4512,9 @@ pub mod insert { text.line(current_line) .first_non_whitespace_char() .map(|c| text.char_to_byte(line_start + c)) - .and_then(|byte| doc.language_config_at(&loader, byte)) - .and_then(|config| config.comment_tokens.as_ref()) - .and_then(|tokens| comment::get_comment_token(text, tokens, current_line)) + .and_then(|byte| { + continued_line_comment_token(doc, &loader, text, current_line, byte) + }) } else { None }; diff --git a/helix-term/tests/test/commands/insert.rs b/helix-term/tests/test/commands/insert.rs index 7f00826b..640a2390 100644 --- a/helix-term/tests/test/commands/insert.rs +++ b/helix-term/tests/test/commands/insert.rs @@ -201,6 +201,36 @@ async fn insert_newline_continue_line_comment() -> anyhow::Result<()> { )) .await?; + // Continuation should use the enclosing layer's comment tokens if an injected layer + // doesn't define comment token. + test(( + indoc! {"\ + // Hello world!#[| + ]# + "}, + ":lang goi", + indoc! {"\ + // Hello world! + // #[| + ]# + "}, + )) + .await?; + + test(( + indoc! {"\ + //go:generate echo hello#[| + ]# + "}, + ":lang goi", + indoc! {"\ + //go:generate echo hello + // #[| + ]# + "}, + )) + .await?; + // The comment is not continued if the cursor is before the comment token. (Note that we // are entering insert-mode with `I`.) test(( @@ -461,6 +491,26 @@ async fn test_open_below_with_multiple_cursors() -> anyhow::Result<()> { )) .await?; + // Open below should continue comment even if language has `comment` grammar + // injection. + test(( + indoc! {"\ + package main + + // VIP#[|]# comment + func main() {} + "}, + ":lang goo", + indoc! {"\ + package main + + // VIP comment + // #[\n|]# + func main() {} + "}, + )) + .await?; + Ok(()) }