Reuse rendering buffer
(cherry picked from commit 4d3da773f2e24625566ebe0a469fd31bbee38649)
diff --git a/src/tty/mod.rs b/src/tty/mod.rs
index e8c7db4..d6767fc 100644
--- a/src/tty/mod.rs
+++ b/src/tty/mod.rs
@@ -34,7 +34,7 @@
pub trait Renderer {
fn move_cursor(&mut self, old: Position, new: Position) -> Result<()>;
- /// Display prompt, line and cursor in terminal output
+ /// Display `prompt`, line and cursor in terminal output
fn refresh_line(
&mut self,
prompt: &str,
@@ -47,8 +47,7 @@
) -> Result<(Position, Position)>;
/// Calculate the number of columns and rows used to display `s` on a
- /// `cols` width terminal
- /// starting at `orig`.
+ /// `cols` width terminal starting at `orig`.
fn calculate_position(&self, s: &str, orig: Position) -> Position;
fn write_and_flush(&mut self, buf: &[u8]) -> Result<()>;
diff --git a/src/tty/unix.rs b/src/tty/unix.rs
index 97821e8..5a8b20f 100644
--- a/src/tty/unix.rs
+++ b/src/tty/unix.rs
@@ -369,6 +369,7 @@
pub struct PosixRenderer {
out: Stdout,
cols: usize, // Number of columns in terminal
+ buffer: String,
}
impl PosixRenderer {
@@ -377,6 +378,7 @@
PosixRenderer {
out: io::stdout(),
cols,
+ buffer: String::with_capacity(1024),
}
}
}
@@ -433,7 +435,7 @@
highlighter: Option<&Highlighter>,
) -> Result<(Position, Position)> {
use std::fmt::Write;
- let mut ab = String::new();
+ self.buffer.clear();
// calculate the position of the end of the input line
let end_pos = self.calculate_position(line, prompt_size);
@@ -445,53 +447,55 @@
let cursor_row_movement = old_rows.checked_sub(current_row).unwrap_or(0);
// move the cursor down as required
if cursor_row_movement > 0 {
- write!(ab, "\x1b[{}B", cursor_row_movement).unwrap();
+ write!(self.buffer, "\x1b[{}B", cursor_row_movement).unwrap();
}
// clear old rows
for _ in 0..old_rows {
- ab.push_str("\r\x1b[0K\x1b[A");
+ self.buffer.push_str("\r\x1b[0K\x1b[A");
}
// clear the line
- ab.push_str("\r\x1b[0K");
+ self.buffer.push_str("\r\x1b[0K");
if let Some(highlighter) = highlighter {
// display the prompt
- ab.push_str(&highlighter.highlight_prompt(prompt));
+ self.buffer.push_str(&highlighter.highlight_prompt(prompt));
// display the input line
- ab.push_str(&highlighter.highlight(line, line.pos()));
+ self.buffer
+ .push_str(&highlighter.highlight(line, line.pos()));
} else {
// display the prompt
- ab.push_str(prompt);
+ self.buffer.push_str(prompt);
// display the input line
- ab.push_str(line);
+ self.buffer.push_str(line);
}
// display hint
if let Some(hint) = hint {
let truncate = truncate(&hint, end_pos.col, self.cols);
if let Some(highlighter) = highlighter {
- ab.push_str(&highlighter.highlight_hint(truncate));
+ self.buffer.push_str(&highlighter.highlight_hint(truncate));
} else {
- ab.push_str(truncate);
+ self.buffer.push_str(truncate);
}
}
// we have to generate our own newline on line wrap
if end_pos.col == 0 && end_pos.row > 0 {
- ab.push_str("\n");
+ self.buffer.push_str("\n");
}
// position the cursor
let cursor_row_movement = end_pos.row - cursor.row;
// move the cursor up as required
if cursor_row_movement > 0 {
- write!(ab, "\x1b[{}A", cursor_row_movement).unwrap();
+ write!(self.buffer, "\x1b[{}A", cursor_row_movement).unwrap();
}
// position the cursor within the line
if cursor.col > 0 {
- write!(ab, "\r\x1b[{}C", cursor.col).unwrap();
+ write!(self.buffer, "\r\x1b[{}C", cursor.col).unwrap();
} else {
- ab.push('\r');
+ self.buffer.push('\r');
}
- try!(self.write_and_flush(ab.as_bytes()));
+ try!(self.out.write_all(self.buffer.as_bytes()));
+ try!(self.out.flush());
Ok((cursor, end_pos))
}
diff --git a/src/tty/windows.rs b/src/tty/windows.rs
index 098cae4..313f26e 100644
--- a/src/tty/windows.rs
+++ b/src/tty/windows.rs
@@ -230,6 +230,7 @@
out: Stdout,
handle: HANDLE,
cols: usize, // Number of columns in terminal
+ buffer: String,
}
impl ConsoleRenderer {
@@ -240,6 +241,7 @@
out: io::stdout(),
handle,
cols,
+ buffer: String::with_capacity(1024),
}
}
@@ -307,29 +309,31 @@
(info.dwSize.X * (old_rows as i16 + 1)) as DWORD,
info.dwCursorPosition,
));
- let mut ab = String::new();
+ self.buffer.clear();
if let Some(highlighter) = highlighter {
// TODO handle ansi escape code (SetConsoleTextAttribute)
// display the prompt
- ab.push_str(&highlighter.highlight_prompt(prompt));
+ self.buffer.push_str(&highlighter.highlight_prompt(prompt));
// display the input line
- ab.push_str(&highlighter.highlight(line, line.pos()));
+ self.buffer
+ .push_str(&highlighter.highlight(line, line.pos()));
} else {
// display the prompt
- ab.push_str(prompt);
+ self.buffer.push_str(prompt);
// display the input line
- ab.push_str(line);
+ self.buffer.push_str(line);
}
// display hint
if let Some(hint) = hint {
let truncate = truncate(&hint, end_pos.col, self.cols);
if let Some(highlighter) = highlighter {
- ab.push_str(&highlighter.highlight_hint(truncate));
+ self.buffer.push_str(&highlighter.highlight_hint(truncate));
} else {
- ab.push_str(truncate);
+ self.buffer.push_str(truncate);
}
}
- try!(self.write_and_flush(ab.as_bytes()));
+ try!(self.out.write_all(self.buffer.as_bytes()));
+ try!(self.out.flush());
// position the cursor
let mut info = try!(self.get_console_screen_buffer_info());