Repository: kkawakam/rustyline
Pull request #232 (2019-05-27 17:35:06)

Non static prompt


Patch:
diff --git a/examples/example.rs b/examples/example.rs
index 21aa77a..a7883a1 100644
--- a/examples/example.rs
+++ b/examples/example.rs
@@ -8,11 +8,12 @@ use rustyline::highlight::{Highlighter, MatchingBracketHighlighter};
 use rustyline::hint::{Hinter, HistoryHinter};
 use rustyline::{Cmd, CompletionType, Config, Context, EditMode, Editor, Helper, KeyPress};
 
-static COLORED_PROMPT: &'static str = "\x1b[1;32m>>\x1b[0m ";
-
-static PROMPT: &'static str = ">> ";
-
-struct MyHelper(FilenameCompleter, MatchingBracketHighlighter, HistoryHinter);
+struct MyHelper {
+    completer: FilenameCompleter,
+    highlighter: MatchingBracketHighlighter,
+    hinter: HistoryHinter,
+    colored_prompt: String,
+}
 
 impl Completer for MyHelper {
     type Candidate = Pair;
@@ -23,20 +24,24 @@ impl Completer for MyHelper {
         pos: usize,
         ctx: &Context<'_>,
     ) -> Result<(usize, Vec<Pair>), ReadlineError> {
-        self.0.complete(line, pos, ctx)
+        self.completer.complete(line, pos, ctx)
     }
 }
 
 impl Hinter for MyHelper {
     fn hint(&self, line: &str, pos: usize, ctx: &Context<'_>) -> Option<String> {
-        self.2.hint(line, pos, ctx)
+        self.hinter.hint(line, pos, ctx)
     }
 }
 
 impl Highlighter for MyHelper {
-    fn highlight_prompt<'p>(&self, prompt: &'p str) -> Cow<'p, str> {
-        if prompt == PROMPT {
-            Borrowed(COLORED_PROMPT)
+    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
+        &'s self,
+        prompt: &'p str,
+        default: bool,
+    ) -> Cow<'b, str> {
+        if default {
+            Borrowed(&self.colored_prompt)
         } else {
             Borrowed(prompt)
         }
@@ -47,11 +52,11 @@ impl Highlighter for MyHelper {
     }
 
     fn highlight<'l>(&self, line: &'l str, pos: usize) -> Cow<'l, str> {
-        self.1.highlight(line, pos)
+        self.highlighter.highlight(line, pos)
     }
 
     fn highlight_char(&self, line: &str, pos: usize) -> bool {
-        self.1.highlight_char(line, pos)
+        self.highlighter.highlight_char(line, pos)
     }
 }
 
@@ -65,11 +70,12 @@ fn main() {
         .edit_mode(EditMode::Emacs)
         .output_stream(OutputStreamType::Stdout)
         .build();
-    let h = MyHelper(
-        FilenameCompleter::new(),
-        MatchingBracketHighlighter::new(),
-        HistoryHinter {},
-    );
+    let h = MyHelper {
+        completer: FilenameCompleter::new(),
+        highlighter: MatchingBracketHighlighter::new(),
+        hinter: HistoryHinter {},
+        colored_prompt: "".to_owned(),
+    };
     let mut rl = Editor::with_config(config);
     rl.set_helper(Some(h));
     rl.bind_sequence(KeyPress::Meta('N'), Cmd::HistorySearchForward);
@@ -77,8 +83,11 @@ fn main() {
     if rl.load_history("history.txt").is_err() {
         println!("No previous history.");
     }
+    let mut count = 1;
     loop {
-        let readline = rl.readline(PROMPT);
+        let p = format!("{}> ", count);
+        rl.helper_mut().unwrap().colored_prompt = format!("\x1b[1;32m{}\x1b[0m", p);
+        let readline = rl.readline(&p);
         match readline {
             Ok(line) => {
                 rl.add_history_entry(line.as_str());
@@ -97,6 +106,7 @@ fn main() {
                 break;
             }
         }
+        count += 1;
     }
     rl.save_history("history.txt").unwrap();
 }
diff --git a/src/edit.rs b/src/edit.rs
index 5a88a38..b419b25 100644
--- a/src/edit.rs
+++ b/src/edit.rs
@@ -116,7 +116,7 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
         }
         if self.highlight_char() {
             let prompt_size = self.prompt_size;
-            self.refresh(self.prompt, prompt_size, Info::NoHint)?;
+            self.refresh(self.prompt, prompt_size, true, Info::NoHint)?;
         } else {
             self.out.move_cursor(self.cursor, cursor)?;
         }
@@ -128,7 +128,13 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
         self.out.move_cursor_at_leftmost(rdr)
     }
 
