mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-09 10:50:40 +00:00
Crossterm Performance Update (#361)
This commit is contained in:
parent
ede8423e92
commit
bddb1a9dde
@ -7,15 +7,17 @@
|
||||
use crate::vec::Vec2;
|
||||
use crate::{backend, theme};
|
||||
use crossterm::{
|
||||
cursor, input, terminal, AlternateScreen, AsyncReader, Attribute,
|
||||
ClearType, Color, Colored, InputEvent as CInputEvent,
|
||||
KeyEvent as CKeyEvent, MouseButton as CMouseButton,
|
||||
MouseEvent as CMouseEvent, Terminal, TerminalCursor,
|
||||
cursor, execute, input, queue, terminal, AlternateScreen, AsyncReader,
|
||||
Attribute, Clear, ClearType, Color, Colored, Command, Goto, Hide,
|
||||
InputEvent as CInputEvent, KeyEvent as CKeyEvent,
|
||||
MouseButton as CMouseButton, MouseEvent as CMouseEvent, Output, RawScreen,
|
||||
SetAttr, SetBg, SetFg, Show, Terminal, TerminalCursor,
|
||||
};
|
||||
|
||||
use crate::event::{Event, Key, MouseButton, MouseEvent};
|
||||
use core::borrow::BorrowMut;
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::io::{self, Stdout, Write};
|
||||
use std::io::{self, BufWriter, Stdout, StdoutLock, Write};
|
||||
|
||||
/// Backend using crossterm
|
||||
pub struct Backend {
|
||||
@ -24,7 +26,7 @@ pub struct Backend {
|
||||
// reader to read user input async.
|
||||
async_reader: AsyncReader,
|
||||
_alternate_screen: AlternateScreen,
|
||||
stdout: RefCell<Stdout>,
|
||||
stdout: RefCell<BufWriter<Stdout>>,
|
||||
cursor: TerminalCursor,
|
||||
terminal: Terminal,
|
||||
}
|
||||
@ -48,22 +50,31 @@ impl Backend {
|
||||
last_button: None,
|
||||
async_reader,
|
||||
_alternate_screen,
|
||||
stdout: RefCell::new(io::stdout()),
|
||||
stdout: RefCell::new(BufWriter::new(io::stdout())),
|
||||
terminal: terminal(),
|
||||
cursor: cursor(),
|
||||
}))
|
||||
}
|
||||
|
||||
fn apply_colors(&self, colors: theme::ColorPair) {
|
||||
with_color(colors.front, |c| self.write(Colored::Fg(*c)));
|
||||
with_color(colors.back, |c| self.write(Colored::Bg(*c)));
|
||||
with_color(colors.front, |c| {
|
||||
queue!(self.stdout.borrow_mut(), SetFg(*c))
|
||||
});
|
||||
with_color(colors.back, |c| {
|
||||
queue!(self.stdout.borrow_mut(), SetBg(*c))
|
||||
});
|
||||
}
|
||||
|
||||
fn write<T>(&self, content: T)
|
||||
where
|
||||
T: std::fmt::Display,
|
||||
{
|
||||
write!(self.stdout.borrow_mut(), "{}", format!("{}", content)).unwrap()
|
||||
write!(self.stdout.borrow_mut(), "{}", format!("{}", content))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn set_attr(&self, attr: Attribute) {
|
||||
queue!(self.stdout.borrow_mut(), SetAttr(attr));
|
||||
}
|
||||
|
||||
fn map_key(&mut self, event: CInputEvent) -> Event {
|
||||
@ -164,11 +175,16 @@ impl backend::Backend for Backend {
|
||||
}
|
||||
|
||||
fn finish(&mut self) {
|
||||
self.cursor.goto(1, 1).unwrap();
|
||||
self.terminal.clear(ClearType::All).unwrap();
|
||||
self.write(Attribute::Reset);
|
||||
execute!(
|
||||
self.stdout.borrow_mut(),
|
||||
Goto(0, 0),
|
||||
Clear(ClearType::All),
|
||||
SetBg(Color::Reset),
|
||||
SetFg(Color::Reset),
|
||||
SetAttr(Attribute::Reset),
|
||||
Show
|
||||
);
|
||||
input().disable_mouse_mode().unwrap();
|
||||
cursor().show().unwrap();
|
||||
}
|
||||
|
||||
fn refresh(&mut self) {
|
||||
@ -182,11 +198,12 @@ impl backend::Backend for Backend {
|
||||
|
||||
fn screen_size(&self) -> Vec2 {
|
||||
let size = self.terminal.terminal_size();
|
||||
Vec2::from(size) + (1, 1)
|
||||
Vec2::from(size)
|
||||
}
|
||||
|
||||
fn print_at(&self, pos: Vec2, text: &str) {
|
||||
self.cursor.goto(pos.x as u16, pos.y as u16).unwrap();
|
||||
queue!(self.stdout.borrow_mut(), Goto(pos.x as u16, pos.y as u16))
|
||||
.unwrap();
|
||||
self.write(text);
|
||||
}
|
||||
|
||||
@ -194,7 +211,7 @@ impl backend::Backend for Backend {
|
||||
if repetitions > 0 {
|
||||
let mut out = self.stdout.borrow_mut();
|
||||
|
||||
self.cursor.goto(pos.x as u16, pos.y as u16).unwrap();
|
||||
queue!(out, Goto(pos.x as u16, pos.y as u16)).unwrap();
|
||||
|
||||
// as I (Timon) wrote this I figured out that calling `write_str` for unix was flushing the stdout.
|
||||
// Current work aground is writing bytes instead of a string to the terminal.
|
||||
@ -214,7 +231,7 @@ impl backend::Backend for Backend {
|
||||
back: color,
|
||||
});
|
||||
|
||||
self.terminal.clear(ClearType::All).unwrap();
|
||||
queue!(self.stdout.borrow_mut(), Clear(ClearType::All)).unwrap();
|
||||
}
|
||||
|
||||
fn set_color(&self, color: theme::ColorPair) -> theme::ColorPair {
|
||||
@ -231,22 +248,22 @@ impl backend::Backend for Backend {
|
||||
fn set_effect(&self, effect: theme::Effect) {
|
||||
match effect {
|
||||
theme::Effect::Simple => (),
|
||||
theme::Effect::Reverse => self.write(Attribute::Reverse),
|
||||
theme::Effect::Bold => self.write(Attribute::Bold),
|
||||
theme::Effect::Italic => self.write(Attribute::Italic),
|
||||
theme::Effect::Strikethrough => self.write(Attribute::CrossedOut),
|
||||
theme::Effect::Underline => self.write(Attribute::Underlined),
|
||||
theme::Effect::Reverse => self.set_attr(Attribute::Reverse),
|
||||
theme::Effect::Bold => self.set_attr(Attribute::Bold),
|
||||
theme::Effect::Italic => self.set_attr(Attribute::Italic),
|
||||
theme::Effect::Strikethrough => self.set_attr(Attribute::CrossedOut),
|
||||
theme::Effect::Underline => self.set_attr(Attribute::Underlined),
|
||||
}
|
||||
}
|
||||
|
||||
fn unset_effect(&self, effect: theme::Effect) {
|
||||
match effect {
|
||||
theme::Effect::Simple => (),
|
||||
theme::Effect::Reverse => self.write(Attribute::Reverse),
|
||||
theme::Effect::Bold => self.write(Attribute::NoBold),
|
||||
theme::Effect::Italic => self.write(Attribute::NoItalic),
|
||||
theme::Effect::Strikethrough => self.write(Attribute::NotCrossedOut),
|
||||
theme::Effect::Underline => self.write(Attribute::Underlined),
|
||||
theme::Effect::Reverse => self.set_attr(Attribute::Reverse),
|
||||
theme::Effect::Bold => self.set_attr(Attribute::NoBold),
|
||||
theme::Effect::Italic => self.set_attr(Attribute::NoItalic),
|
||||
theme::Effect::Strikethrough => self.set_attr(Attribute::NotCrossedOut),
|
||||
theme::Effect::Underline => self.set_attr(Attribute::Underlined),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -97,8 +97,7 @@ impl Core {
|
||||
|
||||
/// Returns a sub-printer ready to draw the content.
|
||||
pub fn sub_printer<'a, 'b>(
|
||||
&self,
|
||||
printer: &Printer<'a, 'b>,
|
||||
&self, printer: &Printer<'a, 'b>,
|
||||
) -> Printer<'a, 'b> {
|
||||
// Draw scrollbar?
|
||||
let scrolling = self.is_scrolling();
|
||||
@ -185,9 +184,7 @@ impl Core {
|
||||
|
||||
/// Handle an event after processing by the content.
|
||||
pub fn on_inner_event(
|
||||
&mut self,
|
||||
event: Event,
|
||||
inner_result: EventResult,
|
||||
&mut self, event: Event, inner_result: EventResult,
|
||||
important_area: Rect,
|
||||
) -> EventResult {
|
||||
match inner_result {
|
||||
@ -365,9 +362,7 @@ impl Core {
|
||||
|
||||
/// Performs `View::call_on_any()`
|
||||
pub fn call_on_any<'a, F>(
|
||||
&mut self,
|
||||
selector: &Selector<'_>,
|
||||
cb: AnyCb<'a>,
|
||||
&mut self, selector: &Selector<'_>, cb: AnyCb<'a>,
|
||||
inner_call_on_any: F,
|
||||
) where
|
||||
F: FnOnce(&Selector, AnyCb),
|
||||
@ -377,9 +372,7 @@ impl Core {
|
||||
|
||||
/// Performs `View::focus_view()`
|
||||
pub fn focus_view<F>(
|
||||
&mut self,
|
||||
selector: &Selector<'_>,
|
||||
inner_focus_view: F,
|
||||
&mut self, selector: &Selector<'_>, inner_focus_view: F,
|
||||
) -> Result<(), ()>
|
||||
where
|
||||
F: FnOnce(&Selector) -> Result<(), ()>,
|
||||
@ -413,8 +406,7 @@ impl Core {
|
||||
|
||||
/// Sets the padding between content and scrollbar.
|
||||
pub fn set_scrollbar_padding<V: Into<Vec2>>(
|
||||
&mut self,
|
||||
scrollbar_padding: V,
|
||||
&mut self, scrollbar_padding: V,
|
||||
) {
|
||||
self.scrollbar_padding = scrollbar_padding.into();
|
||||
}
|
||||
@ -423,8 +415,7 @@ impl Core {
|
||||
///
|
||||
/// Chainable variant.
|
||||
pub fn scrollbar_padding<V: Into<Vec2>>(
|
||||
self,
|
||||
scrollbar_padding: V,
|
||||
self, scrollbar_padding: V,
|
||||
) -> Self {
|
||||
self.with(|s| s.set_scrollbar_padding(scrollbar_padding))
|
||||
}
|
||||
|
@ -54,9 +54,7 @@ impl Default for ScrollStrategy {
|
||||
/// }
|
||||
/// ```
|
||||
pub fn on_event<T, OnEvent, ImportantArea>(
|
||||
scroller: &mut T,
|
||||
event: Event,
|
||||
on_event: OnEvent,
|
||||
scroller: &mut T, event: Event, on_event: OnEvent,
|
||||
important_area: ImportantArea,
|
||||
) -> EventResult
|
||||
where
|
||||
@ -75,9 +73,7 @@ where
|
||||
|
||||
/// Performs `View::important_area` on a `scroll::Scroller`.
|
||||
pub fn important_area<T, ImportantArea>(
|
||||
scroller: &T,
|
||||
size: Vec2,
|
||||
mut important_area: ImportantArea,
|
||||
scroller: &T, size: Vec2, mut important_area: ImportantArea,
|
||||
) -> Rect
|
||||
where
|
||||
T: Scroller,
|
||||
@ -96,10 +92,7 @@ where
|
||||
|
||||
/// Performs `View::layout` on a `scroll::Scroller`.
|
||||
pub fn layout<T, Layout, RequiredSize>(
|
||||
scroller: &mut T,
|
||||
size: Vec2,
|
||||
needs_relayout: bool,
|
||||
layout: Layout,
|
||||
scroller: &mut T, size: Vec2, needs_relayout: bool, layout: Layout,
|
||||
required_size: RequiredSize,
|
||||
) where
|
||||
T: Scroller,
|
||||
@ -118,9 +111,7 @@ pub fn layout<T, Layout, RequiredSize>(
|
||||
|
||||
/// Performs `View::required_size` on a `scroll::Scroller`.
|
||||
pub fn required_size<T, RequiredSize>(
|
||||
scroller: &mut T,
|
||||
size: Vec2,
|
||||
needs_relayout: bool,
|
||||
scroller: &mut T, size: Vec2, needs_relayout: bool,
|
||||
required_size: RequiredSize,
|
||||
) -> Vec2
|
||||
where
|
||||
@ -149,9 +140,7 @@ where
|
||||
///
|
||||
/// This is an alternative to `scroll::draw()` when you just need to print individual lines.
|
||||
pub fn draw_lines<T, LineDrawer>(
|
||||
scroller: &T,
|
||||
printer: &Printer,
|
||||
mut line_drawer: LineDrawer,
|
||||
scroller: &T, printer: &Printer, mut line_drawer: LineDrawer,
|
||||
) where
|
||||
T: Scroller,
|
||||
LineDrawer: FnMut(&T, &Printer, usize),
|
||||
@ -170,11 +159,8 @@ pub fn draw_lines<T, LineDrawer>(
|
||||
///
|
||||
/// `left_border` will be called for each row to draw the left border for the given line number.
|
||||
pub fn draw_frame<T, LeftBorder, TopBorder, RightBorder, BottomBorder>(
|
||||
scroller: &T,
|
||||
printer: &Printer,
|
||||
mut left_border: LeftBorder,
|
||||
mut top_border: TopBorder,
|
||||
mut right_border: RightBorder,
|
||||
scroller: &T, printer: &Printer, mut left_border: LeftBorder,
|
||||
mut top_border: TopBorder, mut right_border: RightBorder,
|
||||
mut bottom_border: BottomBorder,
|
||||
) where
|
||||
T: Scroller,
|
||||
@ -224,9 +210,7 @@ pub fn draw_frame<T, LeftBorder, TopBorder, RightBorder, BottomBorder>(
|
||||
///
|
||||
/// It will print a box with the appropriate `├`, `┤` and so on.
|
||||
pub fn draw_box_frame<T, IsHDelim, IsVDelim>(
|
||||
scroller: &T,
|
||||
printer: &Printer,
|
||||
is_h_delim: IsHDelim,
|
||||
scroller: &T, printer: &Printer, is_h_delim: IsHDelim,
|
||||
is_v_delim: IsVDelim,
|
||||
) where
|
||||
T: Scroller,
|
||||
|
@ -11,9 +11,7 @@ use crate::Vec2;
|
||||
|
||||
/// Implements `View::draw` over the `model`.
|
||||
pub fn draw<Model, GetScroller, Draw>(
|
||||
printer: &Printer,
|
||||
model: &Model,
|
||||
mut get_scroller: GetScroller,
|
||||
printer: &Printer, model: &Model, mut get_scroller: GetScroller,
|
||||
inner_draw: Draw,
|
||||
) where
|
||||
Model: ?Sized,
|
||||
@ -32,12 +30,8 @@ pub fn draw<Model, GetScroller, Draw>(
|
||||
///
|
||||
/// Returns (Inner size, Outer size, New scrolling)
|
||||
fn sizes_when_scrolling<Model, GetScroller, RequiredSize>(
|
||||
constraint: Vec2,
|
||||
scrolling: XY<bool>,
|
||||
strict: bool,
|
||||
model: &mut Model,
|
||||
get_scroller: &mut GetScroller,
|
||||
required_size: &mut RequiredSize,
|
||||
constraint: Vec2, scrolling: XY<bool>, strict: bool, model: &mut Model,
|
||||
get_scroller: &mut GetScroller, required_size: &mut RequiredSize,
|
||||
) -> (Vec2, Vec2, XY<bool>)
|
||||
where
|
||||
Model: ?Sized,
|
||||
@ -83,12 +77,8 @@ where
|
||||
///
|
||||
/// Returns (Inner size, Outer size)
|
||||
fn sizes<Model, GetScroller, RequiredSize>(
|
||||
constraint: Vec2,
|
||||
strict: bool,
|
||||
needs_relayout: bool,
|
||||
model: &mut Model,
|
||||
get_scroller: &mut GetScroller,
|
||||
required_size: &mut RequiredSize,
|
||||
constraint: Vec2, strict: bool, needs_relayout: bool, model: &mut Model,
|
||||
get_scroller: &mut GetScroller, required_size: &mut RequiredSize,
|
||||
) -> (Vec2, Vec2)
|
||||
where
|
||||
Model: ?Sized,
|
||||
@ -151,11 +141,8 @@ where
|
||||
|
||||
/// Implements `View::layout` on the given model.
|
||||
pub fn layout<Model, GetScroller, RequiredSize, Layout>(
|
||||
size: Vec2,
|
||||
needs_relayout: bool,
|
||||
model: &mut Model,
|
||||
mut get_scroller: GetScroller,
|
||||
mut required_size: RequiredSize,
|
||||
size: Vec2, needs_relayout: bool, model: &mut Model,
|
||||
mut get_scroller: GetScroller, mut required_size: RequiredSize,
|
||||
mut layout: Layout,
|
||||
) where
|
||||
Model: ?Sized,
|
||||
@ -185,11 +172,8 @@ pub fn layout<Model, GetScroller, RequiredSize, Layout>(
|
||||
|
||||
/// Implements `View::required_size` on the given model.
|
||||
pub fn required_size<Model, GetScroller, RequiredSize>(
|
||||
constraint: Vec2,
|
||||
needs_relayout: bool,
|
||||
model: &mut Model,
|
||||
mut get_scroller: GetScroller,
|
||||
mut required_size: RequiredSize,
|
||||
constraint: Vec2, needs_relayout: bool, model: &mut Model,
|
||||
mut get_scroller: GetScroller, mut required_size: RequiredSize,
|
||||
) -> Vec2
|
||||
where
|
||||
Model: ?Sized,
|
||||
@ -210,11 +194,8 @@ where
|
||||
|
||||
/// Implements `View::on_event` on the given model.
|
||||
pub fn on_event<Model, GetScroller, OnEvent, ImportantArea>(
|
||||
event: Event,
|
||||
model: &mut Model,
|
||||
mut get_scroller: GetScroller,
|
||||
mut on_event: OnEvent,
|
||||
mut important_area: ImportantArea,
|
||||
event: Event, model: &mut Model, mut get_scroller: GetScroller,
|
||||
mut on_event: OnEvent, mut important_area: ImportantArea,
|
||||
) -> EventResult
|
||||
where
|
||||
Model: ?Sized,
|
||||
|
@ -303,8 +303,8 @@ impl TextArea {
|
||||
}
|
||||
|
||||
fn backspace(&mut self) {
|
||||
self.move_left();
|
||||
self.delete();
|
||||
self.move_left();
|
||||
self.delete();
|
||||
}
|
||||
|
||||
fn delete(&mut self) {
|
||||
|
Loading…
Reference in New Issue
Block a user