ass_editor/commands/event_commands/
split.rs1use super::helpers::{collect_event_lines, parse_event_line};
4use crate::commands::{CommandResult, EditorCommand};
5use crate::core::{EditorDocument, EditorError, Position, Range, Result};
6use ass_core::parser::ast::EventType;
7use ass_core::utils::parse_ass_time;
8
9#[cfg(not(feature = "std"))]
10use alloc::{format, string::String};
11
12#[derive(Debug, Clone)]
14pub struct SplitEventCommand {
15 pub event_index: usize,
16 pub split_time: String, pub description: Option<String>,
18}
19
20impl SplitEventCommand {
21 pub fn new(event_index: usize, split_time: String) -> Self {
23 Self {
24 event_index,
25 split_time,
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 SplitEventCommand {
39 fn execute(&self, document: &mut EditorDocument) -> Result<CommandResult> {
40 let split_time_cs = parse_ass_time(&self.split_time).map_err(|_| {
42 EditorError::command_failed(format!("Invalid time format: {}", self.split_time))
43 })?;
44
45 let content = document.text();
46 let event_lines = collect_event_lines(&content)?;
47
48 if let Some(event_line) = event_lines
49 .into_iter()
50 .find(|event_line| event_line.index == self.event_index)
51 {
52 let event = parse_event_line(event_line.line)?;
53
54 let start_time_cs = event
56 .start_time_cs()
57 .map_err(|_| EditorError::command_failed("Invalid start time in event"))?;
58 let end_time_cs = event
59 .end_time_cs()
60 .map_err(|_| EditorError::command_failed("Invalid end time in event"))?;
61
62 if split_time_cs <= start_time_cs || split_time_cs >= end_time_cs {
63 return Err(EditorError::command_failed(
64 "Split time must be between event start and end times",
65 ));
66 }
67
68 let event_type_str = match event.event_type {
70 EventType::Dialogue => "Dialogue",
71 EventType::Comment => "Comment",
72 _ => "Dialogue", };
74 let first_event = format!(
75 "{}: {},{},{},{},{},{},{},{},{},{}",
76 event_type_str,
77 event.layer,
78 event.start,
79 self.split_time,
80 event.style,
81 event.name,
82 event.margin_l,
83 event.margin_r,
84 event.margin_v,
85 event.effect,
86 event.text
87 );
88
89 let second_event = format!(
90 "{}: {},{},{},{},{},{},{},{},{},{}",
91 event_type_str,
92 event.layer,
93 self.split_time,
94 event.end,
95 event.style,
96 event.name,
97 event.margin_l,
98 event.margin_r,
99 event.margin_v,
100 event.effect,
101 event.text
102 );
103
104 let replacement = format!("{first_event}\n{second_event}");
106 let range = Range::new(
107 Position::new(event_line.start),
108 Position::new(event_line.end),
109 );
110 document.replace(range, &replacement)?;
111
112 let end_pos = Position::new(event_line.start + replacement.len());
113 return Ok(CommandResult::success_with_change(
114 Range::new(Position::new(event_line.start), end_pos),
115 end_pos,
116 )
117 .with_message(format!(
118 "Split event {} at time {}",
119 self.event_index, self.split_time
120 )));
121 }
122
123 Err(EditorError::command_failed(format!(
124 "Event index {} not found",
125 self.event_index
126 )))
127 }
128
129 fn description(&self) -> &str {
130 self.description.as_deref().unwrap_or("Split event")
131 }
132
133 fn memory_usage(&self) -> usize {
134 core::mem::size_of::<Self>()
135 + self.split_time.len()
136 + self.description.as_ref().map_or(0, |d| d.len())
137 }
138}