dialoguer_ext/
history.rs

1use std::collections::VecDeque;
2
3/// Trait for history handling.
4pub trait History<T> {
5    /// This is called with the current position that should
6    /// be read from history. The `pos` represents the number
7    /// of times the `Up`/`Down` arrow key has been pressed.
8    /// This would normally be used as an index to some sort
9    /// of vector. If the `pos` does not have an entry, [`None`](Option::None)
10    /// should be returned.
11    fn read(&self, pos: usize) -> Option<String>;
12
13    /// This is called with the next value you should store
14    /// in history at the first location. Normally history
15    /// is implemented as a FIFO queue.
16    fn write(&mut self, val: &T);
17}
18
19pub struct BasicHistory {
20    max_entries: Option<usize>,
21    deque: VecDeque<String>,
22    no_duplicates: bool,
23}
24
25impl BasicHistory {
26    /// Creates a new basic history value which has no limit on the number of
27    /// entries and allows for duplicates.
28    ///
29    /// # Example
30    ///
31    /// A history with at most 8 entries and no duplicates:
32    ///
33    /// ```rs
34    /// let mut history = BasicHistory::new().max_entries(8).no_duplicates(true);
35    /// ```
36    pub fn new() -> Self {
37        Self {
38            max_entries: None,
39            deque: VecDeque::new(),
40            no_duplicates: false,
41        }
42    }
43
44    /// Limit the number of entries stored in the history.
45    pub fn max_entries(self, max_entries: usize) -> Self {
46        Self {
47            max_entries: Some(max_entries),
48            ..self
49        }
50    }
51
52    /// Prevent duplicates in the history. This means that any previous entries
53    /// that are equal to a new entry are removed before the new entry is added.
54    pub fn no_duplicates(self, no_duplicates: bool) -> Self {
55        Self {
56            no_duplicates,
57            ..self
58        }
59    }
60}
61
62impl<T: ToString> History<T> for BasicHistory {
63    fn read(&self, pos: usize) -> Option<String> {
64        self.deque.get(pos).cloned()
65    }
66
67    fn write(&mut self, val: &T) {
68        let val = val.to_string();
69
70        if self.no_duplicates {
71            self.deque.retain(|v| v != &val);
72        }
73
74        self.deque.push_front(val);
75
76        if let Some(max_entries) = self.max_entries {
77            self.deque.truncate(max_entries);
78        }
79    }
80}
81
82impl Default for BasicHistory {
83    fn default() -> Self {
84        Self::new()
85    }
86}