Skip to main content

ass_editor/extensions/
context.rs

1//! Extension context trait and the default editor context implementation.
2//!
3//! `ExtensionContext` exposes editor functionality to extensions; `EditorContext`
4//! is the concrete adapter that bridges extensions to the `ExtensionManager`.
5
6use crate::core::{EditorDocument, Result};
7use crate::events::DocumentEvent;
8
9use super::command::{ExtensionCommand, MessageLevel};
10use super::manager::ExtensionManager;
11
12#[cfg(not(feature = "std"))]
13use alloc::string::String;
14
15#[cfg(all(not(feature = "multi-thread"), feature = "std"))]
16use std::collections::HashMap;
17
18#[cfg(all(not(feature = "multi-thread"), not(feature = "std")))]
19use alloc::collections::BTreeMap as HashMap;
20
21/// Extension context providing access to editor functionality
22pub trait ExtensionContext {
23    /// Get the current document (if any)
24    fn current_document(&self) -> Option<&EditorDocument>;
25
26    /// Get a mutable reference to the current document
27    fn current_document_mut(&mut self) -> Option<&mut EditorDocument>;
28
29    /// Send an event to the event system
30    fn send_event(&mut self, event: DocumentEvent) -> Result<()>;
31
32    /// Get configuration value
33    fn get_config(&self, key: &str) -> Option<String>;
34
35    /// Set configuration value
36    fn set_config(&mut self, key: String, value: String) -> Result<()>;
37
38    /// Register a command with the editor
39    fn register_command(&mut self, command: ExtensionCommand) -> Result<()>;
40
41    /// Show a message to the user
42    fn show_message(&mut self, message: &str, level: MessageLevel) -> Result<()>;
43
44    /// Get data from another extension
45    fn get_extension_data(&self, extension_name: &str, key: &str) -> Option<String>;
46
47    /// Set data for inter-extension communication
48    fn set_extension_data(&mut self, key: String, value: String) -> Result<()>;
49}
50
51/// Editor context providing access to editor functionality
52/// Adapts to available features automatically
53pub struct EditorContext<'a> {
54    /// Current document (if any)
55    pub document: Option<&'a mut EditorDocument>,
56    /// Reference to the extension manager
57    #[cfg(feature = "multi-thread")]
58    pub manager: ExtensionManager,
59    /// Reference to the extension manager for single-threaded builds
60    #[cfg(not(feature = "multi-thread"))]
61    pub manager: &'a mut ExtensionManager,
62    /// Mutable state for single-threaded builds (config updates)
63    #[cfg(not(feature = "multi-thread"))]
64    pub manager_mut_state: alloc::rc::Rc<core::cell::RefCell<HashMap<String, String>>>,
65    /// Name of the current extension
66    pub extension_name: String,
67}
68
69impl ExtensionContext for EditorContext<'_> {
70    fn current_document(&self) -> Option<&EditorDocument> {
71        self.document.as_deref()
72    }
73
74    fn current_document_mut(&mut self) -> Option<&mut EditorDocument> {
75        self.document.as_deref_mut()
76    }
77
78    fn send_event(&mut self, _event: DocumentEvent) -> Result<()> {
79        // For now, we'll just log the event
80        // In a real implementation, this would use the event system
81        #[cfg(feature = "std")]
82        {
83            eprintln!("Extension {} sent event: {:?}", self.extension_name, _event);
84        }
85        Ok(())
86    }
87
88    fn get_config(&self, key: &str) -> Option<String> {
89        #[cfg(feature = "multi-thread")]
90        {
91            self.manager.get_config(key)
92        }
93        #[cfg(not(feature = "multi-thread"))]
94        {
95            self.manager.get_config(key)
96        }
97    }
98
99    fn set_config(&mut self, key: String, value: String) -> Result<()> {
100        #[cfg(feature = "multi-thread")]
101        {
102            self.manager.set_config(key.clone(), value.clone());
103        }
104        #[cfg(not(feature = "multi-thread"))]
105        {
106            // In single-threaded mode, update the shared config state
107            self.manager_mut_state.borrow_mut().insert(key, value);
108        }
109        Ok(())
110    }
111
112    fn register_command(&mut self, _command: ExtensionCommand) -> Result<()> {
113        // For now, just acknowledge the command in both modes
114        // In a real implementation, this would register with a command system
115        #[cfg(feature = "std")]
116        {
117            eprintln!(
118                "Extension {} registered command: {}",
119                self.extension_name, _command.id
120            );
121        }
122        Ok(())
123    }
124
125    fn show_message(&mut self, _message: &str, _level: MessageLevel) -> Result<()> {
126        // Simple console output for now
127        #[cfg(feature = "std")]
128        {
129            match _level {
130                MessageLevel::Info => eprintln!("[INFO] {}: {}", self.extension_name, _message),
131                MessageLevel::Warning => eprintln!("[WARN] {}: {}", self.extension_name, _message),
132                MessageLevel::Error => eprintln!("[ERROR] {}: {}", self.extension_name, _message),
133                MessageLevel::Success => {
134                    eprintln!("[SUCCESS] {}: {}", self.extension_name, _message)
135                }
136            }
137        }
138        Ok(())
139    }
140
141    fn get_extension_data(&self, extension_name: &str, key: &str) -> Option<String> {
142        self.manager.get_extension_data(extension_name, key)
143    }
144
145    fn set_extension_data(&mut self, key: String, value: String) -> Result<()> {
146        self.manager
147            .set_extension_data(self.extension_name.clone(), key, value);
148        Ok(())
149    }
150}