summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortomsmeding <tom.smeding@gmail.com>2019-02-10 20:37:02 +0100
committertomsmeding <tom.smeding@gmail.com>2019-02-10 20:37:02 +0100
commit3bc00f5f3f030acc8dbbf8018f6c2a99561ca709 (patch)
treee8f0298cc59a9ad235d3b746732e887c00474212
parent42c70e05335f00dfe720860917819135f8a207b9 (diff)
Update organisation and documentHEADmaster
-rw-r--r--build.rs1
-rw-r--r--src/core.rs292
-rw-r--r--src/lib.rs204
-rw-r--r--src/widgets.rs5
-rw-r--r--src/widgets/log.rs39
-rw-r--r--src/widgets/menu.rs11
-rw-r--r--src/widgets/prompt.rs35
m---------vendor/termio0
8 files changed, 384 insertions, 203 deletions
diff --git a/build.rs b/build.rs
index 46c31e3..18c690a 100644
--- a/build.rs
+++ b/build.rs
@@ -41,6 +41,7 @@ fn main() {
.blacklist_item("true_")
.blacklist_item("false_")
.blacklist_item("__bool_true_false_are_defined")
+ .blacklist_function("tprintf")
.blacklist_function("lgw_addf")
.generate()
.expect("Error generating bindings using bindgen");
diff --git a/src/core.rs b/src/core.rs
new file mode 100644
index 0000000..9e67722
--- /dev/null
+++ b/src/core.rs
@@ -0,0 +1,292 @@
+use std::char;
+use std::io;
+use std::marker::PhantomData;
+use std::sync::atomic::{AtomicBool, Ordering};
+
+use crate::bindings;
+use crate::util;
+
+pub const KEY_TAB: i32 = bindings::KEY_TAB as i32;
+pub const KEY_LF: i32 = bindings::KEY_LF as i32;
+pub const KEY_CR: i32 = bindings::KEY_CR as i32;
+pub const KEY_ESC: i32 = bindings::KEY_ESC as i32;
+pub const KEY_BACKSPACE: i32 = bindings::KEY_BACKSPACE as i32;
+
+pub const KEY_RIGHT: i32 = bindings::KEY_RIGHT as i32;
+pub const KEY_UP: i32 = bindings::KEY_UP as i32;
+pub const KEY_LEFT: i32 = bindings::KEY_LEFT as i32;
+pub const KEY_DOWN: i32 = bindings::KEY_DOWN as i32;
+pub const KEY_PAGEUP: i32 = bindings::KEY_PAGEUP as i32;
+pub const KEY_PAGEDOWN: i32 = bindings::KEY_PAGEDOWN as i32;
+pub const KEY_DELETE: i32 = bindings::KEY_DELETE as i32;
+pub const KEY_SHIFTTAB: i32 = bindings::KEY_SHIFTTAB as i32;
+
+/// Modifier combinator.
+pub const KEY_CTRL: i32 = bindings::KEY_CTRL as i32;
+/// Modifier combinator.
+pub const KEY_SHIFT: i32 = bindings::KEY_SHIFT as i32;
+/// Modifier combinator.
+pub const KEY_ALT: i32 = bindings::KEY_ALT as i32;
+/// Modifier combinator.
+pub const KEY_CTRLALT: i32 = bindings::KEY_CTRLALT as i32;
+/// Modifier combinator.
+pub const KEY_CTRLSHIFT: i32 = bindings::KEY_CTRLSHIFT as i32;
+
+/// A style descriptor for a cell on the screen.
+#[derive(Debug, Copy, Clone)]
+pub struct Style {
+ /// The foreground color; valid values are 0, 1, ..., 7 (the eight ANSI
+ /// colors) and 9 (the default color).
+ pub fg: u8,
+
+ /// The background color; valid values are 0, 1, ..., 7 (the eight ANSI
+ /// colors) and 9 (the default color).
+ pub bg: u8,
+
+ /// Whether the character in the cell should be printed bold. If this is
+ /// enabled, the terminal generally uses the bright version of the
+ /// foreground color instead of the normal version. Therefore, there are
+ /// effectively 16, not 8, foreground colors (in addition to the default
+ /// color, 9).
+ pub bold: bool,
+
+ /// Whether to display an underline.
+ pub ul: bool
+}
+
+/// RAII struct for keyboard-input initialization
+///
+/// Only one instance of this struct can be active at a time. Attempting to
+/// create a second instance will panic.
+pub struct Keyboard {
+ _phantom: PhantomData<*mut u8>,
+}
+
+static KEYBOARD_REFCOUNT: AtomicBool = AtomicBool::new(false);
+
+impl Keyboard {
+ /// Grab the keyboard, i.e. enable raw mode.
+ ///
+ /// This disables automatic printing of typed characters (echo), and allows
+ /// reading a single character even when a newline has not yet been
+ /// entered.
+ ///
+ /// If `nosigkeys` is true, interrupt keycodes like ctrl-C, ctrl-\ and
+ /// ctrl-Z will no longer be handled by the shell but will be available to
+ /// be read using `get_key()` just like the other keys.
+ pub fn grab(nosigkeys: bool) -> Self {
+ let prev = KEYBOARD_REFCOUNT.compare_and_swap(
+ false, true, Ordering::SeqCst);
+ if prev {
+ panic!("Can only hold one Keyboard struct at a time!");
+ }
+
+ unsafe { bindings::initkeyboard(nosigkeys); }
+ Self { _phantom: PhantomData }
+ }
+
+ /// Explicitly release the keyboard.
+ ///
+ /// This prevents further use of the Keyboard functionality and
+ /// simultaneously forces its lifetime to extend until this call, delaying
+ /// deinitialization of the keyboard until this call.
+ pub fn end(self) {}
+
+ // None on EOF, otherwise a combination of the KEY_* constants
+ pub fn get_key(&self) -> io::Result<Option<i32>> {
+ match unsafe { bindings::tgetkey() } {
+ -2 => Err(io::Error::last_os_error()),
+ -1 => Ok(None),
+ value => Ok(Some(value)),
+ }
+ }
+
+ pub fn get_line(&self) -> Option<String> {
+ let ptr = unsafe { bindings::tgetline() };
+ if ptr.is_null() {
+ None
+ } else {
+ unsafe { Some(util::string_from_utf8_charp(ptr)) }
+ }
+ }
+}
+
+impl Drop for Keyboard {
+ fn drop(&mut self) {
+ let prev = KEYBOARD_REFCOUNT.compare_and_swap(
+ true, false, Ordering::SeqCst);
+ if !prev {
+ panic!("Internal: No Keyboard was held on Drop of a Keyboard?");
+ }
+
+ unsafe { bindings::endkeyboard(); }
+ }
+}
+
+/// RAII struct for screen-drawing initialization
+///
+/// Only one instance of this struct can be active at a time. Attempting to
+/// create a second instance will panic.
+pub struct Screen<'a> {
+ _keyboard: &'a Keyboard,
+}
+
+static SCREEN_REFCOUNT: AtomicBool = AtomicBool::new(false);
+
+impl<'a> Screen<'a> {
+ /// Grab the screen, i.e. switch to the alternative screen and allocate draw
+ /// buffers.
+ ///
+ /// This function takes and stores a Keyboard reference to ensure that the
+ /// keyboard is initialized while the screen is grabbed.
+ pub fn grab<'b: 'a>(keyboard: &'b Keyboard) -> Self {
+ let prev = SCREEN_REFCOUNT.compare_and_swap(
+ false, true, Ordering::SeqCst);
+ if prev {
+ panic!("Can only hold one Screen struct at a time!");
+ }
+
+ unsafe { bindings::initscreen(); }
+ Self { _keyboard: keyboard }
+ }
+
+ pub fn end(self) {}
+
+ /// Install ctrl-L redraw handler.
+ ///
+ /// If the argument is true, then upon reading ctrl-L in
+ /// `Keyboard::get_key()`, a full redraw is issued, and the the call blocks
+ /// for the next key. Note that if the user only types ctrl-L, this means
+ /// that `get_key` may block while you don't expect it.
+ pub fn install_cl_handler(&self, install: bool) {
+ unsafe { bindings::installCLhandler(install); }
+ }
+
+ /// Install redraw handler.
+ ///
+ /// The argument indicates whether the redraw is a full redraw. The handler
+ /// is called before the redraw is performed. Please do not trigger redraws
+ /// from within the handler.
+ pub fn on_redraw(&self, handler: extern "C" fn(full_redraw: bool)) {
+ unsafe { bindings::installredrawhandler(Some(handler)); }
+ }
+
+ pub fn clear(&self) {
+ unsafe { bindings::clearscreen(); }
+ }
+
+ /// Update style state.
+ ///
+ /// This modifies the style for the characters printed from now on. Note
+ /// that this does not write anything to the terminal.
+ pub fn set_style(&self, style: Style) {
+ let sty = bindings::Style {
+ fg: style.fg as i32,
+ bg: style.bg as i32,
+ bold: style.bold,
+ ul: style.ul,
+ };
+ unsafe { bindings::setstyle(&sty as *const bindings::Style); }
+ }
+
+ /// Update partial style state. see `set_style()`.
+ pub fn set_fg(&self, fg: u8) {
+ unsafe { bindings::setfg(fg as i32); }
+ }
+
+ /// Update partial style state. see `set_style()`.
+ pub fn set_bg(&self, bg: u8) {
+ unsafe { bindings::setbg(bg as i32); }
+ }
+
+ /// Update partial style state. see `set_style()`.
+ pub fn set_bold(&self, bold: bool) {
+ unsafe { bindings::setbold(bold); }
+ }
+
+ /// Update partial style state. see `set_style()`.
+ pub fn set_ul(&self, ul: bool) {
+ unsafe { bindings::setul(ul); }
+ }
+
+ pub fn putc(&self, c: char) {
+ unsafe { bindings::tputc(c as i32); }
+ }
+
+ /// Newlines ('\n') return to the column on which printing started.
+ pub fn print(&self, s: &str) {
+ unsafe { bindings::tprint(s.as_bytes().as_ptr() as *const i8); }
+ }
+
+ pub fn fill_rect(&self, lefttop: (u32, u32), size: (u32, u32), c: char) {
+ unsafe { bindings::fillrect(
+ lefttop.0 as i32, lefttop.1 as i32,
+ size.0 as i32, size.1 as i32,
+ c as i32); }
+ }
+
+ pub fn redraw(&self) {
+ unsafe { bindings::redraw(); }
+ }
+
+ pub fn redraw_full(&self) {
+ unsafe { bindings::redrawfull(); }
+ }
+
+ /// Scrolls a rectangle on the screen by a signed number of lines.
+ pub fn scroll_term(&self, lefttop: (u32, u32), size: (u32, u32), amount: i32) {
+ unsafe { bindings::scrollterm(
+ lefttop.0 as i32, lefttop.1 as i32,
+ size.0 as i32, size.1 as i32,
+ amount); }
+ }
+
+ pub fn get_buffer_char(&self, pos: (u32, u32)) -> char {
+ unsafe {
+ char::from_u32(
+ bindings::getbufferchar(pos.0 as i32, pos.1 as i32) as u32
+ ).unwrap()
+ }
+ }
+
+ /// Updates state; does not actually move the cursor yet (use `redraw()`).
+ pub fn move_to(&self, pos: (u32, u32)) {
+ unsafe { bindings::moveto(pos.0 as i32, pos.1 as i32); }
+ }
+
+ /// Save the (internal) cursor position on a stack.
+ pub fn push_cursor(&self) {
+ unsafe { bindings::pushcursor(); }
+ }
+
+ /// Pop the (internal) cursor position from the stack.
+ pub fn pop_cursor(&self) {
+ unsafe { bindings::popcursor(); }
+ }
+
+ /// Takes effect immediately!
+ pub fn cursor_visible(&self, visible: bool) {
+ unsafe { bindings::cursorvisible(visible); }
+ }
+}
+
+impl<'a> Drop for Screen<'a> {
+ fn drop(&mut self) {
+ let prev = SCREEN_REFCOUNT.compare_and_swap(
+ true, false, Ordering::SeqCst);
+ if !prev {
+ panic!("Internal: No Screen was held on Drop of a Screen?");
+ }
+
+ unsafe { bindings::endscreen(); }
+ }
+}
+
+pub fn get_term_size() -> (u32, u32) {
+ let sz = unsafe { bindings::gettermsize() };
+ (sz.w as u32, sz.h as u32)
+}
+
+pub fn bel() {
+ unsafe { bindings::bel(); }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 7a17a0f..b092b85 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,183 +1,31 @@
-use std::char;
-use std::io;
+//! This crate contains bindings to the C library [termio][1]. Most functions
+//! wrapped are methods on the `Screen` or `Keyboard` structs, while others take
+//! one of these structs as an argument. This organisation ensures that e.g. the
+//! screen can only be redrawn while the double-buffered screen is actually
+//! active, and that keys can only be read from the input while the input stream
+//! is actually in raw mode.
+//!
+//! The `widgets` submodule contains the built-in widget modules in termio.
+//!
+//! All callbacks are `extern "C"` functions, and thus do not accept generic
+//! `Fn` instances. This is due to a limitation of the original termio API.
+//!
+//! In this crate, terminal screen positions and sizes are represented using a
+//! tuple `(x, y): (u32, u32)`. Positions are zero-based.
+//!
+//! The `KEY_` constants describe the return values from `Keyboard::get_key()`.
+//! To create key combinations, e.g. ctrl-A, use addition, e.g. `KEY_CTRL +
+//! 'A'`.
+//!
+//! **Please be aware that to get anything on the screen, you need to call
+//! `redraw()`.**
+//!
+//! [1]: https://github.com/tomsmeding/termio
mod bindings;
mod util;
-pub mod widgets;
-
-// #[cfg(test)]
-// mod tests {
-// #[test]
-// fn it_works() {
-// assert_eq!(2 + 2, 4);
-// }
-// }
-
-// All positions are represented using a tuple (x, y): (u32, u32).
-// Positions are zero-based.
-
-pub const KEY_TAB: i32 = bindings::KEY_TAB as i32;
-pub const KEY_LF: i32 = bindings::KEY_LF as i32;
-pub const KEY_CR: i32 = bindings::KEY_CR as i32;
-pub const KEY_ESC: i32 = bindings::KEY_ESC as i32;
-pub const KEY_BACKSPACE: i32 = bindings::KEY_BACKSPACE as i32;
-
-pub const KEY_RIGHT: i32 = bindings::KEY_RIGHT as i32;
-pub const KEY_UP: i32 = bindings::KEY_UP as i32;
-pub const KEY_LEFT: i32 = bindings::KEY_LEFT as i32;
-pub const KEY_DOWN: i32 = bindings::KEY_DOWN as i32;
-pub const KEY_PAGEUP: i32 = bindings::KEY_PAGEUP as i32;
-pub const KEY_PAGEDOWN: i32 = bindings::KEY_PAGEDOWN as i32;
-pub const KEY_DELETE: i32 = bindings::KEY_DELETE as i32;
-pub const KEY_SHIFTTAB: i32 = bindings::KEY_SHIFTTAB as i32;
-
-pub const KEY_CTRL: i32 = bindings::KEY_CTRL as i32;
-pub const KEY_SHIFT: i32 = bindings::KEY_SHIFT as i32;
-pub const KEY_ALT: i32 = bindings::KEY_ALT as i32;
-pub const KEY_CTRLALT: i32 = bindings::KEY_CTRLALT as i32;
-pub const KEY_CTRLSHIFT: i32 = bindings::KEY_CTRLSHIFT as i32;
-
-#[derive(Debug, Copy, Clone)]
-pub struct Style {
- pub fg: u8, // 0-7, 9
- pub bg: u8, // 0-7, 9
- pub bold: bool,
- pub ul: bool
-}
-
-pub fn init_keyboard(nosigkeys: bool) {
- unsafe { bindings::initkeyboard(nosigkeys); }
-}
-
-pub fn end_keyboard() {
- unsafe { bindings::endkeyboard(); }
-}
-
-pub fn init_screen() {
- unsafe { bindings::initscreen(); }
-}
-
-pub fn end_screen() {
- unsafe { bindings::endscreen(); }
-}
-
-pub fn install_cl_handler(install: bool) {
- unsafe { bindings::installCLhandler(install); }
-}
-
-pub fn install_redraw_handler(handler: extern "C" fn(full_redraw: bool)) {
- unsafe { bindings::installredrawhandler(Some(handler)); }
-}
-
-pub fn clear_screen() {
- unsafe { bindings::clearscreen(); }
-}
-
-pub fn get_term_size() -> (u32, u32) {
- let sz = unsafe { bindings::gettermsize() };
- (sz.w as u32, sz.h as u32)
-}
-
-pub fn set_style(style: Style) {
- let sty = bindings::Style {
- fg: style.fg as i32,
- bg: style.bg as i32,
- bold: style.bold,
- ul: style.ul,
- };
- unsafe { bindings::setstyle(&sty as *const bindings::Style); }
-}
-
-pub fn set_fg(fg: u8) {
- unsafe { bindings::setfg(fg as i32); }
-}
-pub fn set_bg(bg: u8) {
- unsafe { bindings::setbg(bg as i32); }
-}
-
-pub fn set_bold(bold: bool) {
- unsafe { bindings::setbold(bold); }
-}
-
-pub fn set_ul(ul: bool) {
- unsafe { bindings::setul(ul); }
-}
-
-pub fn putc(c: char) {
- unsafe { bindings::tputc(c as i32); }
-}
-
-pub fn print(s: &str) {
- unsafe { bindings::tprintf(
- "%s".as_bytes().as_ptr() as *const i8,
- s.as_bytes().as_ptr() as *const i8); }
-}
-
-pub fn fill_rect(lefttop: (u32, u32), size: (u32, u32), c: char) {
- unsafe { bindings::fillrect(
- lefttop.0 as i32, lefttop.1 as i32,
- size.0 as i32, size.1 as i32,
- c as i32); }
-}
-
-pub fn redraw() {
- unsafe { bindings::redraw(); }
-}
-
-pub fn redraw_full() {
- unsafe { bindings::redrawfull(); }
-}
-
-pub fn scroll_term(lefttop: (u32, u32), size: (u32, u32), c: char) {
- unsafe { bindings::scrollterm(
- lefttop.0 as i32, lefttop.1 as i32,
- size.0 as i32, size.1 as i32,
- c as i32); }
-}
-
-pub fn get_buffer_char(pos: (u32, u32)) -> char {
- unsafe {
- char::from_u32(
- bindings::getbufferchar(pos.0 as i32, pos.1 as i32) as u32
- ).unwrap()
- }
-}
-
-pub fn move_to(pos: (u32, u32)) {
- unsafe { bindings::moveto(pos.0 as i32, pos.1 as i32); }
-}
-
-pub fn push_cursor() {
- unsafe { bindings::pushcursor(); }
-}
-
-pub fn pop_cursor() {
- unsafe { bindings::popcursor(); }
-}
-
-pub fn bel() {
- unsafe { bindings::bel(); }
-}
-
-pub fn cursor_visible(visible: bool) {
- unsafe { bindings::cursorvisible(visible); }
-}
-
-// None on EOF, otherwise a combination of the KEY_* constants
-pub fn get_key() -> io::Result<Option<i32>> {
- match unsafe { bindings::tgetkey() } {
- -2 => Err(io::Error::last_os_error()),
- -1 => Ok(None),
- value => Ok(Some(value)),
- }
-}
+mod core;
+pub mod widgets;
-pub fn get_line() -> Option<String> {
- let ptr = unsafe { bindings::tgetline() };
- if ptr.is_null() {
- None
- } else {
- unsafe { Some(util::string_from_utf8_charp(ptr)) }
- }
-}
+pub use crate::core::*;
diff --git a/src/widgets.rs b/src/widgets.rs
index d8c8e2e..fa79aab 100644
--- a/src/widgets.rs
+++ b/src/widgets.rs
@@ -1,3 +1,8 @@
+//! The built-in widgets in termio.
+//!
+//! The structures and functions for each of the widgets live in their
+//! respective submodules below.
+
pub mod log;
pub mod prompt;
pub mod menu;
diff --git a/src/widgets/log.rs b/src/widgets/log.rs
index 8bd240a..4966cc0 100644
--- a/src/widgets/log.rs
+++ b/src/widgets/log.rs
@@ -1,27 +1,44 @@
+//! Logging events in a scrolling list.
+//!
+//! Events are logged in an upwards scrolled box that forgets about the events
+//! that move off-screen. The logger may optionally add timestamps to events.
+//!
+//! To create a log widget, make a `LogBuilder`, optionally modify properties,
+//! and then use its `create` method to create a `Log` object.
+
use std::ptr;
use crate::bindings;
+use crate::core::Screen;
pub struct Log {
ptr: *mut bindings::Logwidget,
}
-pub struct LogBuilder<'a> {
+pub struct LogBuilder<'a, 'b> {
+ _screen: &'a Screen<'b>,
lefttop: (u32, u32),
size: (u32, u32),
title: Option<&'a str>,
timestamps: bool,
}
-impl<'a> LogBuilder<'a> {
- pub fn add_title<'s: 'a>(&'a mut self, title: &'s str)
- -> &'a mut LogBuilder<'a> {
+impl<'a, 'b> LogBuilder<'a, 'b> {
+ pub fn new(screen: &'a Screen<'b>, lefttop: (u32, u32), size: (u32, u32)) -> Self {
+ LogBuilder {
+ _screen: screen,
+ lefttop, size,
+ title: None,
+ timestamps: false,
+ }
+ }
+
+ pub fn add_title<'s: 'a>(&mut self, title: &'s str) -> &mut Self {
self.title = Some(title);
self
}
- pub fn set_timestamps(&'a mut self, timestamps: bool)
- -> &'a mut LogBuilder<'a> {
+ pub fn set_timestamps(&mut self, timestamps: bool) -> &mut Self {
self.timestamps = timestamps;
self
}
@@ -43,14 +60,8 @@ impl<'a> LogBuilder<'a> {
}
impl Log {
- pub fn new<'a>(lefttop: (u32, u32), size: (u32, u32)) -> LogBuilder<'a> {
- LogBuilder {
- lefttop, size,
- title: None,
- timestamps: false,
- }
- }
-
+ /// Called automatically; should only be needed if something else overwrote
+ /// the widget.
pub fn redraw(&self) {
unsafe { bindings::lgw_redraw(self.ptr); }
}
diff --git a/src/widgets/menu.rs b/src/widgets/menu.rs
index fe899e3..f90e62b 100644
--- a/src/widgets/menu.rs
+++ b/src/widgets/menu.rs
@@ -1,3 +1,9 @@
+//! A selection menu.
+//!
+//! The configuration for a menu is encapsulated in a `Data` struct, which
+//! contains some number of `Item` structs which describe the individual items
+//! to be chosen between.
+
use std::ffi::c_void;
use crate::bindings;
@@ -46,10 +52,15 @@ impl Menu {
}
}
+ /// Called automatically; should only be needed if something else overwrote
+ /// the widget.
pub fn redraw(&self) {
unsafe { bindings::menu_redraw(self.ptr); }
}
+ /// Process the given key in the context of the menu.
+ ///
+ /// The key should be a return value from `Keyboard::get_key()`.
pub fn handle_key(&mut self, key: i32) -> KeyResult {
match unsafe { bindings::menu_handlekey(self.ptr, key) } {
bindings::Menukey_MENUKEY_HANDLED => KeyResult::Handled,
diff --git a/src/widgets/prompt.rs b/src/widgets/prompt.rs
index 0690840..31c8630 100644
--- a/src/widgets/prompt.rs
+++ b/src/widgets/prompt.rs
@@ -1,21 +1,36 @@
+//! A box for getting a line of text input.
+//!
+//! To create a prompt widget, make a `PromptBuilder`, optionally modify
+//! properties, and then use its `create` method to create a `Prompt` object.
+
use std::ptr;
use crate::bindings;
+use crate::core::Screen;
use crate::util;
pub struct Prompt {
ptr: *mut bindings::Promptwidget,
}
-pub struct PromptBuilder<'a> {
+pub struct PromptBuilder<'a, 'b> {
+ _screen: &'a Screen<'b>,
lefttop: (u32, u32),
width: u32,
title: Option<&'a str>,
}
-impl<'a> PromptBuilder<'a> {
- pub fn add_title<'s: 'a>(&'a mut self, title: &'s str)
- -> &'a mut PromptBuilder<'a> {
+impl<'a, 'b> PromptBuilder<'a, 'b> {
+ pub fn new(screen: &'a Screen<'b>, lefttop: (u32, u32), width: u32) -> Self {
+ PromptBuilder {
+ _screen: screen,
+ lefttop, width,
+ title: None,
+ }
+ }
+
+ pub fn add_title<'s: 'a>(&mut self, title: &'s str)
+ -> &mut Self {
self.title = Some(title);
self
}
@@ -36,17 +51,15 @@ impl<'a> PromptBuilder<'a> {
}
impl Prompt {
- pub fn new<'a>(lefttop: (u32, u32), width: u32) -> PromptBuilder<'a> {
- PromptBuilder {
- lefttop, width,
- title: None,
- }
- }
-
+ /// Called automatically; should only be needed if something else overwrote
+ /// the widget.
pub fn redraw(&self) {
unsafe { bindings::prw_redraw(self.ptr); }
}
+ /// Input string if <enter>, None otherwise.
+ ///
+ /// The key should be a return value from `Keyboard::get_key()`.
pub fn handle_key(&mut self, key: i32) -> Option<String> {
let ptr = unsafe { bindings::prw_handlekey(self.ptr, key) };
if ptr.is_null() {
diff --git a/vendor/termio b/vendor/termio
-Subproject e2c2f93cd657ce9a40bcfd6c085328ac54e7a69
+Subproject 0f498cf54d8ecbfc81cf8b03ed2fcf3995b513f