From 33d773ff5a8154bb18c93c48b5a4607f2882bcdf Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Fri, 5 Apr 2013 00:51:54 -0500 Subject: handle optional terminal capabilities slightly better --- src/hexes.rs | 25 +++++++++++++++-------- src/info.rs | 65 +++++++++++++++++++++++++++++++++++++++++++++++------------- test/tput.rs | 6 +++++- 3 files changed, 73 insertions(+), 23 deletions(-) diff --git a/src/hexes.rs b/src/hexes.rs index b1fed14..4de2f12 100644 --- a/src/hexes.rs +++ b/src/hexes.rs @@ -39,10 +39,15 @@ pub fn Term () -> Term { cbreak(); echo(false); - print(info::keypad_xmit()); - print(info::enter_ca_mode()); - print(info::exit_attribute_mode()); - print(info::cursor_normal()); + // XXX need to come up with a better way to handle optional caps + // should be able to use something like has_keypad_xmit or something + for ["smkx", "smcup", "sgr0", "cnorm"].each() |&cap| { + match info::escape(cap) { + Some(e) => print(e), + None => (), // not a big deal if these don't exist + } + } + print(info::clear_screen()); Term { r: Reader(), w: Writer() } @@ -162,10 +167,14 @@ impl Term { impl Drop for Term { fn finalize (&self) { - print(info::keypad_local()); - print(info::exit_ca_mode()); - print(info::exit_attribute_mode()); - print(info::cursor_normal()); + // XXX need to come up with a better way to handle optional caps + // should be able to use something like has_keypad_xmit or something + for ["rmkx", "rmcup", "sgr0", "cnorm"].each() |&cap| { + match info::escape(cap) { + Some(e) => print(e), + None => (), // not a big deal if these don't exist + } + } // XXX should really restore the previous termios mode... cooked(); diff --git a/src/info.rs b/src/info.rs index 5504de1..e4aa546 100644 --- a/src/info.rs +++ b/src/info.rs @@ -26,14 +26,33 @@ pub fn init () { macro_rules! def_escape( ($name:ident -> $escape:expr) => ( - pub fn $name () -> ~str { escape($escape) } + pub fn $name () -> ~str { + let attr = $escape; + match escape(attr) { + Some(e) => e, + None => fail!(fmt!("%s is not supported on this terminal", + attr)), + } + } ); ($name:ident -> $escape:expr, $ty1:ident) => ( - pub fn $name (p1: $ty1) -> ~str { escape1($escape, p1 as int) } + pub fn $name (p1: $ty1) -> ~str { + let attr = $escape; + match escape1(attr, p1 as int) { + Some(e) => e, + None => fail!(fmt!("%s is not supported on this terminal", + attr)), + } + } ); ($name:ident -> $escape:expr, $ty1:ident, $ty2:ident) => ( pub fn $name (p1: $ty1, p2: $ty2) -> ~str { - escape2($escape, p1 as int, p2 as int) + let attr = $escape; + match escape2(attr, p1 as int, p2 as int) { + Some(e) => e, + None => fail!(fmt!("%s is not supported on this terminal", + attr)), + } } ); ) @@ -131,14 +150,24 @@ def_escape!(key_f12 -> "kf12") /// The terminal escape generated by the F<`n`> key. pub fn key_f (n: uint) -> ~str { - escape(fmt!("kf%?", n)) + let attr = fmt!("kf%?", n); + match escape(attr) { + Some(e) => e, + None => fail!(fmt!("%s is not supported on this terminal", attr)), + } } /// The terminal escape corresponding to the `name` terminfo capability. -pub fn escape (name: &str) -> ~str { +pub fn escape (name: &str) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { - str::raw::from_c_str(tigetstr(c_name)) + let e = tigetstr(c_name); + if e == ptr::null() { + None + } + else { + Some(str::raw::from_c_str(e)) + } } } } @@ -148,10 +177,16 @@ pub fn escape (name: &str) -> ~str { * * This capability must take one parameter, which should be passed as `p1`. */ -pub fn escape1 (name: &str, p1: int) -> ~str { +pub fn escape1 (name: &str, p1: int) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { - str::raw::from_c_str(tiparm1(tigetstr(c_name), p1)) + let e = tigetstr(c_name); + if e == ptr::null() { + None + } + else { + Some(str::raw::from_c_str(tiparm1(e, p1))) + } } } } @@ -162,10 +197,16 @@ pub fn escape1 (name: &str, p1: int) -> ~str { * This capability must take two parameters, which should be passed as `p1` * and `p2`. */ -pub fn escape2 (name: &str, p1: int, p2: int) -> ~str { +pub fn escape2 (name: &str, p1: int, p2: int) -> Option<~str> { do str::as_c_str(name) |c_name| { unsafe { - str::raw::from_c_str(tiparm2(tigetstr(c_name), p1, p2)) + let e = tigetstr(c_name); + if e == ptr::null() { + None + } + else { + Some(str::raw::from_c_str(tiparm2(e, p1, p2))) + } } } } @@ -176,10 +217,6 @@ unsafe fn tigetstr (name: *c_char) -> *c_char { fail!(fmt!("%s is not a terminal capability", unsafe { str::raw::from_c_str(name) })); } - else if c_out == ptr::null() { - fail!(fmt!("The current terminal doesn't support %s", - unsafe { str::raw::from_c_str(name) })); - } c_out } diff --git a/test/tput.rs b/test/tput.rs index b2cfc59..3fe9ea1 100644 --- a/test/tput.rs +++ b/test/tput.rs @@ -6,5 +6,9 @@ fn main () { } term::info::init(); - print(term::info::escape(os::args()[1])); + let attr: &str = os::args()[1]; + let escape = term::info::escape(attr).expect( + fmt!("%s is not supported on this terminal", attr) + ); + print(escape); } -- cgit v1.2.3-54-g00ecf