From 7078e8400736dce923be44a4d26f136a22640f93 Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Fri, 14 Apr 2023 11:00:15 -0400 Subject: Fix YAML auto indent YAML indents queries are tweaked to fix auto indent behavior. A new capture type `indent.always` is introduced to address use cases where combining indent captures on a single line is desired. Fixes #6661 --- helix-term/src/commands.rs | 8 +- helix-term/tests/integration.rs | 1 + helix-term/tests/test/languages/go.rs | 41 ++ helix-term/tests/test/languages/mod.rs | 4 + helix-term/tests/test/languages/yaml.rs | 819 ++++++++++++++++++++++++++++++++ 5 files changed, 871 insertions(+), 2 deletions(-) create mode 100644 helix-term/tests/test/languages/go.rs create mode 100644 helix-term/tests/test/languages/mod.rs create mode 100644 helix-term/tests/test/languages/yaml.rs (limited to 'helix-term') diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index 8be0f83a..61c647d0 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -2999,6 +2999,7 @@ fn open(cx: &mut Context, open: Open) { Open::Below => graphemes::prev_grapheme_boundary(text, range.to()), Open::Above => range.from(), }); + let new_line = match open { // adjust position to the end of the line (next line - 1) Open::Below => cursor_line + 1, @@ -3006,13 +3007,15 @@ fn open(cx: &mut Context, open: Open) { Open::Above => cursor_line, }; + let line_num = new_line.saturating_sub(1); + // Index to insert newlines after, as well as the char width // to use to compensate for those inserted newlines. let (line_end_index, line_end_offset_width) = if new_line == 0 { (0, 0) } else { ( - line_end_char_index(&doc.text().slice(..), new_line.saturating_sub(1)), + line_end_char_index(&text, line_num), doc.line_ending.len_chars(), ) }; @@ -3023,10 +3026,11 @@ fn open(cx: &mut Context, open: Open) { &doc.indent_style, doc.tab_width(), text, - new_line.saturating_sub(1), + line_num, line_end_index, cursor_line, ); + let indent_len = indent.len(); let mut text = String::with_capacity(1 + indent_len); text.push_str(doc.line_ending.as_str()); diff --git a/helix-term/tests/integration.rs b/helix-term/tests/integration.rs index a62f0066..9c0e6bbc 100644 --- a/helix-term/tests/integration.rs +++ b/helix-term/tests/integration.rs @@ -18,6 +18,7 @@ mod test { mod auto_indent; mod auto_pairs; mod commands; + mod languages; mod movement; mod picker; mod prompt; diff --git a/helix-term/tests/test/languages/go.rs b/helix-term/tests/test/languages/go.rs new file mode 100644 index 00000000..7bb3651e --- /dev/null +++ b/helix-term/tests/test/languages/go.rs @@ -0,0 +1,41 @@ +use super::*; + +#[tokio::test(flavor = "multi_thread")] +async fn auto_indent() -> anyhow::Result<()> { + let app = || AppBuilder::new().with_file("foo.go", None); + + let enter_tests = [ + ( + helpers::platform_line(indoc! {r##" + type Test struct {#[}|]# + "##}), + "i", + helpers::platform_line(indoc! {"\ + type Test struct { + \t#[|\n]# + } + "}), + ), + ( + helpers::platform_line(indoc! {"\ + func main() { + \tswitch nil {#[}|]# + } + "}), + "i", + helpers::platform_line(indoc! {"\ + func main() { + \tswitch nil { + \t\t#[|\n]# + \t} + } + "}), + ), + ]; + + for test in enter_tests { + test_with_config(app(), test).await?; + } + + Ok(()) +} diff --git a/helix-term/tests/test/languages/mod.rs b/helix-term/tests/test/languages/mod.rs new file mode 100644 index 00000000..51c23db6 --- /dev/null +++ b/helix-term/tests/test/languages/mod.rs @@ -0,0 +1,4 @@ +use super::*; + +mod go; +mod yaml; diff --git a/helix-term/tests/test/languages/yaml.rs b/helix-term/tests/test/languages/yaml.rs new file mode 100644 index 00000000..7669e8a2 --- /dev/null +++ b/helix-term/tests/test/languages/yaml.rs @@ -0,0 +1,819 @@ +use super::*; + +#[tokio::test(flavor = "multi_thread")] +async fn auto_indent() -> anyhow::Result<()> { + let app = || AppBuilder::new().with_file("foo.yaml", None); + + let below_tests = [ + ( + helpers::platform_line(indoc! {r##" + #[t|]#op: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "o", + helpers::platform_line(indoc! {"\ + top: + #[\n|]# + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + b#[a|]#z: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + #[\n|]# + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi#[:|]# + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + #[\n|]# + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi: + more: #[yes|]# + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + #[\n|]# + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi: + more: yes + why: becaus#[e|]# + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + #[\n|]# + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux:#[\n|]# + - 1 + - 2 + bax: foox + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + #[\n|]# + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1#[\n|]# + - 2 + bax: foox + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + #[\n|]# + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook:#[\n|]# + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + #[\n|]# + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: | + some + multi + line + string#[\n|]# + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: | + some + multi + line + string + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + some + multi + line#[\n|]# + string + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + some + multi + line + #[\n|]# + string + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: >#[\n|]# + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + - top:#[\n|]# + baz: foo + bax: foox + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + - top: + #[\n|]# + baz: foo + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + - top: + baz: foo#[\n|]# + bax: foox + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + - top: + baz: foo + #[\n|]# + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + - top: + baz: foo + bax: foox#[\n|]# + fook: + "}), + "o", + helpers::platform_line(indoc! {"\ + - top: + baz: foo + bax: foox + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: + - one: two#[\n|]# + three: four + - top: + baz: foo + bax: foox + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + baz: + - one: two + #[\n|]# + three: four + - top: + baz: foo + bax: foox + "}), + ), + // yaml map without a key + ( + helpers::platform_line(indoc! {"\ + top:#[\n|]# + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + #[\n|]# + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top#[:|]# + bottom: withvalue + "}), + "o", + helpers::platform_line(indoc! {"\ + top: + #[\n|]# + bottom: withvalue + "}), + ), + ( + helpers::platform_line(indoc! {"\ + bottom: withvalue + top#[:|]# + "}), + "o", + helpers::platform_line(indoc! {"\ + bottom: withvalue + top: + #[\n|]# + "}), + ), + ]; + + for test in below_tests { + test_with_config(app(), test).await?; + } + + let above_tests = [ + ( + helpers::platform_line(indoc! {r##" + #[t|]#op: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "O", + helpers::platform_line(indoc! {"\ + #[\n|]# + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + b#[a|]#z: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "O", + helpers::platform_line(indoc! {"\ + top: + #[\n|]# + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi#[:|]# + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + #[\n|]# + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi: + more: #[yes|]# + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + #[\n|]# + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {r##" + top: + baz: foo + bazi: + more: yes + why: becaus#[e|]# + quux: + - 1 + - 2 + bax: foox + fook: + "##}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + #[\n|]# + why: because + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux:#[\n|]# + - 1 + - 2 + bax: foox + fook: + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + #[\n|]# + quux: + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1#[\n|]# + - 2 + bax: foox + fook: + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + #[\n|]# + - 1 + - 2 + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + fook:#[\n|]# + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bazi: + more: yes + why: because + quux: + - 1 + - 2 + bax: foox + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: | + some + multi + line + string#[\n|]# + fook: + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: | + some + multi + line + #[\n|]# + string + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + some#[\n|]# + multi + line + string + fook: + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + #[\n|]# + some + multi + line + string + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + fook:#[\n|]# + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: foo + bax: > + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + - top: + baz: foo#[\n|]# + bax: foox + fook: + "}), + "O", + helpers::platform_line(indoc! {"\ + - top: + #[\n|]# + baz: foo + bax: foox + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + - top: + baz: foo + bax: foox + fook:#[\n|]# + "}), + "O", + helpers::platform_line(indoc! {"\ + - top: + baz: foo + bax: foox + #[\n|]# + fook: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + baz: + - one: two#[\n|]# + three: four + - top: + baz: foo + bax: foox + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + baz: + #[\n|]# + - one: two + three: four + - top: + baz: foo + bax: foox + "}), + ), + // yaml map without a key + ( + helpers::platform_line(indoc! {"\ + top:#[\n|]# + "}), + "O", + helpers::platform_line(indoc! {"\ + #[\n|]# + top: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + bottom: withvalue + top#[:|]# + "}), + "O", + helpers::platform_line(indoc! {"\ + bottom: withvalue + #[\n|]# + top: + "}), + ), + ( + helpers::platform_line(indoc! {"\ + top: + bottom:#[ |]#withvalue + "}), + "O", + helpers::platform_line(indoc! {"\ + top: + #[\n|]# + bottom: withvalue + "}), + ), + ]; + + for test in above_tests { + test_with_config(app(), test).await?; + } + + let enter_tests = [ + ( + helpers::platform_line(indoc! {r##" + foo: #[b|]#ar + "##}), + "i", + helpers::platform_line(indoc! {"\ + foo: + #[|b]#ar + "}), + ), + ( + helpers::platform_line(indoc! {"\ + foo:#[\n|]# + "}), + "i", + helpers::platform_line(indoc! {"\ + foo: + #[|\n]# + "}), + ), + ]; + + for test in enter_tests { + test_with_config(app(), test).await?; + } + + Ok(()) +} -- cgit v1.2.3-70-g09d2