type-render
korin 3 years ago
parent bf803eaf75
commit b02c1deb79
  1. 39
      src/input.rs
  2. 162
      src/main.rs
  3. 120
      src/render.rs
  4. 2
      src/syntax-highlight.rs

@ -1,5 +1,6 @@
use sdl2::keyboard::Keycode;
//use sdl2::keyboard::Keycode;
/*
mod keybinds {
pub(super) enum Clipboard {
CutSelection,
@ -42,7 +43,41 @@ mod keybinds {
WholeLines,
}
}
*/
fn process_input(buffer: &str, modifiers: crate::ModifierKeys, key: Keycode) {
pub struct ModifierKeys {
pub alt: bool,
pub ctrl: bool,
pub shift: bool,
}
impl ModifierKeys {
pub fn new() -> ModifierKeys {
ModifierKeys { alt: false, ctrl: false, shift: false }
}
}
pub fn delete(buffer: &mut String, cursor_position: usize, modifiers: &ModifierKeys) {
if modifiers.ctrl {
loop {
let buffer_chars: Vec<char> = buffer.chars()
.collect();
if cursor_position == buffer.len() {
break
}
if !buffer_chars[cursor_position].is_whitespace() {
buffer.remove(cursor_position);
} else {
break
}
}
} else {
buffer.remove(cursor_position);
}
}
/*
fn process_input(buffer: &str, modifiers: ModifierKeys, key: Keycode) {
}
*/

@ -1,31 +1,25 @@
extern crate sdl2;
use clipboard::{ClipboardProvider, ClipboardContext};
use clipboard::{ClipboardContext, ClipboardProvider};
use sdl2::{
event::{Event, WindowEvent},
keyboard::Keycode,
};
mod render;
mod input;
mod file;
mod input;
mod render;
static SCREEN_WIDTH: u32 = 1280;
static SCREEN_HEIGHT: u32 = 720;
static SCREEN_WIDTH: u32 = 1280;
static SCREEN_HEIGHT: u32 = 720;
// TODO: Make this configurable
static REFRESH_RATE: u32 = 50;
static REFRESH_RATE: u32 = 50;
// TODO: Make this configurable
static UNDO_TIME: u32 = 250;
static UNDO_TIME: u32 = 250;
static UNDO_TIME_COUNT: u32 = (REFRESH_RATE as f32 * (UNDO_TIME as f32 / 1000.0)) as u32;
struct ModifierKeys {
alt: bool,
ctrl: bool,
shift: bool,
}
pub fn main() -> Result<(), String> {
// Initialize clipboard
let mut clipboard_context: ClipboardContext = ClipboardProvider::new().unwrap();
@ -53,7 +47,7 @@ pub fn main() -> Result<(), String> {
let mut undo_timer: u32 = UNDO_TIME_COUNT;
// Initialize input values
let mut modifier_keys = ModifierKeys {alt: false, ctrl: false, shift: false};
let mut modifier_keys = input::ModifierKeys::new();
let mut cursor_position = 0;
let mut selection_anchor: Option<usize> = None;
@ -82,38 +76,32 @@ pub fn main() -> Result<(), String> {
// Event::KeyDown { keycode: Some(Keycode::Escape), .. } |
Event::Quit { .. } => break 'mainloop,
Event::KeyUp { keycode, .. } => {
match keycode{
Some(Keycode::LAlt) | Some(Keycode::RAlt) => {
modifier_keys.alt = false
},
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => {
modifier_keys.ctrl = false
},
Some(Keycode::LShift) | Some(Keycode::RShift) => {
modifier_keys.shift = false
},
Some(Keycode::LGui) | Some(Keycode::RGui) => {
break
},
_ => (),
}
Event::KeyUp { keycode, .. } => match keycode {
Some(Keycode::LAlt) | Some(Keycode::RAlt) => modifier_keys.alt = false,
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => modifier_keys.ctrl = false,
Some(Keycode::LShift) | Some(Keycode::RShift) => modifier_keys.shift = false,
Some(Keycode::LGui) | Some(Keycode::RGui) => break,
_ => (),
},
Event::KeyDown { keycode, .. } => {
match keycode {
Some(Keycode::LAlt) | Some(Keycode::RAlt) => {
modifier_keys.alt = true
},
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => {
modifier_keys.ctrl = true
},
Some(Keycode::LShift) | Some(Keycode::RShift) => {
modifier_keys.shift = true
},
Some(Keycode::LGui) | Some(Keycode::RGui) => {
break
},
Some(Keycode::LAlt) | Some(Keycode::RAlt) => modifier_keys.alt = true,
Some(Keycode::LCtrl) | Some(Keycode::RCtrl) => modifier_keys.ctrl = true,
Some(Keycode::LShift) | Some(Keycode::RShift) => modifier_keys.shift = true,
Some(Keycode::LGui) | Some(Keycode::RGui) => break,
// DELETE key
Some(Keycode::Delete) => {
if buffer.len() > 0 && cursor_position < buffer.len() {
undo_timer = 0;
selection_anchor = None;
input::delete(&mut buffer, cursor_position, &modifier_keys);
draw!();
}
}
_ => (),
};
@ -121,18 +109,6 @@ pub fn main() -> Result<(), String> {
// All modifiers up
(false, false, false) => {
match keycode {
// DELETE key
Some(Keycode::Delete) => {
if buffer.len() > 0 && cursor_position < buffer.len() {
undo_timer = 0;
selection_anchor = None;
buffer.remove(cursor_position);
draw!();
}
},
// ENTER key
Some(Keycode::Return) => {
undo_timer = 0;
@ -143,7 +119,7 @@ pub fn main() -> Result<(), String> {
cursor_position += 1;
draw!();
},
}
// HOME key
Some(Keycode::Home) => {
@ -152,7 +128,7 @@ pub fn main() -> Result<(), String> {
cursor_position = 0;
draw!();
},
}
// END key
Some(Keycode::End) => {
@ -161,17 +137,17 @@ pub fn main() -> Result<(), String> {
cursor_position = buffer.len();
draw!();
},
}
// Left/Back arrow
Some(Keycode::Left) => {
selection_anchor = None;
cursor_position = usize::checked_sub(cursor_position, 1)
.unwrap_or(0);
cursor_position =
usize::checked_sub(cursor_position, 1).unwrap_or(0);
draw!();
},
}
// Right/Forward arrow
Some(Keycode::Right) => {
@ -180,7 +156,7 @@ pub fn main() -> Result<(), String> {
cursor_position = (cursor_position + 1).min(buffer.len());
draw!();
},
}
// BACKSPACE key
// Character backspace
@ -194,11 +170,11 @@ pub fn main() -> Result<(), String> {
draw!();
}
},
}
_ => (),
}
},
}
// CTRL down
(false, true, false) => {
@ -209,7 +185,7 @@ pub fn main() -> Result<(), String> {
cursor_position = 0;
draw!()
},
}
// Undo
Some(Keycode::Z) => {
@ -221,7 +197,7 @@ pub fn main() -> Result<(), String> {
draw!()
}
},
}
// TODO: Cut
Some(Keycode::X) => println!("Cut"),
@ -230,7 +206,7 @@ pub fn main() -> Result<(), String> {
// TODO: Use selection
Some(Keycode::C) => {
clipboard_context.set_contents(buffer.clone()).unwrap()
},
}
// Paste
Some(Keycode::V) => {
@ -242,7 +218,7 @@ pub fn main() -> Result<(), String> {
undo_timer = UNDO_TIME_COUNT;
}
draw!()
},
}
// BACKSPACE key
// Word backspace
@ -252,48 +228,46 @@ pub fn main() -> Result<(), String> {
undo_timer = 0;
selection_anchor = None;
let buffer_chars: Vec<char> = buffer.chars()
.collect();
while !(buffer_chars[cursor_position - 1] == ' ' ||
buffer_chars[cursor_position - 1] == '\n') &&
cursor_position > 1 {
buffer.remove(cursor_position - 1);
cursor_position -= 1;
}
let buffer_chars: Vec<char> = buffer.chars().collect();
while !(buffer_chars[cursor_position - 1] == ' '
|| buffer_chars[cursor_position - 1] == '\n')
&& cursor_position > 1
{
buffer.remove(cursor_position - 1);
cursor_position -= 1;
}
buffer.remove(cursor_position - 1);
cursor_position -= 1;
draw!()
}
},
}
_ => (),
}
},
}
// SHIFT + CTRL down
(true, true, false) => {
match keycode {
Some(Keycode::Z) => {
if undo_position < undo_history.len() {
undo_position += 1;
let last_redo = undo_history[undo_position - 1].clone();
buffer = last_redo.0;
cursor_position = last_redo.1;
(true, true, false) => match keycode {
Some(Keycode::Z) => {
if undo_position < undo_history.len() {
undo_position += 1;
let last_redo = undo_history[undo_position - 1].clone();
buffer = last_redo.0;
cursor_position = last_redo.1;
draw!();
}
},
draw!();
}
}
Some(Keycode::X) => println!("Cut line(s)"),
Some(Keycode::X) => println!("Cut line(s)"),
Some(Keycode::C) => println!("Copy line(s)"),
_ => (),
}
Some(Keycode::C) => println!("Copy line(s)"),
_ => (),
},
_ => (),
}
},
}
// Process user input
Event::TextInput { text, .. } => {
@ -305,7 +279,7 @@ pub fn main() -> Result<(), String> {
cursor_position += 1;
draw!();
},
}
_ => {}
}

