use crate::core::{EditorDocument, EditorError, Position, Range, Result};
use super::{
CommandResult, DeleteTextCommand, EditorCommand, InsertTextCommand, ReplaceTextCommand,
};
#[cfg(not(feature = "std"))]
use alloc::string::ToString;
pub struct TextCommand<'a> {
document: &'a mut EditorDocument,
position: Option<Position>,
range: Option<Range>,
}
impl<'a> TextCommand<'a> {
pub fn new(document: &'a mut EditorDocument) -> Self {
Self {
document,
position: None,
range: None,
}
}
#[must_use]
pub fn at(mut self, position: Position) -> Self {
self.position = Some(position);
self
}
#[must_use]
pub fn range(mut self, range: Range) -> Self {
self.range = Some(range);
self
}
pub fn insert(self, text: &str) -> Result<CommandResult> {
let position = self
.position
.ok_or_else(|| EditorError::command_failed("Position not set for insert operation"))?;
let command = InsertTextCommand::new(position, text.to_string());
command.execute(self.document)
}
pub fn delete(self) -> Result<CommandResult> {
let range = self
.range
.ok_or_else(|| EditorError::command_failed("Range not set for delete operation"))?;
let command = DeleteTextCommand::new(range);
command.execute(self.document)
}
pub fn replace(self, new_text: &str) -> Result<CommandResult> {
let range = self
.range
.ok_or_else(|| EditorError::command_failed("Range not set for replace operation"))?;
let command = ReplaceTextCommand::new(range, new_text.to_string());
command.execute(self.document)
}
}
pub trait DocumentCommandExt {
fn command(&mut self) -> TextCommand<'_>;
fn insert_at(&mut self, position: Position, text: &str) -> Result<CommandResult>;
fn delete_range(&mut self, range: Range) -> Result<CommandResult>;
fn replace_range(&mut self, range: Range, text: &str) -> Result<CommandResult>;
}
impl DocumentCommandExt for EditorDocument {
fn command(&mut self) -> TextCommand<'_> {
TextCommand::new(self)
}
fn insert_at(&mut self, position: Position, text: &str) -> Result<CommandResult> {
let command = InsertTextCommand::new(position, text.to_string());
command.execute(self)
}
fn delete_range(&mut self, range: Range) -> Result<CommandResult> {
let command = DeleteTextCommand::new(range);
command.execute(self)
}
fn replace_range(&mut self, range: Range, text: &str) -> Result<CommandResult> {
let command = ReplaceTextCommand::new(range, text.to_string());
command.execute(self)
}
}