mirror of
https://github.com/lune-org/lune.git
synced 2025-05-04 10:43:57 +01:00
refactor: move REPL logic to separate module
This commit is contained in:
parent
09050be633
commit
87cca0f04b
3 changed files with 117 additions and 89 deletions
12
Cargo.toml
12
Cargo.toml
|
@ -53,6 +53,18 @@ opt-level = "z"
|
|||
strip = true
|
||||
lto = true
|
||||
|
||||
[profile.dev]
|
||||
lto = "off"
|
||||
strip = "none"
|
||||
codegen-units = 256
|
||||
panic = "unwind"
|
||||
opt-level = 0
|
||||
incremental = true
|
||||
overflow-checks = true
|
||||
debug-assertions = true
|
||||
debug = true
|
||||
rpath = false
|
||||
|
||||
# All of the dependencies for Lune.
|
||||
#
|
||||
# Dependencies are categorized as following:
|
||||
|
|
|
@ -18,6 +18,7 @@ use tokio::{
|
|||
};
|
||||
|
||||
pub(crate) mod gen;
|
||||
pub(crate) mod repl;
|
||||
pub(crate) mod setup;
|
||||
pub(crate) mod utils;
|
||||
|
||||
|
@ -154,100 +155,14 @@ impl Cli {
|
|||
if generate_file_requested {
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
}
|
||||
|
||||
// HACK: We know that we didn't get any arguments here but since
|
||||
// script_path is optional clap will not error on its own, to fix
|
||||
// we will duplicate the CLI command and fetch the version of
|
||||
// lune to display
|
||||
let cmd = Cli::command();
|
||||
let lune_version = cmd.get_version();
|
||||
let exit_code_status = repl::show_interface(Cli::command()).await;
|
||||
|
||||
// The version is mandatory and will always exist
|
||||
println!("Lune v{}", lune_version.unwrap());
|
||||
|
||||
let lune_instance = Lune::new();
|
||||
|
||||
let mut repl = DefaultEditor::new()?;
|
||||
|
||||
match repl.load_history(&(|| -> PathBuf {
|
||||
let dir_opt = home::home_dir();
|
||||
|
||||
if let Some(dir) = dir_opt {
|
||||
dir.join(".lune_history")
|
||||
} else {
|
||||
eprintln!("Failed to find user home directory, abort!");
|
||||
// Doesn't feel right to exit directly with a exit code of 1
|
||||
// Lmk if there is a better way of doing this
|
||||
exit(1);
|
||||
}
|
||||
})()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
match err {
|
||||
err => {
|
||||
if let ReadlineError::Io(io_err) = err {
|
||||
if io_err.kind() == ErrorKind::NotFound {
|
||||
std::fs::write(
|
||||
// We know for sure that the home dir already exists
|
||||
home::home_dir().unwrap().join(".lune_history"),
|
||||
String::new(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("WARN: Failed to load REPL history")
|
||||
}
|
||||
};
|
||||
|
||||
// repl.bind_sequence(
|
||||
// KeyEvent(KeyCode::Enter, Modifiers::SHIFT),
|
||||
// EventHandler::Simple(Cmd::AcceptOrInsertLine { accept_in_the_middle: true }),
|
||||
// );
|
||||
|
||||
let mut interrupt_counter = 0u32;
|
||||
|
||||
loop {
|
||||
let mut source_code = String::new();
|
||||
|
||||
match repl.readline("> ") {
|
||||
Ok(code) => {
|
||||
source_code = code.clone();
|
||||
repl.add_history_entry(code.as_str())?;
|
||||
|
||||
// If source code eval was requested, we reset the counter
|
||||
interrupt_counter = 0;
|
||||
}
|
||||
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
// HACK: We actually want the user to do ^C twice to exit,
|
||||
// but the user would need to ^C one more time even after
|
||||
// the check passes, so we check for 1 instead of 2
|
||||
if interrupt_counter != 1 {
|
||||
println!("Interrupt: ^C again to exit");
|
||||
|
||||
// Increment the counter
|
||||
interrupt_counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Eof) => break,
|
||||
Err(err) => {
|
||||
eprintln!("REPL ERROR: {}", err.to_string());
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
let eval_result = lune_instance.run("REPL", source_code).await;
|
||||
|
||||
match eval_result {
|
||||
Ok(_) => (),
|
||||
Err(err) => eprintln!("{}", err),
|
||||
}
|
||||
}
|
||||
|
||||
return Ok(ExitCode::SUCCESS);
|
||||
return exit_code_status;
|
||||
}
|
||||
// Figure out if we should read from stdin or from a file,
|
||||
// reading from stdin is marked by passing a single "-"
|
||||
|
|
101
src/cli/repl.rs
Normal file
101
src/cli/repl.rs
Normal file
|
@ -0,0 +1,101 @@
|
|||
use std::{
|
||||
io::{Error, ErrorKind},
|
||||
path::PathBuf,
|
||||
process::{exit, ExitCode},
|
||||
};
|
||||
|
||||
use clap::Command;
|
||||
use lune::{Lune, LuneError};
|
||||
use rustyline::{error::ReadlineError, DefaultEditor};
|
||||
|
||||
use super::Cli;
|
||||
|
||||
// Isn't dependency injection plain awesome?!
|
||||
pub async fn show_interface(cmd: Command) -> Result<ExitCode, anyhow::Error> {
|
||||
let lune_version = cmd.get_version();
|
||||
|
||||
// The version is mandatory and will always exist
|
||||
println!("Lune v{}", lune_version.unwrap());
|
||||
|
||||
let lune_instance = Lune::new();
|
||||
|
||||
let mut repl = DefaultEditor::new()?;
|
||||
|
||||
match repl.load_history(&(|| -> PathBuf {
|
||||
let dir_opt = home::home_dir();
|
||||
|
||||
if let Some(dir) = dir_opt {
|
||||
dir.join(".lune_history")
|
||||
} else {
|
||||
eprintln!("Failed to find user home directory, abort!");
|
||||
// Doesn't feel right to exit directly with a exit code of 1
|
||||
// Lmk if there is a better way of doing this
|
||||
exit(1);
|
||||
}
|
||||
})()) {
|
||||
Ok(_) => (),
|
||||
Err(err) => {
|
||||
match err {
|
||||
err => {
|
||||
if let ReadlineError::Io(io_err) = err {
|
||||
if io_err.kind() == ErrorKind::NotFound {
|
||||
std::fs::write(
|
||||
// We know for sure that the home dir already exists
|
||||
home::home_dir().unwrap().join(".lune_history"),
|
||||
String::new(),
|
||||
)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("WARN: Failed to load REPL history")
|
||||
}
|
||||
};
|
||||
|
||||
let mut interrupt_counter = 0u32;
|
||||
|
||||
loop {
|
||||
let mut source_code = String::new();
|
||||
|
||||
match repl.readline("> ") {
|
||||
Ok(code) => {
|
||||
source_code = code.clone();
|
||||
repl.add_history_entry(code.as_str())?;
|
||||
|
||||
// If source code eval was requested, we reset the counter
|
||||
interrupt_counter = 0;
|
||||
}
|
||||
|
||||
Err(ReadlineError::Interrupted) => {
|
||||
// HACK: We actually want the user to do ^C twice to exit,
|
||||
// but the user would need to ^C one more time even after
|
||||
// the check passes, so we check for 1 instead of 2
|
||||
if interrupt_counter != 1 {
|
||||
println!("Interrupt: ^C again to exit");
|
||||
|
||||
// Increment the counter
|
||||
interrupt_counter += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Err(ReadlineError::Eof) => break,
|
||||
Err(err) => {
|
||||
eprintln!("REPL ERROR: {}", err.to_string());
|
||||
|
||||
// This isn't a good way to exit imo, once again
|
||||
exit(1);
|
||||
}
|
||||
};
|
||||
|
||||
let eval_result = lune_instance.run("REPL", source_code).await;
|
||||
|
||||
match eval_result {
|
||||
Ok(_) => (),
|
||||
Err(err) => eprintln!("{}", err),
|
||||
};
|
||||
}
|
||||
|
||||
Ok(ExitCode::SUCCESS)
|
||||
}
|
Loading…
Add table
Reference in a new issue