Skip to content

Commit 1ee82f9

Browse files
committed
cli: add shell history
Signed-off-by: Yuki Kishimoto <[email protected]>
1 parent 82918d3 commit 1ee82f9

File tree

4 files changed

+46
-5
lines changed

4 files changed

+46
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@
119119
* js(nostr): expose missing methods to `JsCoordinate` ([Yuki Kishimoto])
120120
* js(sdk): expose `RelayPool::relays` ([Yuki Kishimoto])
121121
* cli: add `serve` command ([Yuki Kishimoto])
122+
* cli: add shell history ([Yuki Kishimoto])
122123
* book: add some python examples ([RydalWater])
123124

124125
### Fixed

Cargo.lock

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

crates/nostr-cli/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ rust-version.workspace = true
77
[dependencies]
88
clap = { version = "4.5", features = ["derive"] }
99
dialoguer = "0.11"
10+
dirs = "5.0"
1011
nostr-relay-builder.workspace = true
1112
nostr-sdk = { workspace = true, features = ["all-nips", "lmdb"] }
1213
once_cell.workspace = true
1314
prettytable-rs = "0.10"
1415
regex = "1.9.6"
15-
rustyline = { version = "14.0", default-features = false }
16+
rustyline = { version = "14.0", default-features = false, features = ["with-file-history"] }
1617
serde_json = { workspace = true, features = ["std"] }
1718
tokio = { workspace = true, features = ["full"] }

crates/nostr-cli/src/main.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,17 @@
22
// Copyright (c) 2023-2024 Rust Nostr Developers
33
// Distributed under the MIT software license
44

5-
use std::fs::File;
5+
use std::fs::{self, File};
66
use std::io::{BufRead, BufReader};
7+
use std::path::PathBuf;
78
use std::time::Duration;
89

910
use clap::Parser;
1011
use nostr_relay_builder::prelude::*;
1112
use nostr_sdk::prelude::*;
1213
use rustyline::error::ReadlineError;
13-
use rustyline::DefaultEditor;
14+
use rustyline::history::FileHistory;
15+
use rustyline::{Config, Editor};
1416
use tokio::time::Instant;
1517

1618
mod cli;
@@ -30,7 +32,18 @@ async fn run() -> Result<()> {
3032

3133
match args.command {
3234
Command::Shell { relays } => {
33-
let db = NostrLMDB::open("./db/nostr-lmdb")?;
35+
// Get data dir
36+
let data_dir: PathBuf = dirs::data_dir().expect("Can't find data directory");
37+
38+
// Compose paths
39+
let nostr_cli_dir: PathBuf = data_dir.join("rust-nostr/cli");
40+
let db_path = nostr_cli_dir.join("data/lmdb");
41+
let history_path = nostr_cli_dir.join(".shell_history");
42+
43+
// Create main dir if not exists
44+
fs::create_dir_all(nostr_cli_dir)?;
45+
46+
let db = NostrLMDB::open(db_path)?;
3447
let client = Client::builder().database(db).build();
3548

3649
// Add relays
@@ -40,15 +53,25 @@ async fn run() -> Result<()> {
4053

4154
client.connect().await;
4255

43-
let rl = &mut DefaultEditor::new()?;
56+
let config = Config::builder().max_history_size(2000)?.build();
57+
let history = FileHistory::with_config(config);
58+
let rl: &mut Editor<(), FileHistory> = &mut Editor::with_history(config, history)?;
59+
60+
// Load history
61+
let _ = rl.load_history(&history_path);
4462

4563
loop {
4664
let readline = rl.readline("nostr> ");
4765
match readline {
4866
Ok(line) => {
67+
// Add to history
4968
rl.add_history_entry(line.as_str())?;
69+
70+
// Split command line
5071
let mut vec: Vec<String> = parser::split(&line)?;
5172
vec.insert(0, String::new());
73+
74+
// Parse command
5275
match ShellCommand::try_parse_from(vec) {
5376
Ok(command) => {
5477
if let Err(e) = handle_command(command, &client).await {
@@ -73,6 +96,9 @@ async fn run() -> Result<()> {
7396
}
7497
}
7598

99+
// Save history to file
100+
rl.save_history(&history_path)?;
101+
76102
Ok(())
77103
}
78104
Command::Serve => {

0 commit comments

Comments
 (0)