From cde80eccad1a091559006cd6f7ac526145c18496 Mon Sep 17 00:00:00 2001 From: rhpidfyre Date: Fri, 31 Jan 2025 03:08:00 -0500 Subject: [PATCH] history tweaks and begin working on up and down arrows --- src/commands.rs | 4 ++-- src/history.rs | 20 +++++++++----------- src/session.rs | 9 +++++---- src/terminal.rs | 44 ++++++++++++++++++++++++++------------------ src/vm/shell.rs | 9 ++------- 5 files changed, 44 insertions(+), 42 deletions(-) diff --git a/src/commands.rs b/src/commands.rs index 265fbaa..25cb2a8 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -96,10 +96,10 @@ impl Command for Pse { if let Some(command) = args.next() { match command { "cd" => if ChangeDirectory(None).change_directory(args).is_some() { - self.history.add(self.rt.input.literal.as_str()) + self.rt.history.add(self.rt.input.literal.as_str()) }, command => if let Ok(mut child) = process::Command::new(command).args(args).spawn() { - self.history.add(self.rt.input.literal.as_str()); + self.rt.history.add(self.rt.input.literal.as_str()); child.wait().ok(); } else { println!("pse: Unknown command: {}", self.rt.input.literal) diff --git a/src/history.rs b/src/history.rs index 2065c23..b6f0ac1 100644 --- a/src/history.rs +++ b/src/history.rs @@ -4,38 +4,36 @@ use crate::{rc::{self}, session::{self, MapDisplay}, valid_pbuf::IsValid}; #[derive(Debug, Clone)] pub struct History { - fs_history: Option>, - history: Vec, + pub history: Vec, + pub index: isize, file: Option, } impl History { pub fn init() -> Self { + let mut history = Vec::new(); let file = rc::config_dir().map(|mut config_dir| { config_dir.push(".history"); config_dir.is_valid_file_or_create(b""); config_dir }); - let fs_history = file.as_ref().and_then(|file| { + file.as_ref().and_then(|file| { File::open(file).map_or_display_none(|file| { Some(BufReader::new(file).lines().map_while(Result::ok).collect::>()) }) - }); - Self { - history: Vec::new(), - fs_history, - file, - } + }).inspect(|fs_history_vec| history = fs_history_vec.clone()); + + Self { history, file, index: -1 } } pub fn write_to_file_fallible(&mut self) { if self.history.is_empty() { return; } - if let (Some(history_file), Some(fs_history)) = (&self.file, &self.fs_history) { + if let Some(history_file) = &self.file { OpenOptions::new() .append(true) .open(history_file.as_path()) .map_or_display(|mut file| { - let newline_maybe = if fs_history.is_empty() { "" } else { "\n" }; + let newline_maybe = if self.history.is_empty() { "" } else { "\n" }; let formatted = format!("{newline_maybe}{}", self.history.join("\n")); file.write_all(formatted.as_bytes()).unwrap_or_else(session::shell_error) }); diff --git a/src/session.rs b/src/session.rs index 0045a36..ebd572d 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1,5 +1,5 @@ use mlua::Lua as Luau; -use std::{cell::RefCell, fs, rc::Rc, usize}; +use std::{cell::RefCell, fs, rc::Rc}; use core::fmt; use crate::{ @@ -50,10 +50,10 @@ pub struct Rt { pub input: Input, pub ps: Rc>, pub vm: Luau, + pub history: History, } pub struct Pse { pub config: Config, - pub history: History, pub rt: Rt } impl Pse { @@ -63,13 +63,14 @@ impl Pse { let rt = Rt { ps: Rc::new(RefCell::new(Self::DEFAULT_PS.to_owned())), vm: Luau::new(), + history: History::init(), input: Input { literal: String::new(), cursor: usize::MIN, }, }; - Self { rt, config, history: History::init() } + Self { rt, config } } pub fn start(&mut self) { @@ -78,6 +79,6 @@ impl Pse { fs::read_to_string(conf_file).map_or_display(|luau_conf| self.vm_exec(luau_conf)); } }; - self.term_input_processor().map_or_display(|()| self.history.write_to_file_fallible()) + self.term_input_processor().map_or_display(|()| self.rt.history.write_to_file_fallible()) } } diff --git a/src/terminal.rs b/src/terminal.rs index c7277bd..3530e5f 100644 --- a/src/terminal.rs +++ b/src/terminal.rs @@ -1,6 +1,6 @@ use crossterm::{cursor, event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, execute, terminal}; use core::fmt; -use std::io::{self, Write}; +use std::{io::{self, Write}, mem}; use thiserror::Error; use crate::{commands::Command, session::{self, Pse}}; @@ -40,6 +40,8 @@ trait SpecificKeybinds { fn key_backspace(&mut self) -> InputResult<()>; fn key_arrow_right(&mut self) -> InputResult<()>; fn key_arrow_left(&mut self) -> InputResult<()>; + fn key_arrow_up(&mut self) -> InputResult<()>; + fn key_arrow_down(&mut self) -> InputResult<()>; } impl SpecificKeybinds for Pse { const EXIT_1: &str = "exit"; @@ -81,10 +83,8 @@ impl SpecificKeybinds for Pse { terminal::Clear(terminal::ClearType::UntilNewLine) ).map_err(InputHandleError::Flush)?; self.rt.input.cursor-=1; - Ok(()) - } else { - Ok(()) } + Ok(()) } fn key_arrow_right(&mut self) -> InputResult<()> { @@ -100,6 +100,18 @@ impl SpecificKeybinds for Pse { None => Ok(()) } } + + fn key_arrow_up(&mut self) -> InputResult<()> { + if self.rt.input.literal.is_empty() { + self.rt.history.index += 1; + // if self.rt.history_index == self.history.fs_history + } + Ok(()) + } + + fn key_arrow_down(&mut self) -> InputResult<()> { + unimplemented!() + } } pub trait TermInputCursor { @@ -110,10 +122,7 @@ impl TermInputCursor for Pse { fn term_input_cursor_move_left(&mut self) -> Option<()> { if self.rt.input.cursor == usize::MIN { None } else { match self.rt.input.cursor>usize::MIN { - true => { - self.rt.input.cursor-=1; - Some(()) - }, + true => { self.rt.input.cursor-=1; Some(()) } false => None } } @@ -122,10 +131,7 @@ impl TermInputCursor for Pse { fn term_input_cursor_move_right(&mut self) -> Option<()> { if self.rt.input.cursor == usize::MAX { None } else { match self.rt.input.cursor { - self.rt.input.cursor+=1; - Some(()) - }, + true => { self.rt.input.cursor+=1; Some(()) }, false => None } } @@ -140,13 +146,15 @@ pub trait TermProcessor { fn term_input_processor(&mut self) -> io::Result<()>; } impl TermProcessor for Pse { - fn term_render(&mut self, def_string: String) -> InputResult<()> { - self.rt.input.literal.insert_str(self.rt.input.cursor, &def_string); + fn term_render(&mut self, text: String) -> InputResult<()> { + self.rt.input.literal.insert_str(self.rt.input.cursor, &text); self.rt.input.cursor+=1; if self.rt.input.cursor != self.rt.input.literal.chars().count() { - + execute!(io::stdout(), terminal::Clear(terminal::ClearType::UntilNewLine)).map_err(InputHandleError::Flush)?; + let slice = &self.rt.input.literal[self.rt.input.cursor..]; + write!(io::stdout(), "{text}{slice}").map_err(InputHandleError::Write)?; } else { - write!(io::stdout(), "{}", def_string).map_err(InputHandleError::Write)?; + write!(io::stdout(), "{text}").map_err(InputHandleError::Write)?; } io::stdout().flush().map_err(InputHandleError::Flush) } @@ -163,8 +171,8 @@ impl TermProcessor for Pse { KeyCode::Tab => todo!(), KeyCode::Right => self.key_arrow_right(), KeyCode::Left => self.key_arrow_left(), - KeyCode::Up => todo!(), - KeyCode::Down => todo!(), + KeyCode::Up => self.key_arrow_up(), + KeyCode::Down => self.key_arrow_down(), keycode => self.key_ctrl(input_key, keycode) }; input_handle.map_or_else(|inp_err| match inp_err { diff --git a/src/vm/shell.rs b/src/vm/shell.rs index fc6ff82..8c8f9a8 100644 --- a/src/vm/shell.rs +++ b/src/vm/shell.rs @@ -29,13 +29,8 @@ impl UserData for Shell { fn add_methods>(methods: &mut M) { methods.add_meta_method_mut(MetaMethod::NewIndex, |_, this, (t_index, t_value): (String, String)| -> lResult<()> { if t_index == "PROMPT" { - match t_value.len() as u16 >= u16::MAX { - true => { mlua::Error::runtime(format!("SHELL.PROMPT's length exceeded or equals the max size. ({})", u16::MAX)); }, - false => { - let mut prompt = this.0.borrow_mut(); - *prompt = t_value; - }, - } + let mut prompt = this.0.borrow_mut(); + *prompt = t_value; } Ok(()) });