-    fn refresh(&mut self, prompt: &str, prompt_size: Position, info: Info<'_>) -> Result<()> {
+    fn refresh(
+        &mut self,
+        prompt: &str,
+        prompt_size: Position,
+        default_prompt: bool,
+        info: Info<'_>,
+    ) -> Result<()> {
         let info = match info {
             Info::NoHint => None,
             Info::Hint => self.hint.as_ref().map(String::as_str),
@@ -142,6 +148,7 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
         let (cursor, end_pos) = self.out.refresh_line(
             prompt,
             prompt_size,
+            default_prompt,
             &self.line,
             info,
             self.cursor.row,
@@ -187,7 +194,7 @@ impl<'out, 'prompt, H: Helper> Refresher for State<'out, 'prompt, H> {
         let prompt_size = self.prompt_size;
         self.hint();
         self.highlight_char();
-        self.refresh(self.prompt, prompt_size, Info::Hint)
+        self.refresh(self.prompt, prompt_size, true, Info::Hint)
     }
 
     fn refresh_line_with_msg(&mut self, msg: Option<String>) -> Result<()> {
@@ -197,6 +204,7 @@ impl<'out, 'prompt, H: Helper> Refresher for State<'out, 'prompt, H> {
         self.refresh(
             self.prompt,
             prompt_size,
+            true,
             Info::Msg(msg.as_ref().map(String::as_str)),
         )
     }
@@ -205,7 +213,7 @@ impl<'out, 'prompt, H: Helper> Refresher for State<'out, 'prompt, H> {
         let prompt_size = self.out.calculate_position(prompt, Position::default());
         self.hint();
         self.highlight_char();
-        self.refresh(prompt, prompt_size, Info::Hint)
+        self.refresh(prompt, prompt_size, false, Info::Hint)
     }
 
     fn doing_insert(&mut self) {
@@ -265,7 +273,7 @@ impl<'out, 'prompt, H: Helper> State<'out, 'prompt, H> {
                     let bits = bits.as_bytes();
                     self.out.write_and_flush(bits)
                 } else {
-                    self.refresh(self.prompt, prompt_size, Info::Hint)
+                    self.refresh(self.prompt, prompt_size, true, Info::Hint)
                 }
             } else {
                 self.refresh_line()
diff --git a/src/highlight.rs b/src/highlight.rs
index 53958a3..6c46ef5 100644
--- a/src/highlight.rs
+++ b/src/highlight.rs
@@ -23,7 +23,12 @@ pub trait Highlighter {
     }
     /// Takes the `prompt` and
     /// returns the highlighted version (with ANSI color).
-    fn highlight_prompt<'p>(&self, prompt: &'p str) -> Cow<'p, str> {
+    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
+        &'s self,
+        prompt: &'p str,
+        default: bool,
+    ) -> Cow<'b, str> {
+        let _ = default;
         Borrowed(prompt)
     }
     /// Takes the `hint` and
@@ -61,8 +66,12 @@ impl<'r, H: ?Sized + Highlighter> Highlighter for &'r H {
         (**self).highlight(line, pos)
     }
 
-    fn highlight_prompt<'p>(&self, prompt: &'p str) -> Cow<'p, str> {
-        (**self).highlight_prompt(prompt)
+    fn highlight_prompt<'b, 's: 'b, 'p: 'b>(
+        &'s self,
+        prompt: &'p str,
+        default: bool,
+    ) -> Cow<'b, str> {
+        (**self).highlight_prompt(prompt, default)
     }
 
     fn highlight_hint<'h>(&self, hint: &'h str) -> Cow<'h, str> {
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index 37f5104..5af0382 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -42,6 +42,7 @@ pub trait Renderer {
         &mut self,
         prompt: &str,
         prompt_size: Position,
+        default_prompt: bool,
         line: &LineBuffer,
         hint: Option<&str>,
         current_row: usize,
@@ -91,6 +92,7 @@ impl<'a, R: Renderer + ?Sized> Renderer for &'a mut R {
         &mut self,
         prompt: &str,
         prompt_size: Position,
+        default_prompt: bool,
         line: &LineBuffer,
         hint: Option<&str>,
         current_row: usize,
@@ -100,6 +102,7 @@ impl<'a, R: Renderer + ?Sized> Renderer for &'a mut R {
         (**self).refresh_line(
             prompt,
             prompt_size,
+            default_prompt,
             line,
             hint,
             current_row,
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 8efe73c..4579cd4 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -508,6 +508,7 @@ impl Renderer for PosixRenderer {
         &mut self,
         prompt: &str,
         prompt_size: Position,
+        default_prompt: bool,
         line: &LineBuffer,
         hint: Option<&str>,
         current_row: usize,
@@ -538,7 +539,8 @@ impl Renderer for PosixRenderer {
 
         if let Some(highlighter) = highlighter {
             // display the prompt
-            self.buffer.push_str(&highlighter.highlight_prompt(prompt));
+            self.buffer
+                .push_str(&highlighter.highlight_prompt(prompt, default_prompt));
             // display the input line
             self.buffer
                 .push_str(&highlighter.highlight(line, line.pos()));
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index ceedc53..2802bdd 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -308,6 +308,7 @@ impl Renderer for ConsoleRenderer {
         &mut self,
         prompt: &str,
         prompt_size: Position,
+        default_prompt: bool,
         line: &LineBuffer,
         hint: Option<&str>,
         current_row: usize,
@@ -332,7 +333,8 @@ impl Renderer for ConsoleRenderer {
         if let Some(highlighter) = highlighter {
             // TODO handle ansi escape code (SetConsoleTextAttribute)
             // display the prompt
-            self.buffer.push_str(&highlighter.highlight_prompt(prompt));
+            self.buffer
+                .push_str(&highlighter.highlight_prompt(prompt, default_prompt));
             // display the input line
             self.buffer
                 .push_str(&highlighter.highlight(line, line.pos()));


Test patch:
diff --git a/src/tty/test.rs b/src/tty/test.rs
index fc80222..19c72fe 100644
--- a/src/tty/test.rs
+++ b/src/tty/test.rs
@@ -76,6 +76,7 @@ impl Renderer for Sink {
         &mut self,
         _: &str,
         prompt_size: Position,
+        _: bool,
         line: &LineBuffer,
         hint: Option<&str>,
         _: usize,