main
  1diff --git a/helix-term/src/ui/prompt.rs b/helix-term/src/ui/prompt.rs
  2index 926f33a3..f3124c63 100644
  3--- a/helix-term/src/ui/prompt.rs
  4+++ b/helix-term/src/ui/prompt.rs
  5@@ -44,6 +44,8 @@ pub struct Prompt {
  6     selection: Option<usize>,
  7     history_register: Option<char>,
  8     history_pos: Option<usize>,
  9+    history_pattern: Option<String>,
 10+    user_edited: bool,
 11     completion_fn: CompletionFn,
 12     callback_fn: CallbackFn,
 13     pub doc_fn: DocFn,
 14@@ -100,6 +102,8 @@ pub fn new(
 15             selection: None,
 16             history_register,
 17             history_pos: None,
 18+            history_pattern: None,
 19+            user_edited: true,
 20             completion_fn: Box::new(completion_fn),
 21             callback_fn: Box::new(callback_fn),
 22             doc_fn: Box::new(|_| None),
 23@@ -346,27 +350,40 @@ pub fn change_history(
 24         register: char,
 25         direction: CompletionDirection,
 26     ) {
 27+        if self.line.is_empty() {
 28+            self.history_pattern = None;
 29+            self.history_pos = None;
 30+        } else if self.user_edited {
 31+            self.history_pattern = Some(self.line.clone());
 32+            self.history_pos = None;
 33+        }
 34         (self.callback_fn)(cx, &self.line, PromptEvent::Abort);
 35-        let mut values = match cx.editor.registers.read(register, cx.editor) {
 36-            Some(values) if values.len() > 0 => values.rev(),
 37+
 38+        let values: Vec<_> = match cx.editor.registers.read(register, cx.editor) {
 39+            Some(values) if values.len() > 0 => {
 40+                if let Some(pattern) = &self.history_pattern {
 41+                    values.filter(|the| the.contains(pattern)).rev().collect()
 42+                } else {
 43+                    values.rev().collect()
 44+                }
 45+            }
 46             _ => return,
 47         };
 48+        if values.is_empty() {
 49+            return;
 50+        }
 51 
 52         let end = values.len().saturating_sub(1);
 53 
 54         let index = match direction {
 55             CompletionDirection::Forward => self.history_pos.map_or(0, |i| i + 1),
 56-            CompletionDirection::Backward => self
 57-                .history_pos
 58-                .unwrap_or_else(|| values.len())
 59-                .saturating_sub(1),
 60+            CompletionDirection::Backward => {
 61+                self.history_pos.unwrap_or(values.len()).saturating_sub(1)
 62+            }
 63         }
 64         .min(end);
 65 
 66-        self.line = values.nth(index).unwrap().to_string();
 67-        // Appease the borrow checker.
 68-        drop(values);
 69-
 70+        self.line = values.into_iter().nth(index).unwrap().to_string();
 71         self.history_pos = Some(index);
 72 
 73         self.move_end();
 74@@ -627,6 +644,7 @@ fn handle_event(&mut self, event: &Event, cx: &mut Context) -> EventResult {
 75             compositor.remove(id);
 76         })));
 77 
 78+        let mut user_edited = true;
 79         match event {
 80             ctrl!('c') | key!(Esc) => {
 81                 (self.callback_fn)(cx, &self.line, PromptEvent::Abort);
 82@@ -713,11 +731,13 @@ fn handle_event(&mut self, event: &Event, cx: &mut Context) -> EventResult {
 83                 }
 84             }
 85             ctrl!('p') | key!(Up) => {
 86+                user_edited = false;
 87                 if let Some(register) = self.history_register {
 88                     self.change_history(cx, register, CompletionDirection::Backward);
 89                 }
 90             }
 91             ctrl!('n') | key!(Down) => {
 92+                user_edited = false;
 93                 if let Some(register) = self.history_register {
 94                     self.change_history(cx, register, CompletionDirection::Forward);
 95                 }
 96@@ -765,6 +785,7 @@ fn handle_event(&mut self, event: &Event, cx: &mut Context) -> EventResult {
 97             }
 98             _ => (),
 99         };
100+        self.user_edited = user_edited;
101 
102         EventResult::Consumed(None)
103     }