use std::collections::HashMap;
use std::marker::PhantomData;
use mg_settings::{EnumMetaData, SettingCompletion};
use completion::{Completer, CompletionResult};
pub struct CommandCompleter<T: Clone> {
metadata: Vec<(String, String)>,
_phantom: PhantomData<T>,
}
impl<T: Clone + EnumMetaData> CommandCompleter<T> {
#[allow(unknown_lints, new_without_default_derive)]
pub fn new() -> CommandCompleter<T> {
let mut data: Vec<_> =
T::get_metadata().iter()
.filter(|&(_, metadata)| !metadata.completion_hidden)
.map(|(setting_name, metadata)| (setting_name.clone(), metadata.help_text.clone()))
.collect();
data.push(("map".to_string(), "Create a new key binding".to_string()));
data.push(("set".to_string(), "Change the value of a setting".to_string()));
data.push(("unmap".to_string(), "Delete a key binding".to_string()));
data.sort();
CommandCompleter {
metadata: data,
_phantom: PhantomData,
}
}
}
impl<T: Clone> Completer for CommandCompleter<T> {
fn completions(&mut self, input: &str) -> Vec<CompletionResult> {
self.metadata.iter()
.filter(|&&(ref command, ref help)|
command.to_lowercase().contains(&input) ||
help.to_lowercase().contains(&input))
.map(|&(ref col1, ref col2)| CompletionResult::new(&[col1, col2]))
.collect()
}
}
pub struct NoCompleter {
}
impl NoCompleter {
#[allow(unknown_lints, new_without_default_derive)]
pub fn new() -> Self {
NoCompleter {
}
}
}
impl Completer for NoCompleter {
fn complete_result(&self, _value: &str) -> String {
String::new()
}
fn completions(&mut self, _input: &str) -> Vec<CompletionResult> {
vec![]
}
}
pub struct SettingCompleter<T> {
selected_name: Option<String>,
setting_names: Vec<(String, String)>,
setting_values: HashMap<String, Vec<String>>,
_phantom: PhantomData<T>,
}
impl<T: EnumMetaData + SettingCompletion> SettingCompleter<T> {
#[allow(unknown_lints, new_without_default_derive)]
pub fn new() -> Self {
let mut data: Vec<_> =
T::get_metadata().iter()
.filter(|&(_, metadata)| !metadata.completion_hidden)
.map(|(setting_name, metadata)| (setting_name.clone(), metadata.help_text.clone()))
.collect();
data.sort();
SettingCompleter {
selected_name: None,
setting_names: data,
setting_values: T::get_value_completions(),
_phantom: PhantomData,
}
}
}
impl<T> Completer for SettingCompleter<T> {
fn complete_result(&self, value: &str) -> String {
if let Some(ref name) = self.selected_name {
format!("set {} = {}", name, value)
}
else {
format!("set {} =", value)
}
}
fn completions(&mut self, input: &str) -> Vec<CompletionResult> {
if input.contains("= ") {
let mut iter = input.split_whitespace();
if let Some(name) = iter.next() {
if let Some(values) = self.setting_values.get(name) {
iter.next(); let input_value = iter.next().unwrap_or_default();
self.selected_name = Some(name.to_string());
return values.iter()
.filter(|value| value.contains(input_value))
.map(|value| CompletionResult::new(&[value, &String::new()]))
.collect();
}
}
vec![]
}
else {
let input = input.trim();
self.selected_name = None;
self.setting_names.iter()
.filter(|&&(ref setting, ref help)|
setting.to_lowercase().contains(input) ||
help.to_lowercase().contains(input))
.map(|&(ref col1, ref col2)| CompletionResult::new(&[col1, col2]))
.collect()
}
}
}