From b77ce7fa292622c5482047ee428c1ead1f4c3643 Mon Sep 17 00:00:00 2001
From: Ed Page <eopage@gmail.com>
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.

As the experiment is meant to be short-lived, this is implemented in a
hacky way and docs aren't updated.
---
 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 f9b4f06165c..ac940ed22b5 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<String>,
     content: &'s str,
 }
 
@@ -234,11 +234,14 @@ fn split_source(input: &str) -> CargoResult<Source<'_>> {
         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<Source<'_>> {
     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<Source<'_>> {
     Ok(source)
 }
 
+fn split_prefix_source<'s>(mut source: Source<'s>, prefix: &str) -> CargoResult<Source<'s>> {
+    let mut frontmatter = String::new();
+    while let Some(rest) = source.content.strip_prefix(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() {}
 "#),
         );
     }