mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-25 08:41:05 +00:00
83 lines
1.7 KiB
Rust
83 lines
1.7 KiB
Rust
#[derive(Default)]
|
|
pub struct Backstack<T: Eq> {
|
|
cursor: usize,
|
|
stack: Vec<T>,
|
|
}
|
|
|
|
impl<T: Eq> Backstack<T> {
|
|
pub fn push(&mut self, item: T) {
|
|
if self.stack.is_empty() {
|
|
self.stack.push(item);
|
|
return;
|
|
}
|
|
|
|
if self.stack[self.cursor] == item {
|
|
return;
|
|
}
|
|
|
|
self.cursor += 1;
|
|
if self.cursor == self.stack.len() {
|
|
self.stack.push(item);
|
|
} else {
|
|
self.stack[self.cursor] = item;
|
|
self.stack.truncate(self.cursor + 1);
|
|
}
|
|
|
|
// Only keep 30 items before the cursor, the cleanup threshold is 60
|
|
if self.stack.len() > 60 {
|
|
let start = self.cursor.saturating_sub(30);
|
|
self.stack.drain(..start);
|
|
self.cursor -= start;
|
|
}
|
|
}
|
|
|
|
pub fn shift_backward(&mut self) -> Option<&T> {
|
|
if self.cursor > 0 {
|
|
self.cursor -= 1;
|
|
Some(&self.stack[self.cursor])
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
pub fn shift_forward(&mut self) -> Option<&T> {
|
|
if self.cursor + 1 == self.stack.len() {
|
|
None
|
|
} else {
|
|
self.cursor += 1;
|
|
Some(&self.stack[self.cursor])
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_backstack() {
|
|
let mut bs = Backstack::default();
|
|
bs.push(1);
|
|
assert_eq!(bs.stack[bs.cursor], 1);
|
|
|
|
bs.push(2);
|
|
bs.push(3);
|
|
assert_eq!(bs.stack[bs.cursor], 3);
|
|
|
|
assert_eq!(bs.shift_backward(), Some(&2));
|
|
assert_eq!(bs.shift_backward(), Some(&1));
|
|
assert_eq!(bs.shift_backward(), None);
|
|
assert_eq!(bs.shift_backward(), None);
|
|
assert_eq!(bs.stack[bs.cursor], 1);
|
|
assert_eq!(bs.shift_forward(), Some(&2));
|
|
assert_eq!(bs.shift_forward(), Some(&3));
|
|
assert_eq!(bs.shift_forward(), None);
|
|
|
|
bs.shift_backward();
|
|
bs.push(4);
|
|
|
|
assert_eq!(bs.stack[bs.cursor], 4);
|
|
assert_eq!(bs.shift_forward(), None);
|
|
assert_eq!(bs.shift_backward(), Some(&2));
|
|
}
|
|
}
|