use super::EditorDocument;
use crate::core::errors::{EditorError, Result};
use crate::core::position::{LineColumn, Position, Range};
#[cfg(not(feature = "std"))]
use alloc::string::{String, ToString};
impl EditorDocument {
#[must_use]
pub fn len_bytes(&self) -> usize {
#[cfg(feature = "rope")]
{
self.text_rope.len_bytes()
}
#[cfg(not(feature = "rope"))]
{
self.text_content.len()
}
}
#[must_use]
pub fn len_lines(&self) -> usize {
#[cfg(feature = "rope")]
{
self.text_rope.len_lines()
}
#[cfg(not(feature = "rope"))]
{
self.text_content.lines().count().max(1)
}
}
#[must_use]
pub fn is_empty(&self) -> bool {
self.len_bytes() == 0
}
#[must_use]
pub fn text(&self) -> String {
#[cfg(feature = "rope")]
{
self.text_rope.to_string()
}
#[cfg(not(feature = "rope"))]
{
self.text_content.clone()
}
}
#[cfg(feature = "rope")]
#[must_use]
pub fn rope(&self) -> &ropey::Rope {
&self.text_rope
}
#[must_use]
pub fn len(&self) -> usize {
#[cfg(feature = "rope")]
{
self.text_rope.len_bytes()
}
#[cfg(not(feature = "rope"))]
{
self.text_content.len()
}
}
pub fn text_range(&self, range: Range) -> Result<String> {
let start = range.start.offset;
let end = range.end.offset;
if end > self.len_bytes() {
return Err(EditorError::InvalidRange {
start,
end,
length: self.len_bytes(),
});
}
#[cfg(feature = "rope")]
{
let start_char = self.text_rope.byte_to_char(start);
let end_char = self.text_rope.byte_to_char(end);
Ok(self.text_rope.slice(start_char..end_char).to_string())
}
#[cfg(not(feature = "rope"))]
{
Ok(self.text_content[start..end].to_string())
}
}
#[cfg(feature = "rope")]
pub fn position_to_line_column(&self, pos: Position) -> Result<LineColumn> {
if pos.offset > self.len_bytes() {
return Err(EditorError::PositionOutOfBounds {
position: pos.offset,
length: self.len_bytes(),
});
}
let line_idx = self.text_rope.byte_to_line(pos.offset);
let line_start = self.text_rope.line_to_byte(line_idx);
let col_offset = pos.offset - line_start;
let line = self.text_rope.line(line_idx);
let mut char_col = 0;
let mut byte_count = 0;
for ch in line.chars() {
if byte_count >= col_offset {
break;
}
byte_count += ch.len_utf8();
char_col += 1;
}
LineColumn::new(line_idx + 1, char_col + 1)
}
#[cfg(not(feature = "rope"))]
pub fn position_to_line_column(&self, pos: Position) -> Result<LineColumn> {
if pos.offset > self.len_bytes() {
return Err(EditorError::PositionOutOfBounds {
position: pos.offset,
length: self.len_bytes(),
});
}
let mut line = 1;
let mut col = 1;
let mut byte_pos = 0;
for ch in self.text_content.chars() {
if byte_pos >= pos.offset {
break;
}
if ch == '\n' {
line += 1;
col = 1;
} else {
col += 1;
}
byte_pos += ch.len_utf8();
}
LineColumn::new(line, col)
}
}