Repository: kkawakam/rustyline (Rust)

Issue:
Crash when searching for a value
This code:
```
fn main() {
    use std::io::{stdin, stdout, Write};

    use rustyline::error::ReadlineError;
    use rustyline::Editor;

    loop {
        let mut editor = Editor::<()>::new();
        if editor.load_history("history.log").is_err() {
        }
        let result = editor.readline("Enter expression (ctrl-C to quit): ");
        match result {
            Ok(mut line) => {
                editor.add_history_entry(line.as_str());
                line = line.trim().to_string();
                if line.len() > 0 {
                    println!("You entered: {}", line);
                }
            },
            Err(ReadlineError::Interrupted) => {
                break
            },
            Err(ReadlineError::Eof) => {
            },
            Err(err) => {
                println!("Error: {:?}", err);
                break
            }
        }
        editor.save_history("history.log").unwrap();
    }
}
```

Fails when run if you do a `ctrl-R` to search for a previous value (which _is_ found). The failure enters when you press Enter on the found value. Console listing with backtrace (Ubuntu-x64, rust 1.38.0):

```
$ RUST_BACKTRACE=full target/debug/expr_repl
Enter expression (ctrl-C to quit): abc
You entered: abc
(reverse-i-search)`ab': abc           thread 'main' panicked at 'assertion failed: self.layout.cursor <= self.layout.end', /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/edit.rs:125:13
stack backtrace:
   0:     0x5565d5ee898b - backtrace::backtrace::libunwind::trace::h89fcc71e59e3bc5b
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/libunwind.rs:88
   1:     0x5565d5ee898b - backtrace::backtrace::trace_unsynchronized::h0bad9be1379e729a
                               at /cargo/registry/src/github.com-1ecc6299db9ec823/backtrace-0.3.34/src/backtrace/mod.rs:66
   2:     0x5565d5ee898b - std::sys_common::backtrace::_print::hd3382a1f33c473da
                               at src/libstd/sys_common/backtrace.rs:47
   3:     0x5565d5ee898b - std::sys_common::backtrace::print::h0ec6f03cfb8e76a6
                               at src/libstd/sys_common/backtrace.rs:36
   4:     0x5565d5ee898b - std::panicking::default_hook::{{closure}}::h96cbf7b454e3f557
                               at src/libstd/panicking.rs:200
   5:     0x5565d5ee8666 - std::panicking::default_hook::h95a8f00337383d83
                               at src/libstd/panicking.rs:214
   6:     0x5565d5ee909d - std::panicking::rust_panic_with_hook::h92f98b46e22f14ed
                               at src/libstd/panicking.rs:477
   7:     0x5565d5ed3df5 - std::panicking::begin_panic::h96738e055e5f4d65
                               at /rustc/625451e376bb2e5283fc4741caa0a3e8a2ca4d54/src/libstd/panicking.rs:411
   8:     0x5565d5e678ec - rustyline::edit::State<H>::move_cursor::hdcb71b31d457715f
                               at /home/vinay/projects/rsconfig/<::std::macros::panic macros>:3
   9:     0x5565d5e67e05 - rustyline::edit::State<H>::edit_move_end::hf8b47e6f67dc66dc
                               at /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/edit.rs:406
  10:     0x5565d5e5be9d - rustyline::readline_edit::ha6e91a48dad7739e
                               at /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/lib.rs:529
  11:     0x5565d5e55950 - rustyline::readline_raw::h8d10993a62be80cd
                               at /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/lib.rs:626
  12:     0x5565d5e5f2c2 - rustyline::Editor<H>::readline_with::h243448f87a7c18a2
                               at /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/lib.rs:755
  13:     0x5565d5e5f5ad - rustyline::Editor<H>::readline::h0d20b4b1450ecb3c
                               at /home/vinay/.cargo/registry/src/github.com-1ecc6299db9ec823/rustyline-5.0.3/src/lib.rs:731
  14:     0x5565d5e62d19 - expr_repl::main::ha34c1f1010ec7764
                               at src/bin/expr_repl.rs:31
  15:     0x5565d5e72ab0 - std::rt::lang_start::{{closure}}::h39369991cd93ebad
                               at /rustc/625451e376bb2e5283fc4741caa0a3e8a2ca4d54/src/libstd/rt.rs:64
  16:     0x5565d5ee8aa3 - std::rt::lang_start_internal::{{closure}}::h4e93c1949c7a1955
                               at src/libstd/rt.rs:49
  17:     0x5565d5ee8aa3 - std::panicking::try::do_call::h9440ccd4dc467eaa
                               at src/libstd/panicking.rs:296
  18:     0x5565d5eeaaba - __rust_maybe_catch_panic
                               at src/libpanic_unwind/lib.rs:80
  19:     0x5565d5ee95ad - std::panicking::try::hc046e7ee42ee744f
                               at src/libstd/panicking.rs:275
  20:     0x5565d5ee95ad - std::panic::catch_unwind::h27dfc457c200aee0
                               at src/libstd/panic.rs:394
  21:     0x5565d5ee95ad - std::rt::lang_start_internal::hea1b49a567afe309
                               at src/libstd/rt.rs:48
  22:     0x5565d5e72a89 - std::rt::lang_start::hbc1f50dfdb872b3d
                               at /rustc/625451e376bb2e5283fc4741caa0a3e8a2ca4d54/src/libstd/rt.rs:64
  23:     0x5565d5e6328a - main
  24:     0x7f4952b44b97 - __libc_start_main
  25:     0x5565d5e520da - _start
  26:                0x0 - <unknown>
