2020-09-02 00:10:29 +02:00
|
|
|
use std::path::PathBuf;
|
2020-08-21 21:37:51 +02:00
|
|
|
|
|
|
|
use crate::completion::{Context, Suggestion};
|
|
|
|
|
2020-08-31 04:28:09 +02:00
|
|
|
const SEP: char = std::path::MAIN_SEPARATOR;
|
2020-08-21 21:37:51 +02:00
|
|
|
|
2020-08-31 04:28:09 +02:00
|
|
|
pub struct Completer;
|
2020-08-21 21:37:51 +02:00
|
|
|
|
2020-09-05 04:10:26 +02:00
|
|
|
pub struct PathSuggestion {
|
|
|
|
pub(crate) path: PathBuf,
|
|
|
|
pub(crate) suggestion: Suggestion,
|
|
|
|
}
|
|
|
|
|
2020-08-31 04:28:09 +02:00
|
|
|
impl Completer {
|
2020-09-05 04:10:26 +02:00
|
|
|
pub fn path_suggestions(&self, _ctx: &Context<'_>, partial: &str) -> Vec<PathSuggestion> {
|
2020-08-21 21:37:51 +02:00
|
|
|
let expanded = nu_parser::expand_ndots(partial);
|
2020-08-31 04:28:09 +02:00
|
|
|
let expanded = expanded.as_ref();
|
|
|
|
|
|
|
|
let (base_dir_name, partial) = match expanded.rfind(SEP) {
|
|
|
|
Some(pos) => expanded.split_at(pos + SEP.len_utf8()),
|
|
|
|
None => ("", expanded),
|
|
|
|
};
|
|
|
|
|
|
|
|
let base_dir = if base_dir_name == "" {
|
2020-09-02 00:10:29 +02:00
|
|
|
PathBuf::from(".")
|
|
|
|
} else if base_dir_name == format!("~{}", SEP) {
|
|
|
|
#[cfg(feature = "directories")]
|
|
|
|
{
|
|
|
|
dirs::home_dir().unwrap_or_else(|| PathBuf::from("~"))
|
|
|
|
}
|
|
|
|
#[cfg(not(feature = "directories"))]
|
|
|
|
{
|
|
|
|
PathBuf::from("~")
|
|
|
|
}
|
2020-08-31 04:28:09 +02:00
|
|
|
} else {
|
2020-09-02 00:10:29 +02:00
|
|
|
PathBuf::from(base_dir_name)
|
2020-08-31 04:28:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
if let Ok(result) = base_dir.read_dir() {
|
|
|
|
result
|
|
|
|
.filter_map(|entry| {
|
|
|
|
entry.ok().and_then(|entry| {
|
|
|
|
let mut file_name = entry.file_name().to_string_lossy().into_owned();
|
|
|
|
if file_name.starts_with(partial) {
|
|
|
|
let mut path = format!("{}{}", base_dir_name, file_name);
|
|
|
|
if entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false) {
|
|
|
|
path.push(std::path::MAIN_SEPARATOR);
|
|
|
|
file_name.push(std::path::MAIN_SEPARATOR);
|
|
|
|
}
|
2020-08-21 21:37:51 +02:00
|
|
|
|
2020-09-05 04:10:26 +02:00
|
|
|
Some(PathSuggestion {
|
|
|
|
path: entry.path(),
|
|
|
|
suggestion: Suggestion {
|
|
|
|
replacement: path,
|
|
|
|
display: file_name,
|
|
|
|
},
|
2020-08-31 04:28:09 +02:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
})
|
2020-08-21 21:37:51 +02:00
|
|
|
})
|
|
|
|
.collect()
|
|
|
|
} else {
|
|
|
|
Vec::new()
|
|
|
|
}
|
|
|
|
}
|
2020-09-05 04:10:26 +02:00
|
|
|
|
|
|
|
pub fn complete(&self, ctx: &Context<'_>, partial: &str) -> Vec<Suggestion> {
|
|
|
|
self.path_suggestions(ctx, partial)
|
|
|
|
.into_iter()
|
|
|
|
.map(|v| v.suggestion)
|
|
|
|
.collect()
|
|
|
|
}
|
2020-08-21 21:37:51 +02:00
|
|
|
}
|