diff --git a/assets/test.rs b/assets/test.rs new file mode 100644 index 0000000..5065550 --- /dev/null +++ b/assets/test.rs @@ -0,0 +1,154 @@ +use std::ops::Deref; + +pub mod plain; +pub mod rust_lang; + +#[derive(Debug, Clone)] +pub enum Language { + PlainText, +} + +#[derive(Debug, Clone)] +pub enum TokenType { + Whitespace { token: Token }, + Keyword { token: Token }, + String { token: Token }, + Number { token: Token }, + Identifier { token: Token }, + Literal { token: Token }, + Comment { token: Token }, + Operator { token: Token }, + Separator { token: Token }, +} + +impl TokenType { + pub fn move_to(&self, line: usize, character: usize, start: usize, end: usize) -> Self { + match self { + TokenType::Whitespace { token } => TokenType::Whitespace { + token: token.move_to(line, character, start, end), + }, + TokenType::Keyword { token } => TokenType::Keyword { + token: token.move_to(line, character, start, end), + }, + TokenType::String { token } => TokenType::String { + token: token.move_to(line, character, start, end), + }, + TokenType::Number { token } => TokenType::Number { + token: token.move_to(line, character, start, end), + }, + TokenType::Identifier { token } => TokenType::Identifier { + token: token.move_to(line, character, start, end), + }, + TokenType::Literal { token } => TokenType::Literal { + token: token.move_to(line, character, start, end), + }, + TokenType::Comment { token } => TokenType::Comment { + token: token.move_to(line, character, start, end), + }, + TokenType::Operator { token } => TokenType::Operator { + token: token.move_to(line, character, start, end), + }, + TokenType::Separator { token } => TokenType::Separator { + token: token.move_to(line, character, start, end), + }, + } + } + + pub fn is_new_line(&self) -> bool { + match self { + TokenType::Whitespace { token } => token.text().as_str() == "\n", + _ => false, + } + } + + pub fn is_space(&self) -> bool { + match self { + TokenType::Whitespace { token } => token.text().as_str() == " ", + _ => false, + } + } +} + +impl Deref for TokenType { + type Target = Token; + + fn deref(&self) -> &::Target { + match self { + TokenType::Whitespace { token } => token, + TokenType::Keyword { token } => token, + TokenType::String { token } => token, + TokenType::Number { token } => token, + TokenType::Identifier { token } => token, + TokenType::Literal { token } => token, + TokenType::Comment { token } => token, + TokenType::Operator { token } => token, + TokenType::Separator { token } => token, + } + } +} + +#[derive(Debug, Clone)] +pub struct Token { + line: usize, + character: usize, + start: usize, + end: usize, + text: String, +} + +#[derive(Debug, Clone, Copy)] +pub struct Span { + pub lo: usize, + pub hi: usize, +} + +impl Token { + pub fn new(text: String, line: usize, character: usize, start: usize, end: usize) -> Self { + Self { + text, + line, + character, + start, + end, + } + } + + pub fn text(&self) -> &String { + &self.text + } + + pub fn line(&self) -> usize { + self.line.clone() + } + + pub fn character(&self) -> usize { + self.character.clone() + } + + pub fn start(&self) -> usize { + self.start.clone() + } + + pub fn end(&self) -> usize { + self.end.clone() + } + + pub fn move_to(&self, line: usize, character: usize, start: usize, end: usize) -> Self { + Self { + text: self.text.clone(), + line, + character, + start, + end, + } + } +} + +pub fn parse(text: String, language: Language) -> Vec { + match language { + Language::PlainText => plain::lexer::Lexer::new(text.as_str()) +// .inspect(|tok| println!("tok: {:?}", tok)) + .map(|t| t.0) + .collect(), + } +} diff --git a/src/app/app_state.rs b/src/app/app_state.rs index 4043fc8..9c94622 100644 --- a/src/app/app_state.rs +++ b/src/app/app_state.rs @@ -1,15 +1,16 @@ use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::ui::file::*; -use crate::ui::file::editor_file::EditorFile; use crate::renderer::Renderer; -use crate::ui::*; use crate::ui::caret::Caret; +use crate::ui::file::editor_file::EditorFile; +use crate::ui::file::*; use crate::ui::menu_bar::MenuBar; +use crate::ui::*; +use sdl2::rect::{Point, Rect}; +use sdl2::VideoSubsystem; use std::boxed::Box; use std::rc::Rc; use std::sync::Arc; -use sdl2::rect::{Rect, Point}; pub struct AppState { menu_bar: MenuBar, @@ -55,23 +56,17 @@ impl AppState { if position == 0 { return; } - buffer.remove(position); + buffer.remove(position - 1); match file.get_character_at(position - 1) { Some(character) => { let dest: &Rect = character.dest(); - caret.move_caret(position - 1, Point::new( - dest.x(), dest.y(), - )); + caret.move_caret(position - 1, Point::new(dest.x(), dest.y())); } _ => { caret.reset_caret(); } } - let new_file = EditorFile::new( - file.path(), - buffer, - self.config.clone(), - ); + let new_file = EditorFile::new(file.path(), buffer, self.config.clone()); self.files[self.current_file] = new_file; } @@ -88,15 +83,11 @@ impl AppState { return; } buffer.remove(position); - let new_file = EditorFile::new( - file.path(), - buffer, - self.config.clone(), - ); + let new_file = EditorFile::new(file.path(), buffer, self.config.clone()); self.files[self.current_file] = new_file; } - pub fn insert_character(&mut self, character: char, renderer: &mut Renderer) { + pub fn insert_text(&mut self, text: String, renderer: &mut Renderer) { let file: &mut EditorFile = if let Some(file) = self.files.get_mut(self.current_file) { file } else { @@ -104,30 +95,40 @@ impl AppState { }; let mut buffer: String = file.buffer(); let caret: &mut Caret = &mut self.caret; - let position: usize = caret.text_position(); - buffer.insert(position, character.clone()); - let new_file = EditorFile::new( - file.path(), - buffer, - self.config.clone(), - ); - if let Some(rect) = get_text_character_rect(character, renderer) { - if let Some(current) = file.get_character_at(position) { - caret.move_caret(position + 1, Point::new( - current.dest().x() + rect.width() as i32, - current.dest().y(), - )); + + let current = match file.get_character_at(caret.text_position()) { + Some(c) => c, + _ => return, + }; + let mut pos = Point::new(current.dest().x(), current.dest().y()); + let mut position: usize = caret.text_position(); + for character in text.chars() { + buffer.insert(position, character); + if let Some(rect) = get_text_character_rect(character, renderer) { + pos = pos + Point::new(rect.width() as i32, 0); + position += 1; + caret.move_caret(position, pos.clone()); } } + + let new_file = EditorFile::new(file.path(), buffer, self.config.clone()); self.files[self.current_file] = new_file; } - fn current_file(&mut self) -> Option<&mut EditorFile> { +// fn current_file(&self) -> Option<&EditorFile> { +// self.files.get(self.current_file) +// } + + fn current_file_mut(&mut self) -> Option<&mut EditorFile> { self.files.get_mut(self.current_file) } - fn on_editor_clicked(&mut self, point: &Point) -> UpdateResult { - let current_file: &mut EditorFile = if let Some(current_file) = self.current_file() { + fn on_editor_clicked( + &mut self, + point: &Point, + video_subsystem: &mut VideoSubsystem, + ) -> UpdateResult { + let current_file: &mut EditorFile = if let Some(current_file) = self.current_file_mut() { current_file } else { return UpdateResult::NoOp; @@ -135,9 +136,11 @@ impl AppState { if !current_file.is_left_click_target(point) { return UpdateResult::NoOp; } + video_subsystem.text_input().start(); match current_file.on_left_click(point) { UpdateResult::MoveCaret(rect, position) => { - self.caret.move_caret(position, Point::new(rect.x(), rect.y())); + self.caret + .move_caret(position, Point::new(rect.x(), rect.y())); } _ => (), }; @@ -149,7 +152,7 @@ impl AppState { impl Render for AppState { fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult { self.menu_bar.render(canvas, renderer); - if let Some(file) = self.files.get_mut(self.current_file) { + if let Some(file) = self.current_file_mut() { file.render(canvas, renderer); } self.caret.render(canvas, renderer); @@ -168,16 +171,21 @@ impl Update for AppState { } } -impl ClickHandler for AppState { - fn on_left_click(&mut self, point: &Point) -> UpdateResult { +impl AppState { + pub fn on_left_click( + &mut self, + point: &Point, + video_subsystem: &mut VideoSubsystem, + ) -> UpdateResult { if self.menu_bar.is_left_click_target(point) { + video_subsystem.text_input().stop(); return self.menu_bar.on_left_click(point); } - self.on_editor_clicked(point); + self.on_editor_clicked(point, video_subsystem); UpdateResult::NoOp } - fn is_left_click_target(&self, _point: &Point) -> bool { + pub fn is_left_click_target(&self, _point: &Point) -> bool { true } } diff --git a/src/app/keyboard_handler.rs b/src/app/keyboard_handler.rs deleted file mode 100644 index 0c50272..0000000 --- a/src/app/keyboard_handler.rs +++ /dev/null @@ -1,281 +0,0 @@ -use sdl2::keyboard::{Keycode, Scancode}; -use sdl2::event::EventPollIterator; -use sdl2::EventPump; - -use crate::app::UpdateResult; - -pub fn resolve_action(key_code: Keycode, event_pump: &mut EventPump) -> UpdateResult { - match key_code { - Keycode::Backspace => return UpdateResult::DeleteFront, - Keycode::Delete => return UpdateResult::DeleteBack, - - Keycode::Escape => return UpdateResult::NoOp, - - Keycode::Space => { - let character: char = ' '; - return UpdateResult::Input(character); - } - Keycode::Exclaim => { - let character: char = '!'; - return UpdateResult::Input(character); - } - Keycode::Quotedbl => { - let character: char = '"'; - return UpdateResult::Input(character); - } - Keycode::Hash => { - let character: char = '#'; - return UpdateResult::Input(character); - } - Keycode::Dollar => { - let character: char = '$'; - return UpdateResult::Input(character); - } - Keycode::Percent => { - let character: char = '%'; - return UpdateResult::Input(character); - } - Keycode::Ampersand => { - let character: char = '&'; - return UpdateResult::Input(character); - } - Keycode::Quote => { - let character: char = '\''; - return UpdateResult::Input(character); - } - Keycode::LeftParen => { - let character: char = '{'; - return UpdateResult::Input(character); - } - Keycode::RightParen => { - let character: char = '}'; - return UpdateResult::Input(character); - } - Keycode::Asterisk => { - let character: char = '*'; - return UpdateResult::Input(character); - } - Keycode::Plus => { - let character: char = '+'; - return UpdateResult::Input(character); - } - Keycode::Comma => { - let character: char = ','; - return UpdateResult::Input(character); - } - Keycode::Minus => { - let character: char = '-'; - return UpdateResult::Input(character); - } - Keycode::Period => { - let character: char = '.'; - return UpdateResult::Input(character); - } - Keycode::Slash => { - let character: char = '/'; - return UpdateResult::Input(character); - } - Keycode::Num0 => { - let character: char = '0'; - return UpdateResult::Input(character); - } - Keycode::Num1 => { - let character: char = '1'; - return UpdateResult::Input(character); - } - Keycode::Num2 => { - let character: char = '2'; - return UpdateResult::Input(character); - } - Keycode::Num3 => { - let character: char = '3'; - return UpdateResult::Input(character); - } - Keycode::Num4 => { - let character: char = '4'; - return UpdateResult::Input(character); - } - Keycode::Num5 => { - let character: char = '5'; - return UpdateResult::Input(character); - } - Keycode::Num6 => { - let character: char = '6'; - return UpdateResult::Input(character); - } - Keycode::Num7 => { - let character: char = '7'; - return UpdateResult::Input(character); - } - Keycode::Num8 => { - let character: char = '8'; - return UpdateResult::Input(character); - } - Keycode::Num9 => { - let character: char = '9'; - return UpdateResult::Input(character); - } - Keycode::Colon => { - let character: char = ':'; - return UpdateResult::Input(character); - } - Keycode::Semicolon => { - let character: char = ';'; - return UpdateResult::Input(character); - } - Keycode::Less => { - let character: char = '<'; - return UpdateResult::Input(character); - } - Keycode::Equals => { - let character: char = '='; - return UpdateResult::Input(character); - } - Keycode::Greater => { - let character: char = '>'; - return UpdateResult::Input(character); - } - Keycode::Question => { - let character: char = '?'; - return UpdateResult::Input(character); - } - Keycode::At => { - let character: char = '@'; - return UpdateResult::Input(character); - } - Keycode::LeftBracket => { - let character: char = '['; - return UpdateResult::Input(character); - } - Keycode::Backslash => { - let character: char = '\\'; - return UpdateResult::Input(character); - } - Keycode::RightBracket => { - let character: char = ']'; - return UpdateResult::Input(character); - } - Keycode::Caret => { - let character: char = '^'; - return UpdateResult::Input(character); - } - Keycode::Underscore => { - let character: char = '_'; - return UpdateResult::Input(character); - } - Keycode::Backquote => { - let character: char = '`'; - return UpdateResult::Input(character); - } - Keycode::A => { - let character: char = if with_shift(event_pump) { 'A' } else { 'a' }; - return UpdateResult::Input(character); - } - Keycode::B => { - let character: char = if with_shift(event_pump) { 'B' } else { 'b' }; - return UpdateResult::Input(character); - } - Keycode::C => { - let character: char = if with_shift(event_pump) { 'C' } else { 'c' }; - return UpdateResult::Input(character); - } - Keycode::D => { - let character: char = if with_shift(event_pump) { 'D' } else { 'd' }; - return UpdateResult::Input(character); - } - Keycode::E => { - let character: char = if with_shift(event_pump) { 'E' } else { 'e' }; - return UpdateResult::Input(character); - } - Keycode::F => { - let character: char = if with_shift(event_pump) { 'F' } else { 'f' }; - return UpdateResult::Input(character); - } - Keycode::G => { - let character: char = if with_shift(event_pump) { 'G' } else { 'g' }; - return UpdateResult::Input(character); - } - Keycode::H => { - let character: char = if with_shift(event_pump) { 'H' } else { 'h' }; - return UpdateResult::Input(character); - } - Keycode::I => { - let character: char = if with_shift(event_pump) { 'I' } else { 'i' }; - return UpdateResult::Input(character); - } - Keycode::J => { - let character: char = if with_shift(event_pump) { 'J' } else { 'j' }; - return UpdateResult::Input(character); - } - Keycode::K => { - let character: char = if with_shift(event_pump) { 'K' } else { 'k' }; - return UpdateResult::Input(character); - } - Keycode::L => { - let character: char = if with_shift(event_pump) { 'L' } else { 'l' }; - return UpdateResult::Input(character); - } - Keycode::M => { - let character: char = if with_shift(event_pump) { 'M' } else { 'm' }; - return UpdateResult::Input(character); - } - Keycode::N => { - let character: char = if with_shift(event_pump) { 'N' } else { 'n' }; - return UpdateResult::Input(character); - } - Keycode::O => { - let character: char = if with_shift(event_pump) { 'O' } else { 'o' }; - return UpdateResult::Input(character); - } - Keycode::P => { - let character: char = if with_shift(event_pump) { 'P' } else { 'p' }; - return UpdateResult::Input(character); - } - Keycode::Q => { - let character: char = if with_shift(event_pump) { 'Q' } else { 'q' }; - return UpdateResult::Input(character); - } - Keycode::R => { - let character: char = if with_shift(event_pump) { 'R' } else { 'r' }; - return UpdateResult::Input(character); - } - Keycode::S => { - let character: char = if with_shift(event_pump) { 'S' } else { 's' }; - return UpdateResult::Input(character); - } - Keycode::T => { - let character: char = if with_shift(event_pump) { 'T' } else { 't' }; - return UpdateResult::Input(character); - } - Keycode::U => { - let character: char = if with_shift(event_pump) { 'U' } else { 'u' }; - return UpdateResult::Input(character); - } - Keycode::V => { - let character: char = if with_shift(event_pump) { 'V' } else { 'v' }; - return UpdateResult::Input(character); - } - Keycode::W => { - let character: char = if with_shift(event_pump) { 'W' } else { 'w' }; - return UpdateResult::Input(character); - } - Keycode::X => { - let character: char = if with_shift(event_pump) { 'X' } else { 'x' }; - return UpdateResult::Input(character); - } - Keycode::Y => { - let character: char = if with_shift(event_pump) { 'Y' } else { 'y' }; - return UpdateResult::Input(character); - } - Keycode::Z => { - let character: char = if with_shift(event_pump) { 'Z' } else { 'z' }; - return UpdateResult::Input(character); - } - _ => UpdateResult::NoOp - } -} - -fn with_shift(event_pump: &mut EventPump) -> bool { - event_pump.keyboard_state().is_scancode_pressed(Scancode::LShift) || - event_pump.keyboard_state().is_scancode_pressed(Scancode::RShift) -} diff --git a/src/app/mod.rs b/src/app/mod.rs index 57fdfb8..cc9b1ef 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -4,24 +4,23 @@ use crate::renderer::Renderer; use crate::themes::*; use crate::ui::*; +use std::rc::Rc; use std::thread::sleep; use std::time::Duration; -use std::rc::Rc; -use sdl2::{Sdl, VideoSubsystem, TimerSubsystem}; use sdl2::event::Event; -use sdl2::EventPump; -use sdl2::keyboard::{Keycode, Mod}; use sdl2::hint; +use sdl2::keyboard::{Keycode, Mod}; use sdl2::mouse::MouseButton; use sdl2::pixels::Color; use sdl2::rect::{Point, Rect}; use sdl2::render::Canvas; -use sdl2::video::Window; use sdl2::ttf::Sdl2TtfContext; +use sdl2::video::Window; +use sdl2::EventPump; +use sdl2::{Sdl, TimerSubsystem, VideoSubsystem}; pub mod app_state; -pub mod keyboard_handler; pub type WindowCanvas = Canvas; @@ -34,7 +33,7 @@ pub enum UpdateResult { MoveCaret(Rect, usize), DeleteFront, DeleteBack, - Input(char) + Input(String), } pub enum Task { @@ -70,7 +69,6 @@ impl Application { .unwrap(); let canvas = window.into_canvas().accelerated().build().unwrap(); -// let font_context = Rc::new(sdl2::ttf::init().unwrap()); Self { sdl_context, @@ -102,17 +100,18 @@ impl Application { UpdateResult::NoOp => (), UpdateResult::MoveCaret(_, _pos) => (), UpdateResult::MouseLeftClicked(point) => { - app_state.on_left_click(&point); + app_state.on_left_click(&point, &mut self.video_subsystem); } UpdateResult::DeleteFront => { app_state.delete_front(); - }, + } UpdateResult::DeleteBack => { app_state.delete_back(); - }, - UpdateResult::Input(text_character) => { - app_state.insert_character(text_character, &mut renderer); - }, + } + UpdateResult::Input(text) => { + println!("text input: {}", text); + app_state.insert_text(text, &mut renderer); + } } for task in self.tasks.iter() { match task { @@ -163,10 +162,15 @@ impl Application { } else { return UpdateResult::NoOp; }; - return keyboard_handler::resolve_action( - keycode, - event_pump - ); + match keycode { + Keycode::Backspace => return UpdateResult::DeleteFront, + Keycode::Delete => return UpdateResult::DeleteBack, + _ => UpdateResult::NoOp, + }; + } + Event::TextInput { text, .. } => { + println!("text input: {}", text); + return UpdateResult::Input(text); } _ => (), } diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index e4774fa..2841fe7 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -1,6 +1,7 @@ use std::ops::Deref; pub mod plain; +pub mod rust_lang; #[derive(Debug, Clone)] pub enum Language { @@ -146,7 +147,7 @@ impl Token { pub fn parse(text: String, language: Language) -> Vec { match language { Language::PlainText => plain::lexer::Lexer::new(text.as_str()) - .inspect(|tok| println!("tok: {:?}", tok)) + // .inspect(|tok| println!("tok: {:?}", tok)) .map(|t| t.0) .collect(), } diff --git a/src/lexer/rust_lang.rs b/src/lexer/rust_lang.rs new file mode 100644 index 0000000..46c7639 --- /dev/null +++ b/src/lexer/rust_lang.rs @@ -0,0 +1,84 @@ +use crate::lexer::{Token, TokenType}; + +pub mod lexer { + use crate::lexer::{Span, Token, TokenType}; + use plex::lexer; + + lexer! { + fn next_token(text: 'a) -> (TokenType, &'a str); + + r"[ \t\r\n]" => (TokenType::Whitespace { + token: Token::new(text.to_string(), 0, 0, 0, 0) + }, text), + + r"(let|fn|type|struct|pub|impl|for|self|Self)" => (TokenType::Keyword { + token: Token::new(text.to_string(), 0, 0, 0, 0) + }, text), + + r"[^ \t\r\n]+" => (TokenType::Identifier { + token: Token::new(text.to_string(), 0, 0, 0, 0) + }, text), + } + + pub struct Lexer<'a> { + original: &'a str, + remaining: &'a str, + line: usize, + character: usize, + } + + impl<'a> Lexer<'a> { + pub fn new(s: &'a str) -> Self { + Self { + original: s, + remaining: s, + line: 0, + character: 0, + } + } + } + + impl<'a> Iterator for Lexer<'a> { + type Item = (TokenType, Span); + + fn next(&mut self) -> Option<(TokenType, Span)> { + loop { + let tok: (TokenType, &str) = + if let Some(((token_type, text), new_remaining)) = next_token(self.remaining) { + self.remaining = new_remaining; + if token_type.is_new_line() { + self.line += 1; + self.character = text.len(); + } else { + self.character += text.len(); + } + (token_type, text) + } else { + return None; + }; + match tok { + (tok, text) => { + let span = self.span_in(text); + let token = tok.move_to( + self.line.clone(), + self.character - text.len(), + span.lo.clone(), + span.hi.clone(), + ); + return Some((token, span)); + } + } + } + } + } + + impl<'a> Lexer<'a> { + fn span_in(&self, s: &str) -> Span { + let lo = s.as_ptr() as usize - self.original.as_ptr() as usize; + Span { + lo, + hi: lo + s.len(), + } + } + } +} diff --git a/src/renderer/managers.rs b/src/renderer/managers.rs index caeb1a3..e20bfa8 100644 --- a/src/renderer/managers.rs +++ b/src/renderer/managers.rs @@ -34,7 +34,7 @@ impl TextDetails { "text({}) size({}) {:?}", self.text, self.font.size, self.color ) - .to_string() + .to_string() } } @@ -72,18 +72,18 @@ pub type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, S #[derive(Clone)] pub struct ResourceManager<'l, K, R, L> - where - K: Hash + Eq, - L: 'l + ResourceLoader<'l, R>, +where + K: Hash + Eq, + L: 'l + ResourceLoader<'l, R>, { loader: &'l L, cache: HashMap>, } impl<'l, K, R, L> ResourceManager<'l, K, R, L> - where - K: Hash + Eq, - L: ResourceLoader<'l, R>, +where + K: Hash + Eq, + L: ResourceLoader<'l, R>, { pub fn new(loader: &'l L) -> Self { Self { @@ -93,10 +93,10 @@ impl<'l, K, R, L> ResourceManager<'l, K, R, L> } pub fn load(&mut self, details: &D) -> Result, String> - where - L: ResourceLoader<'l, R, Args=D>, - D: Eq + Hash + ?Sized, - K: Borrow + for<'a> From<&'a D>, + where + L: ResourceLoader<'l, R, Args = D>, + D: Eq + Hash + ?Sized, + K: Borrow + for<'a> From<&'a D>, { self.cache.get(details).cloned().map_or_else( || { diff --git a/src/renderer/mod.rs b/src/renderer/mod.rs index debdda6..d16dbcf 100644 --- a/src/renderer/mod.rs +++ b/src/renderer/mod.rs @@ -1,12 +1,12 @@ use crate::app::WindowCanvas; use crate::config::Config; -use crate::renderer::managers::{FontManager, TextureManager}; use crate::renderer::managers::TextDetails; -use std::rc::Rc; +use crate::renderer::managers::{FontManager, TextureManager}; use sdl2::rect::{Point, Rect}; use sdl2::render::{Texture, TextureCreator}; use sdl2::ttf::Sdl2TtfContext; use sdl2::video::WindowContext; +use std::rc::Rc; pub mod managers; diff --git a/src/themes/mod.rs b/src/themes/mod.rs index 7681635..6819cd2 100644 --- a/src/themes/mod.rs +++ b/src/themes/mod.rs @@ -1,6 +1,6 @@ use crate::config::directories::*; use sdl2::pixels::Color; -use serde::ser::{Serialize, SerializeMap, Serializer, SerializeSeq}; +use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer}; use serde_json; use std::env; use std::fs; diff --git a/src/ui/caret.rs b/src/ui/caret.rs index 780d8db..e278624 100644 --- a/src/ui/caret.rs +++ b/src/ui/caret.rs @@ -1,12 +1,12 @@ use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; use crate::renderer::Renderer; -use crate::ui::*; use crate::ui::text_character::TextCharacter; -use std::rc::Rc; +use crate::ui::*; use sdl2::pixels::Color; use sdl2::rect::{Point, Rect}; use sdl2::render::Texture; +use std::rc::Rc; #[derive(Clone, Debug, PartialEq)] enum CaretState { @@ -14,11 +14,12 @@ enum CaretState { Blur, } +#[derive(Clone, Debug, PartialEq)] pub struct Caret { pending: bool, text_position: usize, blink_delay: u8, - config: Rc, +// config: Rc, state: CaretState, dest: Rect, reset_position: Rect, @@ -49,7 +50,7 @@ impl Caret { blur_character_color, pending: true, text_position: 0, - config, +// config, } } @@ -96,10 +97,7 @@ impl Render for Caret { self.pending = false; } let start = Point::new(self.dest.x(), self.dest.y()); - let end = Point::new( - self.dest.x(), - self.dest.y() + self.dest.height() as i32, - ); + let end = Point::new(self.dest.x(), self.dest.y() + self.dest.height() as i32); let color = match self.state { CaretState::Bright => &self.bright_character_color, CaretState::Blur => &self.blur_character_color, diff --git a/src/ui/file/editor_file.rs b/src/ui/file/editor_file.rs index b1e87d0..c9c789e 100644 --- a/src/ui/file/editor_file.rs +++ b/src/ui/file/editor_file.rs @@ -1,12 +1,12 @@ -use std::rc::Rc; use sdl2::rect::{Point, Rect}; +use std::rc::Rc; use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::ui::file::editor_file_section::EditorFileSection; use crate::renderer::Renderer; -use crate::ui::*; +use crate::ui::file::editor_file_section::EditorFileSection; use crate::ui::text_character::TextCharacter; +use crate::ui::*; #[derive(Clone)] pub struct EditorFile { @@ -14,14 +14,12 @@ pub struct EditorFile { sections: Vec, render_position: Rect, buffer: String, - config: Rc + config: Rc, } impl EditorFile { pub fn new(path: String, buffer: String, config: Rc) -> Self { - let sections = vec![ - EditorFileSection::new(buffer.clone(), config.clone()) - ]; + let sections = vec![EditorFileSection::new(buffer.clone(), config.clone())]; let x = config.editor_left_margin(); let y = config.editor_top_margin(); Self { @@ -29,7 +27,7 @@ impl EditorFile { sections, render_position: Rect::new(x, y, 0, 0), buffer, - config + config, } } @@ -44,7 +42,7 @@ impl EditorFile { pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { for section in self.sections.iter() { if let Some(text_character) = section.get_character_at(index) { - return Some(text_character) + return Some(text_character); } } None diff --git a/src/ui/file/editor_file_section.rs b/src/ui/file/editor_file_section.rs index 1e9226a..f770da3 100644 --- a/src/ui/file/editor_file_section.rs +++ b/src/ui/file/editor_file_section.rs @@ -1,13 +1,13 @@ -use std::rc::Rc; use sdl2::rect::{Point, Rect}; +use std::rc::Rc; use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::ui::file::editor_file_token::EditorFileToken; use crate::lexer::Language; use crate::renderer::Renderer; -use crate::ui::*; +use crate::ui::file::editor_file_token::EditorFileToken; use crate::ui::text_character::TextCharacter; +use crate::ui::*; #[derive(Clone)] pub struct EditorFileSection { @@ -27,7 +27,11 @@ impl EditorFileSection { tokens.push(token.clone()); } let language = Language::PlainText; - Self { tokens, language, config } + Self { + tokens, + language, + config, + } } pub fn update_positions(&mut self, current: &mut Rect) { @@ -39,7 +43,7 @@ impl EditorFileSection { pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { for token in self.tokens.iter() { if let Some(text_character) = token.get_character_at(index) { - return Some(text_character) + return Some(text_character); } } None diff --git a/src/ui/file/editor_file_token.rs b/src/ui/file/editor_file_token.rs index 74e613e..dd10b0e 100644 --- a/src/ui/file/editor_file_token.rs +++ b/src/ui/file/editor_file_token.rs @@ -3,19 +3,19 @@ use crate::config::Config; use crate::lexer::TokenType; use crate::renderer::managers::{FontDetails, TextDetails}; use crate::renderer::Renderer; -use crate::ui::*; use crate::ui::text_character::*; -use std::rc::Rc; +use crate::ui::*; use sdl2::pixels::Color; use sdl2::rect::{Point, Rect}; use sdl2::render::Texture; use sdl2::ttf::Font; +use std::rc::Rc; #[derive(Clone)] pub struct EditorFileToken { characters: Vec, token_type: TokenType, - config: Rc + config: Rc, } impl EditorFileToken { @@ -23,7 +23,7 @@ impl EditorFileToken { Self { characters: vec![], token_type, - config + config, } } @@ -36,7 +36,7 @@ impl EditorFileToken { pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> { for character in self.characters.iter() { if character.position() == index { - return Some(&character) + return Some(&character); } } None @@ -61,7 +61,7 @@ impl EditorFileToken { self.token_type.start() + index, self.token_type.line(), color.clone(), - self.config.clone() + self.config.clone(), ); text_character.update_view(renderer); self.characters.push(text_character); diff --git a/src/ui/menu_bar.rs b/src/ui/menu_bar.rs index d7aa05c..cfe6589 100644 --- a/src/ui/menu_bar.rs +++ b/src/ui/menu_bar.rs @@ -2,9 +2,9 @@ use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; use crate::renderer::Renderer; use crate::ui::*; -use std::rc::Rc; use sdl2::pixels::Color; -use sdl2::rect::{Rect, Point}; +use sdl2::rect::{Point, Rect}; +use std::rc::Rc; pub struct MenuBar { background_color: Color, diff --git a/src/ui/mod.rs b/src/ui/mod.rs index d3a2103..512eb5a 100644 --- a/src/ui/mod.rs +++ b/src/ui/mod.rs @@ -2,13 +2,13 @@ use sdl2::rect::{Point, Rect}; use crate::app::{UpdateResult, WindowCanvas}; use crate::config::Config; -use crate::renderer::Renderer; use crate::renderer::managers::FontDetails; +use crate::renderer::Renderer; pub mod caret; +pub mod file; pub mod menu_bar; pub mod text_character; -pub mod file; pub fn is_in_rect(point: &Point, rect: &Rect) -> bool { let start = Point::new(rect.x(), rect.y()); diff --git a/src/ui/text_character.rs b/src/ui/text_character.rs index 6644792..fb8b582 100644 --- a/src/ui/text_character.rs +++ b/src/ui/text_character.rs @@ -6,11 +6,11 @@ use crate::renderer::managers::TextDetails; use crate::renderer::Renderer; use crate::ui::*; -use std::rc::Rc; use sdl2::pixels::Color; -use sdl2::rect::{Rect, Point}; +use sdl2::rect::{Point, Rect}; use sdl2::render::Texture; use sdl2::ttf::Font; +use std::rc::Rc; #[derive(Clone)] pub struct TextCharacter { @@ -21,11 +21,17 @@ pub struct TextCharacter { source: Rect, dest: Rect, color: Color, - config: Rc + config: Rc, } impl TextCharacter { - pub fn new(text_character: char, position: usize, line: usize, color: Color, config: Rc) -> Self { + pub fn new( + text_character: char, + position: usize, + line: usize, + color: Color, + config: Rc, + ) -> Self { Self { pending: true, text_character, @@ -34,7 +40,7 @@ impl TextCharacter { source: Rect::new(0, 0, 0, 0), dest: Rect::new(0, 0, 0, 0), color, - config + config, } } @@ -148,10 +154,7 @@ impl Update for TextCharacter { impl ClickHandler for TextCharacter { fn on_left_click(&mut self, _point: &Point) -> UpdateResult { - UpdateResult::MoveCaret( - self.dest().clone(), - self.position() - ) + UpdateResult::MoveCaret(self.dest().clone(), self.position()) } fn is_left_click_target(&self, point: &Point) -> bool {