```




Discussion:
Thanks you for the detailed bug report
#296 fixes the issue for me. Thanks!
Fixed by release 5.0.4



Patch:
diff --git a/src/edit.rs b/src/edit.rs
index 82eaa6045f..fb46cde25a 100644
--- a/src/edit.rs
+++ b/src/edit.rs
@@ -210,6 +210,10 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
             false
         }
     }
+
+    pub fn is_default_prompt(&self) -> bool {
+        self.layout.default_prompt
+    }
 }
 
 impl<'out, 'prompt, H: Helper> Refresher for State<'out, 'prompt, H> {
diff --git a/src/lib.rs b/src/lib.rs
index e052c61a76..45b3c253ee 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -526,12 +526,12 @@ fn readline_edit<H: Helper>(
                     editor.term.cursor = s.layout.cursor.col;
                 }
                 // Accept the line regardless of where the cursor is.
-                s.edit_move_end()?;
-                if s.has_hint() {
+                if s.has_hint() || !s.is_default_prompt() {
                     // Force a refresh without hints to leave the previous
                     // line as the user typed it after a newline.
                     s.refresh_line_with_msg(None)?;
                 }
+                s.edit_move_end()?;
                 break;
             }
             Cmd::BeginningOfHistory => {


Test patch:
diff --git a/src/test/emacs.rs b/src/test/emacs.rs
index 6101405e52..dbd9d33b51 100644
--- a/src/test/emacs.rs
+++ b/src/test/emacs.rs
@@ -159,6 +159,7 @@ fn ctrl_n() {
             KeyPress::Ctrl('N'),
             KeyPress::Enter,
         ],
+        "",
         ("line2", ""),
     );
 }
@@ -169,6 +170,7 @@ fn ctrl_p() {
         EditMode::Emacs,
         &["line1"],
         &[KeyPress::Ctrl('P'), KeyPress::Enter],
+        "",
         ("line1", ""),
     );
 }
diff --git a/src/test/history.rs b/src/test/history.rs
index c53706f05a..c6df13262d 100644
--- a/src/test/history.rs
+++ b/src/test/history.rs
@@ -10,12 +10,14 @@ fn down_key() {
             *mode,
             &["line1"],
             &[KeyPress::Down, KeyPress::Enter],
+            "",
             ("", ""),
         );
         assert_history(
             *mode,
             &["line1", "line2"],
             &[KeyPress::Up, KeyPress::Up, KeyPress::Down, KeyPress::Enter],
+            "",
             ("line2", ""),
         );
         assert_history(
@@ -27,6 +29,7 @@ fn down_key() {
                 KeyPress::Down, // restore original line
                 KeyPress::Enter,
             ],
+            "",
             ("a", ""),
         );
         assert_history(
@@ -37,6 +40,7 @@ fn down_key() {
                 KeyPress::Down, // noop
                 KeyPress::Enter,
             ],
+            "",
             ("a", ""),
         );
     }
@@ -45,17 +49,19 @@ fn down_key() {
 #[test]
 fn up_key() {
     for mode in &[EditMode::Emacs, EditMode::Vi] {
-        assert_history(*mode, &[], &[KeyPress::Up, KeyPress::Enter], ("", ""));
+        assert_history(*mode, &[], &[KeyPress::Up, KeyPress::Enter], "", ("", ""));
         assert_history(
             *mode,
             &["line1"],
             &[KeyPress::Up, KeyPress::Enter],
+            "",
             ("line1", ""),
         );
         assert_history(
             *mode,
             &["line1", "line2"],
             &[KeyPress::Up, KeyPress::Up, KeyPress::Enter],
+            "",
             ("line1", ""),
         );
     }
@@ -68,6 +74,7 @@ fn ctrl_r() {
             *mode,
             &[],
             &[KeyPress::Ctrl('R'), KeyPress::Char('o'), KeyPress::Enter],
+            "",
             ("o", ""),
         );
         assert_history(
@@ -79,6 +86,7 @@ fn ctrl_r() {
                 KeyPress::Right, // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("cargo", ""),
         );
         assert_history(
@@ -90,6 +98,7 @@ fn ctrl_r() {
                 KeyPress::Right, // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("ru", "stc"),
         );
         assert_history(
@@ -102,6 +111,7 @@ fn ctrl_r() {
                 KeyPress::Right, // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("r", "ustc"),
         );
         assert_history(
@@ -114,6 +124,7 @@ fn ctrl_r() {
                 KeyPress::Right, // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("r", "ustc"),
         );
         assert_history(
@@ -126,6 +137,7 @@ fn ctrl_r() {
                 KeyPress::Right,     // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("car", "go"),
         );
         assert_history(
@@ -138,11 +150,29 @@ fn ctrl_r() {
                 KeyPress::Ctrl('G'), // abort (FIXME: doesn't work with vi mode)
                 KeyPress::Enter,
             ],
+            "",
             ("a", ""),
         );
     }
 }
 
+#[test]
+fn ctrl_r_with_long_prompt() {
+    for mode in &[EditMode::Emacs, EditMode::Vi] {
+        assert_history(
+            *mode,
+            &["rustc", "cargo"],
+            &[
+                KeyPress::Ctrl('R'),
+                KeyPress::Char('o'),
+                KeyPress::Enter,
+            ],
+            ">>>>>>>>>>>>>>>>>>>>>>>>>>> ",
+            ("cargo", ""),
+        );
+    }
+}
+
 #[test]
 fn ctrl_s() {
     for mode in &[EditMode::Emacs, EditMode::Vi] {
@@ -157,6 +187,7 @@ fn ctrl_s() {
                 KeyPress::Right, // just to assert cursor pos
                 KeyPress::Enter,
             ],
+            "",
             ("car", "go"),
         );
     }
@@ -168,12 +199,14 @@ fn meta_lt() {
         EditMode::Emacs,
         &[""],
         &[KeyPress::Meta('<'), KeyPress::Enter],
+        "",
         ("", ""),
     );
     assert_history(
         EditMode::Emacs,
         &["rustc", "cargo"],
         &[KeyPress::Meta('<'), KeyPress::Enter],
+        "",
         ("rustc", ""),
     );
 }
@@ -184,12 +217,14 @@ fn meta_gt() {
         EditMode::Emacs,
         &[""],
         &[KeyPress::Meta('>'), KeyPress::Enter],
+        "",
         ("", ""),
     );
     assert_history(
         EditMode::Emacs,
         &["rustc", "cargo"],
         &[KeyPress::Meta('<'), KeyPress::Meta('>'), KeyPress::Enter],
+        "",
         ("", ""),
     );
     assert_history(
@@ -201,6 +236,7 @@ fn meta_gt() {
             KeyPress::Meta('>'), // restore original line
             KeyPress::Enter,
         ],
+        "",
         ("a", ""),
     );
 }
diff --git a/src/test/mod.rs b/src/test/mod.rs
index 395fa72489..b995b905f3 100644
--- a/src/test/mod.rs
+++ b/src/test/mod.rs
@@ -94,14 +94,22 @@ fn assert_cursor(mode: EditMode, initial: (&str, &str), keys: &[KeyPress], expec
 // `entries`: history entries before `keys` pressed
 // `keys`: keys to press
 // `expected`: line status before enter key: strings before and after cursor
-fn assert_history(mode: EditMode, entries: &[&str], keys: &[KeyPress], expected: (&str, &str)) {
+fn assert_history(
+    mode: EditMode,
+    entries: &[&str],
+    keys: &[KeyPress],
+    prompt: &str,
+    expected: (&str, &str),
+) {
     let mut editor = init_editor(mode, keys);
     for entry in entries {
         editor.history.add(*entry);
     }
-    let actual_line = editor.readline("").unwrap();
+    let actual_line = editor.readline(prompt).unwrap();
     assert_eq!(expected.0.to_owned() + expected.1, actual_line);
-    assert_eq!(expected.0.len(), editor.term.cursor);
+    if prompt.is_empty() {
+        assert_eq!(expected.0.len(), editor.term.cursor);
+    }
 }
 
 #[test]
diff --git a/src/test/vi_cmd.rs b/src/test/vi_cmd.rs
index f3ceada111..1c2c143193 100644
--- a/src/test/vi_cmd.rs
+++ b/src/test/vi_cmd.rs
@@ -441,6 +441,7 @@ fn j() {
                 *key,
                 KeyPress::Enter,
             ],
+            "",
             ("line2", ""),
         );
     }
@@ -457,6 +458,7 @@ fn k() {
             EditMode::Vi,
             &["line1"],
             &[KeyPress::Esc, *key, KeyPress::Enter],
+            "",
             ("line1", ""),
         );
     }