@@ -23,6 +23,10 @@ use crate::{
2323/// * Primary clipboard (`+`)
2424#[derive(Debug)]
2525pub struct Registers {
26+ /// The mapping of register to values.
27+ /// Values are stored in reverse order when inserted with `Registers::write`.
28+ /// The order is reversed again in `Registers::read`. This allows us to
29+ /// efficiently prepend new values in `Registers::push`.
2630 inner: HashMap<char, Vec<String>>,
2731 clipboard_provider: Box<dyn ClipboardProvider>,
2832}
@@ -77,11 +81,11 @@ impl Registers {
7781 _ => self
7882 .inner
7983 .get(&name)
80− .map(|values| RegisterValues::new(values.iter().map(Cow::from))),
84+ .map(|values| RegisterValues::new(values.iter().map(Cow::from).rev())),
8185 }
8286 }
8387
84− pub fn write(&mut self, name: char, values: Vec<String>) -> Result<()> {
88+ pub fn write(&mut self, name: char, mut values: Vec<String>) -> Result<()> {
8589 match name {
8690 '_' => Ok(()),
8791 '#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support writing")),
@@ -94,17 +98,19 @@ impl Registers {
9498 _ => unreachable!(),
9599 },
96100 )?;
101+ values.reverse();
97102 self.inner.insert(name, values);
98103 Ok(())
99104 }
100105 _ => {
106+ values.reverse();
101107 self.inner.insert(name, values);
102108 Ok(())
103109 }
104110 }
105111 }
106112
107− pub fn push(&mut self, name: char, value: String) -> Result<()> {
113+ pub fn push(&mut self, name: char, mut value: String) -> Result<()> {
108114 match name {
109115 '_' => Ok(()),
110116 '#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support pushing")),
@@ -121,11 +127,13 @@ impl Registers {
121127 anyhow::bail!("Failed to push to register {name}: clipboard does not match register contents");
122128 }
123129
124− saved_values.push(value);
125− self.clipboard_provider.set_contents(
126− saved_values.join(NATIVE_LINE_ENDING.as_str()),
127− clipboard_type,
128− )?;
130+ saved_values.push(value.clone());
131+ if !contents.is_empty() {
132+ value.push_str(NATIVE_LINE_ENDING.as_str());
133+ }
134+ value.push_str(&contents);
135+ self.clipboard_provider
136+ .set_contents(value, clipboard_type)?;
129137
130138 Ok(())
131139 }
@@ -150,7 +158,7 @@ impl Registers {
150158 .filter(|(name, _)| !matches!(name, '*' | '+'))
151159 .map(|(name, values)| {
152160 let preview = values
153− .first()
161+ .last()
154162 .and_then(|s| s.lines().next())
155163 .unwrap_or("<empty>");
156164
@@ -222,7 +230,7 @@ fn read_from_clipboard<'a>(
222230 let Some(values) = saved_values else { return RegisterValues::new(iter::once(contents.into())) };
223231
224232 if contents_are_saved(values, &contents) {
225− RegisterValues::new(values.iter().map(Cow::from))
233+ RegisterValues::new(values.iter().map(Cow::from).rev())
226234 } else {
227235 RegisterValues::new(iter::once(contents.into()))
228236 }
@@ -243,7 +251,7 @@ fn read_from_clipboard<'a>(
243251
244252fn contents_are_saved(saved_values: &[String], mut contents: &str) -> bool {
245253 let line_ending = NATIVE_LINE_ENDING.as_str();
246− let mut values = saved_values.iter();
254+ let mut values = saved_values.iter().rev();
247255
248256 match values.next() {
249257 Some(first) if contents.starts_with(first) => {