From e75a7aecd6ebd2c381d9dfb606be20cc4326200b Mon Sep 17 00:00:00 2001 From: Smit Barmase Date: Mon, 8 Dec 2025 04:19:17 -0800 Subject: [PATCH] languages: Fix Markdown list items are automatically indented erroneously (#44381) Closes #44223 Regressed in https://github.com/zed-industries/zed/pull/40794 in attempt to fix https://github.com/zed-industries/zed/issues/40757. This PR handles both cases and add more tests around it. Bug is only in Nightly. Release Notes: - N/A --- crates/editor/src/editor_tests.rs | 134 ++++++++++++++++++---- crates/languages/src/markdown/config.toml | 2 +- crates/languages/src/markdown/indents.scm | 2 - 3 files changed, 115 insertions(+), 23 deletions(-) diff --git a/crates/editor/src/editor_tests.rs b/crates/editor/src/editor_tests.rs index 683972254ce0ffb719679d431f0a72485cee97f2..d2653ef3d08916da23248917c727c40860ab129c 100644 --- a/crates/editor/src/editor_tests.rs +++ b/crates/editor/src/editor_tests.rs @@ -27499,7 +27499,7 @@ async fn test_paste_url_from_other_app_creates_markdown_link_over_selected_text( } #[gpui::test] -async fn test_markdown_list_indent_with_multi_cursor(cx: &mut gpui::TestAppContext) { +async fn test_markdown_indents(cx: &mut gpui::TestAppContext) { init_test(cx, |_| {}); let markdown_language = languages::language("markdown", tree_sitter_md::LANGUAGE.into()); @@ -27507,6 +27507,7 @@ async fn test_markdown_list_indent_with_multi_cursor(cx: &mut gpui::TestAppConte cx.update_buffer(|buffer, cx| buffer.set_language(Some(markdown_language), cx)); + // Case 1: Test if adding a character with multi cursors preserves nested list indents cx.set_state(&indoc! {" - [ ] Item 1 - [ ] Item 1.a @@ -27515,44 +27516,137 @@ async fn test_markdown_list_indent_with_multi_cursor(cx: &mut gpui::TestAppConte - [ˇ] Item 2.b " }); - cx.update_editor(|editor, window, cx| { - editor.handle_input("X", window, cx); + editor.handle_input("x", window, cx); + }); + cx.assert_editor_state(indoc! {" + - [ ] Item 1 + - [ ] Item 1.a + - [xˇ] Item 2 + - [xˇ] Item 2.a + - [xˇ] Item 2.b + " }); + // Case 2: Test adding new line after nested list preserves indent of previous line + cx.set_state(&indoc! {" + - [ ] Item 1 + - [ ] Item 1.a + - [x] Item 2 + - [x] Item 2.a + - [x] Item 2.bˇ + " + }); + cx.update_editor(|editor, window, cx| { + editor.newline(&Newline, window, cx); + }); cx.assert_editor_state(indoc! {" - [ ] Item 1 - [ ] Item 1.a - - [Xˇ] Item 2 - - [Xˇ] Item 2.a - - [Xˇ] Item 2.b + - [x] Item 2 + - [x] Item 2.a + - [x] Item 2.b + ˇ " }); -} -#[gpui::test] -async fn test_markdown_list_indent_with_newline(cx: &mut gpui::TestAppContext) { - init_test(cx, |_| {}); + // Case 3: Test adding a new nested list item preserves indent + cx.update_editor(|editor, window, cx| { + editor.handle_input("-", window, cx); + }); + cx.assert_editor_state(indoc! {" + - [ ] Item 1 + - [ ] Item 1.a + - [x] Item 2 + - [x] Item 2.a + - [x] Item 2.b + -ˇ + " + }); + cx.update_editor(|editor, window, cx| { + editor.handle_input(" [x] Item 2.c", window, cx); + }); + cx.assert_editor_state(indoc! {" + - [ ] Item 1 + - [ ] Item 1.a + - [x] Item 2 + - [x] Item 2.a + - [x] Item 2.b + - [x] Item 2.cˇ + " + }); - let markdown_language = languages::language("markdown", tree_sitter_md::LANGUAGE.into()); - let mut cx = EditorTestContext::new(cx).await; + // Case 4: Test adding new line after nested ordered list preserves indent of previous line + cx.set_state(indoc! {" + 1. Item 1 + 1. Item 1.a + 2. Item 2 + 1. Item 2.a + 2. Item 2.bˇ + " + }); + cx.update_editor(|editor, window, cx| { + editor.newline(&Newline, window, cx); + }); + cx.assert_editor_state(indoc! {" + 1. Item 1 + 1. Item 1.a + 2. Item 2 + 1. Item 2.a + 2. Item 2.b + ˇ + " + }); - cx.update_buffer(|buffer, cx| buffer.set_language(Some(markdown_language), cx)); + // Case 5: Adding new ordered list item preserves indent + cx.update_editor(|editor, window, cx| { + editor.handle_input("3", window, cx); + }); + cx.assert_editor_state(indoc! {" + 1. Item 1 + 1. Item 1.a + 2. Item 2 + 1. Item 2.a + 2. Item 2.b + 3ˇ + " + }); + cx.update_editor(|editor, window, cx| { + editor.handle_input(".", window, cx); + }); + cx.assert_editor_state(indoc! {" + 1. Item 1 + 1. Item 1.a + 2. Item 2 + 1. Item 2.a + 2. Item 2.b + 3.ˇ + " + }); + cx.update_editor(|editor, window, cx| { + editor.handle_input(" Item 2.c", window, cx); + }); + cx.assert_editor_state(indoc! {" + 1. Item 1 + 1. Item 1.a + 2. Item 2 + 1. Item 2.a + 2. Item 2.b + 3. Item 2.cˇ + " + }); + // Case 7: Test blockquote newline preserves something cx.set_state(indoc! {" - - [x] list item - - [x] sub list itemˇ + > Item 1ˇ " }); - cx.update_editor(|editor, window, cx| { editor.newline(&Newline, window, cx); }); - cx.assert_editor_state(indoc! {" - - [x] list item - - [x] sub list item - ˇ + > Item 1 + ˇ " }); } diff --git a/crates/languages/src/markdown/config.toml b/crates/languages/src/markdown/config.toml index 2bbda0ef43e9a49b483dbe22cdf0473c8fbcf73c..f786c61b8155b0fa4c93b43e2126cc66d86e22e4 100644 --- a/crates/languages/src/markdown/config.toml +++ b/crates/languages/src/markdown/config.toml @@ -24,5 +24,5 @@ rewrap_prefixes = [ auto_indent_on_paste = false auto_indent_using_last_non_empty_line = false tab_size = 2 -decrease_indent_pattern = "^\\s*$" +decrease_indent_pattern = "^.*$" prettier_parser_name = "markdown" diff --git a/crates/languages/src/markdown/indents.scm b/crates/languages/src/markdown/indents.scm index 7fde3226bbbeb0fb9f0f7a1d90a328923a5228b3..2840e8b4611c05ef4c88e775c970eb79b9b99f4a 100644 --- a/crates/languages/src/markdown/indents.scm +++ b/crates/languages/src/markdown/indents.scm @@ -1,3 +1 @@ (list (list_item) @indent) - -(list_item (list) @indent)