diff --git a/src/editor.rs b/src/editor.rs index 69b4111..05bd54f 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -63,21 +63,13 @@ impl Editor { }; if should_process { - match EditorCommand::try_from(event) { - Ok(command) => { - if matches!(command, EditorCommand::Quit) { - self.should_quit = true; - } else { - self.view.handle_command(command); - } + if let Ok(command) = EditorCommand::try_from(event) { + if matches!(command, EditorCommand::Quit) { + self.should_quit = true; + } else { + self.view.handle_command(command); } - Err(_err) => { - #[cfg(debug_assertions)] - { - panic!("Could not process command: {_err:?}"); - } - } } } } diff --git a/src/editor/editorcommand.rs b/src/editor/editorcommand.rs index c4f98b1..e744a8f 100644 --- a/src/editor/editorcommand.rs +++ b/src/editor/editorcommand.rs @@ -15,9 +15,11 @@ pub enum Direction { pub enum EditorCommand { Move(Direction), Resize(Size), - Quit + Quit, + Insert(char) } +#[allow(clippy::as_conversions)] impl TryFrom for EditorCommand { type Error = String; @@ -27,6 +29,7 @@ impl TryFrom for EditorCommand { code, modifiers, .. }) => match (code, modifiers) { (KeyCode::Char('q'), KeyModifiers::CONTROL) => Ok(Self::Quit), + (KeyCode::Char(character), KeyModifiers::NONE | KeyModifiers::SHIFT) => Ok(Self::Insert(character)), (KeyCode::Up, KeyModifiers::NONE) => Ok(Self::Move(Direction::Up)), (KeyCode::Down, KeyModifiers::NONE) => Ok(Self::Move(Direction::Down)), (KeyCode::Left, KeyModifiers::NONE) => Ok(Self::Move(Direction::Left)), @@ -37,13 +40,10 @@ impl TryFrom for EditorCommand { (KeyCode::End, KeyModifiers::NONE) => Ok(Self::Move(Direction::End)), _ => Err(format!("Unrecognized key: {:?}", code)), }, - Event::Resize(width_u16, height_u16) => { - #[allow(clippy::as_conversions)] - let height = height_u16 as usize; - #[allow(clippy::as_conversions)] - let width = width_u16 as usize; - Ok(Self::Resize(Size {height, width})) - } + Event::Resize(width_u16, height_u16) => Ok(Self::Resize(Size { + height: height_u16 as usize, + width: width_u16 as usize, + })), _ => Err(format!("Unrecognized event: {:?}", event)), } } diff --git a/src/editor/view.rs b/src/editor/view.rs index d2c8c26..4460a7c 100644 --- a/src/editor/view.rs +++ b/src/editor/view.rs @@ -47,7 +47,10 @@ impl View { EditorCommand::Resize(size) => { self.resize(size); }, - EditorCommand::Quit => {} + EditorCommand::Quit => {}, + EditorCommand::Insert(c) => { + self.insert_char(c); + } } } pub fn load(&mut self, file_name: &str) { @@ -113,6 +116,22 @@ impl View { final_message } // endregion: Rendering + + fn insert_char(&mut self, c: char) { + let old_len = self.buffer.lines.get(self.text_location.line_index).map_or(0, Line::grapheme_count); + + self.buffer.insert_char(c, self.text_location); + let new_len = self.buffer.lines.get(self.text_location.line_index).map_or(0, Line::grapheme_count); + + let grapheme_delta = new_len.saturating_sub(old_len); + if grapheme_delta > 0 { + self.move_right(); + } + self.needs_redraw = true; + } + // region: Text Editing + + // endregion: Text Editing // region: Scrolling fn scroll_vertically(&mut self, to: usize) { diff --git a/src/editor/view/buffer.rs b/src/editor/view/buffer.rs index 8a4bf96..92a2f14 100644 --- a/src/editor/view/buffer.rs +++ b/src/editor/view/buffer.rs @@ -1,4 +1,5 @@ use std::{fs::read_to_string, io::Error}; +use super::Location; use super::line::Line; @@ -24,4 +25,16 @@ impl Buffer { pub fn height(&self) -> usize { self.lines.len() } + + pub fn insert_char(&mut self, c: char, at: Location) { + if at.line_index > self.lines.len() { + return; + } + if at.line_index == self.lines.len() { + self.lines.push(Line::from(&c.to_string())); + } + else if let Some(line) = self.lines.get_mut(at.line_index) { + line.insert_char(at.grapheme_index, c); + } + } } \ No newline at end of file diff --git a/src/editor/view/line.rs b/src/editor/view/line.rs index ce134ff..2437bc7 100644 --- a/src/editor/view/line.rs +++ b/src/editor/view/line.rs @@ -30,7 +30,11 @@ pub struct Line { impl Line { pub fn from(line_str: &str) -> Self { - let fragments = line_str + let fragments = Self::str_to_fragments(line_str); + Self { fragments } + } + fn str_to_fragments(line_str: &str) -> Vec { + line_str .graphemes(true) .map(|grapheme| { let unicode_width = grapheme.width(); @@ -49,8 +53,7 @@ impl Line { replacement, } }) - .collect(); - Self { fragments } + .collect() } pub fn get_visible_graphemes(&self, range: Range) -> String { @@ -92,4 +95,20 @@ impl Line { }) .sum() } + pub fn insert_char(&mut self, grapheme_index: usize, c: char) { + let mut result = String::new(); + for (index, fragment) in self.fragments.iter().enumerate() { + if index == grapheme_index { + result.push(c); + } + result.push_str(&fragment.grapheme); + } + + if grapheme_index == self.fragments.len() { + result.push(c); + } + + self.fragments = Self::str_to_fragments(&result); + + } } \ No newline at end of file diff --git a/text b/text index b97ac41..8050281 100644 --- a/text +++ b/text @@ -1,25 +1,7 @@ -# Narrow: -Lörëm ípsüm dólör sït âmét, cönsëctetur âdïpïscïng élit. End of Line, scroll until here -Sëd dö ēiusmód tēmpör ïncïdïdünt üt lâborë ēt dölöre mägnä äliquä. End of Line, scroll until here -L̶̯̈́ö̶͕r̸̝͂e̷̗͆m̸̻̍ ̶̯̊i̵̘͋p̷̪̉s̵̨̒u̷̯̓m̷͕̆ ̸͈͠d̵͈̔ô̷̞ḷ̷̀ö̴̪r̴̍͜ ̵̜͗s̸̲̑ȋ̴ͅt̵̢̄ ̵͛͜a̶̬͛m̶̫̃ě̸̼t̵̯̿,̶͍͐ ̷̢́c̴͈̈o̷͖̕n̶͖͆s̴͓̽ē̷̙t̵͓͊e̴̪̒t̴̺͝u̷̫̐r̵̳̒ ̶̓͜s̶̙̑a̵̠͒d̷̟̚i̵͎̎p̸͈̉ṡ̷̤c̶̳͒i̷̺̐n̷̘͆ģ̵͘ ̵̡̿ẽ̷̼l̴̗͝i̵̗̋t̸̲͋r̷̘̿,̸͓̐ ̷̦̀ś̴͙ȩ̸͒ḑ̸̇ ̶̰̍d̶̝̾i̶̙̾a̴̩̕m̴̥͝ ̷̨͐n̶̩͗ȏ̴̩n̵̆͜ů̷͎m̸̫͊y̷̛͉ ̸̺̊ë̵͚́ḯ̶̻r̵͔̒m̷̪͑ö̴̢́d̶͉͐ ̸̤͊t̶͈̊ḛ̴̛ṁ̴̼p̷̠̌o̸͇̓ŕ̵̠ ̶̫͠í̸̧ṋ̷̈v̸̘̈́i̴̹̿d̶̙͗u̵̪̾n̷̤̅t̷̬͗ ̴͎̈ù̸̳t̶͓͝ ̵̭̾ End of Line, scroll until here -l̴̛̘ā̵̹b̸͚̒o̸̰̚r̷̞̃e̸̙͐ ̶̘̑è̴̪t̷̯̑ ̸̳̓d̵̜̊ŏ̵̲l̵͇̾o̵̘̾r̵̦̀e̴̡͗ ̴̛̖m̸̨͑a̸̜̓g̶̘̊ṇ̴̀ã̸̹ ̵̬̃â̶̭l̷̳͘į̷̓q̶͈̀u̴͉̽y̸̜̾a̵͕͝m̷͍̍ ̴̼̔é̶̲ŗ̵̛ä̷̯t̶̯̄,̵̹̄ ̴̡͘ş̴̉e̵̬̊d̵̯̆ ̵̤̀d̶͎͘i̷̦͗a̵̭̐m̷̲͝ ̶͋͜v̸̪̈́ỏ̸͖l̷̜̎ǘ̸̞p̴̩͐ṫ̴͓ǘ̵̞a̵͛͜.̸̞̔ ̸̬͌A̷̡̓t̶̬̒ ̵̰͠v̸̜̕e̸̟̚r̷̝̉o̵̞̚ ̷̯̏ē̴̹ö̵͉́s̶̻͝ ̵̝̈́e̸̬̓t̴̥͂ ̷̧̏å̸̢c̸̚͜c̸͉̾ǘ̴̺s̸̱͠a̷̤͊m̶͈̒ ̷̙̂ė̸̡t̵̙̾ ̸͈̀j̴̼̊ü̵͖s̸͈̽t̶̤͊ó̶̼ ̷̹̔d̴̬͋ú̴̦o̶͓͊ ̶̭͝d̷̰͛ö̷͍́l̵̺̾ǒ̵̤r̸̫̎e̵̼̔s End of Line, scroll until here +#![warn(clippy::all, clippy::pedantic, clippy::print_stdout, clippy::arithmetic_side_effects, clippy::as_conversions, clippy::integer_division)] +mod editor; +use editor::Editor; -# Wide: -ABCDEFGHIJKLMNOPQRSTUVWXYZ End of Line, scroll until here - -# Ambiguous: -👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋 End of Line, scroll until here -🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿 End of Line, scroll until here - -# Narrow: -Lörëm ípsüm dólör sït âmét, cönsëctetur âdïpïscïng élit. End of Line, scroll until here -Sëd dö ēiusmód tēmpör ïncïdïdünt üt lâborë ēt dölöre mägnä äliquä. End of Line, scroll until here -L̶̯̈́ö̶͕r̸̝͂e̷̗͆m̸̻̍ ̶̯̊i̵̘͋p̷̪̉s̵̨̒u̷̯̓m̷͕̆ ̸͈͠d̵͈̔ô̷̞ḷ̷̀ö̴̪r̴̍͜ ̵̜͗s̸̲̑ȋ̴ͅt̵̢̄ ̵͛͜a̶̬͛m̶̫̃ě̸̼t̵̯̿,̶͍͐ ̷̢́c̴͈̈o̷͖̕n̶͖͆s̴͓̽ē̷̙t̵͓͊e̴̪̒t̴̺͝u̷̫̐r̵̳̒ ̶̓͜s̶̙̑a̵̠͒d̷̟̚i̵͎̎p̸͈̉ṡ̷̤c̶̳͒i̷̺̐n̷̘͆ģ̵͘ ̵̡̿ẽ̷̼l̴̗͝i̵̗̋t̸̲͋r̷̘̿,̸͓̐ ̷̦̀ś̴͙ȩ̸͒ḑ̸̇ ̶̰̍d̶̝̾i̶̙̾a̴̩̕m̴̥͝ ̷̨͐n̶̩͗ȏ̴̩n̵̆͜ů̷͎m̸̫͊y̷̛͉ ̸̺̊ë̵͚́ḯ̶̻r̵͔̒m̷̪͑ö̴̢́d̶͉͐ ̸̤͊t̶͈̊ḛ̴̛ṁ̴̼p̷̠̌o̸͇̓ŕ̵̠ ̶̫͠í̸̧ṋ̷̈v̸̘̈́i̴̹̿d̶̙͗u̵̪̾n̷̤̅t̷̬͗ ̴͎̈ù̸̳t̶͓͝ ̵̭̾ End of Line, scroll until here -l̴̛̘ā̵̹b̸͚̒o̸̰̚r̷̞̃e̸̙͐ ̶̘̑è̴̪t̷̯̑ ̸̳̓d̵̜̊ŏ̵̲l̵͇̾o̵̘̾r̵̦̀e̴̡͗ ̴̛̖m̸̨͑a̸̜̓g̶̘̊ṇ̴̀ã̸̹ ̵̬̃â̶̭l̷̳͘į̷̓q̶͈̀u̴͉̽y̸̜̾a̵͕͝m̷͍̍ ̴̼̔é̶̲ŗ̵̛ä̷̯t̶̯̄,̵̹̄ ̴̡͘ş̴̉e̵̬̊d̵̯̆ ̵̤̀d̶͎͘i̷̦͗a̵̭̐m̷̲͝ ̶͋͜v̸̪̈́ỏ̸͖l̷̜̎ǘ̸̞p̴̩͐ṫ̴͓ǘ̵̞a̵͛͜.̸̞̔ ̸̬͌A̷̡̓t̶̬̒ ̵̰͠v̸̜̕e̸̟̚r̷̝̉o̵̞̚ ̷̯̏ē̴̹ö̵͉́s̶̻͝ ̵̝̈́e̸̬̓t̴̥͂ ̷̧̏å̸̢c̸̚͜c̸͉̾ǘ̴̺s̸̱͠a̷̤͊m̶͈̒ ̷̙̂ė̸̡t̵̙̾ ̸͈̀j̴̼̊ü̵͖s̸͈̽t̶̤͊ó̶̼ ̷̹̔d̴̬͋ú̴̦o̶͓͊ ̶̭͝d̷̰͛ö̷͍́l̵̺̾ǒ̵̤r̸̫̎e̵̼̔s End of Line, scroll until here - -# Wide: -ABCDEFGHIJKLMNOPQRSTUVWXYZ End of Line, scroll until here - -# Ambiguous: -👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋👋 End of Line, scroll until here -🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿🧑🏿‍🤝‍🧑🏿 End of Line, scroll until here \ No newline at end of file +fn main() { + Editor::new().unwrap().run(); +} \ No newline at end of file