Skip to main content

ass_editor/core/document/
plugins.rs

1//! Extension-registry integration for the document
2//!
3//! Lets a document own an `ExtensionRegistry`, parse with custom handlers,
4//! and register custom tag handlers and section processors.
5
6use super::EditorDocument;
7use crate::core::errors::{EditorError, Result};
8
9#[cfg(feature = "std")]
10use std::sync::Arc;
11
12#[cfg(not(feature = "std"))]
13use alloc::string::{String, ToString};
14
15impl EditorDocument {
16    /// Initialize the extension registry with built-in handlers
17    pub fn initialize_registry(&mut self) -> Result<()> {
18        use crate::extensions::registry_integration::RegistryIntegration;
19
20        let mut integration = RegistryIntegration::new();
21
22        // Register all built-in extensions using the function from the builtin module
23        crate::extensions::builtin::register_builtin_extensions(&mut integration)?;
24
25        self.registry_integration = Some(Arc::new(integration));
26        Ok(())
27    }
28
29    /// Get the extension registry for use in parsing
30    pub fn registry(&self) -> Option<&ass_core::plugin::ExtensionRegistry> {
31        self.registry_integration
32            .as_ref()
33            .map(|integration| integration.registry())
34    }
35
36    /// Parse the document content with extension support and process it with a callback
37    ///
38    /// Since Script<'a> requires the source text to outlive it, this method uses a callback
39    /// pattern to process the script while the content is still in scope.
40    pub fn parse_with_extensions<F, R>(&self, f: F) -> Result<R>
41    where
42        F: FnOnce(&ass_core::parser::Script) -> R,
43    {
44        let content = self.text();
45
46        if let Some(integration) = &self.registry_integration {
47            // Parse with the extension registry using the builder pattern
48            let script = ass_core::parser::Script::builder()
49                .with_registry(integration.registry())
50                .parse(&content)
51                .map_err(EditorError::Core)?;
52            Ok(f(&script))
53        } else {
54            // No registry, parse normally
55            let script = ass_core::parser::Script::parse(&content).map_err(EditorError::Core)?;
56            Ok(f(&script))
57        }
58    }
59
60    /// Register a custom tag handler
61    pub fn register_tag_handler(
62        &mut self,
63        extension_name: String,
64        handler: Box<dyn ass_core::plugin::TagHandler>,
65    ) -> Result<()> {
66        if self.registry_integration.is_none() {
67            self.initialize_registry()?;
68        }
69
70        let registry_ref =
71            self.registry_integration
72                .as_mut()
73                .ok_or_else(|| EditorError::ExtensionError {
74                    extension: extension_name.clone(),
75                    message: "Registry integration not available".to_string(),
76                })?;
77
78        if let Some(integration) = Arc::get_mut(registry_ref) {
79            integration.register_custom_tag_handler(extension_name, handler)
80        } else {
81            Err(EditorError::ExtensionError {
82                extension: extension_name,
83                message: "Cannot modify shared registry integration".to_string(),
84            })
85        }
86    }
87
88    /// Register a custom section processor
89    pub fn register_section_processor(
90        &mut self,
91        extension_name: String,
92        processor: Box<dyn ass_core::plugin::SectionProcessor>,
93    ) -> Result<()> {
94        if self.registry_integration.is_none() {
95            self.initialize_registry()?;
96        }
97
98        let registry_ref =
99            self.registry_integration
100                .as_mut()
101                .ok_or_else(|| EditorError::ExtensionError {
102                    extension: extension_name.clone(),
103                    message: "Registry integration not available".to_string(),
104                })?;
105
106        if let Some(integration) = Arc::get_mut(registry_ref) {
107            integration.register_custom_section_processor(extension_name, processor)
108        } else {
109            Err(EditorError::ExtensionError {
110                extension: extension_name,
111                message: "Cannot modify shared registry integration".to_string(),
112            })
113        }
114    }
115}