diff --git a/src/edit.rs b/src/edit.rs index 42b3e62..53e8629 100644 --- a/src/edit.rs +++ b/src/edit.rs @@ -207,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, _history: &mut History) -> Result> { + pub fn read_command(&mut self, history: &mut History) -> Result> { use input::Event::*; loop { @@ -266,6 +266,7 @@ impl Editor { match esc { Left => self.back(1)?, Right => self.forward(1)?, + Up => self.prev_history()?, Home => self.seek_left()?, End => self.seek_right()?, esc => debug!(" Ignored escape: {esc:?}"), @@ -422,4 +423,8 @@ impl Editor { self.display.reset()?; Ok(()) } + + fn prev_history(&mut self) -> Result<()> { + Ok(()) + } } diff --git a/src/error.rs b/src/error.rs index 1e40b27..5c1d8f0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,4 +1,7 @@ -use crate::{lex::Token, topo::Glyph}; +use crate::{ + lex::Token, + topo::{Glyph, Position}, +}; use std::io; use thiserror::Error; use windows::Win32::Foundation::{GetLastError, BOOL}; @@ -36,21 +39,32 @@ pub enum LexError { UnexpectedCharacterInGlob(Glyph), #[error("unexpected eof")] - UnexpectedEOF, + UnexpectedEOF(Position), - #[error("not yet supported: {0}")] - NotYetSupported(String), + #[error("not yet supported: {1}")] + NotYetSupported(Position, String), } impl LexError { - pub fn not_yet(msg: &str) -> Self { - LexError::NotYetSupported(msg.to_string()) + pub fn not_yet(p: Position, msg: &str) -> Self { + LexError::NotYetSupported(p, msg.to_string()) + } + + fn position(&self) -> Position { + use LexError::*; + match self { + UnexpectedCharacter(g) => g.position, + UnexpectedCharacterInBareString(g) => g.position, + UnexpectedCharacterInGlob(g) => g.position, + UnexpectedEOF(p) => *p, + NotYetSupported(p, _) => *p, + } } } #[derive(Debug, Error)] pub enum ParseError { - #[error("lex error")] + #[error("lex error at line {line}, column {col}", line=.0.position().line, col=.0.position().column)] LexError(#[from] LexError), #[error("Unexpected Token: {0:?}")] diff --git a/src/history.rs b/src/history.rs index d7ce8bd..21d28f2 100644 --- a/src/history.rs +++ b/src/history.rs @@ -1,7 +1,13 @@ -pub struct History {} +pub struct History { + events: Vec, +} impl History { pub fn new() -> Self { - Self {} + Self { events: Vec::new() } + } + + pub fn add>(&mut self, event: S) { + self.events.push(event.into()); } } diff --git a/src/lex.rs b/src/lex.rs index 34877fc..45ef286 100644 --- a/src/lex.rs +++ b/src/lex.rs @@ -154,7 +154,7 @@ impl<'text> Tokenizer<'text> { } if progress.is_empty() { - Err(LexError::UnexpectedEOF) + Err(LexError::UnexpectedEOF(self.source.next_position)) } else { Ok(Token::Word(progress.into())) } @@ -175,22 +175,31 @@ impl<'text> Tokenizer<'text> { } if progress.is_empty() { - Err(LexError::UnexpectedEOF) + Err(LexError::UnexpectedEOF(self.source.next_position)) } else { Ok(Token::Glob(progress.into())) } } fn lex_raw_string(&mut self, _progress: Vec) -> Result { - Err(LexError::not_yet("raw strings not done yet")) + Err(LexError::not_yet( + self.source.next_position, + "raw strings not done yet", + )) } fn lex_interp_string(&mut self, _progress: Vec) -> Result { - Err(LexError::not_yet("interpreted strings not done yet")) + Err(LexError::not_yet( + self.source.next_position, + "interpreted strings not done yet", + )) } fn lex_var(&mut self, _progress: Vec) -> Result { - Err(LexError::not_yet("variables are not done yet")) + Err(LexError::not_yet( + self.source.next_position, + "variables are not done yet", + )) } } diff --git a/src/topo.rs b/src/topo.rs index a824998..fd9af1c 100644 --- a/src/topo.rs +++ b/src/topo.rs @@ -47,6 +47,12 @@ impl fmt::Debug for Position { } } +impl fmt::Display for Position { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { + (self as &dyn fmt::Debug).fmt(f) + } +} + /// A Glyph represents a character occurring at some specific position in some input text. #[derive(PartialEq, Clone)] pub struct Glyph { @@ -97,7 +103,7 @@ pub struct Glyphs<'text> { source: Chars<'text>, /// the position of the next character in the source text - next_position: Position, + pub(crate) next_position: Position, /// the number of bytes we've read from our input document so far bytes_read: u64, @@ -153,7 +159,8 @@ impl<'text> Glyphs<'text> { /// takes the next character from our input text pub fn pop(&mut self) -> Result { - self.next().ok_or(LexError::UnexpectedEOF) + self.next() + .ok_or(LexError::UnexpectedEOF(self.next_position)) } /// returns a reference to a character in our lookahead buffer at a given position. This allows