ass_editor/core/document/
incremental_edit.rs1use super::EditorDocument;
8use crate::commands::CommandResult;
9use crate::core::errors::Result;
10use crate::core::position::{Position, Range};
11use ass_core::parser::script::ScriptDeltaOwned;
12
13#[cfg(feature = "std")]
14use crate::events::DocumentEvent;
15
16#[cfg(not(feature = "std"))]
17use alloc::{format, string::ToString, vec, vec::Vec};
18
19impl EditorDocument {
20 pub fn edit_incremental(&mut self, range: Range, new_text: &str) -> Result<ScriptDeltaOwned> {
29 use crate::core::history::Operation;
30
31 let is_simple_edit = new_text.len() <= 100 && !new_text.contains('[') && new_text.matches('\n').count() <= 1 && range.len() <= 50; if is_simple_edit {
38 return self.edit_fast_path(range, new_text);
39 }
40
41 #[cfg(feature = "std")]
43 let old_text = self.text_range(range)?;
44 #[cfg(not(feature = "std"))]
45 let _old_text = self.text_range(range)?;
46
47 let current_text = self.text();
49 let delta = match self
50 .incremental_parser
51 .apply_change(¤t_text, range, new_text)
52 {
53 Ok(delta) => delta,
54 Err(_e) => {
55 #[cfg(feature = "std")]
57 eprintln!("Incremental parsing failed, attempting recovery: {_e}");
58
59 if self.incremental_parser.should_reparse() {
61 self.incremental_parser.clear_cache();
62 }
63
64 match self
66 .incremental_parser
67 .apply_change(¤t_text, range, new_text)
68 {
69 Ok(delta) => delta,
70 Err(_) => {
71 ScriptDeltaOwned {
73 added: Vec::new(),
74 modified: vec![(0, "Script modified".to_string())],
75 removed: Vec::new(),
76 new_issues: Vec::new(),
77 }
78 }
79 }
80 }
81 };
82
83 let undo_data = self.capture_delta_undo_data(&delta)?;
85
86 let operation = Operation::Delta {
88 forward: delta.clone(),
89 undo_data,
90 };
91
92 let result = CommandResult::success_with_change(
94 range,
95 Position::new(range.start.offset + new_text.len()),
96 );
97
98 let result_with_delta = result.with_delta(delta.clone());
100 self.history.record_operation(
101 operation,
102 format!("Incremental edit at {}", range.start.offset),
103 &result_with_delta,
104 );
105
106 self.replace_raw(range, new_text)?;
108
109 self.modified = true;
111
112 #[cfg(feature = "std")]
114 self.emit(DocumentEvent::TextReplaced {
115 range,
116 old_text,
117 new_text: new_text.to_string(),
118 });
119
120 Ok(delta)
121 }
122
123 pub fn insert_incremental(&mut self, pos: Position, text: &str) -> Result<ScriptDeltaOwned> {
125 let range = Range::new(pos, pos); self.edit_incremental(range, text)
127 }
128
129 pub fn delete_incremental(&mut self, range: Range) -> Result<ScriptDeltaOwned> {
131 self.edit_incremental(range, "")
132 }
133}