1#[derive(Debug, Clone, Default)]
7pub struct KillRing {
8 ring: Vec<String>,
9}
10
11impl KillRing {
12 pub fn new() -> Self {
13 Self { ring: Vec::new() }
14 }
15
16 pub fn push(&mut self, text: &str, prepend: bool, accumulate: bool) {
21 if text.is_empty() {
22 return;
23 }
24
25 if accumulate && let Some(last) = self.ring.last_mut() {
26 if prepend {
27 let new_entry = format!("{}{}", text, last);
28 *last = new_entry;
29 } else {
30 last.push_str(text);
31 }
32 return;
33 }
34
35 self.ring.push(text.to_string());
36 }
37
38 pub fn peek(&self) -> Option<&str> {
40 self.ring.last().map(|s| s.as_str())
41 }
42
43 pub fn rotate(&mut self) {
45 if self.ring.len() > 1
46 && let Some(last) = self.ring.pop()
47 {
48 self.ring.insert(0, last);
49 }
50 }
51
52 pub fn len(&self) -> usize {
54 self.ring.len()
55 }
56
57 pub fn is_empty(&self) -> bool {
58 self.ring.is_empty()
59 }
60}
61
62#[cfg(test)]
63mod tests {
64 use super::*;
65
66 #[test]
67 fn test_push_and_peek() {
68 let mut kr = KillRing::new();
69 kr.push("hello", false, false);
70 assert_eq!(kr.peek(), Some("hello"));
71 assert_eq!(kr.len(), 1);
72 }
73
74 #[test]
75 fn test_push_empty_ignored() {
76 let mut kr = KillRing::new();
77 kr.push("", false, false);
78 assert!(kr.is_empty());
79 }
80
81 #[test]
82 fn test_accumulate_append() {
83 let mut kr = KillRing::new();
84 kr.push("hello", false, false);
85 kr.push(" world", false, true);
86 assert_eq!(kr.peek(), Some("hello world"));
87 assert_eq!(kr.len(), 1);
88 }
89
90 #[test]
91 fn test_accumulate_prepend() {
92 let mut kr = KillRing::new();
93 kr.push("world", false, false);
94 kr.push("hello ", true, true);
95 assert_eq!(kr.peek(), Some("hello world"));
96 }
97
98 #[test]
99 fn test_accumulate_without_entries() {
100 let mut kr = KillRing::new();
101 kr.push("hello", false, true);
102 assert_eq!(kr.peek(), Some("hello"));
103 }
104
105 #[test]
106 fn test_rotate_single_entry() {
107 let mut kr = KillRing::new();
108 kr.push("only", false, false);
109 kr.rotate();
110 assert_eq!(kr.peek(), Some("only"));
111 }
112
113 #[test]
114 fn test_rotate_multiple() {
115 let mut kr = KillRing::new();
116 kr.push("first", false, false);
117 kr.push("second", false, false);
118 kr.push("third", false, false);
119 assert_eq!(kr.peek(), Some("third"));
121 kr.rotate(); assert_eq!(kr.peek(), Some("second"));
123 kr.rotate(); assert_eq!(kr.peek(), Some("first"));
125 kr.rotate(); assert_eq!(kr.peek(), Some("third"));
127 }
128}