From f067886cfaae03436a8a45a55b29025f36f27f33 Mon Sep 17 00:00:00 2001 From: Jeremy Wall Date: Sat, 9 Nov 2019 19:27:18 -0600 Subject: [PATCH] DEV: repl ergonomic improvements. * Ctrl-C, Ctrl-D now do the appropriate thing * #exit will now exit the repl --- src/help/repl.txt | 3 +++ src/io/mod.rs | 4 ++++ src/main.rs | 24 ++++++++++++++++++++++-- 3 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/help/repl.txt b/src/help/repl.txt index da4ac5f..68ffb67 100644 --- a/src/help/repl.txt +++ b/src/help/repl.txt @@ -15,4 +15,7 @@ Currently supported commands are: * #del - deletes a previously created named binding + +* #exit + - Exits the repl. \ No newline at end of file diff --git a/src/io/mod.rs b/src/io/mod.rs index df38f55..045a6a8 100644 --- a/src/io/mod.rs +++ b/src/io/mod.rs @@ -24,6 +24,10 @@ impl StatementAccumulator { Self { acc: Vec::new() } } + pub fn reset(&mut self) { + self.acc = Vec::new(); + } + pub fn next_line(&self) -> usize { self.acc.len() + 1 } diff --git a/src/main.rs b/src/main.rs index 2a5c076..9d1c5af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,6 +27,8 @@ use std::path::{Path, PathBuf}; use std::process; use std::rc::Rc; +use rustyline::error::ReadlineError; + use ucglib::build; use ucglib::build::assets::{Cache, MemoryCache}; use ucglib::build::Val; @@ -585,12 +587,28 @@ fn do_repl( build::FileBuilder::new(std::env::current_dir()?, import_paths, cache, registry); // loop let mut lines = ucglib::io::StatementAccumulator::new(); - println!("Welcome to the UCG repl. Ctrl-D to exit"); + println!("Welcome to the UCG repl. Ctrl-D to exit, Ctrl-C to abort expression."); println!("Type '#help' for help."); println!(""); loop { // print prompt - let line = editor.readline(&format!("{}> ", lines.next_line()))?; + let line = match editor.readline(&format!("{}> ", lines.next_line())) { + Ok(l) => l, + Err(e) => { + if let ReadlineError::Eof = e { + eprintln!("Recieved EOF Exiting..."); + process::exit(0); + } + if let ReadlineError::Interrupted = e { + // Reset our lines and start over again + eprintln!("Interrupted!"); + lines.reset(); + continue; + } + eprintln!("Error: {}", e); + process::exit(1); + } + }; // repl commands are only valid while not accumulating a statement; let trimmed = line.trim(); if trimmed.starts_with("#") { @@ -612,6 +630,8 @@ fn do_repl( eprintln!("No such binding {}", key.val); } } + } else if trimmed.starts_with("#exit") { + process::exit(0); } else { eprintln!("Invalid repl command..."); eprintln!("");