Skip to main content

ass_editor/extensions/
manager_lifecycle.rs

1//! Extension manager construction and context creation.
2//!
3//! Provides constructors for the manager and its internal storage along with
4//! the `create_context` bridge used to hand editor access to extensions.
5
6use crate::core::{EditorDocument, Result};
7
8use super::context::{EditorContext, ExtensionContext};
9use super::manager::{ExtensionManager, ExtensionManagerInner};
10
11#[cfg(feature = "std")]
12use super::extension::{MessageHandler, StdMessageHandler};
13
14#[cfg(feature = "std")]
15use super::manager::EventSender;
16
17#[cfg(not(feature = "std"))]
18use super::extension::NoOpMessageHandler;
19
20#[cfg(feature = "std")]
21use std::collections::HashMap;
22
23#[cfg(not(feature = "std"))]
24use alloc::collections::BTreeMap as HashMap;
25
26#[cfg(not(feature = "std"))]
27use alloc::{boxed::Box, string::String};
28
29#[cfg(feature = "std")]
30use std::sync::mpsc;
31
32#[cfg(feature = "multi-thread")]
33use std::sync::Arc;
34
35#[cfg(feature = "multi-thread")]
36use parking_lot::Mutex;
37
38#[cfg(not(feature = "multi-thread"))]
39use core::cell::RefCell;
40
41#[cfg(all(not(feature = "multi-thread"), not(feature = "std")))]
42use alloc::rc::Rc;
43
44#[cfg(all(not(feature = "multi-thread"), feature = "std"))]
45use std::rc::Rc;
46
47impl ExtensionManagerInner {
48    /// Create a new inner manager
49    fn new() -> Self {
50        #[cfg(feature = "std")]
51        let (tx, _rx) = mpsc::channel();
52
53        Self {
54            extensions: HashMap::new(),
55            extension_states: HashMap::new(),
56            commands: HashMap::new(),
57            config: HashMap::new(),
58            extension_data: HashMap::new(),
59            #[cfg(feature = "std")]
60            event_tx: tx,
61            #[cfg(feature = "std")]
62            message_handler: Box::new(StdMessageHandler),
63            #[cfg(not(feature = "std"))]
64            message_handler: Box::new(NoOpMessageHandler),
65        }
66    }
67}
68
69impl ExtensionManager {
70    /// Create a new extension manager
71    pub fn new() -> Self {
72        #[cfg(feature = "multi-thread")]
73        {
74            Self {
75                inner: Arc::new(Mutex::new(ExtensionManagerInner::new())),
76            }
77        }
78        #[cfg(not(feature = "multi-thread"))]
79        {
80            Self {
81                inner: RefCell::new(ExtensionManagerInner::new()),
82            }
83        }
84    }
85
86    /// Create a new extension manager with custom event sender and message handler
87    #[cfg(feature = "std")]
88    pub fn with_event_channel(
89        event_tx: EventSender,
90        message_handler: Box<dyn MessageHandler>,
91    ) -> Self {
92        let inner = ExtensionManagerInner {
93            extensions: HashMap::new(),
94            extension_states: HashMap::new(),
95            commands: HashMap::new(),
96            config: HashMap::new(),
97            extension_data: HashMap::new(),
98            event_tx,
99            message_handler,
100        };
101
102        #[cfg(feature = "multi-thread")]
103        {
104            Self {
105                inner: Arc::new(Mutex::new(inner)),
106            }
107        }
108        #[cfg(not(feature = "multi-thread"))]
109        {
110            Self {
111                inner: RefCell::new(inner),
112            }
113        }
114    }
115
116    /// Create an extension context for use by extensions
117    pub fn create_context<'a>(
118        &'a mut self,
119        extension_name: String,
120        document: Option<&'a mut EditorDocument>,
121    ) -> Result<Box<dyn ExtensionContext + 'a>> {
122        #[cfg(feature = "multi-thread")]
123        {
124            Ok(Box::new(EditorContext {
125                document,
126                manager: self.clone(),
127                extension_name,
128            }))
129        }
130
131        #[cfg(not(feature = "multi-thread"))]
132        {
133            // In single-threaded mode, we share the config state via Rc<RefCell>
134            let config_clone = self.inner.borrow().config.clone();
135            let shared_config = Rc::new(RefCell::new(config_clone));
136
137            Ok(Box::new(EditorContext {
138                document,
139                manager: self,
140                manager_mut_state: shared_config,
141                extension_name,
142            }))
143        }
144    }
145}