aboutsummaryrefslogtreecommitdiff
path: root/vendor/dialoguer/src
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/dialoguer/src')
-rw-r--r--vendor/dialoguer/src/completion.rs4
-rw-r--r--vendor/dialoguer/src/edit.rs131
-rw-r--r--vendor/dialoguer/src/history.rs15
-rw-r--r--vendor/dialoguer/src/lib.rs62
-rw-r--r--vendor/dialoguer/src/paging.rs118
-rw-r--r--vendor/dialoguer/src/prompts/confirm.rs287
-rw-r--r--vendor/dialoguer/src/prompts/fuzzy_select.rs326
-rw-r--r--vendor/dialoguer/src/prompts/input.rs691
-rw-r--r--vendor/dialoguer/src/prompts/mod.rs13
-rw-r--r--vendor/dialoguer/src/prompts/multi_select.rs356
-rw-r--r--vendor/dialoguer/src/prompts/password.rs194
-rw-r--r--vendor/dialoguer/src/prompts/select.rs419
-rw-r--r--vendor/dialoguer/src/prompts/sort.rs348
-rw-r--r--vendor/dialoguer/src/theme.rs976
-rw-r--r--vendor/dialoguer/src/validate.rs49
15 files changed, 0 insertions, 3989 deletions
diff --git a/vendor/dialoguer/src/completion.rs b/vendor/dialoguer/src/completion.rs
deleted file mode 100644
index 98c2a9c..0000000
--- a/vendor/dialoguer/src/completion.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-/// Trait for completion handling.
-pub trait Completion {
- fn get(&self, input: &str) -> Option<String>;
-}
diff --git a/vendor/dialoguer/src/edit.rs b/vendor/dialoguer/src/edit.rs
deleted file mode 100644
index f69844c..0000000
--- a/vendor/dialoguer/src/edit.rs
+++ /dev/null
@@ -1,131 +0,0 @@
-use std::{
- env,
- ffi::{OsStr, OsString},
- fs, io,
- io::{Read, Write},
- process,
-};
-
-/// Launches the default editor to edit a string.
-///
-/// ## Example
-///
-/// ```rust,no_run
-/// use dialoguer::Editor;
-///
-/// if let Some(rv) = Editor::new().edit("Enter a commit message").unwrap() {
-/// println!("Your message:");
-/// println!("{}", rv);
-/// } else {
-/// println!("Abort!");
-/// }
-/// ```
-pub struct Editor {
- editor: OsString,
- extension: String,
- require_save: bool,
- trim_newlines: bool,
-}
-
-fn get_default_editor() -> OsString {
- if let Some(prog) = env::var_os("VISUAL") {
- return prog;
- }
- if let Some(prog) = env::var_os("EDITOR") {
- return prog;
- }
- if cfg!(windows) {
- "notepad.exe".into()
- } else {
- "vi".into()
- }
-}
-
-impl Default for Editor {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Editor {
- /// Creates a new editor.
- pub fn new() -> Self {
- Self {
- editor: get_default_editor(),
- extension: ".txt".into(),
- require_save: true,
- trim_newlines: true,
- }
- }
-
- /// Sets a specific editor executable.
- pub fn executable<S: AsRef<OsStr>>(&mut self, val: S) -> &mut Self {
- self.editor = val.as_ref().into();
- self
- }
-
- /// Sets a specific extension
- pub fn extension(&mut self, val: &str) -> &mut Self {
- self.extension = val.into();
- self
- }
-
- /// Enables or disables the save requirement.
- pub fn require_save(&mut self, val: bool) -> &mut Self {
- self.require_save = val;
- self
- }
-
- /// Enables or disables trailing newline stripping.
- ///
- /// This is on by default.
- pub fn trim_newlines(&mut self, val: bool) -> &mut Self {
- self.trim_newlines = val;
- self
- }
-
- /// Launches the editor to edit a string.
- ///
- /// Returns `None` if the file was not saved or otherwise the
- /// entered text.
- pub fn edit(&self, s: &str) -> io::Result<Option<String>> {
- let mut f = tempfile::Builder::new()
- .prefix("edit-")
- .suffix(&self.extension)
- .rand_bytes(12)
- .tempfile()?;
- f.write_all(s.as_bytes())?;
- f.flush()?;
- let ts = fs::metadata(f.path())?.modified()?;
-
- let s: String = self.editor.clone().into_string().unwrap();
- let (cmd, args) = match shell_words::split(&s) {
- Ok(mut parts) => {
- let cmd = parts.remove(0);
- (cmd, parts)
- }
- Err(_) => (s, vec![]),
- };
-
- let rv = process::Command::new(cmd)
- .args(args)
- .arg(f.path())
- .spawn()?
- .wait()?;
-
- if rv.success() && self.require_save && ts >= fs::metadata(f.path())?.modified()? {
- return Ok(None);
- }
-
- let mut new_f = fs::File::open(f.path())?;
- let mut rv = String::new();
- new_f.read_to_string(&mut rv)?;
-
- if self.trim_newlines {
- let len = rv.trim_end_matches(&['\n', '\r'][..]).len();
- rv.truncate(len);
- }
-
- Ok(Some(rv))
- }
-}
diff --git a/vendor/dialoguer/src/history.rs b/vendor/dialoguer/src/history.rs
deleted file mode 100644
index d0818cc..0000000
--- a/vendor/dialoguer/src/history.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-/// Trait for history handling.
-pub trait History<T> {
- /// This is called with the current position that should
- /// be read from history. The `pos` represents the number
- /// of times the `Up`/`Down` arrow key has been pressed.
- /// This would normally be used as an index to some sort
- /// of vector. If the `pos` does not have an entry, [`None`](Option::None)
- /// should be returned.
- fn read(&self, pos: usize) -> Option<String>;
-
- /// This is called with the next value you should store
- /// in history at the first location. Normally history
- /// is implemented as a FIFO queue.
- fn write(&mut self, val: &T);
-}
diff --git a/vendor/dialoguer/src/lib.rs b/vendor/dialoguer/src/lib.rs
deleted file mode 100644
index cd8e307..0000000
--- a/vendor/dialoguer/src/lib.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-//! dialoguer is a library for Rust that helps you build useful small
-//! interactive user inputs for the command line. It provides utilities
-//! to render various simple dialogs like confirmation prompts, text
-//! inputs and more.
-//!
-//! Best paired with other libraries in the family:
-//!
-//! * [indicatif](https://docs.rs/indicatif)
-//! * [console](https://docs.rs/console)
-//!
-//! # Crate Contents
-//!
-//! * Confirmation prompts
-//! * Input prompts (regular and password)
-//! * Input validation
-//! * Selections prompts (single and multi)
-//! * Fuzzy select prompt
-//! * Other kind of prompts
-//! * Editor launching
-//!
-//! # Crate Features
-//!
-//! The following crate features are available:
-//! * `editor`: enables bindings to launch editor to edit strings
-//! * `fuzzy-select`: enables fuzzy select prompt
-//! * `history`: enables input prompts to be able to track history of inputs
-//! * `password`: enables password input prompt
-//! * `completion`: enables ability to implement custom tab-completion for input prompts
-//!
-//! By default `editor` and `password` are enabled.
-
-#![deny(clippy::all)]
-
-#[cfg(feature = "completion")]
-pub use completion::Completion;
-pub use console;
-#[cfg(feature = "editor")]
-pub use edit::Editor;
-#[cfg(feature = "history")]
-pub use history::History;
-use paging::Paging;
-pub use prompts::{
- confirm::Confirm, input::Input, multi_select::MultiSelect, select::Select, sort::Sort,
-};
-pub use validate::Validator;
-
-#[cfg(feature = "fuzzy-select")]
-pub use prompts::fuzzy_select::FuzzySelect;
-
-#[cfg(feature = "password")]
-pub use prompts::password::Password;
-
-#[cfg(feature = "completion")]
-mod completion;
-#[cfg(feature = "editor")]
-mod edit;
-#[cfg(feature = "history")]
-mod history;
-mod paging;
-mod prompts;
-pub mod theme;
-mod validate;
diff --git a/vendor/dialoguer/src/paging.rs b/vendor/dialoguer/src/paging.rs
deleted file mode 100644
index f85d9b3..0000000
--- a/vendor/dialoguer/src/paging.rs
+++ /dev/null
@@ -1,118 +0,0 @@
-use std::io;
-
-use console::Term;
-
-/// Creates a paging module
-///
-/// The paging module serves as tracking structure to allow paged views
-/// and automatically (de-)activates paging depending on the current terminal size.
-pub struct Paging<'a> {
- pub pages: usize,
- pub current_page: usize,
- pub capacity: usize,
- pub active: bool,
- pub max_capacity: Option<usize>,
- term: &'a Term,
- current_term_size: (u16, u16),
- items_len: usize,
- activity_transition: bool,
-}
-
-impl<'a> Paging<'a> {
- pub fn new(term: &'a Term, items_len: usize, max_capacity: Option<usize>) -> Paging<'a> {
- let term_size = term.size();
- // Subtract -2 because we need space to render the prompt, if paging is active
- let capacity = max_capacity
- .unwrap_or(std::usize::MAX)
- .clamp(3, term_size.0 as usize)
- - 2;
- let pages = (items_len as f64 / capacity as f64).ceil() as usize;
-
- Paging {
- pages,
- current_page: 0,
- capacity,
- active: pages > 1,
- term,
- current_term_size: term_size,
- items_len,
- max_capacity,
- // Set transition initially to true to trigger prompt rendering for inactive paging on start
- activity_transition: true,
- }
- }
-
- /// Updates all internal based on the current terminal size and cursor position
- pub fn update(&mut self, cursor_pos: usize) -> io::Result<()> {
- let new_term_size = self.term.size();
-
- if self.current_term_size != new_term_size {
- self.current_term_size = new_term_size;
- self.capacity = self
- .max_capacity
- .unwrap_or(std::usize::MAX)
- .clamp(3, self.current_term_size.0 as usize)
- - 2;
- self.pages = (self.items_len as f64 / self.capacity as f64).ceil() as usize;
- }
-
- if self.active == (self.pages > 1) {
- self.activity_transition = false;
- } else {
- self.active = self.pages > 1;
- self.activity_transition = true;
- // Clear everything to prevent "ghost" lines in terminal when a resize happened
- self.term.clear_last_lines(self.capacity)?;
- }
-
- if cursor_pos != !0
- && (cursor_pos < self.current_page * self.capacity
- || cursor_pos >= (self.current_page + 1) * self.capacity)
- {
- self.current_page = cursor_pos / self.capacity;
- }
-
- Ok(())
- }
-
- /// Renders a prompt when the following conditions are met:
- /// * Paging is active
- /// * Transition of the paging activity happened (active -> inactive / inactive -> active)
- pub fn render_prompt<F>(&mut self, mut render_prompt: F) -> io::Result<()>
- where
- F: FnMut(Option<(usize, usize)>) -> io::Result<()>,
- {
- if self.active {
- let paging_info = Some((self.current_page + 1, self.pages));
- render_prompt(paging_info)?;
- } else if self.activity_transition {
- render_prompt(None)?;
- }
-
- self.term.flush()?;
-
- Ok(())
- }
-
- /// Navigates to the next page
- pub fn next_page(&mut self) -> usize {
- if self.current_page == self.pages - 1 {
- self.current_page = 0;
- } else {
- self.current_page += 1;
- }
-
- self.current_page * self.capacity
- }
-
- /// Navigates to the previous page
- pub fn previous_page(&mut self) -> usize {
- if self.current_page == 0 {
- self.current_page = self.pages - 1;
- } else {
- self.current_page -= 1;
- }
-
- self.current_page * self.capacity
- }
-}
diff --git a/vendor/dialoguer/src/prompts/confirm.rs b/vendor/dialoguer/src/prompts/confirm.rs
deleted file mode 100644
index 24bcc4c..0000000
--- a/vendor/dialoguer/src/prompts/confirm.rs
+++ /dev/null
@@ -1,287 +0,0 @@
-use std::io;
-
-use crate::theme::{SimpleTheme, TermThemeRenderer, Theme};
-
-use console::{Key, Term};
-
-/// Renders a confirm prompt.
-///
-/// ## Example usage
-///
-/// ```rust,no_run
-/// # fn test() -> Result<(), Box<dyn std::error::Error>> {
-/// use dialoguer::Confirm;
-///
-/// if Confirm::new().with_prompt("Do you want to continue?").interact()? {
-/// println!("Looks like you want to continue");
-/// } else {
-/// println!("nevermind then :(");
-/// }
-/// # Ok(()) } fn main() { test().unwrap(); }
-/// ```
-pub struct Confirm<'a> {
- prompt: String,
- report: bool,
- default: Option<bool>,
- show_default: bool,
- wait_for_newline: bool,
- theme: &'a dyn Theme,
-}
-
-impl Default for Confirm<'static> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Confirm<'static> {
- /// Creates a confirm prompt.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl Confirm<'_> {
- /// Sets the confirm prompt.
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = prompt.into();
- self
- }
-
- /// Indicates whether or not to report the chosen selection after interaction.
- ///
- /// The default is to report the chosen selection.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- #[deprecated(note = "Use with_prompt() instead", since = "0.6.0")]
- #[inline]
- pub fn with_text(&mut self, text: &str) -> &mut Self {
- self.with_prompt(text)
- }
-
- /// Sets when to react to user input.
- ///
- /// When `false` (default), we check on each user keystroke immediately as
- /// it is typed. Valid inputs can be one of 'y', 'n', or a newline to accept
- /// the default.
- ///
- /// When `true`, the user must type their choice and hit the Enter key before
- /// proceeding. Valid inputs can be "yes", "no", "y", "n", or an empty string
- /// to accept the default.
- pub fn wait_for_newline(&mut self, wait: bool) -> &mut Self {
- self.wait_for_newline = wait;
- self
- }
-
- /// Sets a default.
- ///
- /// Out of the box the prompt does not have a default and will continue
- /// to display until the user inputs something and hits enter. If a default is set the user
- /// can instead accept the default with enter.
- pub fn default(&mut self, val: bool) -> &mut Self {
- self.default = Some(val);
- self
- }
-
- /// Disables or enables the default value display.
- ///
- /// The default is to append the default value to the prompt to tell the user.
- pub fn show_default(&mut self, val: bool) -> &mut Self {
- self.show_default = val;
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The dialog is rendered on stderr.
- ///
- /// Result contains `bool` if user answered "yes" or "no" or `default` (configured in [`default`](Self::default) if pushes enter.
- /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'.
- #[inline]
- pub fn interact(&self) -> io::Result<bool> {
- self.interact_on(&Term::stderr())
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The dialog is rendered on stderr.
- ///
- /// Result contains `Some(bool)` if user answered "yes" or "no" or `Some(default)` (configured in [`default`](Self::default)) if pushes enter,
- /// or `None` if user cancelled with 'Esc' or 'q'.
- #[inline]
- pub fn interact_opt(&self) -> io::Result<Option<bool>> {
- self.interact_on_opt(&Term::stderr())
- }
-
- /// Like [interact](#method.interact) but allows a specific terminal to be set.
- ///
- /// ## Examples
- ///
- /// ```rust,no_run
- /// use dialoguer::Confirm;
- /// use console::Term;
- ///
- /// # fn main() -> std::io::Result<()> {
- /// let proceed = Confirm::new()
- /// .with_prompt("Do you wish to continue?")
- /// .interact_on(&Term::stderr())?;
- /// # Ok(())
- /// # }
- /// ```
- #[inline]
- pub fn interact_on(&self, term: &Term) -> io::Result<bool> {
- self._interact_on(term, false)?
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case"))
- }
-
- /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::Confirm;
- /// use console::Term;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let confirmation = Confirm::new()
- /// .interact_on_opt(&Term::stdout())?;
- ///
- /// match confirmation {
- /// Some(answer) => println!("User answered {}", if answer { "yes" } else { "no " }),
- /// None => println!("User did not answer")
- /// }
- ///
- /// Ok(())
- /// }
- /// ```
- #[inline]
- pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<bool>> {
- self._interact_on(term, true)
- }
-
- fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<bool>> {
- let mut render = TermThemeRenderer::new(term, self.theme);
-
- let default_if_show = if self.show_default {
- self.default
- } else {
- None
- };
-
- render.confirm_prompt(&self.prompt, default_if_show)?;
-
- term.hide_cursor()?;
- term.flush()?;
-
- let rv;
-
- if self.wait_for_newline {
- // Waits for user input and for the user to hit the Enter key
- // before validation.
- let mut value = default_if_show;
-
- loop {
- let input = term.read_key()?;
-
- match input {
- Key::Char('y') | Key::Char('Y') => {
- value = Some(true);
- }
- Key::Char('n') | Key::Char('N') => {
- value = Some(false);
- }
- Key::Enter => {
- if !allow_quit {
- value = value.or(self.default);
- }
-
- if value.is_some() || allow_quit {
- rv = value;
- break;
- }
- continue;
- }
- Key::Escape | Key::Char('q') if allow_quit => {
- value = None;
- }
- Key::Unknown => {
- return Err(io::Error::new(
- io::ErrorKind::NotConnected,
- "Not a terminal",
- ))
- }
- _ => {
- continue;
- }
- };
-
- term.clear_line()?;
- render.confirm_prompt(&self.prompt, value)?;
- }
- } else {
- // Default behavior: matches continuously on every keystroke,
- // and does not wait for user to hit the Enter key.
- loop {
- let input = term.read_key()?;
- let value = match input {
- Key::Char('y') | Key::Char('Y') => Some(true),
- Key::Char('n') | Key::Char('N') => Some(false),
- Key::Enter if self.default.is_some() => Some(self.default.unwrap()),
- Key::Escape | Key::Char('q') if allow_quit => None,
- Key::Unknown => {
- return Err(io::Error::new(
- io::ErrorKind::NotConnected,
- "Not a terminal",
- ))
- }
- _ => {
- continue;
- }
- };
-
- rv = value;
- break;
- }
- }
-
- term.clear_line()?;
- if self.report {
- render.confirm_prompt_selection(&self.prompt, rv)?;
- }
- term.show_cursor()?;
- term.flush()?;
-
- Ok(rv)
- }
-}
-
-impl<'a> Confirm<'a> {
- /// Creates a confirm prompt with a specific theme.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::{
- /// Confirm,
- /// theme::ColorfulTheme
- /// };
- ///
- /// # fn main() -> std::io::Result<()> {
- /// let proceed = Confirm::with_theme(&ColorfulTheme::default())
- /// .with_prompt("Do you wish to continue?")
- /// .interact()?;
- /// # Ok(())
- /// # }
- /// ```
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- prompt: "".into(),
- report: true,
- default: None,
- show_default: true,
- wait_for_newline: false,
- theme,
- }
- }
-}
diff --git a/vendor/dialoguer/src/prompts/fuzzy_select.rs b/vendor/dialoguer/src/prompts/fuzzy_select.rs
deleted file mode 100644
index 9b7f992..0000000
--- a/vendor/dialoguer/src/prompts/fuzzy_select.rs
+++ /dev/null
@@ -1,326 +0,0 @@
-use crate::theme::{SimpleTheme, TermThemeRenderer, Theme};
-use console::{Key, Term};
-use fuzzy_matcher::FuzzyMatcher;
-use std::{io, ops::Rem};
-
-/// Renders a selection menu that user can fuzzy match to reduce set.
-///
-/// User can use fuzzy search to limit selectable items.
-/// Interaction returns index of an item selected in the order they appear in `item` invocation or `items` slice.
-///
-/// ## Examples
-///
-/// ```rust,no_run
-/// use dialoguer::{
-/// FuzzySelect,
-/// theme::ColorfulTheme
-/// };
-/// use console::Term;
-///
-/// fn main() -> std::io::Result<()> {
-/// let items = vec!["Item 1", "item 2"];
-/// let selection = FuzzySelect::with_theme(&ColorfulTheme::default())
-/// .items(&items)
-/// .default(0)
-/// .interact_on_opt(&Term::stderr())?;
-///
-/// match selection {
-/// Some(index) => println!("User selected item : {}", items[index]),
-/// None => println!("User did not select anything")
-/// }
-///
-/// Ok(())
-/// }
-/// ```
-
-pub struct FuzzySelect<'a> {
- default: Option<usize>,
- items: Vec<String>,
- prompt: String,
- report: bool,
- clear: bool,
- highlight_matches: bool,
- max_length: Option<usize>,
- theme: &'a dyn Theme,
- /// Search string that a fuzzy search with start with.
- /// Defaults to an empty string.
- initial_text: String,
-}
-
-impl Default for FuzzySelect<'static> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl FuzzySelect<'static> {
- /// Creates the prompt with a specific text.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl FuzzySelect<'_> {
- /// Sets the clear behavior of the menu.
- ///
- /// The default is to clear the menu.
- pub fn clear(&mut self, val: bool) -> &mut Self {
- self.clear = val;
- self
- }
-
- /// Sets a default for the menu
- pub fn default(&mut self, val: usize) -> &mut Self {
- self.default = Some(val);
- self
- }
-
- /// Add a single item to the fuzzy selector.
- pub fn item<T: ToString>(&mut self, item: T) -> &mut Self {
- self.items.push(item.to_string());
- self
- }
-
- /// Adds multiple items to the fuzzy selector.
- pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self {
- for item in items {
- self.items.push(item.to_string());
- }
- self
- }
-
- /// Sets the search text that a fuzzy search starts with.
- pub fn with_initial_text<S: Into<String>>(&mut self, initial_text: S) -> &mut Self {
- self.initial_text = initial_text.into();
- self
- }
-
- /// Prefaces the menu with a prompt.
- ///
- /// When a prompt is set the system also prints out a confirmation after
- /// the fuzzy selection.
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = prompt.into();
- self
- }
-
- /// Indicates whether to report the selected value after interaction.
- ///
- /// The default is to report the selection.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Indicates whether to highlight matched indices
- ///
- /// The default is to highlight the indices
- pub fn highlight_matches(&mut self, val: bool) -> &mut Self {
- self.highlight_matches = val;
- self
- }
-
- /// Sets the maximum number of visible options.
- ///
- /// The default is the height of the terminal minus 2.
- pub fn max_length(&mut self, rows: usize) -> &mut Self {
- self.max_length = Some(rows);
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items using 'Enter' and the index of selected item will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `index` of selected item if user hit 'Enter'.
- /// This unlike [interact_opt](#method.interact_opt) does not allow to quit with 'Esc' or 'q'.
- #[inline]
- pub fn interact(&self) -> io::Result<usize> {
- self.interact_on(&Term::stderr())
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items using 'Enter' and the index of selected item will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Some(index)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'.
- #[inline]
- pub fn interact_opt(&self) -> io::Result<Option<usize>> {
- self.interact_on_opt(&Term::stderr())
- }
-
- /// Like `interact` but allows a specific terminal to be set.
- #[inline]
- pub fn interact_on(&self, term: &Term) -> io::Result<usize> {
- self._interact_on(term, false)?
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case"))
- }
-
- /// Like `interact` but allows a specific terminal to be set.
- #[inline]
- pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<usize>> {
- self._interact_on(term, true)
- }
-
- /// Like `interact` but allows a specific terminal to be set.
- fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<usize>> {
- // Place cursor at the end of the search term
- let mut position = self.initial_text.len();
- let mut search_term = self.initial_text.to_owned();
-
- let mut render = TermThemeRenderer::new(term, self.theme);
- let mut sel = self.default;
-
- let mut size_vec = Vec::new();
- for items in self.items.iter().as_slice() {
- let size = &items.len();
- size_vec.push(*size);
- }
-
- // Fuzzy matcher
- let matcher = fuzzy_matcher::skim::SkimMatcherV2::default();
-
- // Subtract -2 because we need space to render the prompt.
- let visible_term_rows = (term.size().0 as usize).max(3) - 2;
- let visible_term_rows = self
- .max_length
- .unwrap_or(visible_term_rows)
- .min(visible_term_rows);
- // Variable used to determine if we need to scroll through the list.
- let mut starting_row = 0;
-
- term.hide_cursor()?;
-
- loop {
- render.clear()?;
- render.fuzzy_select_prompt(self.prompt.as_str(), &search_term, position)?;
-
- // Maps all items to a tuple of item and its match score.
- let mut filtered_list = self
- .items
- .iter()
- .map(|item| (item, matcher.fuzzy_match(item, &search_term)))
- .filter_map(|(item, score)| score.map(|s| (item, s)))
- .collect::<Vec<_>>();
-
- // Renders all matching items, from best match to worst.
- filtered_list.sort_unstable_by(|(_, s1), (_, s2)| s2.cmp(s1));
-
- for (idx, (item, _)) in filtered_list
- .iter()
- .enumerate()
- .skip(starting_row)
- .take(visible_term_rows)
- {
- render.fuzzy_select_prompt_item(
- item,
- Some(idx) == sel,
- self.highlight_matches,
- &matcher,
- &search_term,
- )?;
- }
- term.flush()?;
-
- match (term.read_key()?, sel) {
- (Key::Escape, _) if allow_quit => {
- if self.clear {
- render.clear()?;
- term.flush()?;
- }
- term.show_cursor()?;
- return Ok(None);
- }
- (Key::ArrowUp | Key::BackTab, _) if !filtered_list.is_empty() => {
- if sel == Some(0) {
- starting_row =
- filtered_list.len().max(visible_term_rows) - visible_term_rows;
- } else if sel == Some(starting_row) {
- starting_row -= 1;
- }
- sel = match sel {
- None => Some(filtered_list.len() - 1),
- Some(sel) => Some(
- ((sel as i64 - 1 + filtered_list.len() as i64)
- % (filtered_list.len() as i64))
- as usize,
- ),
- };
- term.flush()?;
- }
- (Key::ArrowDown | Key::Tab, _) if !filtered_list.is_empty() => {
- sel = match sel {
- None => Some(0),
- Some(sel) => {
- Some((sel as u64 + 1).rem(filtered_list.len() as u64) as usize)
- }
- };
- if sel == Some(visible_term_rows + starting_row) {
- starting_row += 1;
- } else if sel == Some(0) {
- starting_row = 0;
- }
- term.flush()?;
- }
- (Key::ArrowLeft, _) if position > 0 => {
- position -= 1;
- term.flush()?;
- }
- (Key::ArrowRight, _) if position < search_term.len() => {
- position += 1;
- term.flush()?;
- }
- (Key::Enter, Some(sel)) if !filtered_list.is_empty() => {
- if self.clear {
- render.clear()?;
- }
-
- if self.report {
- render
- .input_prompt_selection(self.prompt.as_str(), filtered_list[sel].0)?;
- }
-
- let sel_string = filtered_list[sel].0;
- let sel_string_pos_in_items =
- self.items.iter().position(|item| item.eq(sel_string));
-
- term.show_cursor()?;
- return Ok(sel_string_pos_in_items);
- }
- (Key::Backspace, _) if position > 0 => {
- position -= 1;
- search_term.remove(position);
- term.flush()?;
- }
- (Key::Char(chr), _) if !chr.is_ascii_control() => {
- search_term.insert(position, chr);
- position += 1;
- term.flush()?;
- sel = Some(0);
- starting_row = 0;
- }
-
- _ => {}
- }
-
- render.clear_preserve_prompt(&size_vec)?;
- }
- }
-}
-
-impl<'a> FuzzySelect<'a> {
- /// Same as `new` but with a specific theme.
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- default: None,
- items: vec![],
- prompt: "".into(),
- report: true,
- clear: true,
- highlight_matches: true,
- max_length: None,
- theme,
- initial_text: "".into(),
- }
- }
-}
diff --git a/vendor/dialoguer/src/prompts/input.rs b/vendor/dialoguer/src/prompts/input.rs
deleted file mode 100644
index b7cd829..0000000
--- a/vendor/dialoguer/src/prompts/input.rs
+++ /dev/null
@@ -1,691 +0,0 @@
-use std::{cmp::Ordering, fmt::Debug, io, iter, str::FromStr};
-
-#[cfg(feature = "completion")]
-use crate::completion::Completion;
-#[cfg(feature = "history")]
-use crate::history::History;
-use crate::{
- theme::{SimpleTheme, TermThemeRenderer, Theme},
- validate::Validator,
-};
-
-use console::{Key, Term};
-
-type ValidatorCallback<'a, T> = Box<dyn FnMut(&T) -> Option<String> + 'a>;
-
-/// Renders an input prompt.
-///
-/// ## Example usage
-///
-/// ```rust,no_run
-/// use dialoguer::Input;
-///
-/// # fn test() -> Result<(), Box<dyn std::error::Error>> {
-/// let input : String = Input::new()
-/// .with_prompt("Tea or coffee?")
-/// .with_initial_text("Yes")
-/// .default("No".into())
-/// .interact_text()?;
-/// # Ok(())
-/// # }
-/// ```
-/// It can also be used with turbofish notation:
-///
-/// ```rust,no_run
-/// # fn test() -> Result<(), Box<dyn std::error::Error>> {
-/// # use dialoguer::Input;
-/// let input = Input::<String>::new()
-/// .interact_text()?;
-/// # Ok(())
-/// # }
-/// ```
-pub struct Input<'a, T> {
- prompt: String,
- post_completion_text: Option<String>,
- report: bool,
- default: Option<T>,
- show_default: bool,
- initial_text: Option<String>,
- theme: &'a dyn Theme,
- permit_empty: bool,
- validator: Option<ValidatorCallback<'a, T>>,
- #[cfg(feature = "history")]
- history: Option<&'a mut dyn History<T>>,
- #[cfg(feature = "completion")]
- completion: Option<&'a dyn Completion>,
-}
-
-impl<T> Default for Input<'static, T> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl<T> Input<'_, T> {
- /// Creates an input prompt.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-
- /// Sets the input prompt.
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = prompt.into();
- self
- }
-
- /// Changes the prompt text to the post completion text after input is complete
- pub fn with_post_completion_text<S: Into<String>>(
- &mut self,
- post_completion_text: S,
- ) -> &mut Self {
- self.post_completion_text = Some(post_completion_text.into());
- self
- }
-
- /// Indicates whether to report the input value after interaction.
- ///
- /// The default is to report the input value.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Sets initial text that user can accept or erase.
- pub fn with_initial_text<S: Into<String>>(&mut self, val: S) -> &mut Self {
- self.initial_text = Some(val.into());
- self
- }
-
- /// Sets a default.
- ///
- /// Out of the box the prompt does not have a default and will continue
- /// to display until the user inputs something and hits enter. If a default is set the user
- /// can instead accept the default with enter.
- pub fn default(&mut self, value: T) -> &mut Self {
- self.default = Some(value);
- self
- }
-
- /// Enables or disables an empty input
- ///
- /// By default, if there is no default value set for the input, the user must input a non-empty string.
- pub fn allow_empty(&mut self, val: bool) -> &mut Self {
- self.permit_empty = val;
- self
- }
-
- /// Disables or enables the default value display.
- ///
- /// The default behaviour is to append [`default`](#method.default) to the prompt to tell the
- /// user what is the default value.
- ///
- /// This method does not affect existence of default value, only its display in the prompt!
- pub fn show_default(&mut self, val: bool) -> &mut Self {
- self.show_default = val;
- self
- }
-}
-
-impl<'a, T> Input<'a, T> {
- /// Creates an input prompt with a specific theme.
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- prompt: "".into(),
- post_completion_text: None,
- report: true,
- default: None,
- show_default: true,
- initial_text: None,
- theme,
- permit_empty: false,
- validator: None,
- #[cfg(feature = "history")]
- history: None,
- #[cfg(feature = "completion")]
- completion: None,
- }
- }
-
- /// Enable history processing
- ///
- /// # Example
- ///
- /// ```no_run
- /// # use dialoguer::{History, Input};
- /// # use std::{collections::VecDeque, fmt::Display};
- /// let mut history = MyHistory::default();
- /// loop {
- /// if let Ok(input) = Input::<String>::new()
- /// .with_prompt("hist")
- /// .history_with(&mut history)
- /// .interact_text()
- /// {
- /// // Do something with the input
- /// }
- /// }
- /// # struct MyHistory {
- /// # history: VecDeque<String>,
- /// # }
- /// #
- /// # impl Default for MyHistory {
- /// # fn default() -> Self {
- /// # MyHistory {
- /// # history: VecDeque::new(),
- /// # }
- /// # }
- /// # }
- /// #
- /// # impl<T: ToString> History<T> for MyHistory {
- /// # fn read(&self, pos: usize) -> Option<String> {
- /// # self.history.get(pos).cloned()
- /// # }
- /// #
- /// # fn write(&mut self, val: &T)
- /// # where
- /// # {
- /// # self.history.push_front(val.to_string());
- /// # }
- /// # }
- /// ```
- #[cfg(feature = "history")]
- pub fn history_with<H>(&mut self, history: &'a mut H) -> &mut Self
- where
- H: History<T>,
- {
- self.history = Some(history);
- self
- }
-
- /// Enable completion
- #[cfg(feature = "completion")]
- pub fn completion_with<C>(&mut self, completion: &'a C) -> &mut Self
- where
- C: Completion,
- {
- self.completion = Some(completion);
- self
- }
-}
-
-impl<'a, T> Input<'a, T>
-where
- T: 'a,
-{
- /// Registers a validator.
- ///
- /// # Example
- ///
- /// ```no_run
- /// # use dialoguer::Input;
- /// let mail: String = Input::new()
- /// .with_prompt("Enter email")
- /// .validate_with(|input: &String| -> Result<(), &str> {
- /// if input.contains('@') {
- /// Ok(())
- /// } else {
- /// Err("This is not a mail address")
- /// }
- /// })
- /// .interact()
- /// .unwrap();
- /// ```
- pub fn validate_with<V>(&mut self, mut validator: V) -> &mut Self
- where
- V: Validator<T> + 'a,
- V::Err: ToString,
- {
- let mut old_validator_func = self.validator.take();
-
- self.validator = Some(Box::new(move |value: &T| -> Option<String> {
- if let Some(old) = old_validator_func.as_mut() {
- if let Some(err) = old(value) {
- return Some(err);
- }
- }
-
- match validator.validate(value) {
- Ok(()) => None,
- Err(err) => Some(err.to_string()),
- }
- }));
-
- self
- }
-}
-
-impl<T> Input<'_, T>
-where
- T: Clone + ToString + FromStr,
- <T as FromStr>::Err: Debug + ToString,
-{
- /// Enables the user to enter a printable ascii sequence and returns the result.
- ///
- /// Its difference from [`interact`](#method.interact) is that it only allows ascii characters for string,
- /// while [`interact`](#method.interact) allows virtually any character to be used e.g arrow keys.
- ///
- /// The dialog is rendered on stderr.
- pub fn interact_text(&mut self) -> io::Result<T> {
- self.interact_text_on(&Term::stderr())
- }
-
- /// Like [`interact_text`](#method.interact_text) but allows a specific terminal to be set.
- pub fn interact_text_on(&mut self, term: &Term) -> io::Result<T> {
- let mut render = TermThemeRenderer::new(term, self.theme);
-
- loop {
- let default_string = self.default.as_ref().map(ToString::to_string);
-
- let prompt_len = render.input_prompt(
- &self.prompt,
- if self.show_default {
- default_string.as_deref()
- } else {
- None
- },
- )?;
-
- // Read input by keystroke so that we can suppress ascii control characters
- if !term.features().is_attended() {
- return Ok("".to_owned().parse::<T>().unwrap());
- }
-
- let mut chars: Vec<char> = Vec::new();
- let mut position = 0;
- #[cfg(feature = "history")]
- let mut hist_pos = 0;
-
- if let Some(initial) = self.initial_text.as_ref() {
- term.write_str(initial)?;
- chars = initial.chars().collect();
- position = chars.len();
- }
- term.flush()?;
-
- loop {
- match term.read_key()? {
- Key::Backspace if position > 0 => {
- position -= 1;
- chars.remove(position);
- let line_size = term.size().1 as usize;
- // Case we want to delete last char of a line so the cursor is at the beginning of the next line
- if (position + prompt_len) % (line_size - 1) == 0 {
- term.clear_line()?;
- term.move_cursor_up(1)?;
- term.move_cursor_right(line_size + 1)?;
- } else {
- term.clear_chars(1)?;
- }
-
- let tail: String = chars[position..].iter().collect();
-
- if !tail.is_empty() {
- term.write_str(&tail)?;
-
- let total = position + prompt_len + tail.len();
- let total_line = total / line_size;
- let line_cursor = (position + prompt_len) / line_size;
- term.move_cursor_up(total_line - line_cursor)?;
-
- term.move_cursor_left(line_size)?;
- term.move_cursor_right((position + prompt_len) % line_size)?;
- }
-
- term.flush()?;
- }
- Key::Char(chr) if !chr.is_ascii_control() => {
- chars.insert(position, chr);
- position += 1;
- let tail: String =
- iter::once(&chr).chain(chars[position..].iter()).collect();
- term.write_str(&tail)?;
- term.move_cursor_left(tail.len() - 1)?;
- term.flush()?;
- }
- Key::ArrowLeft if position > 0 => {
- if (position + prompt_len) % term.size().1 as usize == 0 {
- term.move_cursor_up(1)?;
- term.move_cursor_right(term.size().1 as usize)?;
- } else {
- term.move_cursor_left(1)?;
- }
- position -= 1;
- term.flush()?;
- }
- Key::ArrowRight if position < chars.len() => {
- if (position + prompt_len) % (term.size().1 as usize - 1) == 0 {
- term.move_cursor_down(1)?;
- term.move_cursor_left(term.size().1 as usize)?;
- } else {
- term.move_cursor_right(1)?;
- }
- position += 1;
- term.flush()?;
- }
- Key::UnknownEscSeq(seq) if seq == vec!['b'] => {
- let line_size = term.size().1 as usize;
- let nb_space = chars[..position]
- .iter()
- .rev()
- .take_while(|c| c.is_whitespace())
- .count();
- let find_last_space = chars[..position - nb_space]
- .iter()
- .rposition(|c| c.is_whitespace());
-
- // If we find a space we set the cursor to the next char else we set it to the beginning of the input
- if let Some(mut last_space) = find_last_space {
- if last_space < position {
- last_space += 1;
- let new_line = (prompt_len + last_space) / line_size;
- let old_line = (prompt_len + position) / line_size;
- let diff_line = old_line - new_line;
- if diff_line != 0 {
- term.move_cursor_up(old_line - new_line)?;
- }
-
- let new_pos_x = (prompt_len + last_space) % line_size;
- let old_pos_x = (prompt_len + position) % line_size;
- let diff_pos_x = new_pos_x as i64 - old_pos_x as i64;
- //println!("new_pos_x = {}, old_pos_x = {}, diff = {}", new_pos_x, old_pos_x, diff_pos_x);
- if diff_pos_x < 0 {
- term.move_cursor_left(-diff_pos_x as usize)?;
- } else {
- term.move_cursor_right((diff_pos_x) as usize)?;
- }
- position = last_space;
- }
- } else {
- term.move_cursor_left(position)?;
- position = 0;
- }
-
- term.flush()?;
- }
- Key::UnknownEscSeq(seq) if seq == vec!['f'] => {
- let line_size = term.size().1 as usize;
- let find_next_space =
- chars[position..].iter().position(|c| c.is_whitespace());
-
- // If we find a space we set the cursor to the next char else we set it to the beginning of the input
- if let Some(mut next_space) = find_next_space {
- let nb_space = chars[position + next_space..]
- .iter()
- .take_while(|c| c.is_whitespace())
- .count();
- next_space += nb_space;
- let new_line = (prompt_len + position + next_space) / line_size;
- let old_line = (prompt_len + position) / line_size;
- term.move_cursor_down(new_line - old_line)?;
-
- let new_pos_x = (prompt_len + position + next_space) % line_size;
- let old_pos_x = (prompt_len + position) % line_size;
- let diff_pos_x = new_pos_x as i64 - old_pos_x as i64;
- if diff_pos_x < 0 {
- term.move_cursor_left(-diff_pos_x as usize)?;
- } else {
- term.move_cursor_right((diff_pos_x) as usize)?;
- }
- position += next_space;
- } else {
- let new_line = (prompt_len + chars.len()) / line_size;
- let old_line = (prompt_len + position) / line_size;
- term.move_cursor_down(new_line - old_line)?;
-
- let new_pos_x = (prompt_len + chars.len()) % line_size;
- let old_pos_x = (prompt_len + position) % line_size;
- let diff_pos_x = new_pos_x as i64 - old_pos_x as i64;
- match diff_pos_x.cmp(&0) {
- Ordering::Less => {
- term.move_cursor_left((-diff_pos_x - 1) as usize)?;
- }
- Ordering::Equal => {}
- Ordering::Greater => {
- term.move_cursor_right((diff_pos_x) as usize)?;
- }
- }
- position = chars.len();
- }
-
- term.flush()?;
- }
- #[cfg(feature = "completion")]
- Key::ArrowRight | Key::Tab => {
- if let Some(completion) = &self.completion {
- let input: String = chars.clone().into_iter().collect();
- if let Some(x) = completion.get(&input) {
- term.clear_chars(chars.len())?;
- chars.clear();
- position = 0;
- for ch in x.chars() {
- chars.insert(position, ch);
- position += 1;
- }
- term.write_str(&x)?;
- term.flush()?;
- }
- }
- }
- #[cfg(feature = "history")]
- Key::ArrowUp => {
- let line_size = term.size().1 as usize;
- if let Some(history) = &self.history {
- if let Some(previous) = history.read(hist_pos) {
- hist_pos += 1;
- let mut chars_len = chars.len();
- while ((prompt_len + chars_len) / line_size) > 0 {
- term.clear_chars(chars_len)?;
- if (prompt_len + chars_len) % line_size == 0 {
- chars_len -= std::cmp::min(chars_len, line_size);
- } else {
- chars_len -= std::cmp::min(
- chars_len,
- (prompt_len + chars_len + 1) % line_size,
- );
- }
- if chars_len > 0 {
- term.move_cursor_up(1)?;
- term.move_cursor_right(line_size)?;
- }
- }
- term.clear_chars(chars_len)?;
- chars.clear();
- position = 0;
- for ch in previous.chars() {
- chars.insert(position, ch);
- position += 1;
- }
- term.write_str(&previous)?;
- term.flush()?;
- }
- }
- }
- #[cfg(feature = "history")]
- Key::ArrowDown => {
- let line_size = term.size().1 as usize;
- if let Some(history) = &self.history {
- let mut chars_len = chars.len();
- while ((prompt_len + chars_len) / line_size) > 0 {
- term.clear_chars(chars_len)?;
- if (prompt_len + chars_len) % line_size == 0 {
- chars_len -= std::cmp::min(chars_len, line_size);
- } else {
- chars_len -= std::cmp::min(
- chars_len,
- (prompt_len + chars_len + 1) % line_size,
- );
- }
- if chars_len > 0 {
- term.move_cursor_up(1)?;
- term.move_cursor_right(line_size)?;
- }
- }
- term.clear_chars(chars_len)?;
- chars.clear();
- position = 0;
- // Move the history position back one in case we have up arrowed into it
- // and the position is sitting on the next to read
- if let Some(pos) = hist_pos.checked_sub(1) {
- hist_pos = pos;
- // Move it back again to get the previous history entry
- if let Some(pos) = pos.checked_sub(1) {
- if let Some(previous) = history.read(pos) {
- for ch in previous.chars() {
- chars.insert(position, ch);
- position += 1;
- }
- term.write_str(&previous)?;
- }
- }
- }
- term.flush()?;
- }
- }
- Key::Enter => break,
- _ => (),
- }
- }
- let input = chars.iter().collect::<String>();
-
- term.clear_line()?;
- render.clear()?;
-
- if chars.is_empty() {
- if let Some(ref default) = self.default {
- if let Some(ref mut validator) = self.validator {
- if let Some(err) = validator(default) {
- render.error(&err)?;
- continue;
- }
- }
-
- if self.report {
- render.input_prompt_selection(&self.prompt, &default.to_string())?;
- }
- term.flush()?;
- return Ok(default.clone());
- } else if !self.permit_empty {
- continue;
- }
- }
-
- match input.parse::<T>() {
- Ok(value) => {
- if let Some(ref mut validator) = self.validator {
- if let Some(err) = validator(&value) {
- render.error(&err)?;
- continue;
- }
- }
-
- #[cfg(feature = "history")]
- if let Some(history) = &mut self.history {
- history.write(&value);
- }
-
- if self.report {
- if let Some(post_completion_text) = &self.post_completion_text {
- render.input_prompt_selection(post_completion_text, &input)?;
- } else {
- render.input_prompt_selection(&self.prompt, &input)?;
- }
- }
- term.flush()?;
-
- return Ok(value);
- }
- Err(err) => {
- render.error(&err.to_string())?;
- continue;
- }
- }
- }
- }
-}
-
-impl<T> Input<'_, T>
-where
- T: Clone + ToString + FromStr,
- <T as FromStr>::Err: ToString,
-{
- /// Enables user interaction and returns the result.
- ///
- /// Allows any characters as input, including e.g arrow keys.
- /// Some of the keys might have undesired behavior.
- /// For more limited version, see [`interact_text`](#method.interact_text).
- ///
- /// If the user confirms the result is `true`, `false` otherwise.
- /// The dialog is rendered on stderr.
- pub fn interact(&mut self) -> io::Result<T> {
- self.interact_on(&Term::stderr())
- }
-
- /// Like [`interact`](#method.interact) but allows a specific terminal to be set.
- pub fn interact_on(&mut self, term: &Term) -> io::Result<T> {
- let mut render = TermThemeRenderer::new(term, self.theme);
-
- loop {
- let default_string = self.default.as_ref().map(ToString::to_string);
-
- render.input_prompt(
- &self.prompt,
- if self.show_default {
- default_string.as_deref()
- } else {
- None
- },
- )?;
- term.flush()?;
-
- let input = if let Some(initial_text) = self.initial_text.as_ref() {
- term.read_line_initial_text(initial_text)?
- } else {
- term.read_line()?
- };
-
- render.add_line();
- term.clear_line()?;
- render.clear()?;
-
- if input.is_empty() {
- if let Some(ref default) = self.default {
- if let Some(ref mut validator) = self.validator {
- if let Some(err) = validator(default) {
- render.error(&err)?;
- continue;
- }
- }
-
- if self.report {
- render.input_prompt_selection(&self.prompt, &default.to_string())?;
- }
- term.flush()?;
- return Ok(default.clone());
- } else if !self.permit_empty {
- continue;
- }
- }
-
- match input.parse::<T>() {
- Ok(value) => {
- if let Some(ref mut validator) = self.validator {
- if let Some(err) = validator(&value) {
- render.error(&err)?;
- continue;
- }
- }
-
- if self.report {
- render.input_prompt_selection(&self.prompt, &input)?;
- }
- term.flush()?;
-
- return Ok(value);
- }
- Err(err) => {
- render.error(&err.to_string())?;
- continue;
- }
- }
- }
- }
-}
diff --git a/vendor/dialoguer/src/prompts/mod.rs b/vendor/dialoguer/src/prompts/mod.rs
deleted file mode 100644
index 1c13185..0000000
--- a/vendor/dialoguer/src/prompts/mod.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![allow(clippy::needless_doctest_main)]
-
-pub mod confirm;
-pub mod input;
-pub mod multi_select;
-pub mod select;
-pub mod sort;
-
-#[cfg(feature = "fuzzy-select")]
-pub mod fuzzy_select;
-
-#[cfg(feature = "password")]
-pub mod password;
diff --git a/vendor/dialoguer/src/prompts/multi_select.rs b/vendor/dialoguer/src/prompts/multi_select.rs
deleted file mode 100644
index eed55a1..0000000
--- a/vendor/dialoguer/src/prompts/multi_select.rs
+++ /dev/null
@@ -1,356 +0,0 @@
-use std::{io, iter::repeat, ops::Rem};
-
-use crate::{
- theme::{SimpleTheme, TermThemeRenderer, Theme},
- Paging,
-};
-
-use console::{Key, Term};
-
-/// Renders a multi select prompt.
-///
-/// ## Example usage
-/// ```rust,no_run
-/// # fn test() -> Result<(), Box<dyn std::error::Error>> {
-/// use dialoguer::MultiSelect;
-///
-/// let items = vec!["Option 1", "Option 2"];
-/// let chosen : Vec<usize> = MultiSelect::new()
-/// .items(&items)
-/// .interact()?;
-/// # Ok(())
-/// # }
-/// ```
-pub struct MultiSelect<'a> {
- defaults: Vec<bool>,
- items: Vec<String>,
- prompt: Option<String>,
- report: bool,
- clear: bool,
- max_length: Option<usize>,
- theme: &'a dyn Theme,
-}
-
-impl Default for MultiSelect<'static> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl MultiSelect<'static> {
- /// Creates a multi select prompt.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl MultiSelect<'_> {
- /// Sets the clear behavior of the menu.
- ///
- /// The default is to clear the menu.
- pub fn clear(&mut self, val: bool) -> &mut Self {
- self.clear = val;
- self
- }
-
- /// Sets a defaults for the menu.
- pub fn defaults(&mut self, val: &[bool]) -> &mut Self {
- self.defaults = val
- .to_vec()
- .iter()
- .copied()
- .chain(repeat(false))
- .take(self.items.len())
- .collect();
- self
- }
-
- /// Sets an optional max length for a page
- ///
- /// Max length is disabled by None
- pub fn max_length(&mut self, val: usize) -> &mut Self {
- // Paging subtracts two from the capacity, paging does this to
- // make an offset for the page indicator. So to make sure that
- // we can show the intended amount of items we need to add two
- // to our value.
- self.max_length = Some(val + 2);
- self
- }
-
- /// Add a single item to the selector.
- #[inline]
- pub fn item<T: ToString>(&mut self, item: T) -> &mut Self {
- self.item_checked(item, false)
- }
-
- /// Add a single item to the selector with a default checked state.
- pub fn item_checked<T: ToString>(&mut self, item: T, checked: bool) -> &mut Self {
- self.items.push(item.to_string());
- self.defaults.push(checked);
- self
- }
-
- /// Adds multiple items to the selector.
- pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self {
- for item in items {
- self.items.push(item.to_string());
- self.defaults.push(false);
- }
- self
- }
-
- /// Adds multiple items to the selector with checked state
- pub fn items_checked<T: ToString>(&mut self, items: &[(T, bool)]) -> &mut Self {
- for &(ref item, checked) in items {
- self.items.push(item.to_string());
- self.defaults.push(checked);
- }
- self
- }
-
- /// Prefaces the menu with a prompt.
- ///
- /// By default, when a prompt is set the system also prints out a confirmation after
- /// the selection. You can opt-out of this with [`report`](#method.report).
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = Some(prompt.into());
- self
- }
-
- /// Indicates whether to report the selected values after interaction.
- ///
- /// The default is to report the selections.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items with the 'Space' bar and on 'Enter' the indices of selected items will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Vec<index>` if user hit 'Enter'.
- /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'.
- #[inline]
- pub fn interact(&self) -> io::Result<Vec<usize>> {
- self.interact_on(&Term::stderr())
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items with the 'Space' bar and on 'Enter' the indices of selected items will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Some(Vec<index>)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'.
- #[inline]
- pub fn interact_opt(&self) -> io::Result<Option<Vec<usize>>> {
- self.interact_on_opt(&Term::stderr())
- }
-
- /// Like [interact](#method.interact) but allows a specific terminal to be set.
- ///
- /// ## Examples
- ///```rust,no_run
- /// use dialoguer::MultiSelect;
- /// use console::Term;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selections = MultiSelect::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on(&Term::stderr())?;
- ///
- /// println!("User selected options at indices {:?}", selections);
- ///
- /// Ok(())
- /// }
- ///```
- #[inline]
- pub fn interact_on(&self, term: &Term) -> io::Result<Vec<usize>> {
- self._interact_on(term, false)?
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case"))
- }
-
- /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::MultiSelect;
- /// use console::Term;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selections = MultiSelect::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on_opt(&Term::stdout())?;
- ///
- /// match selections {
- /// Some(positions) => println!("User selected options at indices {:?}", positions),
- /// None => println!("User exited using Esc or q")
- /// }
- ///
- /// Ok(())
- /// }
- /// ```
- #[inline]
- pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<Vec<usize>>> {
- self._interact_on(term, true)
- }
-
- fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<Vec<usize>>> {
- if self.items.is_empty() {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- "Empty list of items given to `MultiSelect`",
- ));
- }
-
- let mut paging = Paging::new(term, self.items.len(), self.max_length);
- let mut render = TermThemeRenderer::new(term, self.theme);
- let mut sel = 0;
-
- let mut size_vec = Vec::new();
-
- for items in self
- .items
- .iter()
- .flat_map(|i| i.split('\n'))
- .collect::<Vec<_>>()
- {
- let size = &items.len();
- size_vec.push(*size);
- }
-
- let mut checked: Vec<bool> = self.defaults.clone();
-
- term.hide_cursor()?;
-
- loop {
- if let Some(ref prompt) = self.prompt {
- paging
- .render_prompt(|paging_info| render.multi_select_prompt(prompt, paging_info))?;
- }
-
- for (idx, item) in self
- .items
- .iter()
- .enumerate()
- .skip(paging.current_page * paging.capacity)
- .take(paging.capacity)
- {
- render.multi_select_prompt_item(item, checked[idx], sel == idx)?;
- }
-
- term.flush()?;
-
- match term.read_key()? {
- Key::ArrowDown | Key::Tab | Key::Char('j') => {
- if sel == !0 {
- sel = 0;
- } else {
- sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize;
- }
- }
- Key::ArrowUp | Key::BackTab | Key::Char('k') => {
- if sel == !0 {
- sel = self.items.len() - 1;
- } else {
- sel = ((sel as i64 - 1 + self.items.len() as i64)
- % (self.items.len() as i64)) as usize;
- }
- }
- Key::ArrowLeft | Key::Char('h') => {
- if paging.active {
- sel = paging.previous_page();
- }
- }
- Key::ArrowRight | Key::Char('l') => {
- if paging.active {
- sel = paging.next_page();
- }
- }
- Key::Char(' ') => {
- checked[sel] = !checked[sel];
- }
- Key::Char('a') => {
- if checked.iter().all(|&item_checked| item_checked) {
- checked.fill(false);
- } else {
- checked.fill(true);
- }
- }
- Key::Escape | Key::Char('q') => {
- if allow_quit {
- if self.clear {
- render.clear()?;
- } else {
- term.clear_last_lines(paging.capacity)?;
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(None);
- }
- }
- Key::Enter => {
- if self.clear {
- render.clear()?;
- }
-
- if let Some(ref prompt) = self.prompt {
- if self.report {
- let selections: Vec<_> = checked
- .iter()
- .enumerate()
- .filter_map(|(idx, &checked)| {
- if checked {
- Some(self.items[idx].as_str())
- } else {
- None
- }
- })
- .collect();
-
- render.multi_select_prompt_selection(prompt, &selections[..])?;
- }
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(Some(
- checked
- .into_iter()
- .enumerate()
- .filter_map(|(idx, checked)| if checked { Some(idx) } else { None })
- .collect(),
- ));
- }
- _ => {}
- }
-
- paging.update(sel)?;
-
- if paging.active {
- render.clear()?;
- } else {
- render.clear_preserve_prompt(&size_vec)?;
- }
- }
- }
-}
-
-impl<'a> MultiSelect<'a> {
- /// Creates a multi select prompt with a specific theme.
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- items: vec![],
- defaults: vec![],
- clear: true,
- prompt: None,
- report: true,
- max_length: None,
- theme,
- }
- }
-}
diff --git a/vendor/dialoguer/src/prompts/password.rs b/vendor/dialoguer/src/prompts/password.rs
deleted file mode 100644
index 7327605..0000000
--- a/vendor/dialoguer/src/prompts/password.rs
+++ /dev/null
@@ -1,194 +0,0 @@
-use std::io;
-
-use crate::{
- theme::{SimpleTheme, TermThemeRenderer, Theme},
- validate::PasswordValidator,
-};
-
-use console::Term;
-use zeroize::Zeroizing;
-
-type PasswordValidatorCallback<'a> = Box<dyn Fn(&String) -> Option<String> + 'a>;
-
-/// Renders a password input prompt.
-///
-/// ## Example usage
-///
-/// ```rust,no_run
-/// # fn test() -> Result<(), Box<std::error::Error>> {
-/// use dialoguer::Password;
-///
-/// let password = Password::new().with_prompt("New Password")
-/// .with_confirmation("Confirm password", "Passwords mismatching")
-/// .interact()?;
-/// println!("Length of the password is: {}", password.len());
-/// # Ok(()) } fn main() { test().unwrap(); }
-/// ```
-pub struct Password<'a> {
- prompt: String,
- report: bool,
- theme: &'a dyn Theme,
- allow_empty_password: bool,
- confirmation_prompt: Option<(String, String)>,
- validator: Option<PasswordValidatorCallback<'a>>,
-}
-
-impl Default for Password<'static> {
- fn default() -> Password<'static> {
- Self::new()
- }
-}
-
-impl Password<'static> {
- /// Creates a password input prompt.
- pub fn new() -> Password<'static> {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl<'a> Password<'a> {
- /// Sets the password input prompt.
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = prompt.into();
- self
- }
-
- /// Indicates whether to report confirmation after interaction.
- ///
- /// The default is to report.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Enables confirmation prompting.
- pub fn with_confirmation<A, B>(&mut self, prompt: A, mismatch_err: B) -> &mut Self
- where
- A: Into<String>,
- B: Into<String>,
- {
- self.confirmation_prompt = Some((prompt.into(), mismatch_err.into()));
- self
- }
-
- /// Allows/Disables empty password.
- ///
- /// By default this setting is set to false (i.e. password is not empty).
- pub fn allow_empty_password(&mut self, allow_empty_password: bool) -> &mut Self {
- self.allow_empty_password = allow_empty_password;
- self
- }
-
- /// Registers a validator.
- ///
- /// # Example
- ///
- /// ```no_run
- /// # use dialoguer::Password;
- /// let password: String = Password::new()
- /// .with_prompt("Enter password")
- /// .validate_with(|input: &String| -> Result<(), &str> {
- /// if input.len() > 8 {
- /// Ok(())
- /// } else {
- /// Err("Password must be longer than 8")
- /// }
- /// })
- /// .interact()
- /// .unwrap();
- /// ```
- pub fn validate_with<V>(&mut self, validator: V) -> &mut Self
- where
- V: PasswordValidator + 'a,
- V::Err: ToString,
- {
- let old_validator_func = self.validator.take();
-
- self.validator = Some(Box::new(move |value: &String| -> Option<String> {
- if let Some(old) = &old_validator_func {
- if let Some(err) = old(value) {
- return Some(err);
- }
- }
-
- match validator.validate(value) {
- Ok(()) => None,
- Err(err) => Some(err.to_string()),
- }
- }));
-
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// If the user confirms the result is `true`, `false` otherwise.
- /// The dialog is rendered on stderr.
- pub fn interact(&self) -> io::Result<String> {
- self.interact_on(&Term::stderr())
- }
-
- /// Like `interact` but allows a specific terminal to be set.
- pub fn interact_on(&self, term: &Term) -> io::Result<String> {
- let mut render = TermThemeRenderer::new(term, self.theme);
- render.set_prompts_reset_height(false);
-
- loop {
- let password = Zeroizing::new(self.prompt_password(&mut render, &self.prompt)?);
-
- if let Some(ref validator) = self.validator {
- if let Some(err) = validator(&password) {
- render.error(&err)?;
- continue;
- }
- }
-
- if let Some((ref prompt, ref err)) = self.confirmation_prompt {
- let pw2 = Zeroizing::new(self.prompt_password(&mut render, prompt)?);
-
- if *password != *pw2 {
- render.error(err)?;
- continue;
- }
- }
-
- render.clear()?;
-
- if self.report {
- render.password_prompt_selection(&self.prompt)?;
- }
- term.flush()?;
-
- return Ok((*password).clone());
- }
- }
-
- fn prompt_password(&self, render: &mut TermThemeRenderer, prompt: &str) -> io::Result<String> {
- loop {
- render.password_prompt(prompt)?;
- render.term().flush()?;
-
- let input = render.term().read_secure_line()?;
-
- render.add_line();
-
- if !input.is_empty() || self.allow_empty_password {
- return Ok(input);
- }
- }
- }
-}
-
-impl<'a> Password<'a> {
- /// Creates a password input prompt with a specific theme.
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- prompt: "".into(),
- report: true,
- theme,
- allow_empty_password: false,
- confirmation_prompt: None,
- validator: None,
- }
- }
-}
diff --git a/vendor/dialoguer/src/prompts/select.rs b/vendor/dialoguer/src/prompts/select.rs
deleted file mode 100644
index d080abd..0000000
--- a/vendor/dialoguer/src/prompts/select.rs
+++ /dev/null
@@ -1,419 +0,0 @@
-use std::{io, ops::Rem};
-
-use crate::paging::Paging;
-use crate::theme::{SimpleTheme, TermThemeRenderer, Theme};
-
-use console::{Key, Term};
-
-/// Renders a select prompt.
-///
-/// User can select from one or more options.
-/// Interaction returns index of an item selected in the order they appear in `item` invocation or `items` slice.
-///
-/// ## Examples
-///
-/// ```rust,no_run
-/// use dialoguer::{console::Term, theme::ColorfulTheme, Select};
-///
-/// fn main() -> std::io::Result<()> {
-/// let items = vec!["Item 1", "item 2"];
-/// let selection = Select::with_theme(&ColorfulTheme::default())
-/// .items(&items)
-/// .default(0)
-/// .interact_on_opt(&Term::stderr())?;
-///
-/// match selection {
-/// Some(index) => println!("User selected item : {}", items[index]),
-/// None => println!("User did not select anything")
-/// }
-///
-/// Ok(())
-/// }
-/// ```
-pub struct Select<'a> {
- default: usize,
- items: Vec<String>,
- prompt: Option<String>,
- report: bool,
- clear: bool,
- theme: &'a dyn Theme,
- max_length: Option<usize>,
-}
-
-impl Default for Select<'static> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Select<'static> {
- /// Creates a select prompt builder with default theme.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl Select<'_> {
- /// Indicates whether select menu should be erased from the screen after interaction.
- ///
- /// The default is to clear the menu.
- pub fn clear(&mut self, val: bool) -> &mut Self {
- self.clear = val;
- self
- }
-
- /// Sets initial selected element when select menu is rendered
- ///
- /// Element is indicated by the index at which it appears in `item` method invocation or `items` slice.
- pub fn default(&mut self, val: usize) -> &mut Self {
- self.default = val;
- self
- }
-
- /// Sets an optional max length for a page.
- ///
- /// Max length is disabled by None
- pub fn max_length(&mut self, val: usize) -> &mut Self {
- // Paging subtracts two from the capacity, paging does this to
- // make an offset for the page indicator. So to make sure that
- // we can show the intended amount of items we need to add two
- // to our value.
- self.max_length = Some(val + 2);
- self
- }
-
- /// Add a single item to the selector.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::Select;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selection: usize = Select::new()
- /// .item("Item 1")
- /// .item("Item 2")
- /// .interact()?;
- ///
- /// Ok(())
- /// }
- /// ```
- pub fn item<T: ToString>(&mut self, item: T) -> &mut Self {
- self.items.push(item.to_string());
- self
- }
-
- /// Adds multiple items to the selector.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::Select;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let items = vec!["Item 1", "Item 2"];
- /// let selection: usize = Select::new()
- /// .items(&items)
- /// .interact()?;
- ///
- /// println!("{}", items[selection]);
- ///
- /// Ok(())
- /// }
- /// ```
- pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self {
- for item in items {
- self.items.push(item.to_string());
- }
- self
- }
-
- /// Sets the select prompt.
- ///
- /// By default, when a prompt is set the system also prints out a confirmation after
- /// the selection. You can opt-out of this with [`report`](#method.report).
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::Select;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selection = Select::new()
- /// .with_prompt("Which option do you prefer?")
- /// .item("Option A")
- /// .item("Option B")
- /// .interact()?;
- ///
- /// Ok(())
- /// }
- /// ```
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = Some(prompt.into());
- self.report = true;
- self
- }
-
- /// Indicates whether to report the selected value after interaction.
- ///
- /// The default is to report the selection.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `index` if user selected one of items using 'Enter'.
- /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'.
- #[inline]
- pub fn interact(&self) -> io::Result<usize> {
- self.interact_on(&Term::stderr())
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Some(index)` if user selected one of items using 'Enter' or `None` if user cancelled with 'Esc' or 'q'.
- #[inline]
- pub fn interact_opt(&self) -> io::Result<Option<usize>> {
- self.interact_on_opt(&Term::stderr())
- }
-
- /// Like [interact](#method.interact) but allows a specific terminal to be set.
- ///
- /// ## Examples
- ///```rust,no_run
- /// use dialoguer::{console::Term, Select};
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selection = Select::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on(&Term::stderr())?;
- ///
- /// println!("User selected option at index {}", selection);
- ///
- /// Ok(())
- /// }
- ///```
- #[inline]
- pub fn interact_on(&self, term: &Term) -> io::Result<usize> {
- self._interact_on(term, false)?
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case"))
- }
-
- /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::{console::Term, Select};
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selection = Select::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on_opt(&Term::stdout())?;
- ///
- /// match selection {
- /// Some(position) => println!("User selected option at index {}", position),
- /// None => println!("User did not select anything or exited using Esc or q")
- /// }
- ///
- /// Ok(())
- /// }
- /// ```
- #[inline]
- pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<usize>> {
- self._interact_on(term, true)
- }
-
- /// Like `interact` but allows a specific terminal to be set.
- fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<usize>> {
- if self.items.is_empty() {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- "Empty list of items given to `Select`",
- ));
- }
-
- let mut paging = Paging::new(term, self.items.len(), self.max_length);
- let mut render = TermThemeRenderer::new(term, self.theme);
- let mut sel = self.default;
-
- let mut size_vec = Vec::new();
-
- for items in self
- .items
- .iter()
- .flat_map(|i| i.split('\n'))
- .collect::<Vec<_>>()
- {
- let size = &items.len();
- size_vec.push(*size);
- }
-
- term.hide_cursor()?;
-
- loop {
- if let Some(ref prompt) = self.prompt {
- paging.render_prompt(|paging_info| render.select_prompt(prompt, paging_info))?;
- }
-
- for (idx, item) in self
- .items
- .iter()
- .enumerate()
- .skip(paging.current_page * paging.capacity)
- .take(paging.capacity)
- {
- render.select_prompt_item(item, sel == idx)?;
- }
-
- term.flush()?;
-
- match term.read_key()? {
- Key::ArrowDown | Key::Tab | Key::Char('j') => {
- if sel == !0 {
- sel = 0;
- } else {
- sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize;
- }
- }
- Key::Escape | Key::Char('q') => {
- if allow_quit {
- if self.clear {
- render.clear()?;
- } else {
- term.clear_last_lines(paging.capacity)?;
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(None);
- }
- }
- Key::ArrowUp | Key::BackTab | Key::Char('k') => {
- if sel == !0 {
- sel = self.items.len() - 1;
- } else {
- sel = ((sel as i64 - 1 + self.items.len() as i64)
- % (self.items.len() as i64)) as usize;
- }
- }
- Key::ArrowLeft | Key::Char('h') => {
- if paging.active {
- sel = paging.previous_page();
- }
- }
- Key::ArrowRight | Key::Char('l') => {
- if paging.active {
- sel = paging.next_page();
- }
- }
-
- Key::Enter | Key::Char(' ') if sel != !0 => {
- if self.clear {
- render.clear()?;
- }
-
- if let Some(ref prompt) = self.prompt {
- if self.report {
- render.select_prompt_selection(prompt, &self.items[sel])?;
- }
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(Some(sel));
- }
- _ => {}
- }
-
- paging.update(sel)?;
-
- if paging.active {
- render.clear()?;
- } else {
- render.clear_preserve_prompt(&size_vec)?;
- }
- }
- }
-}
-
-impl<'a> Select<'a> {
- /// Creates a select prompt builder with a specific theme.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::{
- /// Select,
- /// theme::ColorfulTheme
- /// };
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selection = Select::with_theme(&ColorfulTheme::default())
- /// .item("Option A")
- /// .item("Option B")
- /// .interact()?;
- ///
- /// Ok(())
- /// }
- /// ```
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- default: !0,
- items: vec![],
- prompt: None,
- report: false,
- clear: true,
- max_length: None,
- theme,
- }
- }
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
-
- #[test]
- fn test_str() {
- let selections = &[
- "Ice Cream",
- "Vanilla Cupcake",
- "Chocolate Muffin",
- "A Pile of sweet, sweet mustard",
- ];
-
- assert_eq!(
- Select::new().default(0).items(&selections[..]).items,
- selections
- );
- }
-
- #[test]
- fn test_string() {
- let selections = vec!["a".to_string(), "b".to_string()];
-
- assert_eq!(
- Select::new().default(0).items(&selections[..]).items,
- selections
- );
- }
-
- #[test]
- fn test_ref_str() {
- let a = "a";
- let b = "b";
-
- let selections = &[a, b];
-
- assert_eq!(
- Select::new().default(0).items(&selections[..]).items,
- selections
- );
- }
-}
diff --git a/vendor/dialoguer/src/prompts/sort.rs b/vendor/dialoguer/src/prompts/sort.rs
deleted file mode 100644
index 03152bf..0000000
--- a/vendor/dialoguer/src/prompts/sort.rs
+++ /dev/null
@@ -1,348 +0,0 @@
-use std::{io, ops::Rem};
-
-use crate::{
- theme::{SimpleTheme, TermThemeRenderer, Theme},
- Paging,
-};
-
-use console::{Key, Term};
-
-/// Renders a sort prompt.
-///
-/// Returns list of indices in original items list sorted according to user input.
-///
-/// ## Example usage
-/// ```rust,no_run
-/// use dialoguer::Sort;
-///
-/// # fn test() -> Result<(), Box<dyn std::error::Error>> {
-/// let items_to_order = vec!["Item 1", "Item 2", "Item 3"];
-/// let ordered = Sort::new()
-/// .with_prompt("Order the items")
-/// .items(&items_to_order)
-/// .interact()?;
-/// # Ok(())
-/// # }
-/// ```
-pub struct Sort<'a> {
- items: Vec<String>,
- prompt: Option<String>,
- report: bool,
- clear: bool,
- max_length: Option<usize>,
- theme: &'a dyn Theme,
-}
-
-impl Default for Sort<'static> {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Sort<'static> {
- /// Creates a sort prompt.
- pub fn new() -> Self {
- Self::with_theme(&SimpleTheme)
- }
-}
-
-impl Sort<'_> {
- /// Sets the clear behavior of the menu.
- ///
- /// The default is to clear the menu after user interaction.
- pub fn clear(&mut self, val: bool) -> &mut Self {
- self.clear = val;
- self
- }
-
- /// Sets an optional max length for a page
- ///
- /// Max length is disabled by None
- pub fn max_length(&mut self, val: usize) -> &mut Self {
- // Paging subtracts two from the capacity, paging does this to
- // make an offset for the page indicator. So to make sure that
- // we can show the intended amount of items we need to add two
- // to our value.
- self.max_length = Some(val + 2);
- self
- }
-
- /// Add a single item to the selector.
- pub fn item<T: ToString>(&mut self, item: T) -> &mut Self {
- self.items.push(item.to_string());
- self
- }
-
- /// Adds multiple items to the selector.
- pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self {
- for item in items {
- self.items.push(item.to_string());
- }
- self
- }
-
- /// Prefaces the menu with a prompt.
- ///
- /// By default, when a prompt is set the system also prints out a confirmation after
- /// the selection. You can opt-out of this with [`report`](#method.report).
- pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self {
- self.prompt = Some(prompt.into());
- self
- }
-
- /// Indicates whether to report the selected order after interaction.
- ///
- /// The default is to report the selected order.
- pub fn report(&mut self, val: bool) -> &mut Self {
- self.report = val;
- self
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can order the items with the 'Space' bar and the arrows. On 'Enter' ordered list of the incides of items will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Vec<index>` if user hit 'Enter'.
- /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'.
- #[inline]
- pub fn interact(&self) -> io::Result<Vec<usize>> {
- self.interact_on(&Term::stderr())
- }
-
- /// Enables user interaction and returns the result.
- ///
- /// The user can order the items with the 'Space' bar and the arrows. On 'Enter' ordered list of the incides of items will be returned.
- /// The dialog is rendered on stderr.
- /// Result contains `Some(Vec<index>)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'.
- #[inline]
- pub fn interact_opt(&self) -> io::Result<Option<Vec<usize>>> {
- self.interact_on_opt(&Term::stderr())
- }
-
- /// Like [interact](#method.interact) but allows a specific terminal to be set.
- ///
- /// ## Examples
- ///```rust,no_run
- /// use dialoguer::Sort;
- /// use console::Term;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selections = Sort::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on(&Term::stderr())?;
- ///
- /// println!("User sorted options as indices {:?}", selections);
- ///
- /// Ok(())
- /// }
- ///```
- #[inline]
- pub fn interact_on(&self, term: &Term) -> io::Result<Vec<usize>> {
- self._interact_on(term, false)?
- .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case"))
- }
-
- /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set.
- ///
- /// ## Examples
- /// ```rust,no_run
- /// use dialoguer::Sort;
- /// use console::Term;
- ///
- /// fn main() -> std::io::Result<()> {
- /// let selections = Sort::new()
- /// .item("Option A")
- /// .item("Option B")
- /// .interact_on_opt(&Term::stdout())?;
- ///
- /// match selections {
- /// Some(positions) => println!("User sorted options as indices {:?}", positions),
- /// None => println!("User exited using Esc or q")
- /// }
- ///
- /// Ok(())
- /// }
- /// ```
- #[inline]
- pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<Vec<usize>>> {
- self._interact_on(term, true)
- }
-
- fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<Vec<usize>>> {
- if self.items.is_empty() {
- return Err(io::Error::new(
- io::ErrorKind::Other,
- "Empty list of items given to `Sort`",
- ));
- }
-
- let mut paging = Paging::new(term, self.items.len(), self.max_length);
- let mut render = TermThemeRenderer::new(term, self.theme);
- let mut sel = 0;
-
- let mut size_vec = Vec::new();
-
- for items in self.items.iter().as_slice() {
- let size = &items.len();
- size_vec.push(*size);
- }
-
- let mut order: Vec<_> = (0..self.items.len()).collect();
- let mut checked: bool = false;
-
- term.hide_cursor()?;
-
- loop {
- if let Some(ref prompt) = self.prompt {
- paging.render_prompt(|paging_info| render.sort_prompt(prompt, paging_info))?;
- }
-
- for (idx, item) in order
- .iter()
- .enumerate()
- .skip(paging.current_page * paging.capacity)
- .take(paging.capacity)
- {
- render.sort_prompt_item(&self.items[*item], checked, sel == idx)?;
- }
-
- term.flush()?;
-
- match term.read_key()? {
- Key::ArrowDown | Key::Tab | Key::Char('j') => {
- let old_sel = sel;
-
- if sel == !0 {
- sel = 0;
- } else {
- sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize;
- }
-
- if checked && old_sel != sel {
- order.swap(old_sel, sel);
- }
- }
- Key::ArrowUp | Key::BackTab | Key::Char('k') => {
- let old_sel = sel;
-
- if sel == !0 {
- sel = self.items.len() - 1;
- } else {
- sel = ((sel as i64 - 1 + self.items.len() as i64)
- % (self.items.len() as i64)) as usize;
- }
-
- if checked && old_sel != sel {
- order.swap(old_sel, sel);
- }
- }
- Key::ArrowLeft | Key::Char('h') => {
- if paging.active {
- let old_sel = sel;
- let old_page = paging.current_page;
-
- sel = paging.previous_page();
-
- if checked {
- let indexes: Vec<_> = if old_page == 0 {
- let indexes1: Vec<_> = (0..=old_sel).rev().collect();
- let indexes2: Vec<_> = (sel..self.items.len()).rev().collect();
- [indexes1, indexes2].concat()
- } else {
- (sel..=old_sel).rev().collect()
- };
-
- for index in 0..(indexes.len() - 1) {
- order.swap(indexes[index], indexes[index + 1]);
- }
- }
- }
- }
- Key::ArrowRight | Key::Char('l') => {
- if paging.active {
- let old_sel = sel;
- let old_page = paging.current_page;
-
- sel = paging.next_page();
-
- if checked {
- let indexes: Vec<_> = if old_page == paging.pages - 1 {
- let indexes1: Vec<_> = (old_sel..self.items.len()).collect();
- let indexes2: Vec<_> = vec![0];
- [indexes1, indexes2].concat()
- } else {
- (old_sel..=sel).collect()
- };
-
- for index in 0..(indexes.len() - 1) {
- order.swap(indexes[index], indexes[index + 1]);
- }
- }
- }
- }
- Key::Char(' ') => {
- checked = !checked;
- }
- Key::Escape | Key::Char('q') => {
- if allow_quit {
- if self.clear {
- render.clear()?;
- } else {
- term.clear_last_lines(paging.capacity)?;
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(None);
- }
- }
- Key::Enter => {
- if self.clear {
- render.clear()?;
- }
-
- if let Some(ref prompt) = self.prompt {
- if self.report {
- let list: Vec<_> = order
- .iter()
- .enumerate()
- .map(|(_, item)| self.items[*item].as_str())
- .collect();
- render.sort_prompt_selection(prompt, &list[..])?;
- }
- }
-
- term.show_cursor()?;
- term.flush()?;
-
- return Ok(Some(order));
- }
- _ => {}
- }
-
- paging.update(sel)?;
-
- if paging.active {
- render.clear()?;
- } else {
- render.clear_preserve_prompt(&size_vec)?;
- }
- }
- }
-}
-
-impl<'a> Sort<'a> {
- /// Creates a sort prompt with a specific theme.
- pub fn with_theme(theme: &'a dyn Theme) -> Self {
- Self {
- items: vec![],
- clear: true,
- prompt: None,
- report: true,
- max_length: None,
- theme,
- }
- }
-}
diff --git a/vendor/dialoguer/src/theme.rs b/vendor/dialoguer/src/theme.rs
deleted file mode 100644
index 1fbde92..0000000
--- a/vendor/dialoguer/src/theme.rs
+++ /dev/null
@@ -1,976 +0,0 @@
-//! Customizes the rendering of the elements.
-use std::{fmt, io};
-
-use console::{measure_text_width, style, Style, StyledObject, Term};
-#[cfg(feature = "fuzzy-select")]
-use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher};
-
-/// Implements a theme for dialoguer.
-pub trait Theme {
- /// Formats a prompt.
- #[inline]
- fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- write!(f, "{}:", prompt)
- }
-
- /// Formats out an error.
- #[inline]
- fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result {
- write!(f, "error: {}", err)
- }
-
- /// Formats a confirm prompt.
- fn format_confirm_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- default: Option<bool>,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(f, "{} ", &prompt)?;
- }
- match default {
- None => write!(f, "[y/n] ")?,
- Some(true) => write!(f, "[Y/n] ")?,
- Some(false) => write!(f, "[y/N] ")?,
- }
- Ok(())
- }
-
- /// Formats a confirm prompt after selection.
- fn format_confirm_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- selection: Option<bool>,
- ) -> fmt::Result {
- let selection = selection.map(|b| if b { "yes" } else { "no" });
-
- match selection {
- Some(selection) if prompt.is_empty() => {
- write!(f, "{}", selection)
- }
- Some(selection) => {
- write!(f, "{} {}", &prompt, selection)
- }
- None if prompt.is_empty() => Ok(()),
- None => {
- write!(f, "{}", &prompt)
- }
- }
- }
-
- /// Formats an input prompt.
- fn format_input_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- default: Option<&str>,
- ) -> fmt::Result {
- match default {
- Some(default) if prompt.is_empty() => write!(f, "[{}]: ", default),
- Some(default) => write!(f, "{} [{}]: ", prompt, default),
- None => write!(f, "{}: ", prompt),
- }
- }
-
- /// Formats an input prompt after selection.
- #[inline]
- fn format_input_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- sel: &str,
- ) -> fmt::Result {
- write!(f, "{}: {}", prompt, sel)
- }
-
- /// Formats a password prompt.
- #[inline]
- #[cfg(feature = "password")]
- fn format_password_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- self.format_input_prompt(f, prompt, None)
- }
-
- /// Formats a password prompt after selection.
- #[inline]
- #[cfg(feature = "password")]
- fn format_password_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- ) -> fmt::Result {
- self.format_input_prompt_selection(f, prompt, "[hidden]")
- }
-
- /// Formats a select prompt.
- #[inline]
- fn format_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- self.format_prompt(f, prompt)
- }
-
- /// Formats a select prompt after selection.
- #[inline]
- fn format_select_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- sel: &str,
- ) -> fmt::Result {
- self.format_input_prompt_selection(f, prompt, sel)
- }
-
- /// Formats a multi select prompt.
- #[inline]
- fn format_multi_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- self.format_prompt(f, prompt)
- }
-
- /// Formats a sort prompt.
- #[inline]
- fn format_sort_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- self.format_prompt(f, prompt)
- }
-
- /// Formats a multi_select prompt after selection.
- fn format_multi_select_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- selections: &[&str],
- ) -> fmt::Result {
- write!(f, "{}: ", prompt)?;
- for (idx, sel) in selections.iter().enumerate() {
- write!(f, "{}{}", if idx == 0 { "" } else { ", " }, sel)?;
- }
- Ok(())
- }
-
- /// Formats a sort prompt after selection.
- #[inline]
- fn format_sort_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- selections: &[&str],
- ) -> fmt::Result {
- self.format_multi_select_prompt_selection(f, prompt, selections)
- }
-
- /// Formats a select prompt item.
- fn format_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- active: bool,
- ) -> fmt::Result {
- write!(f, "{} {}", if active { ">" } else { " " }, text)
- }
-
- /// Formats a multi select prompt item.
- fn format_multi_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- checked: bool,
- active: bool,
- ) -> fmt::Result {
- write!(
- f,
- "{} {}",
- match (checked, active) {
- (true, true) => "> [x]",
- (true, false) => " [x]",
- (false, true) => "> [ ]",
- (false, false) => " [ ]",
- },
- text
- )
- }
-
- /// Formats a sort prompt item.
- fn format_sort_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- picked: bool,
- active: bool,
- ) -> fmt::Result {
- write!(
- f,
- "{} {}",
- match (picked, active) {
- (true, true) => "> [x]",
- (false, true) => "> [ ]",
- (_, false) => " [ ]",
- },
- text
- )
- }
-
- /// Formats a fuzzy select prompt item.
- #[cfg(feature = "fuzzy-select")]
- fn format_fuzzy_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- active: bool,
- highlight_matches: bool,
- matcher: &SkimMatcherV2,
- search_term: &str,
- ) -> fmt::Result {
- write!(f, "{} ", if active { ">" } else { " " })?;
-
- if highlight_matches {
- if let Some((_score, indices)) = matcher.fuzzy_indices(text, &search_term) {
- for (idx, c) in text.chars().into_iter().enumerate() {
- if indices.contains(&idx) {
- write!(f, "{}", style(c).for_stderr().bold())?;
- } else {
- write!(f, "{}", c)?;
- }
- }
-
- return Ok(());
- }
- }
-
- write!(f, "{}", text)
- }
-
- /// Formats a fuzzy select prompt.
- #[cfg(feature = "fuzzy-select")]
- fn format_fuzzy_select_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- search_term: &str,
- cursor_pos: usize,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(f, "{} ", prompt,)?;
- }
-
- if cursor_pos < search_term.len() {
- let st_head = search_term[0..cursor_pos].to_string();
- let st_tail = search_term[cursor_pos..search_term.len()].to_string();
- let st_cursor = "|".to_string();
- write!(f, "{}{}{}", st_head, st_cursor, st_tail)
- } else {
- let cursor = "|".to_string();
- write!(f, "{}{}", search_term.to_string(), cursor)
- }
- }
-}
-
-/// The default theme.
-pub struct SimpleTheme;
-
-impl Theme for SimpleTheme {}
-
-/// A colorful theme
-pub struct ColorfulTheme {
- /// The style for default values
- pub defaults_style: Style,
- /// The style for prompt
- pub prompt_style: Style,
- /// Prompt prefix value and style
- pub prompt_prefix: StyledObject<String>,
- /// Prompt suffix value and style
- pub prompt_suffix: StyledObject<String>,
- /// Prompt on success prefix value and style
- pub success_prefix: StyledObject<String>,
- /// Prompt on success suffix value and style
- pub success_suffix: StyledObject<String>,
- /// Error prefix value and style
- pub error_prefix: StyledObject<String>,
- /// The style for error message
- pub error_style: Style,
- /// The style for hints
- pub hint_style: Style,
- /// The style for values on prompt success
- pub values_style: Style,
- /// The style for active items
- pub active_item_style: Style,
- /// The style for inactive items
- pub inactive_item_style: Style,
- /// Active item in select prefix value and style
- pub active_item_prefix: StyledObject<String>,
- /// Inctive item in select prefix value and style
- pub inactive_item_prefix: StyledObject<String>,
- /// Checked item in multi select prefix value and style
- pub checked_item_prefix: StyledObject<String>,
- /// Unchecked item in multi select prefix value and style
- pub unchecked_item_prefix: StyledObject<String>,
- /// Picked item in sort prefix value and style
- pub picked_item_prefix: StyledObject<String>,
- /// Unpicked item in sort prefix value and style
- pub unpicked_item_prefix: StyledObject<String>,
- /// Formats the cursor for a fuzzy select prompt
- #[cfg(feature = "fuzzy-select")]
- pub fuzzy_cursor_style: Style,
- // Formats the highlighting if matched characters
- #[cfg(feature = "fuzzy-select")]
- pub fuzzy_match_highlight_style: Style,
- /// Show the selections from certain prompts inline
- pub inline_selections: bool,
-}
-
-impl Default for ColorfulTheme {
- fn default() -> ColorfulTheme {
- ColorfulTheme {
- defaults_style: Style::new().for_stderr().cyan(),
- prompt_style: Style::new().for_stderr().bold(),
- prompt_prefix: style("?".to_string()).for_stderr().yellow(),
- prompt_suffix: style("›".to_string()).for_stderr().black().bright(),
- success_prefix: style("✔".to_string()).for_stderr().green(),
- success_suffix: style("·".to_string()).for_stderr().black().bright(),
- error_prefix: style("✘".to_string()).for_stderr().red(),
- error_style: Style::new().for_stderr().red(),
- hint_style: Style::new().for_stderr().black().bright(),
- values_style: Style::new().for_stderr().green(),
- active_item_style: Style::new().for_stderr().cyan(),
- inactive_item_style: Style::new().for_stderr(),
- active_item_prefix: style("❯".to_string()).for_stderr().green(),
- inactive_item_prefix: style(" ".to_string()).for_stderr(),
- checked_item_prefix: style("✔".to_string()).for_stderr().green(),
- unchecked_item_prefix: style("✔".to_string()).for_stderr().black(),
- picked_item_prefix: style("❯".to_string()).for_stderr().green(),
- unpicked_item_prefix: style(" ".to_string()).for_stderr(),
- #[cfg(feature = "fuzzy-select")]
- fuzzy_cursor_style: Style::new().for_stderr().black().on_white(),
- #[cfg(feature = "fuzzy-select")]
- fuzzy_match_highlight_style: Style::new().for_stderr().bold(),
- inline_selections: true,
- }
- }
-}
-
-impl Theme for ColorfulTheme {
- /// Formats a prompt.
- fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.prompt_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- write!(f, "{}", &self.prompt_suffix)
- }
-
- /// Formats an error
- fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result {
- write!(
- f,
- "{} {}",
- &self.error_prefix,
- self.error_style.apply_to(err)
- )
- }
-
- /// Formats an input prompt.
- fn format_input_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- default: Option<&str>,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.prompt_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- match default {
- Some(default) => write!(
- f,
- "{} {} ",
- self.hint_style.apply_to(&format!("({})", default)),
- &self.prompt_suffix
- ),
- None => write!(f, "{} ", &self.prompt_suffix),
- }
- }
-
- /// Formats a confirm prompt.
- fn format_confirm_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- default: Option<bool>,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.prompt_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- match default {
- None => write!(
- f,
- "{} {}",
- self.hint_style.apply_to("(y/n)"),
- &self.prompt_suffix
- ),
- Some(true) => write!(
- f,
- "{} {} {}",
- self.hint_style.apply_to("(y/n)"),
- &self.prompt_suffix,
- self.defaults_style.apply_to("yes")
- ),
- Some(false) => write!(
- f,
- "{} {} {}",
- self.hint_style.apply_to("(y/n)"),
- &self.prompt_suffix,
- self.defaults_style.apply_to("no")
- ),
- }
- }
-
- /// Formats a confirm prompt after selection.
- fn format_confirm_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- selection: Option<bool>,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.success_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
- let selection = selection.map(|b| if b { "yes" } else { "no" });
-
- match selection {
- Some(selection) => {
- write!(
- f,
- "{} {}",
- &self.success_suffix,
- self.values_style.apply_to(selection)
- )
- }
- None => {
- write!(f, "{}", &self.success_suffix)
- }
- }
- }
-
- /// Formats an input prompt after selection.
- fn format_input_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- sel: &str,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.success_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- write!(
- f,
- "{} {}",
- &self.success_suffix,
- self.values_style.apply_to(sel)
- )
- }
-
- /// Formats a password prompt after selection.
- #[cfg(feature = "password")]
- fn format_password_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- ) -> fmt::Result {
- self.format_input_prompt_selection(f, prompt, "********")
- }
-
- /// Formats a multi select prompt after selection.
- fn format_multi_select_prompt_selection(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- selections: &[&str],
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.success_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- write!(f, "{} ", &self.success_suffix)?;
-
- if self.inline_selections {
- for (idx, sel) in selections.iter().enumerate() {
- write!(
- f,
- "{}{}",
- if idx == 0 { "" } else { ", " },
- self.values_style.apply_to(sel)
- )?;
- }
- }
-
- Ok(())
- }
-
- /// Formats a select prompt item.
- fn format_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- active: bool,
- ) -> fmt::Result {
- let details = if active {
- (
- &self.active_item_prefix,
- self.active_item_style.apply_to(text),
- )
- } else {
- (
- &self.inactive_item_prefix,
- self.inactive_item_style.apply_to(text),
- )
- };
-
- write!(f, "{} {}", details.0, details.1)
- }
-
- /// Formats a multi select prompt item.
- fn format_multi_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- checked: bool,
- active: bool,
- ) -> fmt::Result {
- let details = match (checked, active) {
- (true, true) => (
- &self.checked_item_prefix,
- self.active_item_style.apply_to(text),
- ),
- (true, false) => (
- &self.checked_item_prefix,
- self.inactive_item_style.apply_to(text),
- ),
- (false, true) => (
- &self.unchecked_item_prefix,
- self.active_item_style.apply_to(text),
- ),
- (false, false) => (
- &self.unchecked_item_prefix,
- self.inactive_item_style.apply_to(text),
- ),
- };
-
- write!(f, "{} {}", details.0, details.1)
- }
-
- /// Formats a sort prompt item.
- fn format_sort_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- picked: bool,
- active: bool,
- ) -> fmt::Result {
- let details = match (picked, active) {
- (true, true) => (
- &self.picked_item_prefix,
- self.active_item_style.apply_to(text),
- ),
- (false, true) => (
- &self.unpicked_item_prefix,
- self.active_item_style.apply_to(text),
- ),
- (_, false) => (
- &self.unpicked_item_prefix,
- self.inactive_item_style.apply_to(text),
- ),
- };
-
- write!(f, "{} {}", details.0, details.1)
- }
-
- /// Formats a fuzzy select prompt item.
- #[cfg(feature = "fuzzy-select")]
- fn format_fuzzy_select_prompt_item(
- &self,
- f: &mut dyn fmt::Write,
- text: &str,
- active: bool,
- highlight_matches: bool,
- matcher: &SkimMatcherV2,
- search_term: &str,
- ) -> fmt::Result {
- write!(
- f,
- "{} ",
- if active {
- &self.active_item_prefix
- } else {
- &self.inactive_item_prefix
- }
- )?;
-
- if highlight_matches {
- if let Some((_score, indices)) = matcher.fuzzy_indices(text, &search_term) {
- for (idx, c) in text.chars().into_iter().enumerate() {
- if indices.contains(&idx) {
- if active {
- write!(
- f,
- "{}",
- self.active_item_style
- .apply_to(self.fuzzy_match_highlight_style.apply_to(c))
- )?;
- } else {
- write!(f, "{}", self.fuzzy_match_highlight_style.apply_to(c))?;
- }
- } else {
- if active {
- write!(f, "{}", self.active_item_style.apply_to(c))?;
- } else {
- write!(f, "{}", c)?;
- }
- }
- }
-
- return Ok(());
- }
- }
-
- write!(f, "{}", text)
- }
-
- /// Formats a fuzzy-selectprompt after selection.
- #[cfg(feature = "fuzzy-select")]
- fn format_fuzzy_select_prompt(
- &self,
- f: &mut dyn fmt::Write,
- prompt: &str,
- search_term: &str,
- cursor_pos: usize,
- ) -> fmt::Result {
- if !prompt.is_empty() {
- write!(
- f,
- "{} {} ",
- &self.prompt_prefix,
- self.prompt_style.apply_to(prompt)
- )?;
- }
-
- if cursor_pos < search_term.len() {
- let st_head = search_term[0..cursor_pos].to_string();
- let st_tail = search_term[cursor_pos + 1..search_term.len()].to_string();
- let st_cursor = self
- .fuzzy_cursor_style
- .apply_to(search_term.to_string().chars().nth(cursor_pos).unwrap());
- write!(
- f,
- "{} {}{}{}",
- &self.prompt_suffix, st_head, st_cursor, st_tail
- )
- } else {
- let cursor = self.fuzzy_cursor_style.apply_to(" ");
- write!(
- f,
- "{} {}{}",
- &self.prompt_suffix,
- search_term.to_string(),
- cursor
- )
- }
- }
-}
-
-/// Helper struct to conveniently render a theme of a term.
-pub(crate) struct TermThemeRenderer<'a> {
- term: &'a Term,
- theme: &'a dyn Theme,
- height: usize,
- prompt_height: usize,
- prompts_reset_height: bool,
-}
-
-impl<'a> TermThemeRenderer<'a> {
- pub fn new(term: &'a Term, theme: &'a dyn Theme) -> TermThemeRenderer<'a> {
- TermThemeRenderer {
- term,
- theme,
- height: 0,
- prompt_height: 0,
- prompts_reset_height: true,
- }
- }
-
- #[cfg(feature = "password")]
- pub fn set_prompts_reset_height(&mut self, val: bool) {
- self.prompts_reset_height = val;
- }
-
- #[cfg(feature = "password")]
- pub fn term(&self) -> &Term {
- self.term
- }
-
- pub fn add_line(&mut self) {
- self.height += 1;
- }
-
- fn write_formatted_str<
- F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result,
- >(
- &mut self,
- f: F,
- ) -> io::Result<usize> {
- let mut buf = String::new();
- f(self, &mut buf).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
- self.height += buf.chars().filter(|&x| x == '\n').count();
- self.term.write_str(&buf)?;
- Ok(measure_text_width(&buf))
- }
-
- fn write_formatted_line<
- F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result,
- >(
- &mut self,
- f: F,
- ) -> io::Result<()> {
- let mut buf = String::new();
- f(self, &mut buf).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
- self.height += buf.chars().filter(|&x| x == '\n').count() + 1;
- self.term.write_line(&buf)
- }
-
- fn write_formatted_prompt<
- F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result,
- >(
- &mut self,
- f: F,
- ) -> io::Result<()> {
- self.write_formatted_line(f)?;
- if self.prompts_reset_height {
- self.prompt_height = self.height;
- self.height = 0;
- }
- Ok(())
- }
-
- fn write_paging_info(buf: &mut dyn fmt::Write, paging_info: (usize, usize)) -> fmt::Result {
- write!(buf, " [Page {}/{}] ", paging_info.0, paging_info.1)
- }
-
- pub fn error(&mut self, err: &str) -> io::Result<()> {
- self.write_formatted_line(|this, buf| this.theme.format_error(buf, err))
- }
-
- pub fn confirm_prompt(&mut self, prompt: &str, default: Option<bool>) -> io::Result<usize> {
- self.write_formatted_str(|this, buf| this.theme.format_confirm_prompt(buf, prompt, default))
- }
-
- pub fn confirm_prompt_selection(&mut self, prompt: &str, sel: Option<bool>) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_confirm_prompt_selection(buf, prompt, sel)
- })
- }
-
- #[cfg(feature = "fuzzy-select")]
- pub fn fuzzy_select_prompt(
- &mut self,
- prompt: &str,
- search_term: &str,
- cursor_pos: usize,
- ) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme
- .format_fuzzy_select_prompt(buf, prompt, search_term, cursor_pos)
- })
- }
-
- pub fn input_prompt(&mut self, prompt: &str, default: Option<&str>) -> io::Result<usize> {
- self.write_formatted_str(|this, buf| this.theme.format_input_prompt(buf, prompt, default))
- }
-
- pub fn input_prompt_selection(&mut self, prompt: &str, sel: &str) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_input_prompt_selection(buf, prompt, sel)
- })
- }
-
- #[cfg(feature = "password")]
- pub fn password_prompt(&mut self, prompt: &str) -> io::Result<usize> {
- self.write_formatted_str(|this, buf| {
- write!(buf, "\r")?;
- this.theme.format_password_prompt(buf, prompt)
- })
- }
-
- #[cfg(feature = "password")]
- pub fn password_prompt_selection(&mut self, prompt: &str) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_password_prompt_selection(buf, prompt)
- })
- }
-
- pub fn select_prompt(
- &mut self,
- prompt: &str,
- paging_info: Option<(usize, usize)>,
- ) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_select_prompt(buf, prompt)?;
-
- if let Some(paging_info) = paging_info {
- TermThemeRenderer::write_paging_info(buf, paging_info)?;
- }
-
- Ok(())
- })
- }
-
- pub fn select_prompt_selection(&mut self, prompt: &str, sel: &str) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_select_prompt_selection(buf, prompt, sel)
- })
- }
-
- pub fn select_prompt_item(&mut self, text: &str, active: bool) -> io::Result<()> {
- self.write_formatted_line(|this, buf| {
- this.theme.format_select_prompt_item(buf, text, active)
- })
- }
-
- #[cfg(feature = "fuzzy-select")]
- pub fn fuzzy_select_prompt_item(
- &mut self,
- text: &str,
- active: bool,
- highlight: bool,
- matcher: &SkimMatcherV2,
- search_term: &str,
- ) -> io::Result<()> {
- self.write_formatted_line(|this, buf| {
- this.theme.format_fuzzy_select_prompt_item(
- buf,
- text,
- active,
- highlight,
- matcher,
- search_term,
- )
- })
- }
-
- pub fn multi_select_prompt(
- &mut self,
- prompt: &str,
- paging_info: Option<(usize, usize)>,
- ) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_multi_select_prompt(buf, prompt)?;
-
- if let Some(paging_info) = paging_info {
- TermThemeRenderer::write_paging_info(buf, paging_info)?;
- }
-
- Ok(())
- })
- }
-
- pub fn multi_select_prompt_selection(&mut self, prompt: &str, sel: &[&str]) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme
- .format_multi_select_prompt_selection(buf, prompt, sel)
- })
- }
-
- pub fn multi_select_prompt_item(
- &mut self,
- text: &str,
- checked: bool,
- active: bool,
- ) -> io::Result<()> {
- self.write_formatted_line(|this, buf| {
- this.theme
- .format_multi_select_prompt_item(buf, text, checked, active)
- })
- }
-
- pub fn sort_prompt(
- &mut self,
- prompt: &str,
- paging_info: Option<(usize, usize)>,
- ) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_sort_prompt(buf, prompt)?;
-
- if let Some(paging_info) = paging_info {
- TermThemeRenderer::write_paging_info(buf, paging_info)?;
- }
-
- Ok(())
- })
- }
-
- pub fn sort_prompt_selection(&mut self, prompt: &str, sel: &[&str]) -> io::Result<()> {
- self.write_formatted_prompt(|this, buf| {
- this.theme.format_sort_prompt_selection(buf, prompt, sel)
- })
- }
-
- pub fn sort_prompt_item(&mut self, text: &str, picked: bool, active: bool) -> io::Result<()> {
- self.write_formatted_line(|this, buf| {
- this.theme
- .format_sort_prompt_item(buf, text, picked, active)
- })
- }
-
- pub fn clear(&mut self) -> io::Result<()> {
- self.term
- .clear_last_lines(self.height + self.prompt_height)?;
- self.height = 0;
- self.prompt_height = 0;
- Ok(())
- }
-
- pub fn clear_preserve_prompt(&mut self, size_vec: &[usize]) -> io::Result<()> {
- let mut new_height = self.height;
- let prefix_width = 2;
- //Check each item size, increment on finding an overflow
- for size in size_vec {
- if *size > self.term.size().1 as usize {
- new_height += (((*size as f64 + prefix_width as f64) / self.term.size().1 as f64)
- .ceil()) as usize
- - 1;
- }
- }
-
- self.term.clear_last_lines(new_height)?;
- self.height = 0;
- Ok(())
- }
-}
diff --git a/vendor/dialoguer/src/validate.rs b/vendor/dialoguer/src/validate.rs
deleted file mode 100644
index addc9b4..0000000
--- a/vendor/dialoguer/src/validate.rs
+++ /dev/null
@@ -1,49 +0,0 @@
-//! Provides validation for text inputs
-
-/// Trait for input validators.
-///
-/// A generic implementation for `Fn(&str) -> Result<(), E>` is provided
-/// to facilitate development.
-pub trait Validator<T> {
- type Err;
-
- /// Invoked with the value to validate.
- ///
- /// If this produces `Ok(())` then the value is used and parsed, if
- /// an error is returned validation fails with that error.
- fn validate(&mut self, input: &T) -> Result<(), Self::Err>;
-}
-
-impl<T, F, E> Validator<T> for F
-where
- F: FnMut(&T) -> Result<(), E>,
-{
- type Err = E;
-
- fn validate(&mut self, input: &T) -> Result<(), Self::Err> {
- self(input)
- }
-}
-
-/// Trait for password validators.
-#[allow(clippy::ptr_arg)]
-pub trait PasswordValidator {
- type Err;
-
- /// Invoked with the value to validate.
- ///
- /// If this produces `Ok(())` then the value is used and parsed, if
- /// an error is returned validation fails with that error.
- fn validate(&self, input: &String) -> Result<(), Self::Err>;
-}
-
-impl<F, E> PasswordValidator for F
-where
- F: Fn(&String) -> Result<(), E>,
-{
- type Err = E;
-
- fn validate(&self, input: &String) -> Result<(), Self::Err> {
- self(input)
- }
-}