From 52af3dd60ca849dcd62e56c8eda4d583f3dae40c Mon Sep 17 00:00:00 2001 From: Ibrahim Khan <2005ibrahimkhan@gmail.com> Date: Fri, 4 Sep 2026 11:09:15 +0000 Subject: [PATCH] vim: Continue multiline comments with `o` (#63751) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Objective In Vim mode, pressing `o` to open a line inside a documentation-style block comment preserves indentation but drops the `* ` prefix. The behavior for pressing Return is already correct as it continues this prefix in the next line. This change makes both actions behave consistently. Fixes #55049 ## Solution Make Vim’s `o` and `O` commands copy documentation-comment prefixes such as `* ` onto the new line. This happens only when the current line is parsed as a comment. Also added regression coverage for this and folded it into the existing `test_o_comment` test. ## Testing - `CC=clang CXX=clang++ cargo test -p vim test_o_comment -- --nocapture` - `CC=clang CXX=clang++ cargo test -p vim` - `CC=clang CXX=clang++ cargo test -p multi_buffer` - `cargo fmt --all -- --check` - `CC=clang CXX=clang++ ./script/clippy -p vim -p multi_buffer` - Tested on Linux aarch64. ## Self-Review Checklist: - [x] I reviewed the diff for quality, security, and reliability - [x] Unsafe blocks, if any, have justifying comments - [x] The content adheres to the Zed UI standards - [x] Tests cover the changed behavior - [x] Performance impact is acceptable --- Release Notes: - Fixed Vim `o` comment continuation in C-style multiline comments. --- crates/multi_buffer/src/multi_buffer.rs | 11 +++++++++-- crates/vim/src/normal.rs | 4 ++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/crates/multi_buffer/src/multi_buffer.rs b/crates/multi_buffer/src/multi_buffer.rs index e07cd34e92..b5fe19682b 100644 --- a/crates/multi_buffer/src/multi_buffer.rs +++ b/crates/multi_buffer/src/multi_buffer.rs @@ -4532,8 +4532,15 @@ impl MultiBufferSnapshot { if self.language_settings(cx).extend_comment_on_newline && let Some(language_scope) = self.language_scope_at(Point::new(row.0, 0)) { - let delimiters = language_scope.line_comment_prefixes(); - for delimiter in delimiters { + let documentation_delimiter = language_scope + .documentation_comment() + .filter(|_| language_scope.override_name() == Some("comment")) + .map(|comment| &comment.prefix); + for delimiter in language_scope + .line_comment_prefixes() + .iter() + .chain(documentation_delimiter) + { if *self .chars_at(Point::new(row.0, indent.len() as u32)) .take(delimiter.chars().count()) diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index 7cb89a0053..113d4e20a5 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -2174,6 +2174,10 @@ mod test { cx.shared_state().await.assert_eq("// hello\n// ˇ\n"); cx.simulate_shared_keystrokes("x escape shift-o").await; cx.shared_state().await.assert_eq("// hello\n// ˇ\n// x\n"); + + cx.set_state("/*\n * helloˇ\n */\n", Mode::Normal); + cx.simulate_keystrokes("o"); + cx.assert_state("/*\n * hello\n * ˇ\n */\n", Mode::Insert); } #[gpui::test]