From a3609b9f4e0b3a49472c5902220e22c7ff13d191 Mon Sep 17 00:00:00 2001 From: Ed Page Date: Wed, 3 Jan 2024 16:39:43 -0600 Subject: [PATCH] feat(embedded): Add prefix-char frontmatter syntax support This is a follow up to #13241 with another syntax being discussed. This one is a bit more polarizing but we're hoping first-hand experience with it can help people get a feel for how well it works in practice. --- src/cargo/util/toml/embedded.rs | 66 +++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 8 deletions(-) diff --git a/src/cargo/util/toml/embedded.rs b/src/cargo/util/toml/embedded.rs index f9b4f06165c7..0e0cbac14086 100644 --- a/src/cargo/util/toml/embedded.rs +++ b/src/cargo/util/toml/embedded.rs @@ -185,7 +185,7 @@ fn sanitize_name(name: &str) -> String { struct Source<'s> { shebang: Option<&'s str>, info: Option<&'s str>, - frontmatter: Option<&'s str>, + frontmatter: Option, content: &'s str, } @@ -234,11 +234,14 @@ fn split_source(input: &str) -> CargoResult> { 0 => { return Ok(source); } + 1 if tick_char == '#' => { + // Attribute + return Ok(source); + } + 2 if tick_char == '#' => { + return split_prefix_source(source); + } 1 | 2 => { - if tick_char == '#' { - // Attribute - return Ok(source); - } anyhow::bail!("found {tick_end} `{tick_char}` in rust frontmatter, expected at least 3") } _ => source.content.split_at(tick_end), @@ -252,7 +255,7 @@ fn split_source(input: &str) -> CargoResult> { let Some((frontmatter, content)) = source.content.split_once(fence_pattern) else { anyhow::bail!("no closing `{fence_pattern}` found for frontmatter"); }; - source.frontmatter = Some(frontmatter); + source.frontmatter = Some(frontmatter.to_owned()); source.content = content; let (line, content) = source @@ -268,6 +271,22 @@ fn split_source(input: &str) -> CargoResult> { Ok(source) } +fn split_prefix_source(mut source: Source<'_>) -> CargoResult> { + let mut frontmatter = String::new(); + while let Some(rest) = source.content.strip_prefix("##") { + if !rest.is_empty() && !rest.starts_with(' ') { + anyhow::bail!("frontmatter must have a space between `##` and the content"); + } + let (line, rest) = rest.split_once('\n').unwrap_or((rest, "")); + frontmatter.push_str(" "); + frontmatter.push_str(line); + frontmatter.push('\n'); + source.content = rest; + } + source.frontmatter = Some(frontmatter); + Ok(source) +} + #[cfg(test)] mod test_expand { use super::*; @@ -375,7 +394,7 @@ fn main() {} } #[test] - fn test_dash() { + fn test_dash_fence() { snapbox::assert_matches( r#"[[bin]] name = "test-" @@ -408,7 +427,7 @@ fn main() {} } #[test] - fn test_hash() { + fn test_hash_fence() { snapbox::assert_matches( r#"[[bin]] name = "test-" @@ -436,6 +455,37 @@ strip = true time="0.1.25" ### fn main() {} +"#), + ); + } + + #[test] + fn test_hash_prefix() { + snapbox::assert_matches( + r#"[[bin]] +name = "test-" +path = [..] + +[dependencies] +time = "0.1.25" + +[package] +autobenches = false +autobins = false +autoexamples = false +autotests = false +build = false +edition = "2021" +name = "test-" + +[profile.release] +strip = true + +[workspace] +"#, + si!(r#"## [dependencies] +## time="0.1.25" +fn main() {} "#), ); }