diff --git a/src/libextra/term.rs b/src/libextra/term.rs index 691a6b4dc624..26a9e568e613 100644 --- a/src/libextra/term.rs +++ b/src/libextra/term.rs @@ -43,12 +43,20 @@ pub static color_bright_magenta: u8 = 13u8; pub static color_bright_cyan: u8 = 14u8; pub static color_bright_white: u8 = 15u8; +#[cfg(not(target_os = "win32"))] pub struct Terminal { color_supported: bool, priv out: @io::Writer, priv ti: ~TermInfo } +#[cfg(target_os = "win32")] +pub struct Terminal { + color_supported: bool, + priv out: @io::Writer, +} + +#[cfg(not(target_os = "win32"))] pub impl Terminal { pub fn new(out: @io::Writer) -> Result { let term = os::getenv("TERM"); @@ -74,19 +82,50 @@ pub impl Terminal { } fn fg(&self, color: u8) { if self.color_supported { - self.out.write(expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(), - [Number(color as int)], [], [])); + let s = expand(*self.ti.strings.find_equiv(&("setaf")).unwrap(), + [Number(color as int)], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } } } fn bg(&self, color: u8) { if self.color_supported { - self.out.write(expand(*self.ti.strings.find_equiv(&("setab")).unwrap(), - [Number(color as int)], [], [])); + let s = expand(*self.ti.strings.find_equiv(&("setab")).unwrap(), + [Number(color as int)], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } } } fn reset(&self) { if self.color_supported { - self.out.write(expand(*self.ti.strings.find_equiv(&("op")).unwrap(), [], [], [])); + let s = expand(*self.ti.strings.find_equiv(&("op")).unwrap(), [], [], []); + if s.is_ok() { + self.out.write(s.get()); + } else { + warn!(s.get_err()); + } } } } + +#[cfg(target_os = "win32")] +pub impl Terminal { + pub fn new(out: @io::Writer) -> Result { + return Ok(Terminal {out: out, color_supported: false}); + } + + fn fg(&self, color: u8) { + } + + fn bg(&self, color: u8) { + } + + fn reset(&self) { + } +} diff --git a/src/libextra/terminfo/parm.rs b/src/libextra/terminfo/parm.rs index c4cc16d058ed..aee4b4494499 100644 --- a/src/libextra/terminfo/parm.rs +++ b/src/libextra/terminfo/parm.rs @@ -27,13 +27,27 @@ enum States { IfBody } +/// Types of parameters a capability can use pub enum Param { String(~str), Char(char), Number(int) } -pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Param]) -> ~[u8] { +/** + Expand a parameterized capability + + # Arguments + * `cap` - string to expand + * `params` - vector of params for %p1 etc + * `sta` - vector of params corresponding to static variables + * `dyn` - vector of params corresponding to stativ variables + + To be compatible with ncurses, `sta` and `dyn` should be the same between calls to `expand` for + multiple capabilities for the same terminal. + */ +pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Param]) + -> Result<~[u8], ~str> { assert!(cap.len() != 0, "expanding an empty capability makes no sense"); assert!(params.len() <= 9, "only 9 parameters are supported by capability strings"); @@ -68,15 +82,15 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa '%' => { output.push(cap[i]); state = Nothing }, 'c' => match stack.pop() { Char(c) => output.push(c as u8), - _ => fail!("a non-char was used with %c") + _ => return Err(~"a non-char was used with %c") }, 's' => match stack.pop() { String(s) => output.push_all(s.to_bytes()), - _ => fail!("a non-str was used with %s") + _ => return Err(~"a non-str was used with %s") }, 'd' => match stack.pop() { Number(x) => output.push_all(x.to_str().to_bytes()), - _ => fail!("a non-number was used with %d") + _ => return Err(~"a non-number was used with %d") }, 'p' => state = PushParam, 'P' => state = SetVar, @@ -85,52 +99,52 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa '{' => state = IntConstant, 'l' => match stack.pop() { String(s) => stack.push(Number(s.len() as int)), - _ => fail!("a non-str was used with %l") + _ => return Err(~"a non-str was used with %l") }, '+' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x + y)), - (_, _) => fail!("non-numbers on stack with +") + (_, _) => return Err(~"non-numbers on stack with +") }, '-' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x - y)), - (_, _) => fail!("non-numbers on stack with -") + (_, _) => return Err(~"non-numbers on stack with -") }, '*' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x * y)), - (_, _) => fail!("non-numbers on stack with *") + (_, _) => return Err(~"non-numbers on stack with *") }, '/' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x / y)), - (_, _) => fail!("non-numbers on stack with /") + (_, _) => return Err(~"non-numbers on stack with /") }, 'm' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x % y)), - (_, _) => fail!("non-numbers on stack with %") + (_, _) => return Err(~"non-numbers on stack with %") }, '&' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x & y)), - (_, _) => fail!("non-numbers on stack with &") + (_, _) => return Err(~"non-numbers on stack with &") }, '|' => match (stack.pop(), stack.pop()) { (Number(x), Number(y)) => stack.push(Number(x | y)), - (_, _) => fail!("non-numbers on stack with |") + (_, _) => return Err(~"non-numbers on stack with |") }, - 'A' => fail!("logical operations unimplemented"), - 'O' => fail!("logical operations unimplemented"), - '!' => fail!("logical operations unimplemented"), + 'A' => return Err(~"logical operations unimplemented"), + 'O' => return Err(~"logical operations unimplemented"), + '!' => return Err(~"logical operations unimplemented"), '~' => match stack.pop() { Number(x) => stack.push(Number(!x)), - _ => fail!("non-number on stack with %~") + _ => return Err(~"non-number on stack with %~") }, 'i' => match (copy params[0], copy params[1]) { (Number(x), Number(y)) => { params[0] = Number(x + 1); params[1] = Number(y + 1); }, - (_, _) => fail!("first two params not numbers with %i") + (_, _) => return Err(~"first two params not numbers with %i") }, - '?' => state = fail!("if expressions unimplemented"), - _ => fail!("unrecognized format option %c", cur) + '?' => state = return Err(fmt!("if expressions unimplemented (%?)", cap)), + _ => return Err(fmt!("unrecognized format option %c", cur)) } }, PushParam => { @@ -145,7 +159,7 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa let idx = (cur as u8) - ('a' as u8); dyn[idx] = stack.pop(); } else { - fail!("bad variable name in %P"); + return Err(~"bad variable name in %P"); } }, GetVar => { @@ -156,7 +170,7 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa let idx = (cur as u8) - ('a' as u8); stack.push(copy dyn[idx]); } else { - fail!("bad variable name in %g"); + return Err(~"bad variable name in %g"); } }, CharConstant => { @@ -174,14 +188,14 @@ pub fn expand(cap: &[u8], params: &mut [Param], sta: &mut [Param], dyn: &mut [Pa intstate.push(cur as u8); old_state = Nothing; } - _ => fail!("unimplemented state") + _ => return Err(~"unimplemented state") } if state == old_state { state = Nothing; } i += 1; } - output + Ok(output) } #[cfg(test)] diff --git a/src/libextra/terminfo/parser/compiled.rs b/src/libextra/terminfo/parser/compiled.rs index 2d5979c26345..e63ec1ab5f99 100644 --- a/src/libextra/terminfo/parser/compiled.rs +++ b/src/libextra/terminfo/parser/compiled.rs @@ -1,6 +1,4 @@ /// ncurses-compatible compiled terminfo format parsing (term(5)) -/// -/// does *not* handle obsolete termcap capabilities! use core::prelude::*; @@ -150,6 +148,7 @@ pub static stringnames: &'static[&'static str] = &'static[ "cbt", "_", "cr", "cs "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu", "box1"]; +/// Parse a compiled terminfo entry, using long capability names if `longnames` is true pub fn parse(file: @Reader, longnames: bool) -> Result<~TermInfo, ~str> { let bnames, snames, nnames; diff --git a/src/libextra/terminfo/searcher.rs b/src/libextra/terminfo/searcher.rs index f440ce7c9eb4..c2ff8a46ed45 100644 --- a/src/libextra/terminfo/searcher.rs +++ b/src/libextra/terminfo/searcher.rs @@ -12,10 +12,10 @@ /// Does not support hashed database, only filesystem! use core::prelude::*; -use core::{os, str, vec}; +use core::{os, str}; use core::os::getenv; use core::io::{file_reader, Reader}; -use path = core::path::PosixPath; +use path = core::path::Path; /// Return path to database entry for `term` pub fn get_dbpath_for_term(term: &str) -> Option<~path> { diff --git a/src/libextra/terminfo/terminfo.rs b/src/libextra/terminfo/terminfo.rs index 1c7f107e4fb6..141a5b6bf7f9 100644 --- a/src/libextra/terminfo/terminfo.rs +++ b/src/libextra/terminfo/terminfo.rs @@ -10,10 +10,15 @@ use core::hashmap::HashMap; +/// A parsed terminfo entry. pub struct TermInfo { + /// Names for the terminal names: ~[~str], + /// Map of capability name to boolean value bools: HashMap<~str, bool>, + /// Map of capability name to numeric value numbers: HashMap<~str, u16>, + /// Map of capability name to raw (unexpanded) string strings: HashMap<~str, ~[u8]> } diff --git a/src/librustpkg/util.rs b/src/librustpkg/util.rs index 213ac4f22e26..8071546136f0 100644 --- a/src/librustpkg/util.rs +++ b/src/librustpkg/util.rs @@ -280,7 +280,7 @@ pub fn need_dir(s: &Path) { fn pretty_message<'a>(msg: &'a str, prefix: &'a str, color: u8, out: @io::Writer) { let term = term::Terminal::new(out); match term { - Ok(ref t) if t.color_supported => { + Ok(ref t) => { t.fg(color); out.write_str(prefix); t.reset(); diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index 094082f41e79..fa4a74b89545 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -191,7 +191,7 @@ fn diagnosticcolor(lvl: level) -> u8 { } fn print_diagnostic(topic: &str, lvl: level, msg: &str) { - let term = term::Terminal::new(io::stderr()); + let t = term::Terminal::new(io::stderr()); let stderr = io::stderr(); @@ -199,18 +199,18 @@ fn print_diagnostic(topic: &str, lvl: level, msg: &str) { stderr.write_str(fmt!("%s ", topic)); } - match term { - Ok(t) => { + match t { + Ok(term) => { if stderr.get_type() == io::Screen { - t.fg(diagnosticcolor(lvl)); + term.fg(diagnosticcolor(lvl)); stderr.write_str(fmt!("%s: ", diagnosticstr(lvl))); - t.reset(); + term.reset(); stderr.write_str(fmt!("%s\n", msg)); + } else { + stderr.write_str(fmt!("%s: %s\n", diagnosticstr(lvl), msg)); } - } - Err(_) => { - stderr.write_str(fmt!("%s: %s\n", diagnosticstr(lvl), msg)); - } + }, + _ => stderr.write_str(fmt!("%s: %s\n", diagnosticstr(lvl), msg)) } }