zrd_core/
state.rs

1//! Platform-agnostic editor state
2
3#[derive(Debug, Clone, Copy, PartialEq, Eq)]
4pub struct BufferPosition {
5    pub row: usize,
6    pub column: usize,
7}
8
9impl BufferPosition {
10    pub fn new(row: usize, column: usize) -> Self {
11        Self { row, column }
12    }
13
14    pub fn zero() -> Self {
15        Self { row: 0, column: 0 }
16    }
17}
18
19#[derive(Clone)]
20pub struct EditorState {
21    /// Lines of text in the buffer
22    pub lines: Vec<String>,
23    /// Cursor position (row, column in bytes)
24    pub cursor: BufferPosition,
25    /// Selection anchor for text selection
26    pub selection_anchor: Option<BufferPosition>,
27    /// Font size (may be ignored by TUI)
28    pub font_size: f32,
29}
30
31impl EditorState {
32    pub fn new() -> Self {
33        Self {
34            lines: vec![String::new()],
35            cursor: BufferPosition::zero(),
36            selection_anchor: None,
37            font_size: 48.0,
38        }
39    }
40
41    pub fn clone_for_undo(&self) -> Self {
42        Self {
43            lines: self.lines.clone(),
44            cursor: self.cursor,
45            selection_anchor: self.selection_anchor,
46            font_size: self.font_size,
47        }
48    }
49
50    /// Get the content as a single string
51    pub fn to_string(&self) -> String {
52        self.lines.join("\n")
53    }
54
55    /// Create from a string
56    pub fn from_string(content: String) -> Self {
57        let lines: Vec<String> = if content.is_empty() {
58            vec![String::new()]
59        } else {
60            content.split('\n').map(|s| s.to_string()).collect()
61        };
62
63        Self {
64            lines,
65            cursor: BufferPosition::zero(),
66            selection_anchor: None,
67            font_size: 48.0,
68        }
69    }
70
71    pub fn line_count(&self) -> usize {
72        self.lines.len()
73    }
74
75    pub fn line(&self, row: usize) -> Option<&str> {
76        self.lines.get(row).map(|s| s.as_str())
77    }
78
79    pub fn line_len(&self, row: usize) -> usize {
80        self.lines.get(row).map(|s| s.len()).unwrap_or(0)
81    }
82}