use crate::session::COMMANDS;
use plg_frontend::stdlib_predicates;
use plg_shared::builtins::{atom_names, functor_names};
pub fn candidates(prefix: &str, session_preds: &[String]) -> Vec<String> {
let mut out: Vec<String> = atom_names()
.map(str::to_string)
.chain(functor_names().map(|(n, _)| n.to_string()))
.chain(stdlib_predicates().iter().map(|(n, _)| n.clone()))
.chain(session_preds.iter().cloned())
.filter(|c| c.starts_with(prefix))
.collect();
out.sort();
out.dedup();
out
}
pub fn command_candidates(prefix: &str) -> Vec<String> {
let mut out: Vec<String> = COMMANDS
.iter()
.map(|c| c.name)
.filter(|n| n.starts_with(prefix))
.map(str::to_string)
.collect();
out.sort();
out.dedup();
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn command_candidates_by_prefix() {
assert_eq!(command_candidates("l"), ["list", "load"]);
assert_eq!(command_candidates("e"), ["edit"]);
assert_eq!(command_candidates("sav"), ["save"]);
assert_eq!(command_candidates("x"), Vec::<String>::new());
}
#[test]
fn command_candidates_empty_prefix_offers_all_sorted() {
assert_eq!(
command_candidates(""),
["edit", "help", "list", "load", "quit", "reset", "save"]
);
}
#[test]
fn command_candidates_return_canonical_not_aliases() {
assert!(!command_candidates("l").contains(&"ls".to_string()));
}
#[test]
fn predicate_candidates_include_stdlib() {
let cands = candidates("", &[]);
for name in [
"append", "member", "length", "reverse", "nth0", "nth1", "last",
] {
assert!(cands.iter().any(|c| c == name), "stdlib {name} missing");
}
}
#[test]
fn predicate_candidates_filter_by_prefix() {
let cands = candidates("app", &[]);
assert!(cands.iter().any(|c| c == "append"));
assert!(cands.iter().all(|c| c.starts_with("app")));
}
}