From 731bd6947775768d1d1c6582f6a45ce86af3e6c5 Mon Sep 17 00:00:00 2001 From: Jordan Orelli Date: Sat, 17 Feb 2024 13:38:29 -0600 Subject: [PATCH] pressing escape no longer crashes the shell --- src/edit.rs | 3 ++- src/history.rs | 7 +++++++ src/input.rs | 4 +++- src/interactive.rs | 5 ++++- src/main.rs | 2 ++ src/parse.rs | 19 ++++++++++++++++++- 6 files changed, 36 insertions(+), 4 deletions(-) create mode 100644 src/history.rs diff --git a/src/edit.rs b/src/edit.rs index d4056c3..42b3e62 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -1,4 +1,5 @@ use crate::{ + history::History, input::{self, ControlCharacter, Escape}, log::*, output, @@ -206,7 +207,7 @@ impl Editor { /// reads one command from the editor. This function blocks until the user has entered an /// entire command. - pub fn read_command(&mut self) -> Result> { + pub fn read_command(&mut self, _history: &mut History) -> Result> { use input::Event::*; loop { diff --git a/src/history.rs b/src/history.rs new file mode 100644 index 0000000..d7ce8bd --- /dev/null +++ b/src/history.rs @@ -0,0 +1,7 @@ +pub struct History {} + +impl History { + pub fn new() -> Self { + Self {} + } +} diff --git a/src/input.rs b/src/input.rs index ae8efb9..01705a1 100644 --- a/src/input.rs +++ b/src/input.rs @@ -239,6 +239,8 @@ impl Reader { let c = as_escape_character(&record).ok_or(InputError::BadEscapeSequence)?; if let Some(escape) = self.escapes.step(c) { return Ok(escape); + } else { + return Ok(Escape::Empty); } } } @@ -416,7 +418,7 @@ impl EscapeNode { impl EscapeCursor { fn step(&mut self, c: char) -> Option { debug!("step: {c}"); - let child = self.target.child(c).unwrap(); + let child = self.target.child(c)?; match child.as_ref() { EscapeNode::Terminal { v, .. } => { self.reset(); diff --git a/src/interactive.rs b/src/interactive.rs index dfd3b7e..c4760bd 100644 --- a/src/interactive.rs +++ b/src/interactive.rs @@ -1,5 +1,6 @@ use crate::{ edit, + history::History, log::*, output, run::{self, Eval}, @@ -39,10 +40,12 @@ impl Session { stderr: self.stderr.clone(), state: &mut state, }; + let mut history = History::new(); + info!("ยป shell session start --------"); loop { self.editor.show_prompt()?; - let text = match self.editor.read_command()? { + let text = match self.editor.read_command(&mut history)? { Some(text) => text, None => break, }; diff --git a/src/main.rs b/src/main.rs index e7a5c75..5c636a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,8 @@ mod lex; /// a real primitive line editor mod edit; +mod history; + /// logging configuration mod log; diff --git a/src/parse.rs b/src/parse.rs index b6db748..52104e7 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -103,7 +103,7 @@ fn next_id() -> usize { /// within a parse tree. The cursor helps with the ownership structure: so long as there is a /// cursor to any node on the tree, the tree remains in memory. Once there are no cursors pointed /// at the tree, it is dropped. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Cursor { pub target: Rc, root: Rc, @@ -148,6 +148,7 @@ impl Cursor { Ok(()) } + /// moves the cursor up to the root of the tree in place pub fn up_to_root(&mut self) { self.goto(Rc::clone(&self.root)); } @@ -174,6 +175,22 @@ impl Cursor { Rc::clone(&self.root) } + fn text_tree(&self) -> String { + let mut p = self.clone(); + p.up_to_root(); + let mut buf = String::new(); + self.text_tree_helper(0, &mut buf); + buf + } + + fn text_tree_helper(&self, depth: u32, mut buf: &mut String) { + let line = format!("{:?}\n", self.value()); + *buf = buf.to_owned() + &line; + for child in self.iter_children() { + child.text_tree_helper(depth + 1, &mut buf); + } + } + fn goto(&mut self, next: Rc) { self.prev = self.target.id; self.target = next;