| 551 | } |
| 552 | |
| 553 | pub fn rl( |
| 554 | os: &Os, |
| 555 | sender: PromptQuerySender, |
| 556 | receiver: PromptQueryResponseReceiver, |
| 557 | paste_state: PasteState, |
| 558 | ) -> Result<Editor<ChatHelper, FileHistory>> { |
| 559 | let edit_mode = match os.database.settings.get_string(Setting::ChatEditMode).as_deref() { |
| 560 | Some("vi" | "vim") => EditMode::Vi, |
| 561 | _ => EditMode::Emacs, |
| 562 | }; |
| 563 | let config = Config::builder() |
| 564 | .history_ignore_space(true) |
| 565 | .completion_type(CompletionType::List) |
| 566 | .edit_mode(edit_mode) |
| 567 | .build(); |
| 568 | |
| 569 | let history_hints_enabled = os |
| 570 | .database |
| 571 | .settings |
| 572 | .get_bool(Setting::ChatEnableHistoryHints) |
| 573 | .unwrap_or(false); |
| 574 | |
| 575 | let history_path = PathResolver::new(os).global().cli_bash_history()?; |
| 576 | |
| 577 | // Generate available commands based on enabled experiments |
| 578 | let available_commands = get_available_commands(os); |
| 579 | |
| 580 | let h = ChatHelper { |
| 581 | completer: ChatCompleter::new(sender, receiver, available_commands.clone()), |
| 582 | hinter: ChatHinter::new(history_hints_enabled, history_path, available_commands), |
| 583 | validator: MultiLineValidator, |
| 584 | }; |
| 585 | |
| 586 | let mut rl = Editor::with_config(config)?; |
| 587 | rl.set_helper(Some(h)); |
| 588 | |
| 589 | // Load history from CLI bash history file |
| 590 | if let Err(e) = rl.load_history(&rl.helper().unwrap().get_history_path()) { |
| 591 | if !matches!(e, ReadlineError::Io(ref io_err) if io_err.kind() == std::io::ErrorKind::NotFound) { |
| 592 | eprintln!("Warning: Failed to load history: {}", e); |
| 593 | } |
| 594 | } |
| 595 | |
| 596 | // Add custom keybinding for Ctrl+D to open delegate command (configurable) |
| 597 | if ExperimentManager::is_enabled(os, ExperimentName::Delegate) { |
| 598 | if let Some(key) = os.database.settings.get_string(Setting::DelegateModeKey) { |
| 599 | if key.len() == 1 { |
| 600 | rl.bind_sequence( |
| 601 | KeyEvent(KeyCode::Char(key.chars().next().unwrap()), Modifiers::CTRL), |
| 602 | EventHandler::Simple(Cmd::Insert(1, "/delegate ".to_string())), |
| 603 | ); |
| 604 | } |
| 605 | }; |
| 606 | } |
| 607 | |
| 608 | // Add custom keybinding for Alt+Enter to insert a newline |
| 609 | rl.bind_sequence( |
| 610 | KeyEvent(KeyCode::Enter, Modifiers::ALT), |