edtui_papier/actions/
insert.rs1use jagged::index::RowIndex;
2use serde::{Deserialize, Serialize};
3
4use super::{Execute, SwitchMode};
5use crate::{
6 helper::{insert_char, line_break},
7 EditorMode, EditorState,
8};
9
10#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
12pub struct InsertChar(pub char);
13
14impl Execute for InsertChar {
15 fn execute(&mut self, state: &mut EditorState) {
16 insert_char(&mut state.lines, &mut state.cursor, self.0, false, &mut state.highlighter);
17 }
18}
19
20#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
22pub struct LineBreak(pub usize);
23
24impl Execute for LineBreak {
25 fn execute(&mut self, state: &mut EditorState) {
26 for _ in 0..self.0 {
27 line_break(&mut state.lines, &mut state.cursor, &mut state.highlighter);
28 }
29 }
30}
31
32#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
35pub struct AppendNewline(pub usize);
36
37impl Execute for AppendNewline {
38 fn execute(&mut self, state: &mut EditorState) {
39 state.cursor.col = 0;
40 for _ in 0..self.0 {
41 state.cursor.row += 1;
42 state.lines.insert(RowIndex::new(state.cursor.row), vec![]);
43 state.highlighter.insert_line(state.cursor.row, &"".to_string());
44 }
45 SwitchMode(EditorMode::Insert).execute(state);
46 }
47}
48
49#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
52pub struct InsertNewline(pub usize);
53
54impl Execute for InsertNewline {
55 fn execute(&mut self, state: &mut EditorState) {
56 state.cursor.col = 0;
57 for _ in 0..self.0 {
58 state.lines.insert(RowIndex::new(state.cursor.row), vec![]);
59 state.highlighter.insert_line(state.cursor.row, &"".to_string());
60 }
61 SwitchMode(EditorMode::Insert).execute(state);
62 }
63}
64
65#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
68pub struct PushLine<'a>(pub &'a str);
69
70impl Execute for PushLine<'_> {
71 fn execute(&mut self, state: &mut EditorState) {
72 let chars: Vec<char> = self.0.chars().collect();
73 state.lines.push(chars.clone());
74 state.highlighter.append(&chars.iter().collect::<String>());
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use super::*;
81 use crate::{Index2, Lines};
82 fn test_state() -> EditorState {
83 EditorState::new(Lines::from("Hello World!\n\n123."), "txt")
84 }
85
86 #[test]
87 fn test_insert_char() {
88 let mut state = test_state();
89
90 InsertChar('!').execute(&mut state);
91 assert_eq!(state.cursor, Index2::new(0, 1));
92 assert_eq!(state.lines, Lines::from("!Hello World!\n\n123."));
93
94 state.cursor = Index2::new(0, 13);
95 InsertChar('!').execute(&mut state);
96 assert_eq!(state.cursor, Index2::new(0, 14));
97 assert_eq!(state.lines, Lines::from("!Hello World!!\n\n123."));
98 }
99
100 #[test]
101 fn test_linebreak() {
102 let mut state = test_state();
103
104 LineBreak(1).execute(&mut state);
105 assert_eq!(state.cursor, Index2::new(1, 0));
106 assert_eq!(state.lines, Lines::from("\nHello World!\n\n123."));
107
108 state.cursor = Index2::new(1, 5);
109 LineBreak(1).execute(&mut state);
110 assert_eq!(state.cursor, Index2::new(2, 0));
111 assert_eq!(state.lines, Lines::from("\nHello\n World!\n\n123."));
112 }
113
114 #[test]
115 fn test_append_newline() {
116 let mut state = test_state();
117
118 AppendNewline(1).execute(&mut state);
119 assert_eq!(state.cursor, Index2::new(1, 0));
120 assert_eq!(state.lines, Lines::from("Hello World!\n\n\n123."));
121 }
122
123 #[test]
124 fn test_insert_newline() {
125 let mut state = test_state();
126
127 InsertNewline(1).execute(&mut state);
128 assert_eq!(state.cursor, Index2::new(0, 0));
129 assert_eq!(state.lines, Lines::from("\nHello World!\n\n123."));
130
131 state.cursor = Index2::new(2, 1);
132 InsertNewline(1).execute(&mut state);
133 assert_eq!(state.cursor, Index2::new(2, 0));
134 assert_eq!(state.lines, Lines::from("\nHello World!\n\n\n123."));
135 }
136
137 #[test]
138 fn test_push_line() {
139 let mut state = test_state();
140
141 PushLine("456.").execute(&mut state);
142 assert_eq!(state.lines, Lines::from("Hello World!\n\n123.\n456."));
143 }
144}