Skip to content

Commit 030c5f6

Browse files
authored
Merge pull request #142 from yvan-sraka/completion-feature
Implement a first proposal of a completion feature
2 parents 1b84eaf + e25c386 commit 030c5f6

File tree

5 files changed

+86
-0
lines changed

5 files changed

+86
-0
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ editor = ["tempfile"]
2121
fuzzy-select = ["fuzzy-matcher"]
2222
history = []
2323
password = ["zeroize"]
24+
completion = []
2425

2526
[dependencies]
2627
console = "0.15.0"
@@ -44,3 +45,7 @@ required-features = ["fuzzy-select"]
4445
[[example]]
4546
name = "history"
4647
required-features = ["history"]
48+
49+
[[example]]
50+
name = "completion"
51+
required-features = ["completion"]

examples/completion.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
use dialoguer::{theme::ColorfulTheme, Completion, Input};
2+
3+
fn main() -> Result<(), std::io::Error> {
4+
println!("Use the Right arrow or Tab to complete your command");
5+
let completion = MyCompletion::default();
6+
Input::<String>::with_theme(&ColorfulTheme::default())
7+
.with_prompt("dialoguer")
8+
.completion_with(&completion)
9+
.interact_text()?;
10+
Ok(())
11+
}
12+
13+
struct MyCompletion {
14+
options: Vec<String>,
15+
}
16+
17+
impl Default for MyCompletion {
18+
fn default() -> Self {
19+
MyCompletion {
20+
options: vec![
21+
"orange".to_string(),
22+
"apple".to_string(),
23+
"banana".to_string(),
24+
],
25+
}
26+
}
27+
}
28+
29+
impl Completion for MyCompletion {
30+
/// Simple completion implementation based on substring
31+
fn get(&self, input: &str) -> Option<String> {
32+
let s = input.to_string();
33+
let ss: Vec<&String> = self.options.iter().filter(|x| s == x[..s.len()]).collect();
34+
if ss.len() == 1 {
35+
Some(ss[0].to_string())
36+
} else {
37+
None
38+
}
39+
}
40+
}

src/completion.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/// Trait for completion handling.
2+
pub trait Completion {
3+
fn get(&self, input: &str) -> Option<String>;
4+
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
//! * Other kind of prompts
1919
//! * Editor launching
2020
21+
#[cfg(feature = "completion")]
22+
pub use completion::Completion;
2123
pub use console;
2224
#[cfg(feature = "editor")]
2325
pub use edit::Editor;
@@ -35,6 +37,8 @@ pub use prompts::fuzzy_select::FuzzySelect;
3537
#[cfg(feature = "password")]
3638
pub use prompts::password::Password;
3739

40+
#[cfg(feature = "completion")]
41+
mod completion;
3842
#[cfg(feature = "editor")]
3943
mod edit;
4044
#[cfg(feature = "history")]

src/prompts/input.rs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use std::{fmt::Debug, io, iter, str::FromStr};
22

3+
#[cfg(feature = "completion")]
4+
use crate::completion::Completion;
35
#[cfg(feature = "history")]
46
use crate::history::History;
57
use crate::{
@@ -45,6 +47,8 @@ pub struct Input<'a, T> {
4547
validator: Option<Box<dyn FnMut(&T) -> Option<String> + 'a>>,
4648
#[cfg(feature = "history")]
4749
history: Option<&'a mut dyn History<T>>,
50+
#[cfg(feature = "completion")]
51+
completion: Option<&'a dyn Completion>,
4852
}
4953

5054
impl<T> Default for Input<'static, T> {
@@ -114,6 +118,8 @@ impl<'a, T> Input<'a, T> {
114118
validator: None,
115119
#[cfg(feature = "history")]
116120
history: None,
121+
#[cfg(feature = "completion")]
122+
completion: None,
117123
}
118124
}
119125

@@ -166,6 +172,16 @@ impl<'a, T> Input<'a, T> {
166172
self.history = Some(history);
167173
self
168174
}
175+
176+
/// Enable completion
177+
#[cfg(feature = "completion")]
178+
pub fn completion_with<C>(&mut self, completion: &'a C) -> &mut Self
179+
where
180+
C: Completion,
181+
{
182+
self.completion = Some(completion);
183+
self
184+
}
169185
}
170186

171187
impl<'a, T> Input<'a, T>
@@ -297,6 +313,23 @@ where
297313
position += 1;
298314
term.flush()?;
299315
}
316+
#[cfg(feature = "completion")]
317+
Key::ArrowRight | Key::Tab => {
318+
if let Some(completion) = &self.completion {
319+
let input: String = chars.clone().into_iter().collect();
320+
if let Some(x) = completion.get(&input) {
321+
term.clear_chars(chars.len())?;
322+
chars.clear();
323+
position = 0;
324+
for ch in x.chars() {
325+
chars.insert(position, ch);
326+
position += 1;
327+
}
328+
term.write_str(&x)?;
329+
term.flush()?;
330+
}
331+
}
332+
}
300333
#[cfg(feature = "history")]
301334
Key::ArrowUp => {
302335
if let Some(history) = &self.history {

0 commit comments

Comments
 (0)