valis_core/modules/script/
repl.rs1use std::borrow::Cow::{self, Borrowed, Owned};
2
3use rlua::Lua;
4use rustyline::{CompletionType, Config, EditMode, Editor, Helper};
5use rustyline::completion::{Candidate, Completer};
6use rustyline::Context;
7use rustyline::highlight::Highlighter;
8use rustyline::hint::Hinter;
9use rustyline::validate::Validator;
10
11use crate::modules::script::engine::prepare_context;
12
13struct CustomCompleter {
14 commands: Vec<&'static str>,
15}
16
17impl Completer for CustomCompleter {
18 type Candidate = SimpleCandidate;
19
20 fn complete(
21 &self,
22 line: &str,
23 pos: usize,
24 _ctx: &Context<'_>,
25 ) -> Result<(usize, Vec<SimpleCandidate>), rustyline::error::ReadlineError> {
26 let mut candidates = Vec::new();
27 for command in &self.commands {
28 if command.starts_with(line) {
29 candidates.push(SimpleCandidate {
30 display: command.to_string(),
31 replacement: command[pos..].to_string(),
32 });
33 }
34 }
35
36 Ok((0, candidates))
37 }
38}
39
40#[derive(Debug, Clone)]
41struct SimpleCandidate {
42 display: String,
43 replacement: String,
44}
45
46impl Candidate for SimpleCandidate {
47 fn display(&self) -> &str {
48 &self.display
49 }
50
51 fn replacement(&self) -> &str {
52 &self.replacement
53 }
54}
55
56struct CustomHelper {
57 completer: CustomCompleter,
58}
59
60impl Helper for CustomHelper {}
61
62impl Completer for CustomHelper {
63 type Candidate = SimpleCandidate;
64
65 fn complete(
66 &self,
67 line: &str,
68 pos: usize,
69 ctx: &Context<'_>,
70 ) -> Result<(usize, Vec<SimpleCandidate>), rustyline::error::ReadlineError> {
71 self.completer.complete(line, pos, ctx)
72 }
73}
74
75impl Hinter for CustomHelper {
76 type Hint = String;
77
78 fn hint(&self, _line: &str, _pos: usize, _ctx: &Context<'_>) -> Option<String> {
79 None
80 }
81}
82
83impl Highlighter for CustomHelper {
84 fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
85 Borrowed(line)
86 }
87
88 fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
89 Borrowed(hint)
90 }
91}
92
93impl Validator for CustomHelper {}
94
95pub fn repl() {
97 let config = Config::builder()
98 .edit_mode(EditMode::Emacs)
99 .completion_type(CompletionType::List)
100 .build();
101
102 let commands = vec!["git_clone", "run"];
103 let completer = CustomCompleter { commands };
104
105 let helper = CustomHelper { completer };
106 let mut editor = Editor::with_config(config);
107 editor.set_helper(Some(helper));
108
109 let lua = Lua::new();
110 lua.context(|lua_ctx| {
111 prepare_context(&lua_ctx);
112 let prelude = include_str!("prelude.lua");
113 lua_ctx.load(prelude).exec().unwrap();
114 });
115
116 loop {
117 let readline = editor.readline(">> ");
118 match readline {
119 Ok(line) => {
120 editor.add_history_entry(line.as_str());
121 if line.trim() == "quit" {
122 break;
123 }
124 lua.context(|lua_ctx| match lua_ctx.load(line.as_str()).exec() {
126 Ok(_) => {}
127 Err(e) => {
128 eprintln!("Error: {}", e);
129 }
130 });
131 }
132 Err(_) => break,
133 }
134 }
135}