Skip to content

Commit 67aae6d

Browse files
committed
Add dirs-next dependency and implement REPL history management
- Added `dirs-next` as a dependency in `Cargo.toml` to facilitate platform-specific directory handling. - Implemented functions to manage REPL history, including loading and saving history to a designated path based on the platform's state directory. - Enhanced the REPL to utilize the new history management functions, improving user experience by preserving command history across sessions.
1 parent 08a813c commit 67aae6d

File tree

3 files changed

+125
-1
lines changed

3 files changed

+125
-1
lines changed

Cargo.lock

Lines changed: 64 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ rust_xlsxwriter = { version = "0.93", features = ["chrono"] }
3434
rustc-literal-escaper = "0.0.7"
3535
rustyline = "17.0"
3636
flt = { version = "0.0.2" }
37+
dirs = { version = "2.0.0", package = "dirs-next" }
3738

3839
[dev-dependencies]
3940
criterion = "0.5"

src/bin/datu/repl.rs

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! REPL for datu
22
3+
use std::path::PathBuf;
4+
35
use anyhow::Result;
46
use datu::cli::repl::ReplPipelineBuilder;
57
use flt::parser::parse_expr;
@@ -9,15 +11,72 @@ use rustyline::error::ReadlineError;
911
/// Maximum number of inputs to keep in REPL history.
1012
const HISTORY_DEPTH: usize = 1000;
1113

14+
#[cfg(any(
15+
target_os = "android",
16+
target_os = "dragonfly",
17+
target_os = "freebsd",
18+
target_os = "linux",
19+
target_os = "netbsd",
20+
target_os = "openbsd",
21+
target_os = "redox",
22+
))]
23+
fn platform_state_dir() -> Option<PathBuf> {
24+
dirs::state_dir()
25+
}
26+
27+
#[cfg(not(any(
28+
target_os = "android",
29+
target_os = "dragonfly",
30+
target_os = "freebsd",
31+
target_os = "linux",
32+
target_os = "netbsd",
33+
target_os = "openbsd",
34+
target_os = "redox",
35+
)))]
36+
fn platform_state_dir() -> Option<PathBuf> {
37+
None
38+
}
39+
40+
fn repl_history_path() -> Option<PathBuf> {
41+
platform_state_dir()
42+
.or_else(dirs::data_local_dir)
43+
.map(|dir| dir.join("datu").join("history"))
44+
}
45+
46+
fn load_repl_history(rl: &mut DefaultEditor) -> Result<()> {
47+
let Some(history_path) = repl_history_path() else {
48+
return Ok(());
49+
};
50+
println!("Loading REPL history from: {:?}", history_path);
51+
if history_path.exists() {
52+
rl.load_history(&history_path)?;
53+
}
54+
Ok(())
55+
}
56+
57+
fn save_repl_history(rl: &mut DefaultEditor) -> Result<()> {
58+
let Some(history_path) = repl_history_path() else {
59+
return Ok(());
60+
};
61+
if let Some(parent) = history_path.parent() {
62+
std::fs::create_dir_all(parent)?;
63+
}
64+
rl.save_history(&history_path)?;
65+
Ok(())
66+
}
67+
1268
/// Runs the datu REPL.
1369
pub async fn run() -> Result<()> {
1470
let config = rustyline::Config::builder()
1571
.max_history_size(HISTORY_DEPTH)?
1672
.auto_add_history(true)
1773
.build();
1874
let mut rl = DefaultEditor::with_config(config)?;
75+
let _ = load_repl_history(&mut rl);
1976
let mut context = ReplPipelineBuilder::new();
20-
repl(&mut rl, &mut context).await
77+
let repl_result = repl(&mut rl, &mut context).await;
78+
let _ = save_repl_history(&mut rl);
79+
repl_result
2180
}
2281

2382
/// Reads, evaluates, and prints in a loop until EOF.

0 commit comments

Comments
 (0)