xtask_todo_lib/devshell/completion/
helper.rs1use std::borrow::Cow;
4use std::cell::RefCell;
5use std::rc::Rc;
6
7use rustyline::completion::Completer;
8use rustyline::highlight::Highlighter;
9use rustyline::hint::{Hint, Hinter};
10use rustyline::validate::{ValidationContext, ValidationResult, Validator};
11use rustyline::Context;
12use rustyline::Helper;
13
14use super::super::vfs::Vfs;
15use super::super::vm::SessionHolder;
16use super::candidates::{complete_commands, complete_path, list_dir_names_for_completion};
17use super::context::{completion_context, CompletionKind};
18
19pub struct DevShellHelper {
21 pub vfs: Rc<RefCell<Vfs>>,
22 pub vm_session: Rc<RefCell<SessionHolder>>,
23}
24
25impl DevShellHelper {
26 #[must_use]
27 pub const fn new(vfs: Rc<RefCell<Vfs>>, vm_session: Rc<RefCell<SessionHolder>>) -> Self {
28 Self { vfs, vm_session }
29 }
30}
31
32#[derive(Debug)]
34pub struct NoHint;
35impl Hint for NoHint {
36 fn display(&self) -> &'static str {
37 ""
38 }
39 fn completion(&self) -> Option<&str> {
40 None
41 }
42}
43
44impl Completer for DevShellHelper {
45 type Candidate = String;
46
47 fn complete(
48 &self,
49 line: &str,
50 pos: usize,
51 _ctx: &Context<'_>,
52 ) -> Result<(usize, Vec<String>), rustyline::error::ReadlineError> {
53 let Some(ctx) = completion_context(line, pos) else {
54 return Ok((pos, vec![]));
55 };
56 let candidates = match ctx.kind {
57 CompletionKind::Command => complete_commands(&ctx.prefix),
58 CompletionKind::Other => vec![],
59 CompletionKind::Path => {
60 let parent = if ctx.prefix.contains('/') {
61 let idx = ctx.prefix.rfind('/').unwrap();
62 if idx == 0 {
63 "/".to_string()
64 } else {
65 ctx.prefix[..idx].to_string()
66 }
67 } else {
68 ".".to_string()
69 };
70 let abs_parent = self.vfs.borrow().resolve_to_absolute(&parent);
71 let names = list_dir_names_for_completion(&self.vfs, &self.vm_session, &abs_parent);
72 complete_path(&ctx.prefix, &names)
73 }
74 };
75 Ok((ctx.start, candidates))
76 }
77}
78
79impl Hinter for DevShellHelper {
80 type Hint = NoHint;
81
82 fn hint(&self, _line: &str, _pos: usize, _ctx: &Context<'_>) -> Option<NoHint> {
83 None
84 }
85}
86
87impl Highlighter for DevShellHelper {
88 fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> {
89 Cow::Borrowed(line)
90 }
91}
92
93impl Validator for DevShellHelper {
94 fn validate(
95 &self,
96 _ctx: &mut ValidationContext<'_>,
97 ) -> Result<ValidationResult, rustyline::error::ReadlineError> {
98 Ok(ValidationResult::Valid(None))
99 }
100}
101
102impl Helper for DevShellHelper {}