WIP making the buffer faster.

This commit is contained in:
Nathan Vegdahl 2017-12-31 19:30:28 -08:00
parent 66a80baeed
commit 945505c5ff
2 changed files with 112 additions and 63 deletions

View File

@ -17,7 +17,7 @@ use utils::digit_count;
pub mod formatter; pub mod formatter;
mod screen; mod screen;
use self::screen::Screen; use self::screen::{Color, Screen, Style};
/// Generalized ui loop. /// Generalized ui loop.
macro_rules! ui_loop { macro_rules! ui_loop {
@ -203,8 +203,7 @@ impl<'a> TermUI<'a> {
} }
fn go_to_line_ui_loop(&mut self) { fn go_to_line_ui_loop(&mut self) {
let foreground = color::Black; let style = Style(Color::Black, Color::Cyan);
let background = color::Cyan;
let mut cancel = false; let mut cancel = false;
let prefix = "Jump to line: "; let prefix = "Jump to line: ";
@ -220,15 +219,14 @@ impl<'a> TermUI<'a> {
self.screen.clear(); self.screen.clear();
self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1)); self.draw_editor(&self.editor, (0, 0), (self.height - 1, self.width - 1));
for i in 0..self.width { for i in 0..self.width {
self.screen.draw(i, 0, " ", foreground, background); self.screen.draw(i, 0, " ", style);
} }
self.screen.draw(1, 0, prefix, foreground, background); self.screen.draw(1, 0, prefix, style);
self.screen.draw( self.screen.draw(
prefix.len() + 1, prefix.len() + 1,
0, 0,
&line[..], &line[..],
foreground, style,
background,
); );
}, },
@ -281,19 +279,18 @@ impl<'a> TermUI<'a> {
c1: (usize, usize), c1: (usize, usize),
c2: (usize, usize), c2: (usize, usize),
) { ) {
let fg = color::Black; let style = Style(Color::Black, Color::Cyan);
let bg = color::Cyan;
// Fill in top row with info line color // Fill in top row with info line color
for i in c1.1..(c2.1 + 1) { for i in c1.1..(c2.1 + 1) {
self.screen.draw(i, c1.0, " ", fg, bg); self.screen.draw(i, c1.0, " ", style);
} }
// Filename and dirty marker // Filename and dirty marker
let filename = editor.file_path.display(); let filename = editor.file_path.display();
let dirty_char = if editor.dirty { "*" } else { "" }; let dirty_char = if editor.dirty { "*" } else { "" };
let name = format!("{}{}", filename, dirty_char); let name = format!("{}{}", filename, dirty_char);
self.screen.draw(c1.1 + 1, c1.0, &name[..], fg, bg); self.screen.draw(c1.1 + 1, c1.0, &name[..], style);
// Percentage position in document // Percentage position in document
// TODO: use view instead of cursor for calculation if there is more // TODO: use view instead of cursor for calculation if there is more
@ -306,7 +303,7 @@ impl<'a> TermUI<'a> {
}; };
let pstring = format!("{}%", percentage); let pstring = format!("{}%", percentage);
self.screen self.screen
.draw(c2.1 - pstring.len(), c1.0, &pstring[..], fg, bg); .draw(c2.1 - pstring.len(), c1.0, &pstring[..], style);
// Text encoding info and tab style // Text encoding info and tab style
let nl = match editor.line_ending_type { let nl = match editor.line_ending_type {
@ -325,7 +322,7 @@ impl<'a> TermUI<'a> {
"UTF8:{} {}:{}", "UTF8:{} {}:{}",
nl, soft_tabs_str, editor.soft_tab_width as usize nl, soft_tabs_str, editor.soft_tab_width as usize
); );
self.screen.draw(c2.1 - 30, c1.0, &info_line[..], fg, bg); self.screen.draw(c2.1 - 30, c1.0, &info_line[..], style);
// Draw main text editing area // Draw main text editing area
self.draw_editor_text(editor, (c1.0 + 1, c1.1), c2); self.draw_editor_text(editor, (c1.0 + 1, c1.1), c2);
@ -364,7 +361,8 @@ impl<'a> TermUI<'a> {
// Fill in the gutter with the appropriate background // Fill in the gutter with the appropriate background
for y in c1.0..(c2.0 + 1) { for y in c1.0..(c2.0 + 1) {
for x in c1.1..(c1.1 + gutter_width - 1) { for x in c1.1..(c1.1 + gutter_width - 1) {
self.screen.draw(x, y, " ", color::White, color::Blue); self.screen
.draw(x, y, " ", Style(Color::White, Color::Blue));
} }
} }
@ -379,8 +377,7 @@ impl<'a> TermUI<'a> {
lnx, lnx,
lny, lny,
&format!("{}", line_num)[..], &format!("{}", line_num)[..],
color::White, Style(Color::White, Color::Blue),
color::Blue,
); );
} }
} }
@ -430,8 +427,7 @@ impl<'a> TermUI<'a> {
px as usize, px as usize,
py as usize, py as usize,
" ", " ",
color::Black, Style(Color::Black, Color::White),
color::White,
); );
} }
} else if g == "\t" { } else if g == "\t" {
@ -442,8 +438,7 @@ impl<'a> TermUI<'a> {
tpx as usize, tpx as usize,
py as usize, py as usize,
" ", " ",
color::White, Style(Color::White, Color::Black),
color::Black,
); );
} }
} }
@ -453,8 +448,7 @@ impl<'a> TermUI<'a> {
px as usize, px as usize,
py as usize, py as usize,
" ", " ",
color::Black, Style(Color::Black, Color::White),
color::White,
); );
} }
} else { } else {
@ -463,16 +457,14 @@ impl<'a> TermUI<'a> {
px as usize, px as usize,
py as usize, py as usize,
g, g,
color::Black, Style(Color::Black, Color::White),
color::White,
); );
} else { } else {
self.screen.draw( self.screen.draw(
px as usize, px as usize,
py as usize, py as usize,
g, g,
color::White, Style(Color::White, Color::Black),
color::Black,
); );
} }
} }
@ -524,8 +516,12 @@ impl<'a> TermUI<'a> {
if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize) if (px >= c1.1 as isize) && (py >= c1.0 as isize) && (px <= c2.1 as isize)
&& (py <= c2.0 as isize) && (py <= c2.0 as isize)
{ {
self.screen self.screen.draw(
.draw(px as usize, py as usize, " ", color::Black, color::White); px as usize,
py as usize,
" ",
Style(Color::Black, Color::White),
);
} }
} }
} }

