From cb4a43d00c7fdcf789478169c3559d8dd4bfd267 Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Sun, 26 Feb 2023 00:29:29 +0100 Subject: [PATCH] basic navigation & character insert --- .gitignore | 2 + Cargo.lock | 58 +++++++++++++++++++++ Cargo.toml | 9 ++++ src/editor.rs | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 6 +++ 5 files changed, 217 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/editor.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e49dec6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +err diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..e53dcd8 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,58 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "libc" +version = "0.2.139" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "201de327520df007757c1f0adce6e827fe8562fbc28bfd9c15571c66ca1f5f79" + +[[package]] +name = "lili" +version = "0.1.0" +dependencies = [ + "termion", +] + +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" + +[[package]] +name = "redox_syscall" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_termios" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8440d8acb4fd3d277125b4bd01a6f38aee8d814b3b5fc09b3f2b825d37d3fe8f" +dependencies = [ + "redox_syscall", +] + +[[package]] +name = "termion" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "659c1f379f3408c7e5e84c7d0da6d93404e3800b6b9d063ba24436419302ec90" +dependencies = [ + "libc", + "numtoa", + "redox_syscall", + "redox_termios", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b76decc --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "lili" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +termion = "2.0.1" diff --git a/src/editor.rs b/src/editor.rs new file mode 100644 index 0000000..4a28ff6 --- /dev/null +++ b/src/editor.rs @@ -0,0 +1,142 @@ +use std::{ + io::{stdin, stdout, Write}, + ops::Range, +}; +use termion::{ + clear, cursor, + event::{Event, Key}, + input::TermRead, + raw::IntoRawMode, +}; + +pub struct Editor { + text: String, + lines: Vec, + cursor: Cursor, + quit: bool, +} + +struct Cursor { + line: usize, + column: usize, +} + +// #[derive(Clone, Copy)] +type Line = Range; + +impl Editor { + pub fn new() -> Self { + Editor { + // text: String::new(), + text: include_str!("editor.rs").into(), + lines: Vec::new(), + cursor: Cursor { line: 0, column: 0 }, + quit: false, + } + } + + pub fn run(mut self) { + println!("{}", clear::All); + stdout().flush().unwrap(); + let _t = stdout().into_raw_mode().unwrap(); + + while !self.quit { + self.find_lines(); + self.draw(); + self.input(); + } + println!("{}", clear::All); + stdout().flush().unwrap(); + // self.term.suspend_raw_mode().unwrap(); + } + + fn input(&mut self) { + for event in stdin().events().take(1).flatten() { + // dbg!(&event); + if let Event::Key(key) = event { + match key { + Key::Esc => self.quit = true, + Key::Char(char) => self.insert_char(char), + Key::Left => self.move_left(), + Key::Right => self.move_right(), + Key::Up => self.move_up(), + Key::Down => self.move_down(), + _ => (), + } + } + } + } + + fn move_left(&mut self) { + if self.cursor.column > 0 { + self.cursor.column -= 1; + } else if self.cursor.line > 0 { + self.cursor.line -= 1; + self.cursor.column = self.current_line().len(); + } + } + + fn move_right(&mut self) { + if self.cursor.column < self.current_line().len() { + self.cursor.column += 1; + } else if self.cursor.line < self.lines.len() { + self.cursor.line += 1; + self.cursor.column = 0; + } + } + + fn move_up(&mut self) { + if self.cursor.line > 0 { + self.cursor.line -= 1; + self.cursor.column = self.cursor.column.min(self.current_line().len()); + } + } + + fn move_down(&mut self) { + if self.cursor.line < self.lines.len() { + self.cursor.line += 1; + self.cursor.column = self.cursor.column.min(self.current_line().len()); + } + } + + fn current_line(&self) -> &Line { + self.lines.get(self.cursor.line).unwrap_or(&(0..0)) + } + + fn find_lines(&mut self) { + self.lines.clear(); + let mut this_line = 0..0; + for (index, char) in self.text.chars().enumerate() { + if char == '\n' { + this_line.end = index; + self.lines.push(this_line.clone()); + this_line.start = index + 1; + } + } + } + + fn draw(&self) { + print!("{}", clear::All); + + for (row, line) in self.lines.iter().enumerate() { + let text = &self.text[line.clone()]; + print!( + "{}{}", + cursor::Goto(1, row as u16 + 1), + text.replace('\t', " ") + ); + } + print!( + "{}", + cursor::Goto(self.cursor.column as u16 + 1, self.cursor.line as u16 + 1) + ); + stdout().flush().unwrap(); + } + + fn insert_char(&mut self, ch: char) { + let index = self.current_line().start + self.cursor.column; + self.text.insert(index, ch); + self.move_right(); + self.find_lines(); + } +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..bf43878 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,6 @@ +mod editor; +use editor::Editor; + +fn main() { + Editor::new().run(); +}