From 89a2b2b6b85c9bffe44be04b36cc2b638016d3fa Mon Sep 17 00:00:00 2001 From: Max Brunsfeld Date: Mon, 22 Dec 2025 14:44:09 -0800 Subject: [PATCH] Store repo and revision in TOML front matter --- Cargo.lock | 1 + crates/edit_prediction/Cargo.toml | 1 + crates/edit_prediction/src/example_spec.rs | 58 +++++++++++++--------- 3 files changed, 37 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d73200e3ced437f1e61e8c5b0da06f306358eb14..f464f307d2f3afbe4f8d3a7d9a0c142edc72a83e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5253,6 +5253,7 @@ dependencies = [ "text", "thiserror 2.0.17", "time", + "toml 0.8.23", "ui", "util", "uuid", diff --git a/crates/edit_prediction/Cargo.toml b/crates/edit_prediction/Cargo.toml index 5145777ff0733d674f33a597db6682e611e4d0fc..f2534545abc04ce769cf46be7692f7954bb0bfcf 100644 --- a/crates/edit_prediction/Cargo.toml +++ b/crates/edit_prediction/Cargo.toml @@ -56,6 +56,7 @@ telemetry_events.workspace = true text.workspace = true thiserror.workspace = true time.workspace = true +toml.workspace = true ui.workspace = true util.workspace = true uuid.workspace = true diff --git a/crates/edit_prediction/src/example_spec.rs b/crates/edit_prediction/src/example_spec.rs index 8a30c7b85c494fcc7a0b32ece665f814e8452bc4..2b76d4dda1a22f07a7ea402c84e76ea31529d14d 100644 --- a/crates/edit_prediction/src/example_spec.rs +++ b/crates/edit_prediction/src/example_spec.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use std::{fmt::Write as _, mem, path::Path, sync::Arc}; +use std::{borrow::Cow, mem, path::Path, sync::Arc}; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct ExampleSpec { @@ -20,19 +20,36 @@ const EDIT_HISTORY_HEADING: &str = "Edit History"; const CURSOR_POSITION_HEADING: &str = "Cursor Position"; const EXPECTED_PATCH_HEADING: &str = "Expected Patch"; const EXPECTED_CONTEXT_HEADING: &str = "Expected Context"; -const REPOSITORY_URL_FIELD: &str = "repository_url"; -const REVISION_FIELD: &str = "revision"; + +#[derive(Serialize, Deserialize)] +struct FrontMatter<'a> { + repository_url: Cow<'a, str>, + revision: Cow<'a, str>, +} impl ExampleSpec { /// Format this example spec as markdown. pub fn to_markdown(&self) -> String { + use std::fmt::Write as _; + + let front_matter = FrontMatter { + repository_url: Cow::Borrowed(&self.repository_url), + revision: Cow::Borrowed(&self.revision), + }; + let front_matter_toml = + toml::to_string_pretty(&front_matter).unwrap_or_else(|_| String::new()); + let mut markdown = String::new(); - _ = writeln!(markdown, "# {}", self.name); + _ = writeln!(markdown, "+++"); + markdown.push_str(&front_matter_toml); + if !markdown.ends_with('\n') { + markdown.push('\n'); + } + _ = writeln!(markdown, "+++"); markdown.push('\n'); - _ = writeln!(markdown, "repository_url = {}", self.repository_url); - _ = writeln!(markdown, "revision = {}", self.revision); + _ = writeln!(markdown, "# {}", self.name); markdown.push('\n'); if !self.uncommitted_diff.is_empty() { @@ -87,11 +104,9 @@ impl ExampleSpec { } /// Parse an example spec from markdown. - pub fn from_markdown(name: String, input: &str) -> anyhow::Result { + pub fn from_markdown(name: String, mut input: &str) -> anyhow::Result { use pulldown_cmark::{CodeBlockKind, CowStr, Event, HeadingLevel, Parser, Tag, TagEnd}; - let parser = Parser::new(input); - let mut spec = ExampleSpec { name, repository_url: String::new(), @@ -103,6 +118,17 @@ impl ExampleSpec { expected_patch: String::new(), }; + if let Some(rest) = input.strip_prefix("+++\n") + && let Some((front_matter, rest)) = rest.split_once("+++\n") + { + if let Ok(data) = toml::from_str::>(front_matter) { + spec.repository_url = data.repository_url.into_owned(); + spec.revision = data.revision.into_owned(); + } + input = rest.trim_start(); + } + + let parser = Parser::new(input); let mut text = String::new(); let mut block_info: CowStr = "".into(); @@ -123,20 +149,6 @@ impl ExampleSpec { match event { Event::Text(line) => { text.push_str(&line); - - if let Section::Start = current_section - && let Some((field, value)) = line.split_once('=') - { - match field.trim() { - REPOSITORY_URL_FIELD => { - spec.repository_url = value.trim().to_string(); - } - REVISION_FIELD => { - spec.revision = value.trim().to_string(); - } - _ => {} - } - } } Event::End(TagEnd::Heading(HeadingLevel::H2)) => { let title = mem::take(&mut text);