diff --git a/announce.md b/announce.md index f1bf70cb9..5ec02a68e 100644 --- a/announce.md +++ b/announce.md @@ -34,3 +34,4 @@ It works in _all_ languages that properly inject comment tokens. For instance, J Closes https://github.com/helix-editor/helix/issues/7364 Closes https://github.com/helix-editor/helix/issues/11647 +Related to to https://github.com/helix-editor/helix/issues/9425 diff --git a/helix-core/src/comment.rs b/helix-core/src/comment.rs index 29febf264..1506d563a 100644 --- a/helix-core/src/comment.rs +++ b/helix-core/src/comment.rs @@ -229,14 +229,14 @@ pub fn find_block_comments( pub fn create_block_comment_transaction( _doc: &Rope, ranges: &[Range], - commented: bool, + was_commented: bool, comment_changes: Vec, ) -> (Vec, SmallVec<[Range; 1]>) { let mut changes: Vec = Vec::with_capacity(ranges.len() * 2); let mut ranges: SmallVec<[Range; 1]> = SmallVec::with_capacity(ranges.len()); let mut offs = 0; for change in comment_changes { - if commented { + if was_commented { if let CommentChange::Commented { range, start_pos, @@ -248,16 +248,11 @@ pub fn create_block_comment_transaction( } = change { let from = range.from(); - changes.push(( - from + start_pos, - from + start_pos + start_token.len() + start_margin as usize, - None, - )); - changes.push(( - from + end_pos - end_token.len() - end_margin as usize + 1, - from + end_pos + 1, - None, - )); + let keep_from = from + start_pos + start_token.len() + start_margin as usize; + changes.push((from + start_pos, keep_from, None)); + let keep_until = from + end_pos - end_token.len() - end_margin as usize + 1; + changes.push((keep_until, from + end_pos + 1, None)); + ranges.push(Range::new(keep_from, keep_until).with_direction(range.direction())); } } else { // uncommented so manually map ranges through changes @@ -303,13 +298,28 @@ pub fn toggle_block_comments( ranges: &Vec, tokens: &[BlockCommentToken], selections: &mut SmallVec<[Range; 1]>, - added_chars: &mut usize, + added_chars: &mut isize, ) -> Vec { let text = doc.slice(..); - let (commented, comment_changes) = find_block_comments(tokens, text, ranges); + let (was_commented, comment_changes) = find_block_comments(tokens, text, ranges); let (changes, new_ranges) = - create_block_comment_transaction(doc, ranges, commented, comment_changes); - if commented { + create_block_comment_transaction(doc, ranges, was_commented, comment_changes); + + if was_commented { + for (i, range) in new_ranges.iter().enumerate() { + // every 2 elements (from, to) in `changes` corresponds + // the `from` - `to` represents the range of text that will be deleted. + // to 1 element in `new_ranges` + let (from, to, _) = changes[i * 2]; + let (from2, to2, _) = changes[i * 2 + 1]; + *added_chars -= to2 as isize - from2 as isize; + selections.push(Range::new( + (range.anchor as isize + *added_chars).try_into().unwrap(), + (range.head as isize + *added_chars).try_into().unwrap(), + )); + *added_chars -= to as isize - from as isize; + } + changes } else { // when we add comment tokens, we want to extend our selection to @@ -323,9 +333,12 @@ pub fn toggle_block_comments( // Will not underflow because the new range must always be // at least the same size as the old range, since we're // adding comment token characters, never removing. - let range = Range::new(range.from() + *added_chars, range.to() + *added_chars); + let range = Range::new( + range.anchor + *added_chars as usize, + range.head + *added_chars as usize, + ); selections.push(range); - *added_chars += range.len() - old_range.len(); + *added_chars += range.len() as isize - old_range.len() as isize; } changes diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 35a7a16c5..83b2d7d98 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -5124,6 +5124,7 @@ fn toggle_comments_impl<'a>( .and_then(|lc| lc.block_comment_tokens.as_ref()) .map(|tc| &tc[..]); + // TODO: figure out how to avoid this clone let syntax = doc.syntax().cloned(); let transaction = comment_transaction( @@ -5307,8 +5308,6 @@ fn toggle_block_comments(cx: &mut Context) { cx, Box::new( |doc_line_token, doc_block_tokens, rope, selection, mut get_injected_tokens| { - // when we add comment tokens, we want to extend our selection to - // also include the added tokens. let mut selections = SmallVec::new(); let mut added_chars = 0; let transaction = Transaction::change( diff --git a/helix-term/tests/test/commands.rs b/helix-term/tests/test/commands.rs index f485e4600..716452912 100644 --- a/helix-term/tests/test/commands.rs +++ b/helix-term/tests/test/commands.rs @@ -681,7 +681,7 @@ async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> { indoc! {r#"\

Comment toggle on this line should use the HTML comment token(s).

"#}, @@ -689,7 +689,7 @@ async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> { indoc! {r#"\

Comment toggle on this line should use the HTML comment token(s).

"#}, @@ -701,7 +701,7 @@ async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> { indoc! {r#"\

Comment toggle on this line should use the HTML comment token(s).

"#}, @@ -709,7 +709,7 @@ async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> { indoc! {r#"\

Comment toggle on this line should use the HTML comment token(s).

"#}, @@ -742,7 +742,6 @@ async fn test_injected_comment_tokens_simple() -> anyhow::Result<()> { /// Selections in different regions #[tokio::test(flavor = "multi_thread")] async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<()> { - return Ok(()); // Comments two different injection layers with different comments test(( indoc! {r#"\ @@ -860,7 +859,6 @@ async fn test_injected_comment_tokens_multiple_selections() -> anyhow::Result<() /// from the injection with the bigger scope #[tokio::test(flavor = "multi_thread")] async fn test_injected_comment_tokens_selection_across_different_layers() -> anyhow::Result<()> { - return Ok(()); test(( indoc! {r#"\

Comment tog#[|gle on this line should use the HTML comment token(s).