Skip to content

Commit 7e28241

Browse files
author
Niko Matsakis
committed
autogenerate list of owners + teams
1 parent 6255bff commit 7e28241

File tree

76 files changed

+408
-128
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+408
-128
lines changed

crates/mdbook-goals/src/mdbook_preprocessor.rs

Lines changed: 90 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ impl<'c> GoalPreprocessorWithContext<'c> {
127127
fn process_book_item(&mut self, book_item: &mut BookItem) -> anyhow::Result<()> {
128128
match book_item {
129129
BookItem::Chapter(chapter) => {
130+
self.replace_metadata_placeholders(chapter)?;
130131
self.replace_team_asks(chapter)?;
131132
self.replace_goal_lists(chapter)?;
132133
self.replace_goal_count(chapter)?;
@@ -173,14 +174,27 @@ impl<'c> GoalPreprocessorWithContext<'c> {
173174
}
174175

175176
fn replace_goal_lists(&mut self, chapter: &mut Chapter) -> anyhow::Result<()> {
176-
self.replace_goal_lists_helper(chapter, &re::FLAGSHIP_GOAL_LIST, |status| status.is_flagship && status.is_not_not_accepted())?;
177-
self.replace_goal_lists_helper(chapter, &re::OTHER_GOAL_LIST, |status| !status.is_flagship && status.is_not_not_accepted())?;
178-
self.replace_goal_lists_helper(chapter, &re::GOAL_LIST, |status| status.is_not_not_accepted())?;
179-
self.replace_goal_lists_helper(chapter, &re::GOAL_NOT_ACCEPTED_LIST, |status| !status.is_not_not_accepted())?;
177+
self.replace_goal_lists_helper(chapter, &re::FLAGSHIP_GOAL_LIST, |status| {
178+
status.is_flagship && status.is_not_not_accepted()
179+
})?;
180+
self.replace_goal_lists_helper(chapter, &re::OTHER_GOAL_LIST, |status| {
181+
!status.is_flagship && status.is_not_not_accepted()
182+
})?;
183+
self.replace_goal_lists_helper(chapter, &re::GOAL_LIST, |status| {
184+
status.is_not_not_accepted()
185+
})?;
186+
self.replace_goal_lists_helper(chapter, &re::GOAL_NOT_ACCEPTED_LIST, |status| {
187+
!status.is_not_not_accepted()
188+
})?;
180189
Ok(())
181190
}
182-
183-
fn replace_goal_lists_helper(&mut self, chapter: &mut Chapter, regex: &Regex, filter: impl Fn(Status) -> bool) -> anyhow::Result<()> {
191+
192+
fn replace_goal_lists_helper(
193+
&mut self,
194+
chapter: &mut Chapter,
195+
regex: &Regex,
196+
filter: impl Fn(Status) -> bool,
197+
) -> anyhow::Result<()> {
184198
loop {
185199
let Some(m) = regex.find(&chapter.content) else {
186200
return Ok(());
@@ -193,7 +207,8 @@ impl<'c> GoalPreprocessorWithContext<'c> {
193207

194208
// Extract out the list of goals with the given status.
195209
let goals = self.goal_documents(chapter_path)?;
196-
let mut goals_with_status: Vec<&GoalDocument> = goals.iter().filter(|g| filter(g.metadata.status)).collect();
210+
let mut goals_with_status: Vec<&GoalDocument> =
211+
goals.iter().filter(|g| filter(g.metadata.status)).collect();
197212

198213
goals_with_status.sort_by_key(|g| &g.metadata.title);
199214

@@ -246,25 +261,23 @@ impl<'c> GoalPreprocessorWithContext<'c> {
246261
Ok(())
247262
}
248263

264+
/// Find the goal documents for the milestone in which this `chapter_path` resides.
265+
/// e.g., if invoked with `2024h2/xxx.md`, will find all goal documents in `2024h2`.
249266
fn goal_documents(&mut self, chapter_path: &Path) -> anyhow::Result<Arc<Vec<GoalDocument>>> {
250267
// let chapter_path = self.ctx.config.book.src.join(chapter_path);
251268

252-
if let Some(goals) = self.goal_document_map.get(chapter_path) {
269+
let Some(milestone_path) = chapter_path.parent() else {
270+
anyhow::bail!("cannot get goal documents from `{chapter_path:?}`")
271+
};
272+
273+
if let Some(goals) = self.goal_document_map.get(milestone_path) {
253274
return Ok(goals.clone());
254275
}
255276

256-
let goal_documents = goal::goals_in_dir(
257-
self.ctx
258-
.config
259-
.book
260-
.src
261-
.join(chapter_path)
262-
.parent()
263-
.unwrap(),
264-
)?;
277+
let goal_documents = goal::goals_in_dir(&self.ctx.config.book.src.join(milestone_path))?;
265278
let goals = Arc::new(goal_documents);
266279
self.goal_document_map
267-
.insert(chapter_path.to_path_buf(), goals.clone());
280+
.insert(milestone_path.to_path_buf(), goals.clone());
268281
Ok(goals)
269282
}
270283

@@ -365,4 +378,63 @@ impl<'c> GoalPreprocessorWithContext<'c> {
365378
}
366379
Ok(())
367380
}
381+
382+
/// Replace TEAMS_WITH_ASKS placeholder with a list of teams.
383+
/// All goal documents should have this in their metadata table;
384+
/// that is enforced during goal parsing.
385+
fn replace_metadata_placeholders(&mut self, chapter: &mut Chapter) -> anyhow::Result<()> {
386+
self.replace_metadata_placeholder(chapter, &re::TASK_OWNERS, |goal| {
387+
goal.task_owners.iter().cloned().collect()
388+
})?;
389+
390+
self.replace_metadata_placeholder(chapter, &re::TEAMS_WITH_ASKS, |goal| {
391+
goal.teams_with_asks()
392+
.iter()
393+
.map(|team_name| team_name.name())
394+
.collect()
395+
})?;
396+
397+
Ok(())
398+
}
399+
400+
/// Replace one of the placeholders that occur in the goal document metadata,
401+
/// like [`re::TASK_OWNERS`][].
402+
fn replace_metadata_placeholder(
403+
&mut self,
404+
chapter: &mut Chapter,
405+
regex: &Regex,
406+
op: impl Fn(&GoalDocument) -> Vec<String>,
407+
) -> anyhow::Result<()> {
408+
let Some(m) = regex.find(&chapter.content) else {
409+
return Ok(());
410+
};
411+
let range = m.range();
412+
413+
let Some(chapter_path) = chapter.path.as_ref() else {
414+
anyhow::bail!(
415+
"goal chapter `{}` has TEAMS_WITH_ASKS placeholder but no path",
416+
chapter.name
417+
);
418+
};
419+
420+
// Hack: leave this stuff alone in the template
421+
if chapter_path.file_name().unwrap() == "TEMPLATE.md" {
422+
return Ok(());
423+
}
424+
425+
let goals = self.goal_documents(&chapter_path)?;
426+
let chapter_in_context = self.ctx.config.book.src.join(chapter_path);
427+
let Some(goal) = goals.iter().find(|gd| gd.path == chapter_in_context) else {
428+
anyhow::bail!(
429+
"goal chapter `{}` has no goal document at path {:?}",
430+
chapter.name,
431+
chapter_path,
432+
);
433+
};
434+
435+
let replacement = op(goal).join(", ");
436+
chapter.content.replace_range(range, &replacement);
437+
438+
Ok(())
439+
}
368440
}

0 commit comments

Comments
 (0)