mirror of
https://github.com/aljazceru/turso.git
synced 2026-02-15 21:14:21 +01:00
Only initialize Rustyline if we are in a tty
This commit is contained in:
6
Cargo.lock
generated
6
Cargo.lock
generated
@@ -1575,9 +1575,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.171"
|
||||
version = "0.2.172"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
|
||||
checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa"
|
||||
|
||||
[[package]]
|
||||
name = "libgit2-sys"
|
||||
@@ -1702,8 +1702,10 @@ dependencies = [
|
||||
"ctrlc",
|
||||
"dirs 5.0.1",
|
||||
"env_logger 0.10.2",
|
||||
"libc",
|
||||
"limbo_core",
|
||||
"miette",
|
||||
"nix 0.29.0",
|
||||
"nu-ansi-term 0.50.1",
|
||||
"rustyline",
|
||||
"shlex",
|
||||
|
||||
@@ -28,10 +28,12 @@ csv = "1.3.1"
|
||||
ctrlc = "3.4.4"
|
||||
dirs = "5.0.1"
|
||||
env_logger = "0.10.1"
|
||||
libc = "0.2.172"
|
||||
limbo_core = { path = "../core", default-features = true, features = [
|
||||
"completion",
|
||||
] }
|
||||
miette = { version = "7.4.0", features = ["fancy"] }
|
||||
nix = "0.29.0"
|
||||
nu-ansi-term = "0.50.1"
|
||||
rustyline = { version = "15.0.0", default-features = true, features = [
|
||||
"derive",
|
||||
|
||||
59
cli/app.rs
59
cli/app.rs
@@ -7,6 +7,7 @@ use crate::{
|
||||
helper::LimboHelper,
|
||||
input::{get_io, get_writer, DbLocation, OutputMode, Settings},
|
||||
opcodes_dictionary::OPCODE_DESCRIPTIONS,
|
||||
HISTORY_FILE,
|
||||
};
|
||||
use comfy_table::{Attribute, Cell, CellAlignment, Color, ContentArrangement, Row, Table};
|
||||
use limbo_core::{Database, LimboError, OwnedValue, Statement, StepResult};
|
||||
@@ -14,10 +15,10 @@ use tracing_appender::non_blocking::WorkerGuard;
|
||||
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt, EnvFilter};
|
||||
|
||||
use clap::Parser;
|
||||
use rustyline::{history::DefaultHistory, Editor};
|
||||
use rustyline::{error::ReadlineError, history::DefaultHistory, Editor};
|
||||
use std::{
|
||||
fmt,
|
||||
io::{self, Write},
|
||||
io::{self, BufRead as _, Write},
|
||||
path::PathBuf,
|
||||
rc::Rc,
|
||||
sync::{
|
||||
@@ -62,7 +63,7 @@ pub struct Opts {
|
||||
|
||||
const PROMPT: &str = "limbo> ";
|
||||
|
||||
pub struct Limbo<'a> {
|
||||
pub struct Limbo {
|
||||
pub prompt: String,
|
||||
io: Arc<dyn limbo_core::IO>,
|
||||
writer: Box<dyn Write>,
|
||||
@@ -70,7 +71,7 @@ pub struct Limbo<'a> {
|
||||
pub interrupt_count: Arc<AtomicUsize>,
|
||||
input_buff: String,
|
||||
opts: Settings,
|
||||
pub rl: &'a mut Editor<LimboHelper, DefaultHistory>,
|
||||
pub rl: Option<Editor<LimboHelper, DefaultHistory>>,
|
||||
}
|
||||
|
||||
struct QueryStatistics {
|
||||
@@ -105,8 +106,8 @@ macro_rules! query_internal {
|
||||
|
||||
static COLORS: &[Color] = &[Color::Green, Color::Black, Color::Grey];
|
||||
|
||||
impl<'a> Limbo<'a> {
|
||||
pub fn new(rl: &'a mut rustyline::Editor<LimboHelper, DefaultHistory>) -> anyhow::Result<Self> {
|
||||
impl Limbo {
|
||||
pub fn new() -> anyhow::Result<Self> {
|
||||
let opts = Opts::parse();
|
||||
let db_file = opts
|
||||
.database
|
||||
@@ -133,8 +134,6 @@ impl<'a> Limbo<'a> {
|
||||
)
|
||||
};
|
||||
let conn = db.connect()?;
|
||||
let h = LimboHelper::new(conn.clone(), io.clone());
|
||||
rl.set_helper(Some(h));
|
||||
let interrupt_count = Arc::new(AtomicUsize::new(0));
|
||||
{
|
||||
let interrupt_count: Arc<AtomicUsize> = Arc::clone(&interrupt_count);
|
||||
@@ -154,12 +153,19 @@ impl<'a> Limbo<'a> {
|
||||
interrupt_count,
|
||||
input_buff: String::new(),
|
||||
opts: Settings::from(opts),
|
||||
rl,
|
||||
rl: None,
|
||||
};
|
||||
app.first_run(sql, quiet)?;
|
||||
Ok(app)
|
||||
}
|
||||
|
||||
pub fn with_readline(mut self, mut rl: Editor<LimboHelper, DefaultHistory>) -> Self {
|
||||
let h = LimboHelper::new(self.conn.clone(), self.io.clone());
|
||||
rl.set_helper(Some(h));
|
||||
self.rl = Some(rl);
|
||||
self
|
||||
}
|
||||
|
||||
fn first_run(&mut self, sql: Option<String>, quiet: bool) -> io::Result<()> {
|
||||
if let Some(sql) = sql {
|
||||
self.handle_first_input(&sql);
|
||||
@@ -470,8 +476,9 @@ impl<'a> Limbo<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_line(&mut self, line: &str) -> rustyline::Result<()> {
|
||||
self.rl.add_history_entry(line.to_owned())?;
|
||||
fn reset_line(&mut self, _line: &str) -> rustyline::Result<()> {
|
||||
// Entry is auto added to history
|
||||
// self.rl.add_history_entry(line.to_owned())?;
|
||||
self.interrupt_count.store(0, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
@@ -973,4 +980,34 @@ impl<'a> Limbo<'a> {
|
||||
self.run_query(buff.as_str());
|
||||
self.reset_input();
|
||||
}
|
||||
|
||||
pub fn readline(&mut self) -> Result<String, ReadlineError> {
|
||||
if let Some(rl) = &mut self.rl {
|
||||
Ok(rl.readline(&self.prompt)?)
|
||||
} else {
|
||||
let mut input = String::new();
|
||||
println!("");
|
||||
let mut reader = std::io::stdin().lock();
|
||||
if reader.read_line(&mut input)? == 0 {
|
||||
return Err(ReadlineError::Eof.into());
|
||||
}
|
||||
// Remove trailing newline
|
||||
if input.ends_with('\n') {
|
||||
input.pop();
|
||||
if input.ends_with('\r') {
|
||||
input.pop();
|
||||
}
|
||||
}
|
||||
|
||||
Ok(input)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Limbo {
|
||||
fn drop(&mut self) {
|
||||
if let Some(rl) = &mut self.rl {
|
||||
let _ = rl.save_history(HISTORY_FILE.as_path());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
37
cli/main.rs
37
cli/main.rs
@@ -5,26 +5,41 @@ mod helper;
|
||||
mod input;
|
||||
mod opcodes_dictionary;
|
||||
|
||||
use nix::unistd::isatty;
|
||||
use rustyline::{error::ReadlineError, Config, Editor};
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{atomic::Ordering, LazyLock},
|
||||
};
|
||||
|
||||
fn rustyline_config() -> Config {
|
||||
Config::builder()
|
||||
.completion_type(rustyline::CompletionType::List)
|
||||
.auto_add_history(true)
|
||||
.build()
|
||||
}
|
||||
|
||||
pub static HOME_DIR: LazyLock<PathBuf> =
|
||||
LazyLock::new(|| dirs::home_dir().expect("Could not determine home directory"));
|
||||
|
||||
pub static HISTORY_FILE: LazyLock<PathBuf> = LazyLock::new(|| HOME_DIR.join(".limbo_history"));
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let mut rl = Editor::with_config(rustyline_config())?;
|
||||
let mut app = app::Limbo::new(&mut rl)?;
|
||||
let mut app = app::Limbo::new()?;
|
||||
let _guard = app.init_tracing()?;
|
||||
let home = dirs::home_dir().expect("Could not determine home directory");
|
||||
let history_file = home.join(".limbo_history");
|
||||
if history_file.exists() {
|
||||
app.rl.load_history(history_file.as_path())?;
|
||||
|
||||
if is_a_tty() {
|
||||
let mut rl = Editor::with_config(rustyline_config())?;
|
||||
if HISTORY_FILE.exists() {
|
||||
rl.load_history(HISTORY_FILE.as_path())?;
|
||||
}
|
||||
app = app.with_readline(rl);
|
||||
} else {
|
||||
tracing::debug!("not in tty");
|
||||
}
|
||||
|
||||
loop {
|
||||
let readline = app.rl.readline(&app.prompt);
|
||||
let readline = app.readline();
|
||||
match readline {
|
||||
Ok(line) => match app.handle_input_line(line.trim()) {
|
||||
Ok(_) => {}
|
||||
@@ -54,6 +69,10 @@ fn main() -> anyhow::Result<()> {
|
||||
}
|
||||
}
|
||||
}
|
||||
rl.save_history(history_file.as_path())?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Return whether or not STDIN is a TTY
|
||||
fn is_a_tty() -> bool {
|
||||
isatty(libc::STDIN_FILENO).unwrap_or(false)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user