mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-27 19:26:09 +00:00
Add stub termion backend
Not supported: input, colors, effects, async
This commit is contained in:
parent
90c9d51a6c
commit
df4397a174
@ -1,5 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
authors = ["Alexandre Bury <alexandre.bury@gmail.com>"]
|
||||||
|
build = "build.rs"
|
||||||
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
description = "A TUI (Text User Interface) library focused on ease-of-use."
|
||||||
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
documentation = "https://gyscos.github.io/Cursive/cursive/index.html"
|
||||||
exclude = ["doc", "assets"]
|
exclude = ["doc", "assets"]
|
||||||
@ -9,10 +10,13 @@ name = "cursive"
|
|||||||
readme = "Readme.md"
|
readme = "Readme.md"
|
||||||
repository = "https://github.com/gyscos/Cursive"
|
repository = "https://github.com/gyscos/Cursive"
|
||||||
version = "0.3.1"
|
version = "0.3.1"
|
||||||
build="build.rs"
|
|
||||||
|
[build-dependencies]
|
||||||
|
skeptic = "0.6"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
odds = "0.2"
|
odds = "0.2"
|
||||||
|
termion = "1.1.1"
|
||||||
toml = "0.2"
|
toml = "0.2"
|
||||||
unicode-segmentation = "0.1"
|
unicode-segmentation = "0.1"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
@ -25,8 +29,5 @@ version = "5.82.0"
|
|||||||
rand = "0.3"
|
rand = "0.3"
|
||||||
skeptic = "0.6"
|
skeptic = "0.6"
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
skeptic = "0.6"
|
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "cursive"
|
name = "cursive"
|
||||||
|
@ -74,7 +74,7 @@ impl backend::Backend for NcursesBackend {
|
|||||||
ncurses::clear();
|
ncurses::clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh(&self) {
|
fn refresh(&mut self) {
|
||||||
ncurses::refresh();
|
ncurses::refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,15 +3,18 @@ use theme;
|
|||||||
|
|
||||||
// Module is not named `ncurses` to avoir naming conflict
|
// Module is not named `ncurses` to avoir naming conflict
|
||||||
mod curses;
|
mod curses;
|
||||||
|
mod termion;
|
||||||
|
|
||||||
pub use self::curses::NcursesBackend;
|
pub use self::curses::NcursesBackend;
|
||||||
|
pub use self::termion::TermionBackend;
|
||||||
|
|
||||||
pub trait Backend {
|
pub trait Backend {
|
||||||
fn init() -> Self;
|
fn init() -> Self;
|
||||||
|
// TODO: take `self` by value?
|
||||||
fn finish(&mut self);
|
fn finish(&mut self);
|
||||||
|
|
||||||
fn clear(&self);
|
fn clear(&self);
|
||||||
fn refresh(&self);
|
fn refresh(&mut self);
|
||||||
|
|
||||||
fn has_colors(&self) -> bool;
|
fn has_colors(&self) -> bool;
|
||||||
|
|
||||||
@ -24,6 +27,7 @@ pub trait Backend {
|
|||||||
fn set_refresh_rate(&mut self, fps: u32);
|
fn set_refresh_rate(&mut self, fps: u32);
|
||||||
fn screen_size(&self) -> (usize, usize);
|
fn screen_size(&self) -> (usize, usize);
|
||||||
|
|
||||||
|
// TODO: unify those into a single method?
|
||||||
fn with_color<F: FnOnce()>(&self, color: theme::ColorStyle, f: F);
|
fn with_color<F: FnOnce()>(&self, color: theme::ColorStyle, f: F);
|
||||||
fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F);
|
fn with_effect<F: FnOnce()>(&self, effect: theme::Effect, f: F);
|
||||||
}
|
}
|
||||||
|
85
src/backend/termion.rs
Normal file
85
src/backend/termion.rs
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
|
||||||
|
|
||||||
|
use ::backend;
|
||||||
|
use ::event::{Event, Key};
|
||||||
|
use std::io::Write;
|
||||||
|
use termion;
|
||||||
|
use termion::input::TermRead;
|
||||||
|
use termion::raw::IntoRawMode;
|
||||||
|
use ::theme::{BaseColor, Color, ColorStyle, Effect};
|
||||||
|
|
||||||
|
pub struct TermionBackend {
|
||||||
|
terminal: termion::raw::RawTerminal<::std::io::Stdout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl backend::Backend for TermionBackend {
|
||||||
|
fn init() -> Self {
|
||||||
|
print!("{}", termion::cursor::Hide);
|
||||||
|
Self::clear();
|
||||||
|
|
||||||
|
|
||||||
|
TermionBackend {
|
||||||
|
terminal: ::std::io::stdout().into_raw_mode().unwrap(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(&mut self) {
|
||||||
|
// Maybe we should clear everything?
|
||||||
|
print!("{}{}", termion::cursor::Show, termion::cursor::Goto(1, 1));
|
||||||
|
Self::clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_color_style(&mut self, style: ColorStyle, foreground: &Color,
|
||||||
|
background: &Color) {
|
||||||
|
// Do we _need_ to save the color?
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_color<F: FnOnce()>(&self, color: ColorStyle, f: F) {
|
||||||
|
// TODO: actually use colors
|
||||||
|
// TODO: careful! need to remember the previous state
|
||||||
|
// and apply it back
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_effect<F: FnOnce()>(&self, effect: Effect, f: F) {
|
||||||
|
// TODO: actually use effects
|
||||||
|
// TODO: careful! need to remember the previous state
|
||||||
|
// and apply it back
|
||||||
|
f();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn has_colors(&self) -> bool {
|
||||||
|
// TODO: color support detection?
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn screen_size(&self) -> (usize, usize) {
|
||||||
|
let (x, y) = termion::terminal_size().unwrap_or((1, 1));
|
||||||
|
(x as usize, y as usize)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn clear() {
|
||||||
|
print!("{}", termion::clear::All);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn refresh(&mut self) {
|
||||||
|
// Not sure termion needs a refresh phase
|
||||||
|
self.terminal.flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_at(&self, (x, y): (usize, usize), text: &str) {
|
||||||
|
// TODO: terminals are 1-based. Should we add 1 here?
|
||||||
|
print!("{}{}", termion::cursor::Goto(x as u16, y as u16), text);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_refresh_rate(&mut self, fps: u32) {
|
||||||
|
// TODO: handle async refresh, when no input is entered.
|
||||||
|
// Could be done with a timeout on the event polling,
|
||||||
|
// if it was supportedd.
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_event(&self) -> Event {
|
||||||
|
::std::io::stdin().keys().next();
|
||||||
|
Event::Key(Key::Enter)
|
||||||
|
}
|
||||||
|
}
|
@ -61,6 +61,7 @@ extern crate toml;
|
|||||||
extern crate unicode_segmentation;
|
extern crate unicode_segmentation;
|
||||||
extern crate unicode_width;
|
extern crate unicode_width;
|
||||||
extern crate odds;
|
extern crate odds;
|
||||||
|
extern crate termion;
|
||||||
|
|
||||||
macro_rules! println_stderr(
|
macro_rules! println_stderr(
|
||||||
($($arg:tt)*) => { {
|
($($arg:tt)*) => { {
|
||||||
@ -105,7 +106,7 @@ mod utf8;
|
|||||||
mod backend;
|
mod backend;
|
||||||
|
|
||||||
|
|
||||||
use backend::{Backend, NcursesBackend};
|
use backend::{Backend};
|
||||||
|
|
||||||
use event::{Callback, Event, EventResult};
|
use event::{Callback, Event, EventResult};
|
||||||
|
|
||||||
@ -155,7 +156,7 @@ new_default!(Cursive);
|
|||||||
// Use the Ncurses backend.
|
// Use the Ncurses backend.
|
||||||
// TODO: make this feature-driven
|
// TODO: make this feature-driven
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub type B = NcursesBackend;
|
pub type B = backend::TermionBackend;
|
||||||
|
|
||||||
impl Cursive {
|
impl Cursive {
|
||||||
/// Creates a new Cursive root, and initialize ncurses.
|
/// Creates a new Cursive root, and initialize ncurses.
|
||||||
@ -493,7 +494,6 @@ impl Cursive {
|
|||||||
let id = self.active_screen;
|
let id = self.active_screen;
|
||||||
self.screens.get_mut(id).unwrap().draw(&printer);
|
self.screens.get_mut(id).unwrap().draw(&printer);
|
||||||
|
|
||||||
self.backend.refresh();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the event loop.
|
/// Runs the event loop.
|
||||||
@ -518,6 +518,7 @@ impl Cursive {
|
|||||||
// TODO: Do we need to redraw every view every time?
|
// TODO: Do we need to redraw every view every time?
|
||||||
// (Is this getting repetitive? :p)
|
// (Is this getting repetitive? :p)
|
||||||
self.draw();
|
self.draw();
|
||||||
|
self.backend.refresh();
|
||||||
|
|
||||||
// Wait for next event.
|
// Wait for next event.
|
||||||
// (If set_fps was called, this returns -1 now and then)
|
// (If set_fps was called, this returns -1 now and then)
|
||||||
|
@ -104,8 +104,11 @@ impl<'a> Printer<'a> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let len = min(len, self.size.x - p.x);
|
let len = min(len, self.size.x - p.x);
|
||||||
|
let text: String = ::std::iter::repeat(c).take(len).collect();
|
||||||
|
|
||||||
let p = p + self.offset;
|
let p = p + self.offset;
|
||||||
|
// self.backend.print_at((p.x, p.y), &text);
|
||||||
|
self.print(p, &text);
|
||||||
for x in 0..len {
|
for x in 0..len {
|
||||||
self.backend.print_at((p.x + x, p.y), c);
|
self.backend.print_at((p.x + x, p.y), c);
|
||||||
}
|
}
|
||||||
|
@ -60,7 +60,8 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
|||||||
|
|
||||||
fn wrap_draw(&self, printer: &Printer) {
|
fn wrap_draw(&self, printer: &Printer) {
|
||||||
|
|
||||||
if printer.size.y == 0 || printer.size.x == 0 {
|
if printer.size.y <= self.top_padding as usize ||
|
||||||
|
printer.size.x <= self.left_padding as usize {
|
||||||
// Nothing to do if there's no place to draw.
|
// Nothing to do if there's no place to draw.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ impl<T: View> ViewWrapper for ShadowView<T> {
|
|||||||
printer.size - (1, 1),
|
printer.size - (1, 1),
|
||||||
true));
|
true));
|
||||||
|
|
||||||
if printer.theme.shadow {
|
if printer.theme.shadow && false {
|
||||||
let h = printer.size.y;
|
let h = printer.size.y;
|
||||||
let w = printer.size.x;
|
let w = printer.size.x;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user