history tweaks and begin working on up and down arrows

This commit is contained in:
rhpidfyre 2025-01-31 03:08:00 -05:00
parent c91b486214
commit cde80eccad
5 changed files with 44 additions and 42 deletions

View File

@ -96,10 +96,10 @@ impl Command for Pse {
if let Some(command) = args.next() { if let Some(command) = args.next() {
match command { match command {
"cd" => if ChangeDirectory(None).change_directory(args).is_some() { "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() { 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(); child.wait().ok();
} else { } else {
println!("pse: Unknown command: {}", self.rt.input.literal) println!("pse: Unknown command: {}", self.rt.input.literal)

View File

@ -4,38 +4,36 @@ use crate::{rc::{self}, session::{self, MapDisplay}, valid_pbuf::IsValid};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct History { pub struct History {
fs_history: Option<Vec<String>>, pub history: Vec<String>,
history: Vec<String>, pub index: isize,
file: Option<PathBuf>, file: Option<PathBuf>,
} }
impl History { impl History {
pub fn init() -> Self { pub fn init() -> Self {
let mut history = Vec::new();
let file = rc::config_dir().map(|mut config_dir| { let file = rc::config_dir().map(|mut config_dir| {
config_dir.push(".history"); config_dir.push(".history");
config_dir.is_valid_file_or_create(b""); config_dir.is_valid_file_or_create(b"");
config_dir 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| { File::open(file).map_or_display_none(|file| {
Some(BufReader::new(file).lines().map_while(Result::ok).collect::<Vec<String>>()) Some(BufReader::new(file).lines().map_while(Result::ok).collect::<Vec<String>>())
}) })
}); }).inspect(|fs_history_vec| history = fs_history_vec.clone());
Self {
history: Vec::new(), Self { history, file, index: -1 }
fs_history,
file,
}
} }
pub fn write_to_file_fallible(&mut self) { pub fn write_to_file_fallible(&mut self) {
if self.history.is_empty() { return; } 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() OpenOptions::new()
.append(true) .append(true)
.open(history_file.as_path()) .open(history_file.as_path())
.map_or_display(|mut file| { .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")); let formatted = format!("{newline_maybe}{}", self.history.join("\n"));
file.write_all(formatted.as_bytes()).unwrap_or_else(session::shell_error) file.write_all(formatted.as_bytes()).unwrap_or_else(session::shell_error)
}); });

View File

@ -1,5 +1,5 @@
use mlua::Lua as Luau; use mlua::Lua as Luau;
use std::{cell::RefCell, fs, rc::Rc, usize}; use std::{cell::RefCell, fs, rc::Rc};
use core::fmt; use core::fmt;
use crate::{ use crate::{
@ -50,10 +50,10 @@ pub struct Rt {
pub input: Input, pub input: Input,
pub ps: Rc<RefCell<String>>, pub ps: Rc<RefCell<String>>,
pub vm: Luau, pub vm: Luau,
pub history: History,
} }
pub struct Pse { pub struct Pse {
pub config: Config, pub config: Config,
pub history: History,
pub rt: Rt pub rt: Rt
} }
impl Pse { impl Pse {
@ -63,13 +63,14 @@ impl Pse {
let rt = Rt { let rt = Rt {
ps: Rc::new(RefCell::new(Self::DEFAULT_PS.to_owned())), ps: Rc::new(RefCell::new(Self::DEFAULT_PS.to_owned())),
vm: Luau::new(), vm: Luau::new(),
history: History::init(),
input: Input { input: Input {
literal: String::new(), literal: String::new(),
cursor: usize::MIN, cursor: usize::MIN,
}, },
}; };
Self { rt, config, history: History::init() } Self { rt, config }
} }
pub fn start(&mut self) { 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)); 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())
} }
} }

View File

@ -1,6 +1,6 @@
use crossterm::{cursor, event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, execute, terminal}; use crossterm::{cursor, event::{self, Event, KeyCode, KeyEvent, KeyModifiers}, execute, terminal};
use core::fmt; use core::fmt;
use std::io::{self, Write}; use std::{io::{self, Write}, mem};
use thiserror::Error; use thiserror::Error;
use crate::{commands::Command, session::{self, Pse}}; use crate::{commands::Command, session::{self, Pse}};
@ -40,6 +40,8 @@ trait SpecificKeybinds {
fn key_backspace(&mut self) -> InputResult<()>; fn key_backspace(&mut self) -> InputResult<()>;
fn key_arrow_right(&mut self) -> InputResult<()>; fn key_arrow_right(&mut self) -> InputResult<()>;
fn key_arrow_left(&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 { impl SpecificKeybinds for Pse {
const EXIT_1: &str = "exit"; const EXIT_1: &str = "exit";
@ -81,10 +83,8 @@ impl SpecificKeybinds for Pse {
terminal::Clear(terminal::ClearType::UntilNewLine) terminal::Clear(terminal::ClearType::UntilNewLine)
).map_err(InputHandleError::Flush)?; ).map_err(InputHandleError::Flush)?;
self.rt.input.cursor-=1; self.rt.input.cursor-=1;
Ok(())
} else {
Ok(())
} }
Ok(())
} }
fn key_arrow_right(&mut self) -> InputResult<()> { fn key_arrow_right(&mut self) -> InputResult<()> {
@ -100,6 +100,18 @@ impl SpecificKeybinds for Pse {
None => Ok(()) 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 { pub trait TermInputCursor {
@ -110,10 +122,7 @@ impl TermInputCursor for Pse {
fn term_input_cursor_move_left(&mut self) -> Option<()> { fn term_input_cursor_move_left(&mut self) -> Option<()> {
if self.rt.input.cursor == usize::MIN { None } else { if self.rt.input.cursor == usize::MIN { None } else {
match self.rt.input.cursor>usize::MIN { match self.rt.input.cursor>usize::MIN {
true => { true => { self.rt.input.cursor-=1; Some(()) }
self.rt.input.cursor-=1;
Some(())
},
false => None false => None
} }
} }
@ -122,10 +131,7 @@ impl TermInputCursor for Pse {
fn term_input_cursor_move_right(&mut self) -> Option<()> { fn term_input_cursor_move_right(&mut self) -> Option<()> {
if self.rt.input.cursor == usize::MAX { None } else { if self.rt.input.cursor == usize::MAX { None } else {
match self.rt.input.cursor<self.rt.input.literal.chars().count() { match self.rt.input.cursor<self.rt.input.literal.chars().count() {
true => { true => { self.rt.input.cursor+=1; Some(()) },
self.rt.input.cursor+=1;
Some(())
},
false => None false => None
} }
} }
@ -140,13 +146,15 @@ pub trait TermProcessor {
fn term_input_processor(&mut self) -> io::Result<()>; fn term_input_processor(&mut self) -> io::Result<()>;
} }
impl TermProcessor for Pse { impl TermProcessor for Pse {
fn term_render(&mut self, def_string: String) -> InputResult<()> { fn term_render(&mut self, text: String) -> InputResult<()> {
self.rt.input.literal.insert_str(self.rt.input.cursor, &def_string); self.rt.input.literal.insert_str(self.rt.input.cursor, &text);
self.rt.input.cursor+=1; self.rt.input.cursor+=1;
if self.rt.input.cursor != self.rt.input.literal.chars().count() { 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 { } 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) io::stdout().flush().map_err(InputHandleError::Flush)
} }
@ -163,8 +171,8 @@ impl TermProcessor for Pse {
KeyCode::Tab => todo!(), KeyCode::Tab => todo!(),
KeyCode::Right => self.key_arrow_right(), KeyCode::Right => self.key_arrow_right(),
KeyCode::Left => self.key_arrow_left(), KeyCode::Left => self.key_arrow_left(),
KeyCode::Up => todo!(), KeyCode::Up => self.key_arrow_up(),
KeyCode::Down => todo!(), KeyCode::Down => self.key_arrow_down(),
keycode => self.key_ctrl(input_key, keycode) keycode => self.key_ctrl(input_key, keycode)
}; };
input_handle.map_or_else(|inp_err| match inp_err { input_handle.map_or_else(|inp_err| match inp_err {

View File

@ -29,13 +29,8 @@ impl UserData for Shell {
fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) { fn add_methods<M: UserDataMethods<Self>>(methods: &mut M) {
methods.add_meta_method_mut(MetaMethod::NewIndex, |_, this, (t_index, t_value): (String, String)| -> lResult<()> { methods.add_meta_method_mut(MetaMethod::NewIndex, |_, this, (t_index, t_value): (String, String)| -> lResult<()> {
if t_index == "PROMPT" { if t_index == "PROMPT" {
match t_value.len() as u16 >= u16::MAX { let mut prompt = this.0.borrow_mut();
true => { mlua::Error::runtime(format!("SHELL.PROMPT's length exceeded or equals the max size. ({})", u16::MAX)); }, *prompt = t_value;
false => {
let mut prompt = this.0.borrow_mut();
*prompt = t_value;
},
}
} }
Ok(()) Ok(())
}); });