@@ -152,8 +152,46 @@ pub mod completers {
155− // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
156 pub fn filename(input: &str) -> Vec<Completion> {
155 pub fn filename(input: &str) -> Vec<Completion> {
156+ filename_impl(input, |entry| {
157+ let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
160+ FileMatch::AcceptIncomplete
167+ pub fn directory(input: &str) -> Vec<Completion> {
168+ filename_impl(input, |entry| {
169+ let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
179+ #[derive(Copy, Clone, PartialEq, Eq)]
181+ /// Entry should be ignored
183+ /// Entry is usable but can't be the end (for instance if the entry is a directory and we
184+ /// try to match a file)
186+ /// Entry is usable and can be the end of the match
190+ // TODO: we could return an iter/lazy thing so it can fetch as many as it needs.
191+ fn filename_impl<F>(input: &str, filter_fn: F) -> Vec<Completion>
193+ F: Fn(&ignore::DirEntry) -> FileMatch,
157 // Rust's filename handling is really annoying.
195 // Rust's filename handling is really annoying.
159 use ignore::WalkBuilder;
197 use ignore::WalkBuilder;
@@ -184,7 +222,13 @@ pub mod completers {
184 .max_depth(Some(1))
222 .max_depth(Some(1))
186 .filter_map(|file| {
224 .filter_map(|file| {
187− file.ok().map(|entry| {
225+ file.ok().and_then(|entry| {
226+ let fmatch = filter_fn(&entry);
228+ if fmatch == FileMatch::Reject {
188 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
232 let is_dir = entry.file_type().map_or(false, |entry| entry.is_dir());
190 let path = entry.path();
234 let path = entry.path();
@@ -199,11 +243,12 @@ pub mod completers {
199 path.strip_prefix(&dir).unwrap_or(path).to_path_buf()
243 path.strip_prefix(&dir).unwrap_or(path).to_path_buf()
202− if is_dir {
246+ if fmatch == FileMatch::AcceptIncomplete {
203 path.push("");
247 path.push("");
205 let path = path.to_str().unwrap().to_owned();
250 let path = path.to_str().unwrap().to_owned();
206− (end.clone(), Cow::from(path))
251+ Some((end.clone(), Cow::from(path)))
208 }) // TODO: unwrap or skip
253 }) // TODO: unwrap or skip
209 .filter(|(_, path)| !path.is_empty()) // TODO
254 .filter(|(_, path)| !path.is_empty()) // TODO