1use std::env;
4use std::fs;
5use std::path::{Path, PathBuf};
6
7use crate::{CompletionItem, Context};
8
9pub fn env_vars(_ctx: &Context, incomplete: &str) -> Vec<CompletionItem> {
11 let needle = incomplete.to_lowercase();
12 env::vars()
13 .filter(|(key, _)| key.to_lowercase().contains(&needle))
14 .map(|(key, _)| CompletionItem::new(key))
15 .collect()
16}
17
18pub fn directories(_ctx: &Context, incomplete: &str) -> Vec<CompletionItem> {
22 let (base_dir, prefix) = match incomplete.rsplit_once(std::path::MAIN_SEPARATOR) {
23 Some((parent, tail)) if !parent.is_empty() => (PathBuf::from(parent), tail),
24 _ => (PathBuf::from("."), incomplete),
25 };
26
27 fs::read_dir(&base_dir)
28 .into_iter()
29 .flatten()
30 .filter_map(|entry| entry.ok())
31 .filter_map(|entry| {
32 let path = entry.path();
33 if !path.is_dir() {
34 return None;
35 }
36
37 let name = entry.file_name().to_string_lossy().to_string();
38 if !name.starts_with(prefix) {
39 return None;
40 }
41
42 let value = if base_dir == Path::new(".") {
43 name
44 } else {
45 format!(
46 "{}{}{}",
47 base_dir.display(),
48 std::path::MAIN_SEPARATOR,
49 name
50 )
51 };
52 Some(CompletionItem::new(value))
53 })
54 .collect()
55}
56
57pub fn items(
59 values: &'static [&'static str],
60) -> impl Fn(&Context, &str) -> Vec<CompletionItem> + Send + Sync + 'static {
61 move |_ctx: &Context, incomplete: &str| {
62 values
63 .iter()
64 .copied()
65 .filter(|value| value.contains(incomplete))
66 .map(CompletionItem::new)
67 .collect()
68 }
69}
70
71pub fn items_with_help(
73 values: &'static [(&'static str, &'static str)],
74) -> impl Fn(&Context, &str) -> Vec<CompletionItem> + Send + Sync + 'static {
75 move |_ctx: &Context, incomplete: &str| {
76 values
77 .iter()
78 .copied()
79 .filter(|(value, help)| value.contains(incomplete) || help.contains(incomplete))
80 .map(|(value, help)| CompletionItem::new(value).with_help(help))
81 .collect()
82 }
83}