From 979837b297d96102c13816db3c274d0ed896ec69 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Sun, 12 Sep 2021 02:02:57 +0900 Subject: [PATCH] complete --- src/components/completion.rs | 3 +- src/components/table_filter.rs | 136 +++++++++++++++++---------------- 2 files changed, 72 insertions(+), 67 deletions(-) diff --git a/src/components/completion.rs b/src/components/completion.rs index 2388c0e..b0d7cea 100644 --- a/src/components/completion.rs +++ b/src/components/completion.rs @@ -26,13 +26,12 @@ impl CompletionComponent { key_config, state: ListState::default(), word: word.into(), - candidates: Vec::new(), + candidates: RESERVED_WORDS.iter().map(|w| w.to_string()).collect(), } } pub fn update(&mut self, word: impl Into) { self.word = word.into(); - self.candidates = RESERVED_WORDS.iter().map(|w| w.to_string()).collect(); self.state.select(None); self.state.select(Some(0)) } diff --git a/src/components/table_filter.rs b/src/components/table_filter.rs index 2476be4..5112e17 100644 --- a/src/components/table_filter.rs +++ b/src/components/table_filter.rs @@ -63,6 +63,70 @@ impl TableFilterComponent { self.completion .update(input.last().unwrap_or(&String::new())); } + + fn complete(&mut self) -> anyhow::Result { + if let Some(candidate) = self.completion.selected_candidate() { + let mut input = Vec::new(); + let first = self + .input + .iter() + .enumerate() + .filter(|(i, _)| i < &self.input_idx.saturating_sub(self.completion.word().len())) + .map(|(_, c)| c.to_string()) + .collect::>(); + let last = self + .input + .iter() + .enumerate() + .filter(|(i, _)| i >= &self.input_idx) + .map(|(_, c)| c.to_string()) + .collect::>(); + + let is_last_word = last.first().map_or(false, |c| c == &" ".to_string()); + + let middle = if is_last_word { + candidate + .chars() + .map(|c| c.to_string()) + .collect::>() + } else { + let mut c = candidate + .chars() + .map(|c| c.to_string()) + .collect::>(); + c.push(" ".to_string()); + c + }; + + input.extend(first); + input.extend(middle.clone()); + input.extend(last); + + self.input = input.join("").chars().collect(); + self.input_idx += &middle.len(); + if is_last_word { + self.input_idx += 1; + } + self.input_idx -= self.completion.word().len(); + self.input_cursor_position += middle + .join("") + .chars() + .map(compute_character_width) + .sum::(); + if is_last_word { + self.input_cursor_position += " ".to_string().width() as u16 + } + self.input_cursor_position -= self + .completion + .word() + .chars() + .map(compute_character_width) + .sum::(); + self.update_completion(); + return Ok(EventState::Consumed); + } + Ok(EventState::NotConsumed) + } } impl DrawableComponent for TableFilterComponent { @@ -132,69 +196,7 @@ impl Component for TableFilterComponent { // apply comletion candidates if key == self.key_config.enter { - if let Some(candidate) = self.completion.selected_candidate() { - let mut input = Vec::new(); - - let first = self - .input - .iter() - .enumerate() - .filter(|(i, _)| { - i < &self.input_idx.saturating_sub(self.completion.word().len()) - }) - .map(|(_, c)| c.to_string()) - .collect::>(); - - let last = self - .input - .iter() - .enumerate() - .filter(|(i, _)| i >= &self.input_idx) - .map(|(_, c)| c.to_string()) - .collect::>(); - - let is_last_word = last.first().map_or(false, |c| c == &" ".to_string()); - let middle = if is_last_word { - candidate - .chars() - .map(|c| c.to_string()) - .collect::>() - } else { - let mut c = candidate - .chars() - .map(|c| c.to_string()) - .collect::>(); - c.push(" ".to_string()); - c - }; - - input.extend(first); - input.extend(middle.clone()); - input.extend(last); - - self.input = input.join("").chars().collect(); - self.input_idx += &middle.len(); - if is_last_word { - self.input_idx += 1; - } - self.input_idx -= self.completion.word().len(); - self.input_cursor_position += middle - .join("") - .chars() - .map(compute_character_width) - .sum::(); - if is_last_word { - self.input_cursor_position += " ".to_string().width() as u16 - } - self.input_cursor_position -= self - .completion - .word() - .chars() - .map(compute_character_width) - .sum::(); - self.update_completion(); - return Ok(EventState::Consumed); - } + self.complete()?; } self.completion.selected_candidate(); @@ -259,9 +261,13 @@ impl Component for TableFilterComponent { mod test { use super::{KeyConfig, TableFilterComponent}; - fn test_update_completion() { + #[test] + fn test_complete() { let mut filter = TableFilterComponent::new(KeyConfig::default()); filter.input_idx = 3; - filter.input = vec!['a', 'b', ' ', 'c', 'd', 'e', 'f', 'g'] + filter.input = vec!['a', 'b', ' ', 'c', 'd', 'e', 'f', 'g']; + filter.completion.state.select(Some(0)); + assert!(filter.complete().is_ok()); + assert_eq!(filter.input, vec!['a', 'b', ' ', 'c', 'd', 'e', 'f', 'g']); } }