ass_editor/core/document/
ass_api.rs1use super::EditorDocument;
8use crate::core::errors::Result;
9use crate::core::position::{Position, Range};
10use ass_core::parser::ast::Section;
11
12#[cfg(not(feature = "std"))]
13use alloc::{
14 format,
15 string::{String, ToString},
16 vec::Vec,
17};
18
19impl EditorDocument {
20 pub fn events_count(&self) -> Result<usize> {
24 self.parse_script_with(|script| {
25 let mut count = 0;
26 for section in script.sections() {
27 if let Section::Events(events) = section {
28 count += events.len();
29 }
30 }
31 count
32 })
33 }
34
35 pub fn styles_count(&self) -> Result<usize> {
37 self.parse_script_with(|script| {
38 let mut count = 0;
39 for section in script.sections() {
40 if let Section::Styles(styles) = section {
41 count += styles.len();
42 }
43 }
44 count
45 })
46 }
47
48 pub fn script_info_fields(&self) -> Result<Vec<String>> {
50 self.parse_script_with(|script| {
51 let mut fields = Vec::new();
52 for section in script.sections() {
53 if let Section::ScriptInfo(info) = section {
54 for (key, _) in &info.fields {
55 fields.push(key.to_string());
56 }
57 }
58 }
59 fields
60 })
61 }
62
63 pub fn sections_count(&self) -> Result<usize> {
65 self.parse_script_with(|script| script.sections().len())
66 }
67
68 pub fn has_events(&self) -> Result<bool> {
70 self.parse_script_with(|script| {
71 script
72 .sections()
73 .iter()
74 .any(|section| matches!(section, Section::Events(_)))
75 })
76 }
77
78 pub fn has_styles(&self) -> Result<bool> {
80 self.parse_script_with(|script| {
81 script
82 .sections()
83 .iter()
84 .any(|section| matches!(section, Section::Styles(_)))
85 })
86 }
87
88 pub fn find_event_text(&self, pattern: &str) -> Result<Vec<String>> {
90 self.parse_script_with(|script| {
91 let mut matches = Vec::new();
92 for section in script.sections() {
93 if let Section::Events(events) = section {
94 for event in events {
95 if event.text.contains(pattern) {
96 matches.push(event.text.to_string());
97 }
98 }
99 }
100 }
101 matches
102 })
103 }
104
105 pub fn edit_event_text(&mut self, old_text: &str, new_text: &str) -> Result<()> {
107 let content = self.text();
108
109 if let Some(pos) = content.find(old_text) {
110 let range = Range::new(Position::new(pos), Position::new(pos + old_text.len()));
111 self.replace(range, new_text)?;
112 }
113
114 Ok(())
115 }
116
117 pub fn get_script_info_field(&self, key: &str) -> Result<Option<String>> {
119 self.parse_script_with(|script| {
120 script.sections().iter().find_map(|section| {
121 if let Section::ScriptInfo(info) = section {
122 info.fields
123 .iter()
124 .find(|(k, _)| *k == key)
125 .map(|(_, v)| v.to_string())
126 } else {
127 None
128 }
129 })
130 })
131 }
132
133 pub fn set_script_info_field(&mut self, key: &str, value: &str) -> Result<()> {
135 let content = self.text();
137 let field_pattern = format!("{key}:");
138
139 if let Some(pos) = content.find(&field_pattern) {
140 let line_start = pos;
142 let line_end = content[pos..].find('\n').map_or(content.len(), |n| pos + n);
143
144 let range = Range::new(Position::new(line_start), Position::new(line_end));
145
146 let new_line = format!("{key}: {value}");
147 self.replace(range, &new_line)?;
148 }
149
150 Ok(())
151 }
152}