Fix backspace, fix add text
This commit is contained in:
parent
c25fe0a4f5
commit
9460b6931a
154
assets/test.rs
Normal file
154
assets/test.rs
Normal file
@ -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) -> &<Self as Deref>::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<TokenType> {
|
||||||
|
match language {
|
||||||
|
Language::PlainText => plain::lexer::Lexer::new(text.as_str())
|
||||||
|
// .inspect(|tok| println!("tok: {:?}", tok))
|
||||||
|
.map(|t| t.0)
|
||||||
|
.collect(),
|
||||||
|
}
|
||||||
|
}
|
@ -1,15 +1,16 @@
|
|||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult, WindowCanvas};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::ui::file::*;
|
|
||||||
use crate::ui::file::editor_file::EditorFile;
|
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
|
||||||
use crate::ui::caret::Caret;
|
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::menu_bar::MenuBar;
|
||||||
|
use crate::ui::*;
|
||||||
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use sdl2::VideoSubsystem;
|
||||||
use std::boxed::Box;
|
use std::boxed::Box;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use sdl2::rect::{Rect, Point};
|
|
||||||
|
|
||||||
pub struct AppState {
|
pub struct AppState {
|
||||||
menu_bar: MenuBar,
|
menu_bar: MenuBar,
|
||||||
@ -55,23 +56,17 @@ impl AppState {
|
|||||||
if position == 0 {
|
if position == 0 {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buffer.remove(position);
|
buffer.remove(position - 1);
|
||||||
match file.get_character_at(position - 1) {
|
match file.get_character_at(position - 1) {
|
||||||
Some(character) => {
|
Some(character) => {
|
||||||
let dest: &Rect = character.dest();
|
let dest: &Rect = character.dest();
|
||||||
caret.move_caret(position - 1, Point::new(
|
caret.move_caret(position - 1, Point::new(dest.x(), dest.y()));
|
||||||
dest.x(), dest.y(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
caret.reset_caret();
|
caret.reset_caret();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let new_file = EditorFile::new(
|
let new_file = EditorFile::new(file.path(), buffer, self.config.clone());
|
||||||
file.path(),
|
|
||||||
buffer,
|
|
||||||
self.config.clone(),
|
|
||||||
);
|
|
||||||
self.files[self.current_file] = new_file;
|
self.files[self.current_file] = new_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,15 +83,11 @@ impl AppState {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
buffer.remove(position);
|
buffer.remove(position);
|
||||||
let new_file = EditorFile::new(
|
let new_file = EditorFile::new(file.path(), buffer, self.config.clone());
|
||||||
file.path(),
|
|
||||||
buffer,
|
|
||||||
self.config.clone(),
|
|
||||||
);
|
|
||||||
self.files[self.current_file] = new_file;
|
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) {
|
let file: &mut EditorFile = if let Some(file) = self.files.get_mut(self.current_file) {
|
||||||
file
|
file
|
||||||
} else {
|
} else {
|
||||||
@ -104,30 +95,40 @@ impl AppState {
|
|||||||
};
|
};
|
||||||
let mut buffer: String = file.buffer();
|
let mut buffer: String = file.buffer();
|
||||||
let caret: &mut Caret = &mut self.caret;
|
let caret: &mut Caret = &mut self.caret;
|
||||||
let position: usize = caret.text_position();
|
|
||||||
buffer.insert(position, character.clone());
|
let current = match file.get_character_at(caret.text_position()) {
|
||||||
let new_file = EditorFile::new(
|
Some(c) => c,
|
||||||
file.path(),
|
_ => return,
|
||||||
buffer,
|
};
|
||||||
self.config.clone(),
|
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) {
|
if let Some(rect) = get_text_character_rect(character, renderer) {
|
||||||
if let Some(current) = file.get_character_at(position) {
|
pos = pos + Point::new(rect.width() as i32, 0);
|
||||||
caret.move_caret(position + 1, Point::new(
|
position += 1;
|
||||||
current.dest().x() + rect.width() as i32,
|
caret.move_caret(position, pos.clone());
|
||||||
current.dest().y(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let new_file = EditorFile::new(file.path(), buffer, self.config.clone());
|
||||||
self.files[self.current_file] = new_file;
|
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)
|
self.files.get_mut(self.current_file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_editor_clicked(&mut self, point: &Point) -> UpdateResult {
|
fn on_editor_clicked(
|
||||||
let current_file: &mut EditorFile = if let Some(current_file) = self.current_file() {
|
&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
|
current_file
|
||||||
} else {
|
} else {
|
||||||
return UpdateResult::NoOp;
|
return UpdateResult::NoOp;
|
||||||
@ -135,9 +136,11 @@ impl AppState {
|
|||||||
if !current_file.is_left_click_target(point) {
|
if !current_file.is_left_click_target(point) {
|
||||||
return UpdateResult::NoOp;
|
return UpdateResult::NoOp;
|
||||||
}
|
}
|
||||||
|
video_subsystem.text_input().start();
|
||||||
match current_file.on_left_click(point) {
|
match current_file.on_left_click(point) {
|
||||||
UpdateResult::MoveCaret(rect, position) => {
|
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 {
|
impl Render for AppState {
|
||||||
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
fn render(&mut self, canvas: &mut WindowCanvas, renderer: &mut Renderer) -> UpdateResult {
|
||||||
self.menu_bar.render(canvas, renderer);
|
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);
|
file.render(canvas, renderer);
|
||||||
}
|
}
|
||||||
self.caret.render(canvas, renderer);
|
self.caret.render(canvas, renderer);
|
||||||
@ -168,16 +171,21 @@ impl Update for AppState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClickHandler for AppState {
|
impl AppState {
|
||||||
fn on_left_click(&mut self, point: &Point) -> UpdateResult {
|
pub fn on_left_click(
|
||||||
|
&mut self,
|
||||||
|
point: &Point,
|
||||||
|
video_subsystem: &mut VideoSubsystem,
|
||||||
|
) -> UpdateResult {
|
||||||
if self.menu_bar.is_left_click_target(point) {
|
if self.menu_bar.is_left_click_target(point) {
|
||||||
|
video_subsystem.text_input().stop();
|
||||||
return self.menu_bar.on_left_click(point);
|
return self.menu_bar.on_left_click(point);
|
||||||
}
|
}
|
||||||
self.on_editor_clicked(point);
|
self.on_editor_clicked(point, video_subsystem);
|
||||||
UpdateResult::NoOp
|
UpdateResult::NoOp
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_left_click_target(&self, _point: &Point) -> bool {
|
pub fn is_left_click_target(&self, _point: &Point) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
@ -4,24 +4,23 @@ use crate::renderer::Renderer;
|
|||||||
use crate::themes::*;
|
use crate::themes::*;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
|
use std::rc::Rc;
|
||||||
use std::thread::sleep;
|
use std::thread::sleep;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::rc::Rc;
|
|
||||||
|
|
||||||
use sdl2::{Sdl, VideoSubsystem, TimerSubsystem};
|
|
||||||
use sdl2::event::Event;
|
use sdl2::event::Event;
|
||||||
use sdl2::EventPump;
|
|
||||||
use sdl2::keyboard::{Keycode, Mod};
|
|
||||||
use sdl2::hint;
|
use sdl2::hint;
|
||||||
|
use sdl2::keyboard::{Keycode, Mod};
|
||||||
use sdl2::mouse::MouseButton;
|
use sdl2::mouse::MouseButton;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use sdl2::render::Canvas;
|
use sdl2::render::Canvas;
|
||||||
use sdl2::video::Window;
|
|
||||||
use sdl2::ttf::Sdl2TtfContext;
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
|
use sdl2::video::Window;
|
||||||
|
use sdl2::EventPump;
|
||||||
|
use sdl2::{Sdl, TimerSubsystem, VideoSubsystem};
|
||||||
|
|
||||||
pub mod app_state;
|
pub mod app_state;
|
||||||
pub mod keyboard_handler;
|
|
||||||
|
|
||||||
pub type WindowCanvas = Canvas<Window>;
|
pub type WindowCanvas = Canvas<Window>;
|
||||||
|
|
||||||
@ -34,7 +33,7 @@ pub enum UpdateResult {
|
|||||||
MoveCaret(Rect, usize),
|
MoveCaret(Rect, usize),
|
||||||
DeleteFront,
|
DeleteFront,
|
||||||
DeleteBack,
|
DeleteBack,
|
||||||
Input(char)
|
Input(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum Task {
|
pub enum Task {
|
||||||
@ -70,7 +69,6 @@ impl Application {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
let canvas = window.into_canvas().accelerated().build().unwrap();
|
let canvas = window.into_canvas().accelerated().build().unwrap();
|
||||||
// let font_context = Rc::new(sdl2::ttf::init().unwrap());
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
sdl_context,
|
sdl_context,
|
||||||
@ -102,17 +100,18 @@ impl Application {
|
|||||||
UpdateResult::NoOp => (),
|
UpdateResult::NoOp => (),
|
||||||
UpdateResult::MoveCaret(_, _pos) => (),
|
UpdateResult::MoveCaret(_, _pos) => (),
|
||||||
UpdateResult::MouseLeftClicked(point) => {
|
UpdateResult::MouseLeftClicked(point) => {
|
||||||
app_state.on_left_click(&point);
|
app_state.on_left_click(&point, &mut self.video_subsystem);
|
||||||
}
|
}
|
||||||
UpdateResult::DeleteFront => {
|
UpdateResult::DeleteFront => {
|
||||||
app_state.delete_front();
|
app_state.delete_front();
|
||||||
},
|
}
|
||||||
UpdateResult::DeleteBack => {
|
UpdateResult::DeleteBack => {
|
||||||
app_state.delete_back();
|
app_state.delete_back();
|
||||||
},
|
}
|
||||||
UpdateResult::Input(text_character) => {
|
UpdateResult::Input(text) => {
|
||||||
app_state.insert_character(text_character, &mut renderer);
|
println!("text input: {}", text);
|
||||||
},
|
app_state.insert_text(text, &mut renderer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for task in self.tasks.iter() {
|
for task in self.tasks.iter() {
|
||||||
match task {
|
match task {
|
||||||
@ -163,10 +162,15 @@ impl Application {
|
|||||||
} else {
|
} else {
|
||||||
return UpdateResult::NoOp;
|
return UpdateResult::NoOp;
|
||||||
};
|
};
|
||||||
return keyboard_handler::resolve_action(
|
match keycode {
|
||||||
keycode,
|
Keycode::Backspace => return UpdateResult::DeleteFront,
|
||||||
event_pump
|
Keycode::Delete => return UpdateResult::DeleteBack,
|
||||||
);
|
_ => UpdateResult::NoOp,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
Event::TextInput { text, .. } => {
|
||||||
|
println!("text input: {}", text);
|
||||||
|
return UpdateResult::Input(text);
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
pub mod plain;
|
pub mod plain;
|
||||||
|
pub mod rust_lang;
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum Language {
|
pub enum Language {
|
||||||
@ -146,7 +147,7 @@ impl Token {
|
|||||||
pub fn parse(text: String, language: Language) -> Vec<TokenType> {
|
pub fn parse(text: String, language: Language) -> Vec<TokenType> {
|
||||||
match language {
|
match language {
|
||||||
Language::PlainText => plain::lexer::Lexer::new(text.as_str())
|
Language::PlainText => plain::lexer::Lexer::new(text.as_str())
|
||||||
.inspect(|tok| println!("tok: {:?}", tok))
|
// .inspect(|tok| println!("tok: {:?}", tok))
|
||||||
.map(|t| t.0)
|
.map(|t| t.0)
|
||||||
.collect(),
|
.collect(),
|
||||||
}
|
}
|
||||||
|
84
src/lexer/rust_lang.rs
Normal file
84
src/lexer/rust_lang.rs
Normal file
@ -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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -72,7 +72,7 @@ pub type FontManager<'l> = ResourceManager<'l, FontDetails, Font<'l, 'static>, S
|
|||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct ResourceManager<'l, K, R, L>
|
pub struct ResourceManager<'l, K, R, L>
|
||||||
where
|
where
|
||||||
K: Hash + Eq,
|
K: Hash + Eq,
|
||||||
L: 'l + ResourceLoader<'l, R>,
|
L: 'l + ResourceLoader<'l, R>,
|
||||||
{
|
{
|
||||||
@ -81,7 +81,7 @@ pub struct ResourceManager<'l, K, R, L>
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'l, K, R, L> ResourceManager<'l, K, R, L>
|
impl<'l, K, R, L> ResourceManager<'l, K, R, L>
|
||||||
where
|
where
|
||||||
K: Hash + Eq,
|
K: Hash + Eq,
|
||||||
L: ResourceLoader<'l, R>,
|
L: ResourceLoader<'l, R>,
|
||||||
{
|
{
|
||||||
@ -94,7 +94,7 @@ impl<'l, K, R, L> ResourceManager<'l, K, R, L>
|
|||||||
|
|
||||||
pub fn load<D>(&mut self, details: &D) -> Result<Rc<R>, String>
|
pub fn load<D>(&mut self, details: &D) -> Result<Rc<R>, String>
|
||||||
where
|
where
|
||||||
L: ResourceLoader<'l, R, Args=D>,
|
L: ResourceLoader<'l, R, Args = D>,
|
||||||
D: Eq + Hash + ?Sized,
|
D: Eq + Hash + ?Sized,
|
||||||
K: Borrow<D> + for<'a> From<&'a D>,
|
K: Borrow<D> + for<'a> From<&'a D>,
|
||||||
{
|
{
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::app::WindowCanvas;
|
use crate::app::WindowCanvas;
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::renderer::managers::{FontManager, TextureManager};
|
|
||||||
use crate::renderer::managers::TextDetails;
|
use crate::renderer::managers::TextDetails;
|
||||||
use std::rc::Rc;
|
use crate::renderer::managers::{FontManager, TextureManager};
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use sdl2::render::{Texture, TextureCreator};
|
use sdl2::render::{Texture, TextureCreator};
|
||||||
use sdl2::ttf::Sdl2TtfContext;
|
use sdl2::ttf::Sdl2TtfContext;
|
||||||
use sdl2::video::WindowContext;
|
use sdl2::video::WindowContext;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub mod managers;
|
pub mod managers;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::config::directories::*;
|
use crate::config::directories::*;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use serde::ser::{Serialize, SerializeMap, Serializer, SerializeSeq};
|
use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
|
||||||
use serde_json;
|
use serde_json;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult, WindowCanvas};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
|
||||||
use crate::ui::text_character::TextCharacter;
|
use crate::ui::text_character::TextCharacter;
|
||||||
use std::rc::Rc;
|
use crate::ui::*;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
enum CaretState {
|
enum CaretState {
|
||||||
@ -14,11 +14,12 @@ enum CaretState {
|
|||||||
Blur,
|
Blur,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Caret {
|
pub struct Caret {
|
||||||
pending: bool,
|
pending: bool,
|
||||||
text_position: usize,
|
text_position: usize,
|
||||||
blink_delay: u8,
|
blink_delay: u8,
|
||||||
config: Rc<Config>,
|
// config: Rc<Config>,
|
||||||
state: CaretState,
|
state: CaretState,
|
||||||
dest: Rect,
|
dest: Rect,
|
||||||
reset_position: Rect,
|
reset_position: Rect,
|
||||||
@ -49,7 +50,7 @@ impl Caret {
|
|||||||
blur_character_color,
|
blur_character_color,
|
||||||
pending: true,
|
pending: true,
|
||||||
text_position: 0,
|
text_position: 0,
|
||||||
config,
|
// config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +97,7 @@ impl Render for Caret {
|
|||||||
self.pending = false;
|
self.pending = false;
|
||||||
}
|
}
|
||||||
let start = Point::new(self.dest.x(), self.dest.y());
|
let start = Point::new(self.dest.x(), self.dest.y());
|
||||||
let end = Point::new(
|
let end = Point::new(self.dest.x(), self.dest.y() + self.dest.height() as i32);
|
||||||
self.dest.x(),
|
|
||||||
self.dest.y() + self.dest.height() as i32,
|
|
||||||
);
|
|
||||||
let color = match self.state {
|
let color = match self.state {
|
||||||
CaretState::Bright => &self.bright_character_color,
|
CaretState::Bright => &self.bright_character_color,
|
||||||
CaretState::Blur => &self.blur_character_color,
|
CaretState::Blur => &self.blur_character_color,
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult, WindowCanvas};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::ui::file::editor_file_section::EditorFileSection;
|
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::file::editor_file_section::EditorFileSection;
|
||||||
use crate::ui::text_character::TextCharacter;
|
use crate::ui::text_character::TextCharacter;
|
||||||
|
use crate::ui::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EditorFile {
|
pub struct EditorFile {
|
||||||
@ -14,14 +14,12 @@ pub struct EditorFile {
|
|||||||
sections: Vec<EditorFileSection>,
|
sections: Vec<EditorFileSection>,
|
||||||
render_position: Rect,
|
render_position: Rect,
|
||||||
buffer: String,
|
buffer: String,
|
||||||
config: Rc<Config>
|
config: Rc<Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFile {
|
impl EditorFile {
|
||||||
pub fn new(path: String, buffer: String, config: Rc<Config>) -> Self {
|
pub fn new(path: String, buffer: String, config: Rc<Config>) -> Self {
|
||||||
let sections = vec![
|
let sections = vec![EditorFileSection::new(buffer.clone(), config.clone())];
|
||||||
EditorFileSection::new(buffer.clone(), config.clone())
|
|
||||||
];
|
|
||||||
let x = config.editor_left_margin();
|
let x = config.editor_left_margin();
|
||||||
let y = config.editor_top_margin();
|
let y = config.editor_top_margin();
|
||||||
Self {
|
Self {
|
||||||
@ -29,7 +27,7 @@ impl EditorFile {
|
|||||||
sections,
|
sections,
|
||||||
render_position: Rect::new(x, y, 0, 0),
|
render_position: Rect::new(x, y, 0, 0),
|
||||||
buffer,
|
buffer,
|
||||||
config
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +42,7 @@ impl EditorFile {
|
|||||||
pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> {
|
pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> {
|
||||||
for section in self.sections.iter() {
|
for section in self.sections.iter() {
|
||||||
if let Some(text_character) = section.get_character_at(index) {
|
if let Some(text_character) = section.get_character_at(index) {
|
||||||
return Some(text_character)
|
return Some(text_character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
use std::rc::Rc;
|
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult, WindowCanvas};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::ui::file::editor_file_token::EditorFileToken;
|
|
||||||
use crate::lexer::Language;
|
use crate::lexer::Language;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::file::editor_file_token::EditorFileToken;
|
||||||
use crate::ui::text_character::TextCharacter;
|
use crate::ui::text_character::TextCharacter;
|
||||||
|
use crate::ui::*;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EditorFileSection {
|
pub struct EditorFileSection {
|
||||||
@ -27,7 +27,11 @@ impl EditorFileSection {
|
|||||||
tokens.push(token.clone());
|
tokens.push(token.clone());
|
||||||
}
|
}
|
||||||
let language = Language::PlainText;
|
let language = Language::PlainText;
|
||||||
Self { tokens, language, config }
|
Self {
|
||||||
|
tokens,
|
||||||
|
language,
|
||||||
|
config,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_positions(&mut self, current: &mut Rect) {
|
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> {
|
pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> {
|
||||||
for token in self.tokens.iter() {
|
for token in self.tokens.iter() {
|
||||||
if let Some(text_character) = token.get_character_at(index) {
|
if let Some(text_character) = token.get_character_at(index) {
|
||||||
return Some(text_character)
|
return Some(text_character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
|
@ -3,19 +3,19 @@ use crate::config::Config;
|
|||||||
use crate::lexer::TokenType;
|
use crate::lexer::TokenType;
|
||||||
use crate::renderer::managers::{FontDetails, TextDetails};
|
use crate::renderer::managers::{FontDetails, TextDetails};
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
|
||||||
use crate::ui::text_character::*;
|
use crate::ui::text_character::*;
|
||||||
use std::rc::Rc;
|
use crate::ui::*;
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Point, Rect};
|
use sdl2::rect::{Point, Rect};
|
||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct EditorFileToken {
|
pub struct EditorFileToken {
|
||||||
characters: Vec<TextCharacter>,
|
characters: Vec<TextCharacter>,
|
||||||
token_type: TokenType,
|
token_type: TokenType,
|
||||||
config: Rc<Config>
|
config: Rc<Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EditorFileToken {
|
impl EditorFileToken {
|
||||||
@ -23,7 +23,7 @@ impl EditorFileToken {
|
|||||||
Self {
|
Self {
|
||||||
characters: vec![],
|
characters: vec![],
|
||||||
token_type,
|
token_type,
|
||||||
config
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ impl EditorFileToken {
|
|||||||
pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> {
|
pub fn get_character_at(&self, index: usize) -> Option<&TextCharacter> {
|
||||||
for character in self.characters.iter() {
|
for character in self.characters.iter() {
|
||||||
if character.position() == index {
|
if character.position() == index {
|
||||||
return Some(&character)
|
return Some(&character);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@ -61,7 +61,7 @@ impl EditorFileToken {
|
|||||||
self.token_type.start() + index,
|
self.token_type.start() + index,
|
||||||
self.token_type.line(),
|
self.token_type.line(),
|
||||||
color.clone(),
|
color.clone(),
|
||||||
self.config.clone()
|
self.config.clone(),
|
||||||
);
|
);
|
||||||
text_character.update_view(renderer);
|
text_character.update_view(renderer);
|
||||||
self.characters.push(text_character);
|
self.characters.push(text_character);
|
||||||
|
@ -2,9 +2,9 @@ use crate::app::{UpdateResult, WindowCanvas};
|
|||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
use std::rc::Rc;
|
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Rect, Point};
|
use sdl2::rect::{Point, Rect};
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
pub struct MenuBar {
|
pub struct MenuBar {
|
||||||
background_color: Color,
|
background_color: Color,
|
||||||
|
@ -2,13 +2,13 @@ use sdl2::rect::{Point, Rect};
|
|||||||
|
|
||||||
use crate::app::{UpdateResult, WindowCanvas};
|
use crate::app::{UpdateResult, WindowCanvas};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
use crate::renderer::Renderer;
|
|
||||||
use crate::renderer::managers::FontDetails;
|
use crate::renderer::managers::FontDetails;
|
||||||
|
use crate::renderer::Renderer;
|
||||||
|
|
||||||
pub mod caret;
|
pub mod caret;
|
||||||
|
pub mod file;
|
||||||
pub mod menu_bar;
|
pub mod menu_bar;
|
||||||
pub mod text_character;
|
pub mod text_character;
|
||||||
pub mod file;
|
|
||||||
|
|
||||||
pub fn is_in_rect(point: &Point, rect: &Rect) -> bool {
|
pub fn is_in_rect(point: &Point, rect: &Rect) -> bool {
|
||||||
let start = Point::new(rect.x(), rect.y());
|
let start = Point::new(rect.x(), rect.y());
|
||||||
|
@ -6,11 +6,11 @@ use crate::renderer::managers::TextDetails;
|
|||||||
use crate::renderer::Renderer;
|
use crate::renderer::Renderer;
|
||||||
use crate::ui::*;
|
use crate::ui::*;
|
||||||
|
|
||||||
use std::rc::Rc;
|
|
||||||
use sdl2::pixels::Color;
|
use sdl2::pixels::Color;
|
||||||
use sdl2::rect::{Rect, Point};
|
use sdl2::rect::{Point, Rect};
|
||||||
use sdl2::render::Texture;
|
use sdl2::render::Texture;
|
||||||
use sdl2::ttf::Font;
|
use sdl2::ttf::Font;
|
||||||
|
use std::rc::Rc;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TextCharacter {
|
pub struct TextCharacter {
|
||||||
@ -21,11 +21,17 @@ pub struct TextCharacter {
|
|||||||
source: Rect,
|
source: Rect,
|
||||||
dest: Rect,
|
dest: Rect,
|
||||||
color: Color,
|
color: Color,
|
||||||
config: Rc<Config>
|
config: Rc<Config>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TextCharacter {
|
impl TextCharacter {
|
||||||
pub fn new(text_character: char, position: usize, line: usize, color: Color, config: Rc<Config>) -> Self {
|
pub fn new(
|
||||||
|
text_character: char,
|
||||||
|
position: usize,
|
||||||
|
line: usize,
|
||||||
|
color: Color,
|
||||||
|
config: Rc<Config>,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
pending: true,
|
pending: true,
|
||||||
text_character,
|
text_character,
|
||||||
@ -34,7 +40,7 @@ impl TextCharacter {
|
|||||||
source: Rect::new(0, 0, 0, 0),
|
source: Rect::new(0, 0, 0, 0),
|
||||||
dest: Rect::new(0, 0, 0, 0),
|
dest: Rect::new(0, 0, 0, 0),
|
||||||
color,
|
color,
|
||||||
config
|
config,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,10 +154,7 @@ impl Update for TextCharacter {
|
|||||||
|
|
||||||
impl ClickHandler for TextCharacter {
|
impl ClickHandler for TextCharacter {
|
||||||
fn on_left_click(&mut self, _point: &Point) -> UpdateResult {
|
fn on_left_click(&mut self, _point: &Point) -> UpdateResult {
|
||||||
UpdateResult::MoveCaret(
|
UpdateResult::MoveCaret(self.dest().clone(), self.position())
|
||||||
self.dest().clone(),
|
|
||||||
self.position()
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_left_click_target(&self, point: &Point) -> bool {
|
fn is_left_click_target(&self, point: &Point) -> bool {
|
||||||
|
Loading…
Reference in New Issue
Block a user