@@ -0,0 +1,136 @@
1+use std::{borrow::Cow, collections::HashMap, iter};
7+/// A key-value store for saving sets of values.
9+/// Each register corresponds to a `char`. Most chars can be used to store any set of
10+/// values but a few chars are "special registers". Special registers have unique
11+/// behaviors when read or written to:
13+/// * Black hole (`_`): all values read and written are discarded
14+#[derive(Debug, Default)]
15+pub struct Registers {
16+ inner: HashMap<char, Vec<String>>,
20+ pub fn read<'a>(&'a self, name: char, _editor: &'a Editor) -> Option<RegisterValues<'a>> {
22+ '_' => Some(RegisterValues::new(iter::empty())),
26+ .map(|values| RegisterValues::new(values.iter().map(Cow::from))),
30+ pub fn write(&mut self, name: char, values: Vec<String>) -> Result<()> {
34+ self.inner.insert(name, values);
40+ pub fn push(&mut self, name: char, value: String) -> Result<()> {
44+ self.inner.entry(name).or_insert_with(Vec::new).push(value);
50+ pub fn first<'a>(&'a self, name: char, editor: &'a Editor) -> Option<Cow<'a, str>> {
51+ self.read(name, editor).and_then(|mut values| values.next())
54+ pub fn last<'a>(&'a self, name: char, editor: &'a Editor) -> Option<Cow<'a, str>> {
55+ self.read(name, editor).and_then(|values| values.last())
58+ pub fn iter_preview(&self) -> impl Iterator<Item = (char, &str)> {
61+ .map(|(name, values)| {
64+ .and_then(|s| s.lines().next())
65+ .unwrap_or("<empty>");
69+ .chain([('_', "<empty>")].iter().copied())
72+ pub fn clear(&mut self) {
76+ pub fn remove(&mut self, name: char) -> bool {
79+ _ => self.inner.remove(&name).is_some(),
84+// This is a wrapper of an iterator that is both double ended and exact size,
85+// and can return either owned or borrowed values. Regular registers can
86+// return borrowed values while some special registers need to return owned
88+pub struct RegisterValues<'a> {
89+ iter: Box<dyn DoubleEndedExactSizeIterator<Item = Cow<'a, str>> + 'a>,
92+impl<'a> RegisterValues<'a> {
94+ iter: impl DoubleEndedIterator<Item = Cow<'a, str>>
95+ + ExactSizeIterator<Item = Cow<'a, str>>
99+ iter: Box::new(iter),
104+impl<'a> Iterator for RegisterValues<'a> {
105+ type Item = Cow<'a, str>;
107+ fn next(&mut self) -> Option<Self::Item> {
111+ fn size_hint(&self) -> (usize, Option<usize>) {
112+ self.iter.size_hint()
116+impl<'a> DoubleEndedIterator for RegisterValues<'a> {
117+ fn next_back(&mut self) -> Option<Self::Item> {
118+ self.iter.next_back()
122+impl<'a> ExactSizeIterator for RegisterValues<'a> {
123+ fn len(&self) -> usize {
128+// Each RegisterValues iterator is both double ended and exact size. We can't
129+// type RegisterValues as `Box<dyn DoubleEndedIterator + ExactSizeIterator>`
130+// because only one non-auto trait is allowed in trait objects. So we need to
131+// create a new trait that covers both. `RegisterValues` wraps that type so that
132+// trait only needs to live in this module and not be imported for all register
134+trait DoubleEndedExactSizeIterator: DoubleEndedIterator + ExactSizeIterator {}
136+impl<I: DoubleEndedIterator + ExactSizeIterator> DoubleEndedExactSizeIterator for I {}