refactor mega-commit.
- reorganised the entire project so that the entire kernel is a single codebase rather than a kernel and a libk.
This commit is contained in:
@@ -0,0 +1,240 @@
|
||||
use crate::serial_print;
|
||||
use crate::arch::x86_64::drivers::keyboard::{KeyStroke, get_keystroke_async};
|
||||
use crate::prelude::*;
|
||||
use crate::resources::font::Font;
|
||||
use crate::std::application::frame::Frame;
|
||||
use crate::std::application::render::RenderError;
|
||||
use crate::std::application::window::Window;
|
||||
use crate::std::application::{Application, Error};
|
||||
use crate::std::ascii::Writer;
|
||||
use crate::std::maths::geometry::Vec2;
|
||||
use alloc::string::{String, ToString};
|
||||
use alloc::vec::Vec;
|
||||
use crate::serial_println;
|
||||
|
||||
pub struct Editor {
|
||||
cursor_line: usize,
|
||||
cursor_col: usize,
|
||||
|
||||
mode: Mode,
|
||||
buffer: String,
|
||||
window: Window,
|
||||
}
|
||||
|
||||
impl Default for Editor {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Editor {
|
||||
const PADDING: usize = 8;
|
||||
|
||||
pub const fn new() -> Self {
|
||||
Self {
|
||||
cursor_line: 0,
|
||||
cursor_col: 0,
|
||||
|
||||
mode: Mode::Nor,
|
||||
buffer: String::new(),
|
||||
window: Window::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn render(&'a self) -> Result<Frame<'a>, RenderError> {
|
||||
let mut frame = Frame::new(&self.window);
|
||||
let writer = Writer::new(Font::default());
|
||||
|
||||
let (width, height) = writer.font_size().into();
|
||||
|
||||
let mut col = 0;
|
||||
let mut line = 0;
|
||||
let mut scale = 1;
|
||||
|
||||
for ch in self.buffer.chars() {
|
||||
if ch == '\n' {
|
||||
line += scale;
|
||||
col = 0;
|
||||
scale = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if width * (col + 1) > frame.dimensions().x() - 2 * Self::PADDING {
|
||||
line += scale;
|
||||
col = 0;
|
||||
}
|
||||
|
||||
writer.render_glyph(
|
||||
&mut frame,
|
||||
Vec2::new(col * width + Self::PADDING, line * height + Self::PADDING),
|
||||
ch as u8,
|
||||
scale,
|
||||
)?;
|
||||
col += scale;
|
||||
}
|
||||
|
||||
writer
|
||||
.render_glyph(
|
||||
&mut frame,
|
||||
Vec2::new(
|
||||
self.cursor_col * width + Self::PADDING,
|
||||
self.cursor_line * height + Self::PADDING,
|
||||
),
|
||||
b'_',
|
||||
scale,
|
||||
)
|
||||
.expect("TODO: panic message");
|
||||
|
||||
Ok(frame)
|
||||
}
|
||||
|
||||
#[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)]
|
||||
fn get_lines(&self) -> Vec<&str> {
|
||||
self.buffer.split('\n').collect::<Vec<&str>>()
|
||||
}
|
||||
|
||||
#[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)]
|
||||
fn move_cursor(&mut self, x: i32, y: i32) {
|
||||
self.cursor_line = self
|
||||
.cursor_line
|
||||
.checked_add_signed(y as isize)
|
||||
.unwrap_or(self.cursor_line);
|
||||
self.cursor_col = self
|
||||
.cursor_col
|
||||
.checked_add_signed(x as isize)
|
||||
.unwrap_or(self.cursor_col);
|
||||
}
|
||||
|
||||
#[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)]
|
||||
fn delete_char(&mut self) {
|
||||
let i = self.get_char_idx();
|
||||
self.buffer.remove(i);
|
||||
}
|
||||
|
||||
#[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)]
|
||||
fn insert_char(&mut self, c: char) {
|
||||
let i = self.get_char_idx();
|
||||
self.buffer.insert(i, c);
|
||||
}
|
||||
|
||||
#[allow(unused_variables, dead_code, clippy::needless_pass_by_ref_mut)]
|
||||
fn splitline(&mut self) {
|
||||
let i = self.get_char_idx();
|
||||
self.buffer.insert(i, '\n');
|
||||
}
|
||||
|
||||
fn get_char_idx(&self) -> usize {
|
||||
let frame = Frame::new(&self.window);
|
||||
let writer = Writer::new(Font::default());
|
||||
let (width, _height) = writer.font_size().into();
|
||||
|
||||
let mut col = 0;
|
||||
let mut line = 0;
|
||||
let mut scale = 1;
|
||||
|
||||
for (i, ch) in self.buffer.chars().enumerate() {
|
||||
if ch == '\n' {
|
||||
line += scale;
|
||||
col = 0;
|
||||
scale = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if width * (col + 1) > frame.dimensions().x() - 2 * Self::PADDING {
|
||||
line += scale;
|
||||
col = 0;
|
||||
}
|
||||
|
||||
if col == self.cursor_col && line == self.cursor_line {
|
||||
return i;
|
||||
}
|
||||
|
||||
col += scale;
|
||||
}
|
||||
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
impl Application for Editor {
|
||||
type Output = ();
|
||||
async fn run(&mut self, _args: Vec<alloc::string::String>) -> Result<Self::Output, Error> {
|
||||
self.window.set_dimensions(Vec2::new(1280, 800));
|
||||
self.window.set_position(Vec2::new(0, 0));
|
||||
self.window.open();
|
||||
|
||||
self.buffer = "Hello world, this is a test init. idk test \n ewntuiewi gjk gfdfg gndf ngdfgnmdfg ndfgmndfg gdfndfnkg njkdgjkndfjnkg ngnjfgnfgnfg fgn fn gfj gnfg jnfgjfngjk fgnjfgnjk jnkdgjnkdfg gfnd njkgdfgjn d fjnkgjkndfgjkndfgjn gndfjnk njkgdfng jnkfgdjknd jnfkgnjk".to_string();
|
||||
|
||||
loop {
|
||||
if let Err(_err) = self.render().and_then(|frame| frame.render()) {
|
||||
// TODO: Handle error
|
||||
return Err(Error::ApplicationFailed("Rendering failed".to_string()));
|
||||
}
|
||||
|
||||
let keystroke = get_keystroke_async().await;
|
||||
|
||||
match self.mode {
|
||||
Mode::Nor => match keystroke {
|
||||
KeyStroke::Char('i') => self.mode = Mode::Ins,
|
||||
KeyStroke::Char('`') => return Ok(()),
|
||||
_ => {}
|
||||
},
|
||||
Mode::Ins => {
|
||||
match keystroke {
|
||||
KeyStroke::Char(c) => {
|
||||
match c {
|
||||
// escape
|
||||
'\x1B' => self.mode = Mode::Nor,
|
||||
// delete
|
||||
'\x7F' => self.delete_char(),
|
||||
// backspace
|
||||
'\x08' => {
|
||||
self.move_cursor(-1, 0);
|
||||
self.delete_char();
|
||||
}
|
||||
// enter
|
||||
'\n' => self.splitline(),
|
||||
_ => {
|
||||
self.insert_char(c);
|
||||
self.move_cursor(1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
KeyStroke::Left => {
|
||||
serial_println!("Left\n");
|
||||
self.move_cursor(-1, 0);
|
||||
}
|
||||
KeyStroke::Right => {
|
||||
serial_println!("Right\n");
|
||||
self.move_cursor(1, 0);
|
||||
}
|
||||
KeyStroke::Up => {
|
||||
serial_println!("Up\n");
|
||||
self.move_cursor(0, -1);
|
||||
}
|
||||
KeyStroke::Down => {
|
||||
serial_println!("Down\n");
|
||||
self.move_cursor(0, 1);
|
||||
}
|
||||
KeyStroke::None => {}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub enum Mode {
|
||||
Nor,
|
||||
Ins,
|
||||
}
|
||||
|
||||
impl core::fmt::Display for Mode {
|
||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||
match self {
|
||||
Self::Nor => write!(f, "Normal"),
|
||||
Self::Ins => write!(f, "Insert"),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod editor;
|
||||
pub mod shell;
|
||||
@@ -0,0 +1,49 @@
|
||||
// use x86_64::registers::rflags::read;
|
||||
|
||||
use crate::arch::x86_64::drivers::ascii::clear_screen;
|
||||
use crate::prelude::*;
|
||||
use crate::std::application::Application;
|
||||
use crate::std::io::stdin::read_line;
|
||||
use crate::util::editor::Editor;
|
||||
use alloc::vec::Vec;
|
||||
|
||||
static FETCH: &str = "
|
||||
$$$$$$$$\\ $$\\
|
||||
$$ _____| $$ |
|
||||
$$ | $$$$$$\\ $$\\ $$\\ $$$$$$$\\ $$$$$$$ | $$$$$$\\ $$\\ $$\\
|
||||
$$$$$\\ $$ __$$\\ $$ | $$ |$$ __$$\\ $$ __$$ |$$ __$$\\ $$ | $$ |
|
||||
$$ __|$$ / $$ |$$ | $$ |$$ | $$ |$$ / $$ |$$ | \\__|$$ | $$ |
|
||||
$$ | $$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ |$$ | $$ | $$ |
|
||||
$$ | \\$$$$$$ |\\$$$$$$ |$$ | $$ |\\$$$$$$$ |$$ | \\$$$$$$$ |
|
||||
\\__| \\______/ \\______/ \\__| \\__| \\_______|\\__| \\____$$ |
|
||||
$$$$$$\\ $$$$$$\\ $$\\ $$\\ $$\\ $$\\ $$ |
|
||||
$$ __$$\\ $$ __$$\\ $$ | $$ |$$$$ | \\$$$$$$ |
|
||||
$$ / $$ |$$ / \\__| $$ | $$ |\\_$$ | \\______/
|
||||
$$ | $$ |\\$$$$$$\\ \\$$\\ $$ | $$ |
|
||||
$$ | $$ | \\____$$\\ \\$$\\$$ / $$ |
|
||||
$$ | $$ |$$\\ $$ | \\$$$ / $$ |
|
||||
$$$$$$ |\\$$$$$$ | \\$ / $$$$$$\\
|
||||
\\______/ \\______/ \\_/ \\______|
|
||||
";
|
||||
|
||||
pub async fn shell() {
|
||||
println!("{}", FETCH);
|
||||
|
||||
loop {
|
||||
print!(" Shell> ");
|
||||
let line = read_line().await;
|
||||
match line.as_str() {
|
||||
"fetch" => {
|
||||
println!("{}", FETCH);
|
||||
}
|
||||
"editor" => {
|
||||
let mut editor = Editor::new();
|
||||
editor.run(Vec::new()).await.unwrap();
|
||||
}
|
||||
"clear" => clear_screen(),
|
||||
_ => {
|
||||
println!("Unknown command: {}", line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user