use std::{borrow::Cow, collections::HashMap, iter}; use anyhow::Result; use crate::Editor; /// A key-value store for saving sets of values. /// /// Each register corresponds to a `char`. Most chars can be used to store any set of /// values but a few chars are "special registers". Special registers have unique /// behaviors when read or written to: /// /// * Black hole (`_`): all values read and written are discarded #[derive(Debug, Default)] pub struct Registers { inner: HashMap>, } impl Registers { pub fn read<'a>(&'a self, name: char, _editor: &'a Editor) -> Option> { match name { '_' => Some(RegisterValues::new(iter::empty())), _ => self .inner .get(&name) .map(|values| RegisterValues::new(values.iter().map(Cow::from))), } } pub fn write(&mut self, name: char, values: Vec) -> Result<()> { match name { '_' => Ok(()), _ => { self.inner.insert(name, values); Ok(()) } } } pub fn push(&mut self, name: char, value: String) -> Result<()> { match name { '_' => Ok(()), _ => { self.inner.entry(name).or_insert_with(Vec::new).push(value); Ok(()) } } } pub fn first<'a>(&'a self, name: char, editor: &'a Editor) -> Option> { self.read(name, editor).and_then(|mut values| values.next()) } pub fn last<'a>(&'a self, name: char, editor: &'a Editor) -> Option> { self.read(name, editor).and_then(|values| values.last()) } pub fn iter_preview(&self) -> impl Iterator { self.inner .iter() .map(|(name, values)| { let preview = values .first() .and_then(|s| s.lines().next()) .unwrap_or(""); (*name, preview) }) .chain([('_', "")].iter().copied()) } pub fn clear(&mut self) { self.inner.clear() } pub fn remove(&mut self, name: char) -> bool { match name { '_' => false, _ => self.inner.remove(&name).is_some(), } } } // This is a wrapper of an iterator that is both double ended and exact size, // and can return either owned or borrowed values. Regular registers can // return borrowed values while some special registers need to return owned // values. pub struct RegisterValues<'a> { iter: Box> + 'a>, } impl<'a> RegisterValues<'a> { fn new( iter: impl DoubleEndedIterator> + ExactSizeIterator> + 'a, ) -> Self { Self { iter: Box::new(iter), } } } impl<'a> Iterator for RegisterValues<'a> { type Item = Cow<'a, str>; fn next(&mut self) -> Option { self.iter.next() } fn size_hint(&self) -> (usize, Option) { self.iter.size_hint() } } impl<'a> DoubleEndedIterator for RegisterValues<'a> { fn next_back(&mut self) -> Option { self.iter.next_back() } } impl<'a> ExactSizeIterator for RegisterValues<'a> { fn len(&self) -> usize { self.iter.len() } } // Each RegisterValues iterator is both double ended and exact size. We can't // type RegisterValues as `Box` // because only one non-auto trait is allowed in trait objects. So we need to // create a new trait that covers both. `RegisterValues` wraps that type so that // trait only needs to live in this module and not be imported for all register // callsites. trait DoubleEndedExactSizeIterator: DoubleEndedIterator + ExactSizeIterator {} impl DoubleEndedExactSizeIterator for I {}