@ -16,7 +16,7 @@ use crate::file;
type Glyph = Vec<Point>;
struct GlyphMetrics {
width: usize,
width: usize,
height: usize,
}
@ -64,20 +64,20 @@ enum Colors {
impl Colors {
fn color(&self) -> ColorRGB {
match self {
Colors::Background => ColorRGB::new( 32, 32, 32),
Colors::Foreground => ColorRGB::new(255, 255, 255),
Colors::Error => ColorRGB::new(255, 0, 0),
Colors::Warning => ColorRGB::new(255, 170, 0),
Colors::FindBg => ColorRGB::new(246, 185, 63),
Colors::StdFunction => ColorRGB::new(170, 255, 255),
Colors::Comment => ColorRGB::new( 0, 255, 0),
Colors::Keyword => ColorRGB::new( 0, 170, 255),
Colors::Number => ColorRGB::new( 85, 255, 255),
Colors::Operator => ColorRGB::new(255, 85, 0),
Colors::Preprocessor => ColorRGB::new(127, 0, 0),
Colors::SelectionBg => ColorRGB::new(110, 161, 241),
Colors::SelectionFg => ColorRGB::new(255, 255, 255),
Colors::String => ColorRGB::new(255, 85, 255),
Colors::Background => ColorRGB::new(32, 32, 32),
Colors::Foreground => ColorRGB::new(255, 255, 255),
Colors::Error => ColorRGB::new(255, 0, 0),
Colors::Warning => ColorRGB::new(255, 170, 0),
Colors::FindBg => ColorRGB::new(246, 185, 63),
Colors::StdFunction => ColorRGB::new(170, 255, 255),
Colors::Comment => ColorRGB::new(0, 255, 0),
Colors::Keyword => ColorRGB::new(0, 170, 255),
Colors::Number => ColorRGB::new(85, 255, 255),
Colors::Operator => ColorRGB::new(255, 85, 0),
Colors::Preprocessor => ColorRGB::new(127, 0, 0),
Colors::SelectionBg => ColorRGB::new(110, 161, 241),
Colors::SelectionFg => ColorRGB::new(255, 255, 255),
Colors::String => ColorRGB::new(255, 85, 255),
}
}
}
@ -89,17 +89,20 @@ pub fn generate_glyph_data() -> Result<GlyphAtlas, String> {
let contents = file::read_file(file_path)?;
// Get glyph metrics
let glyph_metrics = GlyphMetrics { width: 8, height: 16 };
let glyph_width = glyph_metrics.width;
let glyph_metrics = GlyphMetrics {
width: 8,
height: 16,
};
let glyph_width = glyph_metrics.width;
// Get width of image for proper positioning of pixels
let width_left_byte = contents[0];
let width_left_byte = contents[0];
let width_right_byte = contents[1];
let width_bytes = [width_left_byte, width_right_byte];
let width = u16::from_be_bytes(width_bytes);
println!("Left Byte: {width_left_byte}, Right Byte: {width_right_byte}, Byte Pair: {width}");
let pruned_glyph_table = &contents[width as usize + 2 ..];
let pruned_glyph_table = &contents[width as usize + 2..];
// Generate the glyph atlas
let mut glyph_atlas: Vec<Glyph> = vec![];
@ -121,15 +124,23 @@ pub fn generate_glyph_data() -> Result<GlyphAtlas, String> {
}
glyph_atlas.push(new_glyph);
}
Ok(GlyphAtlas { glyphs: glyph_atlas, metrics: glyph_metrics })
Ok(GlyphAtlas {
glyphs: glyph_atlas,
metrics: glyph_metrics,
})
}
/// Method for generating points to render, using given string
fn draw_text(glyph_atlas: &GlyphAtlas, content: &str, offset: Point) -> Vec<Point> {
fn draw_text(
glyph_atlas: &GlyphAtlas,
window_size: (u32, u32),
content: &str,
offset: Point,
) -> Vec<Point> {
let mut points: Vec<Point> = vec![];
let glyph_width = glyph_atlas.metrics.width;
let glyph_height = glyph_atlas.metrics.height;
let glyph_width = glyph_atlas.metrics.width;
let glyph_height = glyph_atlas.metrics.height;
let content_lines = content.split('\n');
for (y, line) in content_lines.enumerate() {
@ -147,20 +158,30 @@ fn draw_text(glyph_atlas: &GlyphAtlas, content: &str, offset: Point) -> Vec<Poin
let positioned_pixel = Point::new(
pixel.x + x_glyph as i32 + offset.x,
pixel.y + y_glyph as i32 + offset.y
pixel.y + y_glyph as i32 + offset.y,
);
points.push(positioned_pixel);
}
// TODO: Limit X drawing
if x >= (window_size.0 as usize / glyph_width) - 3 {
break;
}
}
if y >= (window_size.1 as usize / glyph_height) - 3 {
break;
}
// TODO: Limit Y drawing
}
points
}
pub fn draw_cursor(glyph_atlas: &GlyphAtlas, mut cursor_position: usize, content: &str, offset: Point) -> (Point, Point) {
let glyph_width = glyph_atlas.metrics.width;
let glyph_height = glyph_atlas.metrics.height;
pub fn draw_cursor(
glyph_atlas: &GlyphAtlas,
mut cursor_position: usize,
content: &str,
offset: Point,
) -> (Point, Point) {
let glyph_width = glyph_atlas.metrics.width;
let glyph_height = glyph_atlas.metrics.height;
let mut x = 0;
let mut y = 0;
@ -173,24 +194,28 @@ pub fn draw_cursor(glyph_atlas: &GlyphAtlas, mut cursor_position: usize, content
y += 1;
}
if idx == cursor_position {
let point_a = Point::new((x * glyph_width) as i32 + offset.x,
(y * glyph_height) as i32 + offset.y
);
let point_b = Point::new(point_a.x,
point_a.y + glyph_height as i32
let point_a = Point::new(
(x * glyph_width) as i32 + offset.x,
(y * glyph_height) as i32 + offset.y,
);
return (point_a, point_b)
let point_b = Point::new(point_a.x, point_a.y + glyph_height as i32);
return (point_a, point_b);
}
}
}
(Point::new(offset.x, offset.y), Point::new(offset.x, offset.y + glyph_height as i32))
(
Point::new(offset.x, offset.y),
Point::new(offset.x, offset.y + glyph_height as i32),
)
}
/// Draw all contents to the window
pub fn draw_everything(canvas: &mut Canvas<Window>,
glyph_atlas: &GlyphAtlas,
buffer: &str,
cursor_position: usize) -> Result<(), String> {
pub fn draw_everything(
canvas: &mut Canvas<Window>,
glyph_atlas: &GlyphAtlas,
buffer: &str,
cursor_position: usize,
) -> Result<(), String> {
// Quick initialization
let window_size = canvas.output_size()?;
let text_offset = Point::new(10, 10);
@ -204,25 +229,26 @@ pub fn draw_everything(canvas: &mut Canvas<Window>,
// Draw text
canvas.set_draw_color(Color::RGB(fg_color.red, fg_color.green, fg_color.blue));
let fb_text = draw_text(&glyph_atlas, buffer, text_offset);
let fb_text = draw_text(&glyph_atlas, window_size, buffer, text_offset);
canvas.draw_points(&fb_text[..])?;
// Draw info
let status = buffer.len().to_formatted_string(&Locale::en);
let status_position = Point::new(
text_offset.x,
window_size.1 as i32 - glyph_atlas.metrics.height as i32 * 2
window_size.1 as i32 - glyph_atlas.metrics.height as i32 * 2,
);
canvas.set_draw_color(Color::RGB(16, 64, 64));
canvas.fill_rect(Rect::new(0,
status_position.y - 5,
window_size.0,
glyph_atlas.metrics.height as u32 + 10
canvas.fill_rect(Rect::new(
0,
status_position.y - 5,
window_size.0,
glyph_atlas.metrics.height as u32 + 10,
))?;
canvas.set_draw_color(Color::RGB(127, 240, 240));
let status_bar = draw_text(&glyph_atlas, &status, status_position);
let status_bar = draw_text(&glyph_atlas, window_size, &status, status_position);
canvas.draw_points(&status_bar[..])?;
// Draw cursor

@ -1,3 +1,4 @@
/*
pub enum Token {
ILLEGAL,
EOF,
@ -25,6 +26,7 @@ pub enum Token {
LT(char),
GT(char)
}
*/
fn find_keyword(input: &str) {
match input {

Loading…
Cancel
Save