sexprs_repl/
lib.rs

1#![allow(unused)]
2pub mod errors;
3use std::borrow::Cow;
4
5pub use errors::{Error, Result};
6use sexprs_formatter::highlight;
7use sexprs_parser::parse_source;
8use sexprs_util::dbg;
9use sexprs_vm::VirtualMachine;
10use rustyline::completion::{Candidate, Completer};
11use rustyline::highlight::{CmdKind, Highlighter};
12use rustyline::hint::{Hint, Hinter};
13use rustyline::line_buffer::LineBuffer;
14use rustyline::validate::{ValidationContext, ValidationResult, Validator};
15use rustyline::{Changeset, CompletionType, Context, Helper};
16
17pub struct VirtualMachinePrompt<'c> {
18    pub vm: &'c VirtualMachine<'c>,
19}
20impl<'c> VirtualMachinePrompt<'c> {
21    pub fn new(vm: &VirtualMachine<'c>) -> VirtualMachinePrompt<'c> {
22        VirtualMachinePrompt {
23            vm: unsafe {
24                std::mem::transmute::<&VirtualMachine, &'c VirtualMachine>(vm)
25            },
26        }
27    }
28}
29impl<'c> Highlighter for VirtualMachinePrompt<'c> {
30    fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
31        Cow::from(
32            highlight(line.to_string(), "lisp")
33                .unwrap_or_else(|_| line.to_string()),
34        )
35    }
36
37    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
38        &'s self,
39        prompt: &'p str,
40        default: bool,
41    ) -> Cow<'b, str> {
42        // on new line
43        // dbg!(prompt, default);
44        Cow::from(prompt)
45    }
46
47    fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
48        // dbg!(hint);
49        // Cow::from(hint)
50        Cow::from(
51            highlight(hint.to_string(), "list")
52                .unwrap_or_else(|_| hint.to_string()),
53        )
54    }
55
56    fn highlight_candidate<'h>(
57        &self,
58        candidate: &'h str,
59        completion: CompletionType,
60    ) -> Cow<'h, str> {
61        dbg!(candidate, completion);
62        Cow::from(candidate)
63    }
64
65    fn highlight_char(&self, line: &str, pos: usize, kind: CmdKind) -> bool {
66        // on key change
67        // dbg!(line, pos, &kind);
68        false
69    }
70}
71
72pub struct DummyHint {
73    display: String,
74    completion: String,
75}
76impl DummyHint {
77    pub fn new(display: String, completion: String) -> DummyHint {
78        DummyHint {
79            display,
80            completion,
81        }
82    }
83}
84
85impl Hint for DummyHint {
86    fn display(&self) -> &str {
87        self.display.clone().leak()
88    }
89
90    fn completion(&self) -> Option<&str> {
91        Some(self.completion.clone().leak())
92    }
93}
94
95impl<'c> Hinter for VirtualMachinePrompt<'c> {
96    type Hint = DummyHint;
97
98    fn hint(
99        &self,
100        line: &str,
101        pos: usize,
102        ctx: &Context<'_>,
103    ) -> Option<Self::Hint> {
104        None
105        // dbg!(line, pos);
106        // Some(DummyHint::new(
107        //     "dummy_hint_display".to_string(),
108        //     "dummy_hint_completion".to_string(),
109        // ))
110    }
111}
112
113pub struct DummyCandidate {
114    display: String,
115    replacement: String,
116}
117impl DummyCandidate {
118    pub fn new(display: String, replacement: String) -> DummyCandidate {
119        DummyCandidate {
120            display,
121            replacement,
122        }
123    }
124}
125
126impl Candidate for DummyCandidate {
127    fn display(&self) -> &str {
128        self.display.clone().leak()
129    }
130
131    fn replacement(&self) -> &str {
132        self.replacement.clone().leak()
133    }
134}
135
136impl<'c> Completer for VirtualMachinePrompt<'c> {
137    type Candidate = DummyCandidate;
138
139    fn complete(
140        &self,
141        line: &str,
142        pos: usize,
143        ctx: &Context<'_>,
144    ) -> rustyline::Result<(usize, Vec<Self::Candidate>)> {
145        // on tab
146        // dbg!(line, pos);
147        // if line.contains("dummy") {
148        //     Ok((
149        //         1,
150        //         vec![DummyCandidate::new(
151        //             "dummy_candidate_display".to_string(),
152        //             "dummy_candidate_replacement".to_string(),
153        //         )],
154        //     ))
155        // } else {
156        //     Ok((0, Vec::new()))
157        // }
158        Ok((0, Vec::new()))
159    }
160
161    fn update(
162        &self,
163        line: &mut LineBuffer,
164        start: usize,
165        elected: &str,
166        cl: &mut Changeset,
167    ) {
168        dbg!(line, start, elected);
169    }
170}
171
172impl<'c> Validator for VirtualMachinePrompt<'c> {
173    fn validate(
174        &self,
175        ctx: &mut ValidationContext<'_>,
176    ) -> rustyline::Result<ValidationResult> {
177        // ValidationResult::Incomplete,
178        // ValidationResult::Invalid(Option<String>),
179        // ValidationResult::Valid(Option<String>),
180        // dbg!(ctx);
181        match parse_source(ctx.input()) {
182            Ok(value) => Ok(ValidationResult::Valid(None)),
183            // Ok(value) => Ok(ValidationResult::Valid(Some(format!(" ;; ok.\n")))),
184            Err(e) => Ok(ValidationResult::Invalid(Some(e.to_string()))),
185        }
186    }
187
188    fn validate_while_typing(&self) -> bool {
189        true
190    }
191}
192
193impl<'c> Helper for VirtualMachinePrompt<'c> {}