1use crate::{Context, Execution, World, error::GuideError};
2use async_trait::async_trait;
3use serde::{Deserialize, Serialize};
4use std::sync::Arc;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
8#[non_exhaustive]
9pub enum GuideScope {
10 Always,
12 TaskMatches(Vec<String>),
14 FilesMatch { pattern: String },
16}
17
18impl GuideScope {
19 pub fn matches(&self, task: &crate::Task) -> bool {
21 match self {
22 GuideScope::Always => true,
23 GuideScope::TaskMatches(patterns) => {
24 patterns.iter().any(|p| task.description.contains(p))
25 }
26 GuideScope::FilesMatch { .. } => true,
27 }
28 }
29}
30
31pub type GuideId = String;
32
33#[async_trait]
34pub trait Guide: Send + Sync + 'static {
35 fn id(&self) -> &GuideId;
36 fn kind(&self) -> Execution;
37 fn scope(&self) -> &GuideScope;
38 async fn apply(&self, ctx: &mut Context, world: &World) -> Result<(), GuideError>;
39}
40
41pub struct GuideEntry {
42 pub factory: fn() -> Arc<dyn Guide>,
43}
44
45inventory::collect!(GuideEntry);
46
47pub fn iter_macro_guides() -> impl Iterator<Item = Arc<dyn Guide>> {
48 inventory::iter::<GuideEntry>().map(|e| (e.factory)())
49}