Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 35 additions & 4 deletions crates/steel-repl/src/repl.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
extern crate rustyline;
use colored::*;
use rustyline::history::FileHistory;
use rustyline::{
Cmd, ConditionalEventHandler, Event, EventContext, EventHandler, KeyEvent, RepeatCount,
};
use steel::compiler::modules::steel_home;
use steel::rvals::{Custom, SteelString};

use std::error::Error;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};

Expand Down Expand Up @@ -182,6 +186,33 @@ pub fn readline_module(vm: &mut Engine) {
vm.register_module(module);
}

struct CtrlCHandler {
close_on_interrupt: Arc<AtomicBool>,
empty_line_cancelled: AtomicBool,
}

impl CtrlCHandler {
fn new(close_on_interrupt: Arc<AtomicBool>) -> Self {
CtrlCHandler {
close_on_interrupt,
empty_line_cancelled: AtomicBool::new(false),
}
}
}

impl ConditionalEventHandler for CtrlCHandler {
fn handle(&self, _: &Event, _: RepeatCount, _: bool, ctx: &EventContext) -> Option<Cmd> {
if !ctx.line().is_empty() {
// if the line is not empty, reset the PREVIOUS_LINE_CANCELLED state
self.empty_line_cancelled.store(false, Ordering::Release);
} else if self.empty_line_cancelled.swap(true, Ordering::Release) {
self.close_on_interrupt.store(true, Ordering::Release);
}

Some(Cmd::Interrupt)
}
}

/// Entry point for the repl
/// Automatically adds the prelude and contracts for the core library
pub fn repl_base(mut vm: Engine) -> std::io::Result<()> {
Expand Down Expand Up @@ -236,7 +267,9 @@ pub fn repl_base(mut vm: Engine) -> std::io::Result<()> {
safepoint.resume();
};

let mut previous_line_cancelled = false;
let close_on_interrupt = Arc::new(AtomicBool::new(false));
let ctrlc = Box::new(CtrlCHandler::new(close_on_interrupt.clone()));
rl.bind_sequence(KeyEvent::ctrl('c'), EventHandler::Conditional(ctrlc));

while rx.try_recv().is_err() {
// Update globals for highlighting
Expand All @@ -257,7 +290,6 @@ pub fn repl_base(mut vm: Engine) -> std::io::Result<()> {
match readline {
Ok(line) => {
rl.add_history_entry(line.as_str()).ok();
previous_line_cancelled = false;
match line.as_str() {
":q" | ":quit" => return Ok(()),
":time" => {
Expand Down Expand Up @@ -316,10 +348,9 @@ pub fn repl_base(mut vm: Engine) -> std::io::Result<()> {
}
}
Err(ReadlineError::Interrupted) => {
if previous_line_cancelled {
if close_on_interrupt.load(Ordering::Acquire) {
break;
} else {
previous_line_cancelled = true;
println!("CTRL-C");
continue;
}
Expand Down
Loading