use std::collections::VecDeque;
use std::sync::Mutex;
use crate::prelude::*;
struct KillRing(VecDeque<WString>);
static KILL_RING: Mutex<KillRing> = Mutex::new(KillRing::new());
impl KillRing {
const fn new() -> Self {
Self(VecDeque::new())
}
#[cfg(test)]
fn is_empty(&self) -> bool {
self.0.is_empty()
}
fn add(&mut self, new_entry: WString) {
if !new_entry.is_empty() {
self.0.push_front(new_entry);
}
}
pub fn replace(&mut self, old_entry: &wstr, new_entry: WString) {
if let Some(old_entry_idx) = self.0.iter().position(|entry| entry == old_entry) {
self.0.remove(old_entry_idx);
}
if !new_entry.is_empty() {
self.add(new_entry);
}
}
pub fn yank(&mut self) -> WString {
self.0.front().cloned().unwrap_or_default()
}
pub fn yank_rotate(&mut self) -> WString {
self.0.rotate_left(1);
self.yank()
}
pub fn entries(&self) -> Vec<WString> {
self.0.iter().cloned().collect()
}
}
pub fn kill_add(new_entry: WString) {
KILL_RING.lock().unwrap().add(new_entry);
}
pub fn kill_replace(old_entry: &wstr, new_entry: WString) {
KILL_RING.lock().unwrap().replace(old_entry, new_entry);
}
pub fn kill_yank_rotate() -> WString {
KILL_RING.lock().unwrap().yank_rotate()
}
pub fn kill_yank() -> WString {
KILL_RING.lock().unwrap().yank()
}
pub fn kill_entries() -> Vec<WString> {
KILL_RING.lock().unwrap().entries()
}
#[cfg(test)]
mod tests {
use super::KillRing;
use crate::prelude::*;
#[test]
fn test_killring() {
let mut kr = KillRing::new();
assert!(kr.is_empty());
kr.add(L!("a").to_owned());
kr.add(L!("b").to_owned());
kr.add(L!("c").to_owned());
assert_eq!(kr.entries(), [L!("c"), L!("b"), L!("a")]);
assert_eq!(kr.yank_rotate(), "b");
assert_eq!(kr.entries(), [L!("b"), L!("a"), L!("c")]);
assert_eq!(kr.yank_rotate(), "a");
assert_eq!(kr.entries(), [L!("a"), L!("c"), L!("b")]);
kr.add(L!("d").to_owned());
assert_eq!(kr.entries(), [L!("d"), L!("a"), L!("c"), L!("b")]);
assert_eq!(kr.yank_rotate(), "a");
assert_eq!(kr.entries(), [L!("a"), L!("c"), L!("b"), L!("d")]);
}
}