diff --git a/src/commands.rs b/src/commands.rs index 1985dfa..13cf25a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -6,27 +6,16 @@ use std::{ path::{Path, PathBuf}, }; -use crate::MapDisplay; +use crate::{rc::History, MapDisplay}; enum ValidStatus { NoRootFolder, TryExists(io::Error) } - trait PathBufIsValid { fn is_valid(&self) -> Result; fn is_valid_or_home(&self) -> Option; } - -trait ChangeDirectory { - fn change_directory(&self, args: SplitWhitespace) -> Option; - fn set_current_dir(&self, new_path: &Path) -> Option; - fn specific_user_dir(&self, user: String) -> Option; - fn cd_args(&self, vec_args: Vec) -> Option; - fn previous_dir(&self) -> Option; - fn home_dir(&self) -> Option; -} - impl PathBufIsValid for PathBuf { fn is_valid(&self) -> Result { match self.try_exists() { @@ -50,6 +39,14 @@ impl PathBufIsValid for PathBuf { } } +trait ChangeDirectory { + fn change_directory(&self, args: SplitWhitespace) -> Option; + fn set_current_dir(&self, new_path: &Path) -> Option; + fn specific_user_dir(&self, user: String) -> Option; + fn cd_args(&self, vec_args: Vec) -> Option; + fn previous_dir(&self) -> Option; + fn home_dir(&self) -> Option; +} impl ChangeDirectory for Command { fn set_current_dir(&self, new_path: &Path) -> Option { std::env::set_current_dir(new_path).map_or_display_none(|()| Some(new_path.to_path_buf())) @@ -117,26 +114,39 @@ impl ChangeDirectory for Command { } } -pub struct Command(String); +pub struct Command { + input: String, + history: Option +} impl Command { pub fn new(input: String) -> Self { - Self(input) + Self { + history: History::init(), + input + } + } + + pub fn history_write(&self) { + if let Some(history_file) = &self.history { + history_file.write(&self.input); + }; } pub fn spawn(&self, command_process: io::Result) { - command_process.map_or_display_none(|mut child| Some(child.wait())); + if let Ok(mut child) = command_process { + self.history_write(); + child.wait().ok(); + } else { + println!("Unknown command: {}", self.input) + } } pub fn exec(&self) { - let mut args = self.0.split_whitespace(); + let mut args = self.input.split_whitespace(); if let Some(command) = args.next() { match command { - "cd" => { - self.change_directory(args); - }, - command => { - self.spawn(process::Command::new(command).args(args).spawn()); - } + "cd" => { self.change_directory(args); }, + command => { self.spawn(process::Command::new(command).args(args).spawn()); } } } } diff --git a/src/rc.rs b/src/rc.rs index a938c51..dbf8f01 100644 --- a/src/rc.rs +++ b/src/rc.rs @@ -1,7 +1,7 @@ -use std::{path::PathBuf, fs::{self, File}, io::{self, Write}}; +use std::{fs::{self, File, OpenOptions}, io::{self, BufRead, BufReader, Write}, path::PathBuf}; use thiserror::Error; -use crate::MapDisplay; +use crate::{shell_error, MapDisplay}; pub const DEFAULT_CONFIG_CONTENT: &str = r#"--!strict @@ -95,9 +95,30 @@ pub fn config_file() -> Option { config_file.is_valid_file_or_create(DEFAULT_CONFIG_CONTENT.as_bytes()) } -// TODO: history.rs -pub fn history_file() -> Option { - let mut config_file = config_dir()?; - config_file.push(".history"); - config_file.is_valid_file_or_create(b"") +pub struct History(PathBuf); +impl History { + pub fn init() -> Option { + config_dir().map(|mut config| { + config.push(".history"); + config.is_valid_file_or_create(b""); + Self(config) + }) + } + + pub fn write>(&self, content: S) { + //feasible hack instead of using about 10 functions + OpenOptions::new().append(true).open(self.0.as_path()).map_or_display(|mut file| { + const NEXTLINE: &str = "\n"; + + if let Err(write_err) = file.write_all(format!("{}{}", NEXTLINE, content.as_ref()).as_bytes()) { + shell_error(write_err); + }; + }); + } + + pub fn read(&self) -> Option> { + File::open(&self.0).map_or_display_none(|file| { + Some(BufReader::new(file).lines().map_while(Result::ok).collect::>()) + }) + } } \ No newline at end of file diff --git a/src/session.rs b/src/session.rs index ba87eda..28f7a1d 100644 --- a/src/session.rs +++ b/src/session.rs @@ -2,7 +2,7 @@ use std::{cell::RefCell, fs, io::{self}, rc::Rc}; use core::fmt; use crate::{ - commands, ps::{self, Ps}, rc, shell_error, vm::{self, LuauVm}, MapDisplay + commands, ps::{self, Ps}, rc::{self}, shell_error, vm::{self, LuauVm}, MapDisplay }; #[derive(Debug, Clone)] @@ -48,7 +48,6 @@ impl LambdaShell { fs::read_to_string(conf_file).map_or_display(|luau_conf| self.vm_exec(luau_conf)); } } - self.ps.borrow().display(); loop { if self.terminate { break } else {