ass_editor/commands/style_commands/
clone.rs1use crate::commands::{CommandResult, EditorCommand};
7use crate::core::{EditorDocument, EditorError, Position, Range, Result};
8
9#[cfg(not(feature = "std"))]
10use alloc::{format, string::String};
11
12#[derive(Debug, Clone)]
14pub struct CloneStyleCommand {
15 pub source_style: String,
16 pub target_style: String,
17 pub description: Option<String>,
18}
19
20impl CloneStyleCommand {
21 pub fn new(source_style: String, target_style: String) -> Self {
23 Self {
24 source_style,
25 target_style,
26 description: None,
27 }
28 }
29
30 #[must_use]
32 pub fn with_description(mut self, description: String) -> Self {
33 self.description = Some(description);
34 self
35 }
36}
37
38impl EditorCommand for CloneStyleCommand {
39 fn execute(&self, document: &mut EditorDocument) -> Result<CommandResult> {
40 let content = document.text();
41 let source_pattern = format!("Style: {}", self.source_style);
42
43 let target_pattern = format!("Style: {}", self.target_style);
45 if content.contains(&target_pattern) {
46 return Err(EditorError::command_failed(format!(
47 "Style '{}' already exists",
48 self.target_style
49 )));
50 }
51
52 if let Some(source_start) = content.find(&source_pattern) {
53 let line_start = content[..source_start]
55 .rfind('\n')
56 .map(|pos| pos + 1)
57 .unwrap_or(0);
58 let line_end = content[source_start..]
59 .find('\n')
60 .map(|pos| source_start + pos)
61 .unwrap_or(content.len());
62
63 let source_line = &content[line_start..line_end];
64
65 let cloned_line = source_line.replace(
67 &format!("Style: {}", self.source_style),
68 &format!("Style: {}", self.target_style),
69 );
70
71 let insert_pos = line_end;
73 let insert_text = format!("\n{cloned_line}");
74
75 document.insert(Position::new(insert_pos), &insert_text)?;
76
77 let end_pos = Position::new(insert_pos + insert_text.len());
78 Ok(CommandResult::success_with_change(
79 Range::new(Position::new(insert_pos), end_pos),
80 end_pos,
81 )
82 .with_message(format!(
83 "Cloned style '{}' to '{}'",
84 self.source_style, self.target_style
85 )))
86 } else {
87 Err(EditorError::command_failed(format!(
88 "Source style '{}' not found",
89 self.source_style
90 )))
91 }
92 }
93
94 fn description(&self) -> &str {
95 self.description.as_deref().unwrap_or("Clone style")
96 }
97
98 fn memory_usage(&self) -> usize {
99 core::mem::size_of::<Self>()
100 + self.source_style.len()
101 + self.target_style.len()
102 + self.description.as_ref().map_or(0, |d| d.len())
103 }
104}