1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
use std::collections::VecDeque;

use futures::channel::mpsc::{self, UnboundedReceiver, UnboundedSender};

pub struct History {
	pub entries: VecDeque<String>,
	pub max_size: usize,
	pub sender: UnboundedSender<String>,
	receiver: UnboundedReceiver<String>,

	current_position: Option<usize>,
}
impl Default for History {
	fn default() -> Self {
		let (sender, receiver) = mpsc::unbounded();
		Self {
			entries: Default::default(),
			max_size: 1000,
			sender,
			receiver,
			current_position: Default::default(),
		}
	}
}

impl History {
	// Update history entries
	pub async fn update(&mut self) {
		// Receive all new lines
		while let Ok(Some(line)) = self.receiver.try_next() {
			// Don't add entry if last entry was same, or line was empty.
			if self.entries.front() == Some(&line) || line.is_empty() {
				continue;
			}
			// Add entry to front of history
			self.entries.push_front(line);
			// Reset offset to newest entry
			self.current_position = None;
			// Check if already have enough entries
			if self.entries.len() > self.max_size {
				// Remove oldest entry
				self.entries.pop_back();
			}
		}
	}

	// Find next history that matches a given string from an index
	pub fn search_next(&mut self, _current: &str) -> Option<&str> {
		if let Some(index) = &mut self.current_position {
			if *index < self.entries.len() - 1 {
				*index += 1;
			}
			Some(&self.entries[*index])
		} else if !self.entries.is_empty() {
			self.current_position = Some(0);
			Some(&self.entries[0])
		} else {
			None
		}
	}
	// Find previous history item that matches a given string from an index
	pub fn search_previous(&mut self, _current: &str) -> Option<&str> {
		if let Some(index) = &mut self.current_position {
			if *index == 0 {
				self.current_position = None;
				return Some("");
			}
			*index -= 1;
			Some(&self.entries[*index])
		} else {
			None
		}
	}
}