View File

@ -12,7 +12,7 @@ use termion::raw::{IntoRawMode, RawTerminal};
pub(crate) struct Screen { pub(crate) struct Screen {
out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>, out: RefCell<AlternateScreen<RawTerminal<io::Stdout>>>,
buf: RefCell<Vec<Option<String>>>, buf: RefCell<Vec<Option<(Style, String)>>>,
w: usize, w: usize,
h: usize, h: usize,
} }
@ -20,11 +20,8 @@ pub(crate) struct Screen {
impl Screen { impl Screen {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let (w, h) = termion::terminal_size().unwrap(); let (w, h) = termion::terminal_size().unwrap();
let buf = std::iter::repeat(Some(format!( let buf = std::iter::repeat(Some((Style(Color::Black, Color::Black), " ".to_string())))
"{}{} ", .take(w as usize * h as usize)
color::Fg(color::Black),
color::Bg(color::Black)
))).take(w as usize * h as usize)
.collect(); .collect();
Screen { Screen {
out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())), out: RefCell::new(AlternateScreen::from(io::stdout().into_raw_mode().unwrap())),
@ -37,20 +34,13 @@ impl Screen {
pub(crate) fn clear(&self) { pub(crate) fn clear(&self) {
for cell in self.buf.borrow_mut().iter_mut() { for cell in self.buf.borrow_mut().iter_mut() {
match *cell { match *cell {
Some(ref mut text) => { Some((ref mut style, ref mut text)) => {
*style = Style(Color::Black, Color::Black);
text.clear(); text.clear();
text.push_str(&format!( text.push_str(" ");
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
));
} }
_ => { _ => {
*cell = Some(format!( *cell = Some((Style(Color::Black, Color::Black), " ".to_string()));
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
));
} }
} }
} }
@ -61,45 +51,40 @@ impl Screen {
self.h = h; self.h = h;
self.buf.borrow_mut().resize( self.buf.borrow_mut().resize(
w * h, w * h,
Some(format!( Some((Style(Color::Black, Color::Black), " ".to_string())),
"{}{} ",
color::Fg(color::Black),
color::Bg(color::Black)
)),
); );
} }
pub(crate) fn present(&self) { pub(crate) fn present(&self) {
let buf = self.buf.borrow(); let buf = self.buf.borrow();
let mut tmp_string = String::new();
for y in 0..self.h { for y in 0..self.h {
for x in 0..self.w { let mut x = 0;
if let Some(ref cell) = buf[y * self.w + x] { let mut last_style = Style(Color::Black, Color::Black);
let mut left_x = 0;
while x < self.w {
if let Some((style, ref text)) = buf[y * self.w + x] {
write!( write!(
self.out.borrow_mut(), self.out.borrow_mut(),
"{}{}", "{}{}{}",
termion::cursor::Goto((x + 1) as u16, (y + 1) as u16), termion::cursor::Goto((x + 1) as u16, (y + 1) as u16),
cell style,
text,
).unwrap(); ).unwrap();
} }
x += 1;
} }
} }
self.out.borrow_mut().flush().unwrap(); self.out.borrow_mut().flush().unwrap();
} }
pub(crate) fn draw<C1: color::Color + Copy, C2: color::Color + Copy>( pub(crate) fn draw(&self, x: usize, y: usize, text: &str, style: Style) {
&self,
x: usize,
y: usize,
text: &str,
fg: C1,
bg: C2,
) {
let mut buf = self.buf.borrow_mut(); let mut buf = self.buf.borrow_mut();
let mut x = x; let mut x = x;
for g in UnicodeSegmentation::graphemes(text, true) { for g in UnicodeSegmentation::graphemes(text, true) {
let width = UnicodeWidthStr::width(g); let width = UnicodeWidthStr::width(g);
if width > 0 { if width > 0 {
buf[y * self.w + x] = Some(format!("{}{}{}", color::Fg(fg), color::Bg(bg), g)); buf[y * self.w + x] = Some((style, g.to_string()));
x += 1; x += 1;
for _ in 0..(width - 1) { for _ in 0..(width - 1) {
buf[y * self.w + x] = None; buf[y * self.w + x] = None;
@ -130,3 +115,71 @@ impl Drop for Screen {
self.show_cursor(); self.show_cursor();
} }
} }
#[derive(Debug, Copy, Clone, PartialEq)]
pub(crate) enum Color {
Black,
Blue,
Cyan,
Green,
LightBlack,
LightBlue,
LightCyan,
LightGreen,
LightMagenta,
LightRed,
LightWhite,
LightYellow,
Magenta,
Red,
Rgb(u8, u8, u8),
White,
Yellow,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub(crate) struct Style(pub Color, pub Color); // Fg, Bg
impl std::fmt::Display for Style {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
match self.0 {
Color::Black => write!(f, "{}", color::Fg(color::Black)),
Color::Blue => write!(f, "{}", color::Fg(color::Blue)),
Color::Cyan => write!(f, "{}", color::Fg(color::Cyan)),
Color::Green => write!(f, "{}", color::Fg(color::Green)),
Color::LightBlack => write!(f, "{}", color::Fg(color::LightBlack)),
Color::LightBlue => write!(f, "{}", color::Fg(color::LightBlue)),
Color::LightCyan => write!(f, "{}", color::Fg(color::LightCyan)),
Color::LightGreen => write!(f, "{}", color::Fg(color::LightGreen)),
Color::LightMagenta => write!(f, "{}", color::Fg(color::LightMagenta)),
Color::LightRed => write!(f, "{}", color::Fg(color::LightRed)),
Color::LightWhite => write!(f, "{}", color::Fg(color::LightWhite)),
Color::LightYellow => write!(f, "{}", color::Fg(color::LightYellow)),
Color::Magenta => write!(f, "{}", color::Fg(color::Magenta)),
Color::Red => write!(f, "{}", color::Fg(color::Red)),
Color::Rgb(r, g, b) => write!(f, "{}", color::Fg(color::Rgb(r, g, b))),
Color::White => write!(f, "{}", color::Fg(color::White)),
Color::Yellow => write!(f, "{}", color::Fg(color::Yellow)),
}?;
match self.1 {
Color::Black => write!(f, "{}", color::Bg(color::Black)),
Color::Blue => write!(f, "{}", color::Bg(color::Blue)),
Color::Cyan => write!(f, "{}", color::Bg(color::Cyan)),
Color::Green => write!(f, "{}", color::Bg(color::Green)),
Color::LightBlack => write!(f, "{}", color::Bg(color::LightBlack)),
Color::LightBlue => write!(f, "{}", color::Bg(color::LightBlue)),
Color::LightCyan => write!(f, "{}", color::Bg(color::LightCyan)),
Color::LightGreen => write!(f, "{}", color::Bg(color::LightGreen)),
Color::LightMagenta => write!(f, "{}", color::Bg(color::LightMagenta)),
Color::LightRed => write!(f, "{}", color::Bg(color::LightRed)),
Color::LightWhite => write!(f, "{}", color::Bg(color::LightWhite)),
Color::LightYellow => write!(f, "{}", color::Bg(color::LightYellow)),
Color::Magenta => write!(f, "{}", color::Bg(color::Magenta)),
Color::Red => write!(f, "{}", color::Bg(color::Red)),
Color::Rgb(r, g, b) => write!(f, "{}", color::Bg(color::Rgb(r, g, b))),
Color::White => write!(f, "{}", color::Bg(color::White)),
Color::Yellow => write!(f, "{}", color::Bg(color::Yellow)),
}
}
}