-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
use crossterm::event::{read, Event::Key, KeyCode::Char, KeyEvent, KeyModifiers}; | ||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode}; | ||
use crossterm::event::{read, Event, Event::Key, KeyCode::Char, KeyEvent, KeyModifiers}; | ||
use crossterm::execute; | ||
use crossterm::terminal::{disable_raw_mode, enable_raw_mode, Clear, ClearType}; | ||
use std::io::stdout; | ||
|
||
pub struct Editor { | ||
should_quit: bool, | ||
|
@@ -10,31 +12,53 @@ impl Editor { | |
Editor { should_quit: false } | ||
} | ||
pub fn run(&mut self) { | ||
if let Err(err) = self.repl() { | ||
panic!("{err:#?}"); | ||
} | ||
print!("Goodbye.\r\n"); | ||
Self::initialize().unwrap(); | ||
let result = self.repl(); | ||
Self::terminate().unwrap(); | ||
result.unwrap(); | ||
This comment has been minimized.
Sorry, something went wrong. |
||
} | ||
fn repl(&mut self) -> Result<(), std::io::Error> { | ||
|
||
fn initialize() -> Result<(), std::io::Error> { | ||
enable_raw_mode()?; | ||
Self::clear_screen() | ||
} | ||
fn terminate() -> Result<(), std::io::Error> { | ||
disable_raw_mode() | ||
} | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
fn clear_screen() -> Result<(), std::io::Error> { | ||
let mut stdout = stdout(); | ||
execute!(stdout, Clear(ClearType::All)) | ||
} | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
|
||
fn repl(&mut self) -> Result<(), std::io::Error> { | ||
loop { | ||
if let Key(KeyEvent { | ||
code, modifiers, kind, state | ||
}) = read()? | ||
{ | ||
println!("Code: {code:?} Modifiers: {modifiers:?} Kind: {kind:?} State: {state:?} \r"); | ||
match code { | ||
Char('q') if modifiers == KeyModifiers::CONTROL => { | ||
self.should_quit = true; | ||
} | ||
_ => (), | ||
} | ||
} | ||
let event = read()?; | ||
self.evaluate_event(&event); | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
self.refresh_screen()?; | ||
if self.should_quit { | ||
break; | ||
} | ||
} | ||
disable_raw_mode()?; | ||
Ok(()) | ||
} | ||
fn evaluate_event(&mut self, event: &Event) { | ||
if let Key(KeyEvent { | ||
code, modifiers, .. | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
}) = event | ||
{ | ||
match code { | ||
Char('q') if *modifiers == KeyModifiers::CONTROL => { | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
self.should_quit = true; | ||
} | ||
_ => (), | ||
} | ||
} | ||
} | ||
fn refresh_screen(&self) -> Result<(), std::io::Error> { | ||
if self.should_quit { | ||
Self::clear_screen()?; | ||
print!("Goodbye.\r\n"); | ||
This comment has been minimized.
Sorry, something went wrong.
pflenker
Author
Owner
|
||
} | ||
Ok(()) | ||
} | ||
} |
We've changed our error handling here a bit and did something strange with the result of
self.repl
.So we have three places where we can run into an error: During the preparation of the terminal, during execution of our loop and during shutting down our terminal.
In all three cases, there is nothing we can do to handle this. We're simply
unwrap
ing here, which will cause apanic
anyways - no need to do our ownpanic
ing.But then what's up with the error that can come from the
repl
loop?You see, we have no idea what to do with it, but we do know that our terminal still needs to be cleaned up -
raw mode
needs to be ended. So we safe the result ofrepl
, then we attempt to wind down the terminal. And if we did this successfully, we're unwrapping whateverrepl
gave us: Either anOk
with nothing in it, or anErr
that would then cause thepanic
on a clear terminal.