use crate::*; use std::{env, fs}; pub struct Suggestion { pub display: BString, pub delta: BString, } fn _path_completion(mut prefix: BString) -> io::Result> { let mut partial_entry = BString::new(); while let Some(c) = prefix.last().cloned() { if c == b'/' { break; } partial_entry.push(c); prefix.pop(); } partial_entry.reverse(); let mut sugs = Vec::new(); if prefix.is_empty() { prefix.push(b'.'); } for entry in fs::read_dir(OsStr::from_bytes(&prefix))? { let entry = entry?; let name = entry.file_name().as_bytes().to_vec(); if name.starts_with(&partial_entry) { let mut delta = name[partial_entry.len()..].to_vec(); let is_dir = entry.metadata().map(|m| m.is_dir()).unwrap_or(false); if is_dir { delta.push(b'/'); } else { delta.push(b' '); } sugs.push(Suggestion { display: name, delta, }); } } Ok(sugs) } pub fn path_completion(prefix: BString) -> Vec { match _path_completion(prefix) { Ok(suggestions) => suggestions, Err(err) => { println!("path completion failed: {err:?}\r"); Vec::new() } } } pub fn variable_completion(session: Arc>, prefix: BString) -> Vec { let se = session.lock().unwrap(); let mut out = Vec::new(); for var in se.vars.keys() { if var.starts_with(&prefix) { out.push(Suggestion { display: var.to_vec(), delta: var[prefix.len()..].to_vec(), }); } } drop(se); for var in env::vars_os() { let var = var.0.as_bytes(); if var.starts_with(&prefix) { out.push(Suggestion { display: var.to_vec(), delta: var[prefix.len()..].to_vec(), }); } } out } pub fn command_completion(session: Arc>, prefix: BString) -> Vec { let se = session.lock().unwrap(); let mut out = Vec::new(); for fun in se.funs.keys().chain(se.builtins.keys()) { if fun.starts_with(&prefix) { out.push(Suggestion { display: fun.to_vec(), delta: fun[prefix.len()..].to_vec(), }) } } for s in out.iter_mut() { s.delta.push(b' '); } out }