summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-term/src/commands.rs4
-rw-r--r--helix-term/src/ui/prompt.rs6
-rw-r--r--helix-view/src/register.rs30
3 files changed, 24 insertions, 16 deletions
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 329b7ab7..6f10848a 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -1911,7 +1911,7 @@ fn search_next_or_prev_impl(cx: &mut Context, movement: Movement, direction: Dir
let register = cx.register.unwrap_or('/');
let config = cx.editor.config();
let scrolloff = config.scrolloff;
- if let Some(query) = cx.editor.registers.last(register, cx.editor) {
+ if let Some(query) = cx.editor.registers.first(register, cx.editor) {
let doc = doc!(cx.editor);
let contents = doc.text().slice(..).to_string();
let search_config = &config.search;
@@ -1983,7 +1983,7 @@ fn search_selection(cx: &mut Context) {
fn make_search_word_bounded(cx: &mut Context) {
let register = cx.register.unwrap_or('/');
- let regex = match cx.editor.registers.last(register, cx.editor) {
+ let regex = match cx.editor.registers.first(register, cx.editor) {
Some(regex) => regex,
None => return,
};
diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
index 8dc2906a..702a6e67 100644
--- a/helix-term/src/ui/prompt.rs
+++ b/helix-term/src/ui/prompt.rs
@@ -307,7 +307,7 @@ impl Prompt {
) {
(self.callback_fn)(cx, &self.line, PromptEvent::Abort);
let mut values = match cx.editor.registers.read(register, cx.editor) {
- Some(values) if values.len() > 0 => values,
+ Some(values) if values.len() > 0 => values.rev(),
_ => return,
};
@@ -473,7 +473,7 @@ impl Prompt {
// Show the most recently entered value as a suggestion.
if let Some(suggestion) = self
.history_register
- .and_then(|reg| cx.editor.registers.last(reg, cx.editor))
+ .and_then(|reg| cx.editor.registers.first(reg, cx.editor))
{
surface.set_string(line_area.x, line_area.y, suggestion, suggestion_color);
}
@@ -570,7 +570,7 @@ impl Component for Prompt {
} else {
let last_item = self
.history_register
- .and_then(|reg| cx.editor.registers.last(reg, cx.editor))
+ .and_then(|reg| cx.editor.registers.first(reg, cx.editor))
.map(|entry| entry.to_string())
.unwrap_or_else(|| String::from(""));
diff --git a/helix-view/src/register.rs b/helix-view/src/register.rs
index e82051dd..61912378 100644
--- a/helix-view/src/register.rs
+++ b/helix-view/src/register.rs
@@ -23,6 +23,10 @@ use crate::{
/// * Primary clipboard (`+`)
#[derive(Debug)]
pub struct Registers {
+ /// The mapping of register to values.
+ /// Values are stored in reverse order when inserted with `Registers::write`.
+ /// The order is reversed again in `Registers::read`. This allows us to
+ /// efficiently prepend new values in `Registers::push`.
inner: HashMap<char, Vec<String>>,
clipboard_provider: Box<dyn ClipboardProvider>,
}
@@ -77,11 +81,11 @@ impl Registers {
_ => self
.inner
.get(&name)
- .map(|values| RegisterValues::new(values.iter().map(Cow::from))),
+ .map(|values| RegisterValues::new(values.iter().map(Cow::from).rev())),
}
}
- pub fn write(&mut self, name: char, values: Vec<String>) -> Result<()> {
+ pub fn write(&mut self, name: char, mut values: Vec<String>) -> Result<()> {
match name {
'_' => Ok(()),
'#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support writing")),
@@ -94,17 +98,19 @@ impl Registers {
_ => unreachable!(),
},
)?;
+ values.reverse();
self.inner.insert(name, values);
Ok(())
}
_ => {
+ values.reverse();
self.inner.insert(name, values);
Ok(())
}
}
}
- pub fn push(&mut self, name: char, value: String) -> Result<()> {
+ pub fn push(&mut self, name: char, mut value: String) -> Result<()> {
match name {
'_' => Ok(()),
'#' | '.' | '%' => Err(anyhow::anyhow!("Register {name} does not support pushing")),
@@ -121,11 +127,13 @@ impl Registers {
anyhow::bail!("Failed to push to register {name}: clipboard does not match register contents");
}
- saved_values.push(value);
- self.clipboard_provider.set_contents(
- saved_values.join(NATIVE_LINE_ENDING.as_str()),
- clipboard_type,
- )?;
+ saved_values.push(value.clone());
+ if !contents.is_empty() {
+ value.push_str(NATIVE_LINE_ENDING.as_str());
+ }
+ value.push_str(&contents);
+ self.clipboard_provider
+ .set_contents(value, clipboard_type)?;
Ok(())
}
@@ -150,7 +158,7 @@ impl Registers {
.filter(|(name, _)| !matches!(name, '*' | '+'))
.map(|(name, values)| {
let preview = values
- .first()
+ .last()
.and_then(|s| s.lines().next())
.unwrap_or("<empty>");
@@ -222,7 +230,7 @@ fn read_from_clipboard<'a>(
let Some(values) = saved_values else { return RegisterValues::new(iter::once(contents.into())) };
if contents_are_saved(values, &contents) {
- RegisterValues::new(values.iter().map(Cow::from))
+ RegisterValues::new(values.iter().map(Cow::from).rev())
} else {
RegisterValues::new(iter::once(contents.into()))
}
@@ -243,7 +251,7 @@ fn read_from_clipboard<'a>(
fn contents_are_saved(saved_values: &[String], mut contents: &str) -> bool {
let line_ending = NATIVE_LINE_ENDING.as_str();
- let mut values = saved_values.iter();
+ let mut values = saved_values.iter().rev();
match values.next() {
Some(first) if contents.starts_with(first) => {