ass_editor/core/fluent/
document_ext.rs1use super::event_ops::EventOps;
4use super::karaoke::KaraokeOps;
5use super::media::{FontsOps, GraphicsOps};
6use super::script_info::ScriptInfoOps;
7use super::style::StyleOps;
8use super::tag::TagOps;
9use super::{AtPosition, SelectRange};
10use crate::core::{EditorDocument, Position, Range};
11
12#[cfg(feature = "rope")]
13use crate::core::errors::EditorError;
14#[cfg(feature = "rope")]
15use crate::core::Result;
16
17impl EditorDocument {
19 pub fn at_pos(&mut self, position: Position) -> AtPosition<'_> {
21 AtPosition::new(self, position)
22 }
23
24 #[cfg(feature = "rope")]
26 pub fn at_line(&mut self, line: usize) -> Result<AtPosition<'_>> {
27 let line_idx = line.saturating_sub(1);
28 if line_idx >= self.rope().len_lines() {
29 return Err(EditorError::InvalidPosition { line, column: 1 });
30 }
31
32 let byte_pos = self.rope().line_to_byte(line_idx);
33 Ok(AtPosition::new(self, Position::new(byte_pos)))
34 }
35
36 pub fn at_start(&mut self) -> AtPosition<'_> {
38 AtPosition::new(self, Position::start())
39 }
40
41 pub fn at_end(&mut self) -> AtPosition<'_> {
43 let end_pos = Position::new(self.len());
44 AtPosition::new(self, end_pos)
45 }
46
47 pub fn select(&mut self, range: Range) -> SelectRange<'_> {
49 SelectRange::new(self, range)
50 }
51
52 pub fn styles(&mut self) -> StyleOps<'_> {
54 StyleOps::new(self)
55 }
56
57 pub fn events(&mut self) -> EventOps<'_> {
59 EventOps::new(self)
60 }
61
62 pub fn tags(&mut self) -> TagOps<'_> {
64 TagOps::new(self)
65 }
66
67 pub fn karaoke(&mut self) -> KaraokeOps<'_> {
69 KaraokeOps::new(self)
70 }
71
72 pub fn info(&mut self) -> ScriptInfoOps<'_> {
74 ScriptInfoOps::new(self)
75 }
76
77 pub fn fonts(&mut self) -> FontsOps<'_> {
79 FontsOps::new(self)
80 }
81
82 pub fn graphics(&mut self) -> GraphicsOps<'_> {
84 GraphicsOps::new(self)
85 }
86
87 #[cfg(feature = "rope")]
89 pub fn position_to_line_col(&self, pos: Position) -> Result<(usize, usize)> {
90 if pos.offset > self.len() {
91 return Err(EditorError::PositionOutOfBounds {
92 position: pos.offset,
93 length: self.len(),
94 });
95 }
96
97 let line_idx = self.rope().byte_to_line(pos.offset);
98 let line_start = self.rope().line_to_byte(line_idx);
99 let col_offset = pos.offset - line_start;
100
101 let line = self.rope().line(line_idx);
103 let mut char_col = 0;
104 let mut byte_count = 0;
105
106 for ch in line.chars() {
107 if byte_count >= col_offset {
108 break;
109 }
110 byte_count += ch.len_utf8();
111 char_col += 1;
112 }
113
114 Ok((line_idx + 1, char_col + 1)) }
116
117 #[cfg(feature = "rope")]
119 pub fn line_column_to_position(&self, line: usize, column: usize) -> Result<Position> {
120 use crate::core::PositionBuilder;
121
122 PositionBuilder::new()
123 .line(line)
124 .column(column)
125 .build(self.rope())
126 }
127}