Skip to content

Commit da8dc7b

Browse files
authored
Adding boolean setting for history hints (#429)
1 parent 10a32bb commit da8dc7b

File tree

2 files changed

+85
-17
lines changed

2 files changed

+85
-17
lines changed

crates/chat-cli/src/cli/chat/prompt.rs

Lines changed: 82 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -217,12 +217,23 @@ impl Completer for ChatCompleter {
217217
pub struct ChatHinter {
218218
/// Command history for providing suggestions based on past commands
219219
history: Vec<String>,
220+
/// Whether history-based hints are enabled
221+
history_hints_enabled: bool,
220222
}
221223

222224
impl ChatHinter {
223225
/// Creates a new ChatHinter instance
224-
pub fn new() -> Self {
225-
Self { history: Vec::new() }
226+
pub fn new(os: &Os) -> Self {
227+
let history_hints_enabled = os
228+
.database
229+
.settings
230+
.get_bool(Setting::ChatEnableHistoryHints)
231+
.unwrap_or(false);
232+
233+
Self {
234+
history: Vec::new(),
235+
history_hints_enabled,
236+
}
226237
}
227238

228239
/// Updates the history with a new command
@@ -247,12 +258,16 @@ impl ChatHinter {
247258
.map(|cmd| cmd[line.len()..].to_string());
248259
}
249260

250-
// Try to find a hint from history
251-
self.history
252-
.iter()
253-
.rev() // Start from most recent
254-
.find(|cmd| cmd.starts_with(line) && cmd.len() > line.len())
255-
.map(|cmd| cmd[line.len()..].to_string())
261+
// Try to find a hint from history, but only if history hints are enabled
262+
if self.history_hints_enabled {
263+
self.history
264+
.iter()
265+
.rev() // Start from most recent
266+
.find(|cmd| cmd.starts_with(line) && cmd.len() > line.len())
267+
.map(|cmd| cmd[line.len()..].to_string())
268+
} else {
269+
None
270+
}
256271
}
257272
}
258273

@@ -370,7 +385,7 @@ pub fn rl(
370385
.build();
371386
let h = ChatHelper {
372387
completer: ChatCompleter::new(sender, receiver),
373-
hinter: ChatHinter::new(),
388+
hinter: ChatHinter::new(os),
374389
validator: MultiLineValidator,
375390
};
376391
let mut rl = Editor::with_config(config)?;
@@ -403,6 +418,23 @@ mod tests {
403418
use rustyline::highlight::Highlighter;
404419

405420
use super::*;
421+
422+
// Helper function to create a mock Os for testing
423+
fn create_mock_os() -> Os {
424+
use crate::database::settings::Settings;
425+
426+
Os {
427+
env: crate::os::Env::new(),
428+
fs: crate::os::Fs::new(),
429+
sysinfo: crate::os::SysInfo::new(),
430+
database: crate::database::Database {
431+
settings: Settings::default(),
432+
},
433+
client: crate::api_client::ApiClient::default(),
434+
telemetry: crate::telemetry::TelemetryThread::default(),
435+
}
436+
}
437+
406438
#[test]
407439
fn test_chat_completer_command_completion() {
408440
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
@@ -448,9 +480,10 @@ mod tests {
448480
fn test_highlight_prompt_basic() {
449481
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
450482
let (_, prompt_response_receiver) = std::sync::mpsc::channel::<Vec<String>>();
483+
let mock_os = create_mock_os();
451484
let helper = ChatHelper {
452485
completer: ChatCompleter::new(prompt_request_sender, prompt_response_receiver),
453-
hinter: ChatHinter::new(),
486+
hinter: ChatHinter::new(&mock_os),
454487
validator: MultiLineValidator,
455488
};
456489

@@ -464,9 +497,10 @@ mod tests {
464497
fn test_highlight_prompt_with_warning() {
465498
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
466499
let (_, prompt_response_receiver) = std::sync::mpsc::channel::<Vec<String>>();
500+
let mock_os = create_mock_os();
467501
let helper = ChatHelper {
468502
completer: ChatCompleter::new(prompt_request_sender, prompt_response_receiver),
469-
hinter: ChatHinter::new(),
503+
hinter: ChatHinter::new(&mock_os),
470504
validator: MultiLineValidator,
471505
};
472506

@@ -480,9 +514,10 @@ mod tests {
480514
fn test_highlight_prompt_with_profile() {
481515
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
482516
let (_, prompt_response_receiver) = std::sync::mpsc::channel::<Vec<String>>();
517+
let mock_os = create_mock_os();
483518
let helper = ChatHelper {
484519
completer: ChatCompleter::new(prompt_request_sender, prompt_response_receiver),
485-
hinter: ChatHinter::new(),
520+
hinter: ChatHinter::new(&mock_os),
486521
validator: MultiLineValidator,
487522
};
488523

@@ -496,9 +531,10 @@ mod tests {
496531
fn test_highlight_prompt_with_profile_and_warning() {
497532
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
498533
let (_, prompt_response_receiver) = std::sync::mpsc::channel::<Vec<String>>();
534+
let mock_os = create_mock_os();
499535
let helper = ChatHelper {
500536
completer: ChatCompleter::new(prompt_request_sender, prompt_response_receiver),
501-
hinter: ChatHinter::new(),
537+
hinter: ChatHinter::new(&mock_os),
502538
validator: MultiLineValidator,
503539
};
504540

@@ -515,9 +551,10 @@ mod tests {
515551
fn test_highlight_prompt_invalid_format() {
516552
let (prompt_request_sender, _) = std::sync::mpsc::channel::<Option<String>>();
517553
let (_, prompt_response_receiver) = std::sync::mpsc::channel::<Vec<String>>();
554+
let mock_os = create_mock_os();
518555
let helper = ChatHelper {
519556
completer: ChatCompleter::new(prompt_request_sender, prompt_response_receiver),
520-
hinter: ChatHinter::new(),
557+
hinter: ChatHinter::new(&mock_os),
521558
validator: MultiLineValidator,
522559
};
523560

@@ -529,7 +566,8 @@ mod tests {
529566

530567
#[test]
531568
fn test_chat_hinter_command_hint() {
532-
let hinter = ChatHinter::new();
569+
let mock_os = create_mock_os();
570+
let hinter = ChatHinter::new(&mock_os);
533571

534572
// Test hint for a command
535573
let line = "/he";
@@ -552,8 +590,15 @@ mod tests {
552590
}
553591

554592
#[test]
555-
fn test_chat_hinter_history_hint() {
556-
let mut hinter = ChatHinter::new();
593+
fn test_chat_hinter_history_hint_enabled() {
594+
let mut mock_os = create_mock_os();
595+
// Set the setting to true
596+
mock_os.database.settings.0.insert(
597+
Setting::ChatEnableHistoryHints.as_ref().to_string(),
598+
serde_json::Value::Bool(true),
599+
);
600+
601+
let mut hinter = ChatHinter::new(&mock_os);
557602

558603
// Add some history
559604
hinter.update_history("Hello, world!");
@@ -568,4 +613,24 @@ mod tests {
568613
let hint = hinter.hint(line, pos, &ctx);
569614
assert_eq!(hint, Some(" are you?".to_string()));
570615
}
616+
617+
#[test]
618+
fn test_chat_hinter_history_hint_disabled() {
619+
let mock_os = create_mock_os();
620+
621+
let mut hinter = ChatHinter::new(&mock_os);
622+
623+
// Add some history
624+
hinter.update_history("Hello, world!");
625+
hinter.update_history("How are you?");
626+
627+
// Test hint from history when disabled
628+
let line = "How";
629+
let pos = line.len();
630+
let empty_history = DefaultHistory::new();
631+
let ctx = Context::new(&empty_history);
632+
633+
let hint = hinter.hint(line, pos, &ctx);
634+
assert_eq!(hint, None);
635+
}
571636
}

crates/chat-cli/src/database/settings.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ pub enum Setting {
3434
McpLoadedBefore,
3535
ChatDefaultModel,
3636
ChatDisableAutoCompaction,
37+
ChatEnableHistoryHints,
3738
}
3839

3940
impl AsRef<str> for Setting {
@@ -56,6 +57,7 @@ impl AsRef<str> for Setting {
5657
Self::McpLoadedBefore => "mcp.loadedBefore",
5758
Self::ChatDefaultModel => "chat.defaultModel",
5859
Self::ChatDisableAutoCompaction => "chat.disableAutoCompaction",
60+
Self::ChatEnableHistoryHints => "chat.enableHistoryHints",
5961
}
6062
}
6163
}
@@ -88,6 +90,7 @@ impl TryFrom<&str> for Setting {
8890
"mcp.loadedBefore" => Ok(Self::McpLoadedBefore),
8991
"chat.defaultModel" => Ok(Self::ChatDefaultModel),
9092
"chat.disableAutoCompaction" => Ok(Self::ChatDisableAutoCompaction),
93+
"chat.enableHistoryHints" => Ok(Self::ChatEnableHistoryHints),
9194
_ => Err(DatabaseError::InvalidSetting(value.to_string())),
9295
}
9396
}

0 commit comments

Comments
 (0)