Extract several components into crates
This commit is contained in:
parent
61127339bc
commit
4a62372fd3
|
@ -1,12 +1,14 @@
|
||||||
|
mod state;
|
||||||
|
mod types;
|
||||||
|
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{self, KeyCode, KeyEvent, KeyModifiers},
|
event::{self, KeyCode, KeyEvent, KeyModifiers},
|
||||||
terminal::{disable_raw_mode, enable_raw_mode},
|
terminal::{disable_raw_mode, enable_raw_mode},
|
||||||
};
|
};
|
||||||
|
use state::AppState;
|
||||||
use std::{
|
use std::{
|
||||||
env,
|
env,
|
||||||
fs::File,
|
io,
|
||||||
io::{self, BufRead, BufReader, Read},
|
|
||||||
path::PathBuf,
|
|
||||||
sync::mpsc,
|
sync::mpsc,
|
||||||
thread,
|
thread,
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
|
@ -23,112 +25,6 @@ const TITLE: &str = "Text Editor Challenge";
|
||||||
const COPYRIGHT: &str = "(c) Savanni D'Gerinel - all rights reserved";
|
const COPYRIGHT: &str = "(c) Savanni D'Gerinel - all rights reserved";
|
||||||
const TICK_RATE_MS: u64 = 200;
|
const TICK_RATE_MS: u64 = 200;
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct Document {
|
|
||||||
rows: Vec<String>
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Document {
|
|
||||||
fn contents(&self) -> String {
|
|
||||||
self.rows.join("\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
fn row_length(&self, idx: usize) -> usize {
|
|
||||||
self.rows[idx].len()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn row_count(&self) -> usize {
|
|
||||||
self.rows.len()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct AppState {
|
|
||||||
path: Option<PathBuf>,
|
|
||||||
cursor: Cursor,
|
|
||||||
contents: Document, // Obviously this is bad, but it's also only temporary.
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AppState {
|
|
||||||
fn open(path: PathBuf) -> Self {
|
|
||||||
let mut file = File::open(path.clone()).unwrap();
|
|
||||||
let mut reader = BufReader::new(file);
|
|
||||||
let contents = reader
|
|
||||||
.lines()
|
|
||||||
.collect::<Result<Vec<String>, std::io::Error>>()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
Self {
|
|
||||||
path: Some(path),
|
|
||||||
cursor: Default::default(),
|
|
||||||
contents: Document{ rows: contents },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_up(&mut self) {
|
|
||||||
self.cursor.cursor_up(&self.contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_down(&mut self) {
|
|
||||||
self.cursor.cursor_down(&self.contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_right(&mut self) {
|
|
||||||
self.cursor.cursor_right(&self.contents);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_left(&mut self) {
|
|
||||||
self.cursor.cursor_left();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct Cursor {
|
|
||||||
row: usize,
|
|
||||||
column: usize,
|
|
||||||
desired_column: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Cursor {
|
|
||||||
fn cursor_up(&mut self, doc: &Document) {
|
|
||||||
if self.row > 0 {
|
|
||||||
self.row -= 1;
|
|
||||||
}
|
|
||||||
self.correct_columns(doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_down(&mut self, doc: &Document) {
|
|
||||||
if self.row < doc.row_count() - 1 {
|
|
||||||
self.row += 1;
|
|
||||||
}
|
|
||||||
self.correct_columns(doc);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn correct_columns(&mut self, doc: &Document) {
|
|
||||||
let row_len = doc.row_length(self.row);
|
|
||||||
if self.desired_column < row_len {
|
|
||||||
self.column = self.desired_column;
|
|
||||||
} else {
|
|
||||||
self.column = row_len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_right(&mut self, doc: &Document) {
|
|
||||||
if self.column < doc.row_length(self.row) {
|
|
||||||
self.column += 1;
|
|
||||||
}
|
|
||||||
self.desired_column = self.column;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn cursor_left(&mut self) {
|
|
||||||
if self.column > 0 {
|
|
||||||
self.column -= 1;
|
|
||||||
}
|
|
||||||
self.desired_column = self.column;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fn render<T>(app_state: &AppState, terminal: &mut Terminal<T>) -> Result<(), anyhow::Error>
|
fn render<T>(app_state: &AppState, terminal: &mut Terminal<T>) -> Result<(), anyhow::Error>
|
||||||
where
|
where
|
||||||
T: tui::backend::Backend,
|
T: tui::backend::Backend,
|
||||||
|
@ -183,8 +79,9 @@ where
|
||||||
rect.render_widget(contents, chunks[1]);
|
rect.render_widget(contents, chunks[1]);
|
||||||
|
|
||||||
// TODO: keeping track of the index of the top row and subtract that from the cursor row.
|
// TODO: keeping track of the index of the top row and subtract that from the cursor row.
|
||||||
let row = app_state.cursor.row as u16;
|
let (row, column) = app_state.cursor.addr();
|
||||||
let column = app_state.cursor.column as u16;
|
let row = row as u16;
|
||||||
|
let column = column as u16;
|
||||||
rect.set_cursor(chunks[1].x + column, chunks[1].y + row);
|
rect.set_cursor(chunks[1].x + column, chunks[1].y + row);
|
||||||
})?;
|
})?;
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
use crate::types::{Cursor, Document};
|
||||||
|
use std::{fs::File, io::{BufRead, BufReader}, path::PathBuf};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct AppState {
|
||||||
|
pub path: Option<PathBuf>,
|
||||||
|
pub cursor: Cursor,
|
||||||
|
pub contents: Document, // Obviously this is bad, but it's also only temporary.
|
||||||
|
}
|
||||||
|
|
||||||
|
impl AppState {
|
||||||
|
pub fn open(path: PathBuf) -> Self {
|
||||||
|
let file = File::open(path.clone()).unwrap();
|
||||||
|
let reader = BufReader::new(file);
|
||||||
|
let contents = reader
|
||||||
|
.lines()
|
||||||
|
.collect::<Result<Vec<String>, std::io::Error>>()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
path: Some(path),
|
||||||
|
cursor: Default::default(),
|
||||||
|
contents: Document::new(contents),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_up(&mut self) {
|
||||||
|
self.cursor.cursor_up(&self.contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_down(&mut self) {
|
||||||
|
self.cursor.cursor_down(&self.contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_right(&mut self) {
|
||||||
|
self.cursor.cursor_right(&self.contents);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_left(&mut self) {
|
||||||
|
self.cursor.cursor_left();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,77 @@
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Document {
|
||||||
|
rows: Vec<String>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Document {
|
||||||
|
pub fn new(contents: Vec<String>) -> Self {
|
||||||
|
Self{
|
||||||
|
rows: contents
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn contents(&self) -> String {
|
||||||
|
self.rows.join("\n")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn row_length(&self, idx: usize) -> usize {
|
||||||
|
self.rows[idx].len()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn row_count(&self) -> usize {
|
||||||
|
self.rows.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct Cursor {
|
||||||
|
row: usize,
|
||||||
|
column: usize,
|
||||||
|
desired_column: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Cursor {
|
||||||
|
pub fn addr(&self) -> (usize, usize) {
|
||||||
|
(self.row, self.column)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_up(&mut self, doc: &Document) {
|
||||||
|
if self.row > 0 {
|
||||||
|
self.row -= 1;
|
||||||
|
}
|
||||||
|
self.correct_columns(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_down(&mut self, doc: &Document) {
|
||||||
|
if self.row < doc.row_count() - 1 {
|
||||||
|
self.row += 1;
|
||||||
|
}
|
||||||
|
self.correct_columns(doc);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn correct_columns(&mut self, doc: &Document) {
|
||||||
|
let row_len = doc.row_length(self.row);
|
||||||
|
if self.desired_column < row_len {
|
||||||
|
self.column = self.desired_column;
|
||||||
|
} else {
|
||||||
|
self.column = row_len;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_right(&mut self, doc: &Document) {
|
||||||
|
if self.column < doc.row_length(self.row) {
|
||||||
|
self.column += 1;
|
||||||
|
}
|
||||||
|
self.desired_column = self.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cursor_left(&mut self) {
|
||||||
|
if self.column > 0 {
|
||||||
|
self.column -= 1;
|
||||||
|
}
|
||||||
|
self.desired_column = self.column;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue