basic navigation & character insert
This commit is contained in:
commit
cb4a43d00c
5 changed files with 217 additions and 0 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
/target
|
||||||
|
err
|
58
Cargo.lock
generated
Normal file
58
Cargo.lock
generated
Normal file
|
@ -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",
|
||||||
|
]
|
9
Cargo.toml
Normal file
9
Cargo.toml
Normal file
|
@ -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"
|
142
src/editor.rs
Normal file
142
src/editor.rs
Normal file
|
@ -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<Line>,
|
||||||
|
cursor: Cursor,
|
||||||
|
quit: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Cursor {
|
||||||
|
line: usize,
|
||||||
|
column: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
// #[derive(Clone, Copy)]
|
||||||
|
type Line = Range<usize>;
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
6
src/main.rs
Normal file
6
src/main.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
mod editor;
|
||||||
|
use editor::Editor;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
Editor::new().run();
|
||||||
|
}
|
Loading…
Reference in a new issue