1use std::marker::PhantomData;
2
3use clap::Parser;
4use nu_ansi_term::{Color, Style};
5use reedline::{
6 default_emacs_keybindings, DefaultHinter, DefaultPrompt, EditMode, Emacs, IdeMenu,
7 KeyModifiers, MenuBuilder, Prompt, Reedline, ReedlineEvent, ReedlineMenu,
8};
9
10use crate::{ClapEditor, ReedCompleter};
11
12pub struct ClapEditorBuilder<C: Parser + Send + Sync + 'static> {
13 prompt: Box<dyn Prompt>,
14 edit_mode: Box<dyn EditMode>,
15 hook: Box<dyn FnOnce(Reedline) -> Reedline>,
16 c_phantom: PhantomData<C>,
17}
18
19impl<C: Parser + Send + Sync + 'static> ClapEditorBuilder<C> {
20 pub(crate) fn new() -> Self {
21 Self {
22 prompt: Box::<DefaultPrompt>::default(),
23 edit_mode: {
24 let mut keybindings = default_emacs_keybindings();
25 keybindings.add_binding(
26 KeyModifiers::NONE,
27 reedline::KeyCode::Tab,
28 ReedlineEvent::UntilFound(vec![
29 ReedlineEvent::Menu("completion_menu".to_string()),
30 ReedlineEvent::MenuNext,
31 ]),
32 );
33 Box::new(Emacs::new(keybindings))
34 },
35 hook: Box::new(|e| e),
36 c_phantom: PhantomData,
37 }
38 }
39
40 pub fn with_prompt(mut self, prompt: Box<dyn Prompt>) -> Self {
41 self.prompt = prompt;
42 self
43 }
44
45 pub fn with_edit_mode(mut self, edit_mode: Box<dyn EditMode>) -> Self {
46 self.edit_mode = edit_mode;
47 self
48 }
49
50 pub fn with_editor_hook(mut self, hook: impl FnOnce(Reedline) -> Reedline + 'static) -> Self {
51 self.hook = Box::new(hook);
52 self
53 }
54
55 pub fn build(self) -> ClapEditor<C> {
56 let completion_menu = Box::new(
57 IdeMenu::default()
58 .with_default_border()
59 .with_name("completion_menu"),
60 );
61
62 let rl = Reedline::create()
63 .with_completer(Box::new(ReedCompleter::<C> {
64 c_phantom: PhantomData,
65 }))
66 .with_menu(ReedlineMenu::EngineCompleter(completion_menu))
67 .with_hinter(Box::new(
68 DefaultHinter::default().with_style(Style::new().italic().fg(Color::DarkGray)),
69 ))
70 .with_edit_mode(self.edit_mode);
71 let rl = (self.hook)(rl);
72 ClapEditor {
73 rl,
74 prompt: self.prompt,
75 c_phantom: PhantomData,
76 }
77 }
78}