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!("{}{}{}", base_dir.display(), std::path::MAIN_SEPARATOR, name)
46 };
47 Some(CompletionItem::new(value))
48 })
49 .collect()
50}
51
52pub fn items(
54 values: &'static [&'static str],
55) -> impl Fn(&Context, &str) -> Vec<CompletionItem> + Send + Sync + 'static {
56 move |_ctx: &Context, incomplete: &str| {
57 values
58 .iter()
59 .copied()
60 .filter(|value| value.contains(incomplete))
61 .map(CompletionItem::new)
62 .collect()
63 }
64}
65
66pub fn items_with_help(
68 values: &'static [(&'static str, &'static str)],
69) -> impl Fn(&Context, &str) -> Vec<CompletionItem> + Send + Sync + 'static {
70 move |_ctx: &Context, incomplete: &str| {
71 values
72 .iter()
73 .copied()
74 .filter(|(value, help)| value.contains(incomplete) || help.contains(incomplete))
75 .map(|(value, help)| CompletionItem::new(value).with_help(help))
76 .collect()
77 }
78}