term-0.7.0/.cargo_vcs_info.json0000644000000001120000000000000120000ustar { "git": { "sha1": "8d1259b21b25b00974122f6660ea8b9866a4dae6" } } term-0.7.0/.circleci/config.yml000064400000000000000000000006240000000000000144010ustar 00000000000000version: 2.1 jobs: test: parameters: version: type: string default: "latest" docker: - image: cimg/rust:<< parameters.version >> steps: - checkout - run: cargo test --verbose workflows: version: 2 test: jobs: - test: matrix: parameters: version: - "1.36" - "1.49" term-0.7.0/.gitignore000064400000000000000000000000240000000000000125400ustar 00000000000000/target /Cargo.lock term-0.7.0/Cargo.toml0000644000000024460000000000000100120ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies # # If you believe there's an error in this file please file an # issue against the rust-lang/cargo repository. If you're # editing this file be aware that the upstream Cargo.toml # will likely look very different (and much more reasonable) [package] edition = "2018" name = "term" version = "0.7.0" authors = ["The Rust Project Developers", "Steven Allen"] exclude = ["/scripts/*", "/.travis.yml", "/appveyor.yml"] description = "A terminal formatting library\n" homepage = "https://github.com/Stebalien/term" documentation = "https://docs.rs/term/" readme = "README.md" categories = ["command-line-interface"] license = "MIT/Apache-2.0" repository = "https://github.com/Stebalien/term" [dependencies.dirs-next] version = "2" [features] default = [] [target."cfg(windows)".dependencies.rustversion] version = "1" [target."cfg(windows)".dependencies.winapi] version = "0.3" features = ["consoleapi", "wincon", "handleapi", "fileapi"] [badges.appveyor] repository = "Stebalien/term" [badges.circle-ci] repository = "Stebalien/term" term-0.7.0/Cargo.toml.orig000064400000000000000000000013620000000000000134450ustar 00000000000000[package] name = "term" version = "0.7.0" authors = ["The Rust Project Developers", "Steven Allen"] license = "MIT/Apache-2.0" readme = "README.md" repository = "https://github.com/Stebalien/term" homepage = "https://github.com/Stebalien/term" documentation = "https://docs.rs/term/" description = """ A terminal formatting library """ categories = ["command-line-interface"] exclude = ["/scripts/*", "/.travis.yml", "/appveyor.yml"] edition = "2018" [badges] circle-ci = { repository = "Stebalien/term" } appveyor = { repository = "Stebalien/term" } [dependencies] dirs-next = "2" [target.'cfg(windows)'.dependencies] winapi = { version = "0.3", features = ["consoleapi", "wincon", "handleapi", "fileapi"] } rustversion = "1" [features] default=[] term-0.7.0/LICENSE-APACHE000064400000000000000000000251370000000000000125100ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. term-0.7.0/LICENSE-MIT000064400000000000000000000020570000000000000122140ustar 00000000000000Copyright (c) 2019 The Rust Project Developers Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. term-0.7.0/README.md000064400000000000000000000017670000000000000120460ustar 00000000000000term ==== A Rust library for terminfo parsing and terminal colors. [![CircleCI](https://circleci.com/gh/Stebalien/term.svg?style=svg)](https://circleci.com/gh/Stebalien/term) [![AppVeyor](https://ci.appveyor.com/api/projects/status/2duvop23k4n3owyt?svg=true)](https://ci.appveyor.com/project/Stebalien/term) [Documentation](https://docs.rs/term/) ## MSRV 1.36 - the minimum version testable on circleci. ## Usage Add this to your `Cargo.toml`: ```toml [dependencies] term = "*" ``` ## Packaging and Distributing For all terminals but windows consoles, this library depends on a non-hashed (for now) terminfo database being present. For example, on Debian derivitives, you should depend on ncurses-term; on Arch Linux, you depend on ncurses; and on MinGW, you should depend on mingw32-terminfo. Unfortunately, if you're using a non-windows console on Windows (e.g. MinGW, Cygwin, Git Bash), you'll need to set the TERMINFO environment variable to point to the directory containing the terminfo database. term-0.7.0/rustfmt.toml000064400000000000000000000001270000000000000131550ustar 00000000000000wrap_match_arms = true struct_lit_multiline_style = "ForceMulti" wrap_comments = false term-0.7.0/src/lib.rs000064400000000000000000000320230000000000000124570ustar 00000000000000// Copyright 2013-2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Terminal formatting library. //! //! This crate provides the `Terminal` trait, which abstracts over an [ANSI //! Terminal][ansi] to provide color printing, among other things. There are two //! implementations, the `TerminfoTerminal`, which uses control characters from //! a [terminfo][ti] database, and `WinConsole`, which uses the [Win32 Console //! API][win]. //! //! # Usage //! //! This crate is [on crates.io](https://crates.io/crates/term) and can be //! used by adding `term` to the dependencies in your project's `Cargo.toml`. //! //! ```toml //! [dependencies] //! //! term = "*" //! ``` //! //! and this to your crate root: //! //! ```rust //! extern crate term; //! ``` //! //! # Examples //! //! ```no_run //! extern crate term; //! use std::io::prelude::*; //! //! fn main() { //! let mut t = term::stdout().unwrap(); //! //! t.fg(term::color::GREEN).unwrap(); //! write!(t, "hello, ").unwrap(); //! //! t.fg(term::color::RED).unwrap(); //! writeln!(t, "world!").unwrap(); //! //! t.reset().unwrap(); //! } //! ``` //! //! [ansi]: https://en.wikipedia.org/wiki/ANSI_escape_code //! [win]: http://msdn.microsoft.com/en-us/library/windows/desktop/ms682010%28v=vs.85%29.aspx //! [ti]: https://en.wikipedia.org/wiki/Terminfo #![doc( html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", html_favicon_url = "https://doc.rust-lang.org/favicon.ico", html_root_url = "https://stebalien.github.io/doc/term/term/", test(attr(deny(warnings))) )] #![deny(missing_docs)] #![cfg_attr(test, deny(warnings))] #![allow(clippy::redundant_field_names)] use std::io::prelude::*; pub use crate::terminfo::TerminfoTerminal; #[cfg(windows)] pub use win::{WinConsole, WinConsoleInfo}; use std::io::{self, Stderr, Stdout}; pub mod terminfo; #[cfg(windows)] mod win; /// Alias for stdout terminals. pub type StdoutTerminal = dyn Terminal + Send; /// Alias for stderr terminals. pub type StderrTerminal = dyn Terminal + Send; #[cfg(not(windows))] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. pub fn stdout() -> Option> { TerminfoTerminal::new(io::stdout()).map(|t| Box::new(t) as Box) } #[cfg(windows)] /// Return a Terminal wrapping stdout, or None if a terminal couldn't be /// opened. pub fn stdout() -> Option> { TerminfoTerminal::new(io::stdout()) .map(|t| Box::new(t) as Box) .or_else(|| { WinConsole::new(io::stdout()) .ok() .map(|t| Box::new(t) as Box) }) } #[cfg(not(windows))] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. pub fn stderr() -> Option> { TerminfoTerminal::new(io::stderr()).map(|t| Box::new(t) as Box) } #[cfg(windows)] /// Return a Terminal wrapping stderr, or None if a terminal couldn't be /// opened. pub fn stderr() -> Option> { TerminfoTerminal::new(io::stderr()) .map(|t| Box::new(t) as Box) .or_else(|| { WinConsole::new(io::stderr()) .ok() .map(|t| Box::new(t) as Box) }) } /// Terminal color definitions #[allow(missing_docs)] pub mod color { /// Number for a terminal color pub type Color = u32; pub const BLACK: Color = 0; pub const RED: Color = 1; pub const GREEN: Color = 2; pub const YELLOW: Color = 3; pub const BLUE: Color = 4; pub const MAGENTA: Color = 5; pub const CYAN: Color = 6; pub const WHITE: Color = 7; pub const BRIGHT_BLACK: Color = 8; pub const BRIGHT_RED: Color = 9; pub const BRIGHT_GREEN: Color = 10; pub const BRIGHT_YELLOW: Color = 11; pub const BRIGHT_BLUE: Color = 12; pub const BRIGHT_MAGENTA: Color = 13; pub const BRIGHT_CYAN: Color = 14; pub const BRIGHT_WHITE: Color = 15; } /// Terminal attributes for use with term.attr(). /// /// Most attributes can only be turned on and must be turned off with term.reset(). /// The ones that can be turned off explicitly take a boolean value. /// Color is also represented as an attribute for convenience. #[derive(Debug, PartialEq, Hash, Eq, Copy, Clone)] pub enum Attr { /// Bold (or possibly bright) mode Bold, /// Dim mode, also called faint or half-bright. Often not supported Dim, /// Italics mode. Often not supported Italic(bool), /// Underline mode Underline(bool), /// Blink mode Blink, /// Standout mode. Often implemented as Reverse, sometimes coupled with Bold Standout(bool), /// Reverse mode, inverts the foreground and background colors Reverse, /// Secure mode, also called invis mode. Hides the printed text Secure, /// Convenience attribute to set the foreground color ForegroundColor(color::Color), /// Convenience attribute to set the background color BackgroundColor(color::Color), } /// An error arising from interacting with the terminal. #[derive(Debug)] pub enum Error { /// Indicates an error from any underlying IO Io(io::Error), /// Indicates an error during terminfo parsing TerminfoParsing(terminfo::Error), /// Indicates an error expanding a parameterized string from the terminfo database ParameterizedExpansion(terminfo::parm::Error), /// Indicates that the terminal does not support the requested operation. NotSupported, /// Indicates that the `TERM` environment variable was unset, and thus we were unable to detect /// which terminal we should be using. TermUnset, /// Indicates that we were unable to find a terminfo entry for the requested terminal. TerminfoEntryNotFound, /// Indicates that the cursor could not be moved to the requested position. CursorDestinationInvalid, /// Indicates that the terminal does not support displaying the requested color. /// /// This is like `NotSupported`, but more specific. ColorOutOfRange, #[doc(hidden)] /// Please don't match against this - if you do, we can't promise we won't break your crate /// with a semver-compliant version bump. __Nonexhaustive, } // manually implemented because std::io::Error does not implement Eq/PartialEq impl std::cmp::PartialEq for Error { fn eq(&self, other: &Error) -> bool { use crate::Error::*; match *self { Io(_) => false, TerminfoParsing(ref inner1) => match *other { TerminfoParsing(ref inner2) => inner1 == inner2, _ => false, }, ParameterizedExpansion(ref inner1) => match *other { ParameterizedExpansion(ref inner2) => inner1 == inner2, _ => false, }, NotSupported => match *other { NotSupported => true, _ => false, }, TermUnset => match *other { TermUnset => true, _ => false, }, TerminfoEntryNotFound => match *other { TerminfoEntryNotFound => true, _ => false, }, CursorDestinationInvalid => match *other { CursorDestinationInvalid => true, _ => false, }, ColorOutOfRange => match *other { ColorOutOfRange => true, _ => false, }, __Nonexhaustive => match *other { __Nonexhaustive => true, _ => false, }, } } } /// The canonical `Result` type using this crate's Error type. pub type Result = std::result::Result; impl std::fmt::Display for Error { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { use crate::Error::*; match *self { Io(ref io) => io.fmt(f), TerminfoParsing(ref e) => e.fmt(f), ParameterizedExpansion(ref e) => e.fmt(f), NotSupported => f.write_str("operation not supported by the terminal"), TermUnset => { f.write_str("TERM environment variable unset, unable to detect a terminal") } TerminfoEntryNotFound => { f.write_str("could not find a terminfo entry for this terminal") } CursorDestinationInvalid => f.write_str("could not move cursor to requested position"), ColorOutOfRange => f.write_str("color not supported by the terminal"), __Nonexhaustive => f.write_str("placeholder variant that shouldn't be used"), } } } impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { Error::Io(ref io) => Some(io), Error::TerminfoParsing(ref e) => Some(e), Error::ParameterizedExpansion(ref e) => Some(e), _ => None, } } } impl From for io::Error { fn from(err: Error) -> io::Error { let kind = match err { Error::Io(ref e) => e.kind(), _ => io::ErrorKind::Other, }; io::Error::new(kind, err) } } impl std::convert::From for Error { fn from(val: io::Error) -> Self { Error::Io(val) } } impl std::convert::From for Error { fn from(val: terminfo::Error) -> Self { Error::TerminfoParsing(val) } } impl std::convert::From for Error { fn from(val: terminfo::parm::Error) -> Self { Error::ParameterizedExpansion(val) } } /// A terminal with similar capabilities to an ANSI Terminal /// (foreground/background colors etc). pub trait Terminal: Write { /// The terminal's output writer type. type Output: Write; /// Sets the foreground color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, /// the corresponding normal color will be used instead. /// /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there /// was an error. fn fg(&mut self, color: color::Color) -> Result<()>; /// Sets the background color to the given color. /// /// If the color is a bright color, but the terminal only supports 8 colors, /// the corresponding normal color will be used instead. /// /// Returns `Ok(())` if the color change code was sent to the terminal, or `Err(e)` if there /// was an error. fn bg(&mut self, color: color::Color) -> Result<()>; /// Sets the given terminal attribute, if supported. Returns `Ok(())` if the attribute is /// supported and was sent to the terminal, or `Err(e)` if there was an error or the attribute /// wasn't supported. fn attr(&mut self, attr: Attr) -> Result<()>; /// Returns whether the given terminal attribute is supported. fn supports_attr(&self, attr: Attr) -> bool; /// Resets all terminal attributes and colors to their defaults. /// /// Returns `Ok(())` if the reset code was printed, or `Err(e)` if there was an error. /// /// *Note: This does not flush.* /// /// That means the reset command may get buffered so, if you aren't planning on doing anything /// else that might flush stdout's buffer (e.g. writing a line of text), you should flush after /// calling reset. fn reset(&mut self) -> Result<()>; /// Returns true if reset is supported. fn supports_reset(&self) -> bool; /// Returns true if color is fully supported. /// /// If this function returns `true`, `bg`, `fg`, and `reset` will never /// return `Err(Error::NotSupported)`. fn supports_color(&self) -> bool; /// Moves the cursor up one line. /// /// Returns `Ok(())` if the cursor movement code was printed, or `Err(e)` if there was an /// error. fn cursor_up(&mut self) -> Result<()>; /// Deletes the text from the cursor location to the end of the line. /// /// Returns `Ok(())` if the deletion code was printed, or `Err(e)` if there was an error. fn delete_line(&mut self) -> Result<()>; /// Moves the cursor to the left edge of the current line. /// /// Returns `Ok(true)` if the deletion code was printed, or `Err(e)` if there was an error. fn carriage_return(&mut self) -> Result<()>; /// Gets an immutable reference to the stream inside fn get_ref(&self) -> &Self::Output; /// Gets a mutable reference to the stream inside fn get_mut(&mut self) -> &mut Self::Output; /// Returns the contained stream, destroying the `Terminal` fn into_inner(self) -> Self::Output where Self: Sized; } term-0.7.0/src/terminfo/mod.rs000064400000000000000000000312510000000000000143150ustar 00000000000000// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Terminfo database interface. use std::collections::HashMap; use std::env; use std::fs::File; use std::io; use std::io::prelude::*; use std::io::BufReader; use std::path::Path; #[cfg(windows)] use crate::win; use self::parm::{expand, Param, Variables}; use self::parser::compiled::parse; use self::searcher::get_dbpath_for_term; use self::Error::*; use crate::color; use crate::Attr; use crate::Result; use crate::Terminal; /// Returns true if the named terminal supports basic ANSI escape codes. fn is_ansi(name: &str) -> bool { // SORTED! We binary search this. static ANSI_TERM_PREFIX: &[&str] = &[ "Eterm", "ansi", "eterm", "iterm", "konsole", "linux", "mrxvt", "msyscon", "rxvt", "screen", "tmux", "xterm", ]; match ANSI_TERM_PREFIX.binary_search(&name) { Ok(_) => true, Err(0) => false, Err(idx) => name.starts_with(ANSI_TERM_PREFIX[idx - 1]), } } /// A parsed terminfo database entry. #[derive(Debug, Clone)] pub struct TermInfo { /// Names for the terminal pub names: Vec, /// Map of capability name to boolean value pub bools: HashMap<&'static str, bool>, /// Map of capability name to numeric value pub numbers: HashMap<&'static str, u32>, /// Map of capability name to raw (unexpanded) string pub strings: HashMap<&'static str, Vec>, } impl TermInfo { /// Create a `TermInfo` based on current environment. pub fn from_env() -> Result { let term_var = env::var("TERM").ok(); let term_name = term_var.as_ref().map(|s| &**s).or_else(|| { env::var("MSYSCON").ok().and_then(|s| { if s == "mintty.exe" { Some("msyscon") } else { None } }) }); #[cfg(windows)] { if term_name.is_none() && win::supports_ansi() { // Microsoft people seem to be fine with pretending to be xterm: // https://github.com/Microsoft/WSL/issues/1446 // The basic ANSI fallback terminal will be uses. return TermInfo::from_name("xterm"); } } if let Some(term_name) = term_name { TermInfo::from_name(term_name) } else { Err(crate::Error::TermUnset) } } /// Create a `TermInfo` for the named terminal. pub fn from_name(name: &str) -> Result { if let Some(path) = get_dbpath_for_term(name) { match TermInfo::from_path(&path) { Ok(term) => return Ok(term), // Skip IO Errors (e.g., permission denied). Err(crate::Error::Io(_)) => {} // Don't ignore malformed terminfo databases. Err(e) => return Err(e), } } // Basic ANSI fallback terminal. if is_ansi(name) { let mut strings = HashMap::new(); strings.insert("sgr0", b"\x1B[0m".to_vec()); strings.insert("bold", b"\x1B[1m".to_vec()); strings.insert("setaf", b"\x1B[3%p1%dm".to_vec()); strings.insert("setab", b"\x1B[4%p1%dm".to_vec()); let mut numbers = HashMap::new(); numbers.insert("colors", 8); Ok(TermInfo { names: vec![name.to_owned()], bools: HashMap::new(), numbers: numbers, strings: strings, }) } else { Err(crate::Error::TerminfoEntryNotFound) } } /// Parse the given `TermInfo`. pub fn from_path>(path: P) -> Result { Self::_from_path(path.as_ref()) } // Keep the metadata small // (That is, this uses a &Path so that this function need not be instantiated // for every type // which implements AsRef. One day, if/when rustc is a bit smarter, it // might do this for // us. Alas. ) fn _from_path(path: &Path) -> Result { let file = File::open(path).map_err(crate::Error::Io)?; let mut reader = BufReader::new(file); parse(&mut reader, false) } /// Retrieve a capability `cmd` and expand it with `params`, writing result to `out`. pub fn apply_cap(&self, cmd: &str, params: &[Param], out: &mut dyn io::Write) -> Result<()> { match self.strings.get(cmd) { Some(cmd) => match expand(cmd, params, &mut Variables::new()) { Ok(s) => { out.write_all(&s)?; Ok(()) } Err(e) => Err(e.into()), }, None => Err(crate::Error::NotSupported), } } /// Write the reset string to `out`. pub fn reset(&self, out: &mut dyn io::Write) -> Result<()> { // are there any terminals that have color/attrs and not sgr0? // Try falling back to sgr, then op let cmd = match [ ("sgr0", &[] as &[Param]), ("sgr", &[Param::Number(0)]), ("op", &[]), ] .iter() .filter_map(|&(cap, params)| self.strings.get(cap).map(|c| (c, params))) .next() { Some((op, params)) => match expand(op, params, &mut Variables::new()) { Ok(cmd) => cmd, Err(e) => return Err(e.into()), }, None => return Err(crate::Error::NotSupported), }; out.write_all(&cmd)?; Ok(()) } } #[derive(Debug, Eq, PartialEq)] /// An error from parsing a terminfo entry pub enum Error { /// The "magic" number at the start of the file was wrong. /// /// It should be `0x11A` (16bit numbers) or `0x21e` (32bit numbers) BadMagic(u16), /// The names in the file were not valid UTF-8. /// /// In theory these should only be ASCII, but to work with the Rust `str` type, we treat them /// as UTF-8. This is valid, except when a terminfo file decides to be invalid. This hasn't /// been encountered in the wild. NotUtf8(::std::str::Utf8Error), /// The names section of the file was empty ShortNames, /// More boolean parameters are present in the file than this crate knows how to interpret. TooManyBools, /// More number parameters are present in the file than this crate knows how to interpret. TooManyNumbers, /// More string parameters are present in the file than this crate knows how to interpret. TooManyStrings, /// The length of some field was not >= -1. InvalidLength, /// The names table was missing a trailing null terminator. NamesMissingNull, /// The strings table was missing a trailing null terminator. StringsMissingNull, } impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { match *self { BadMagic(v) => write!(f, "bad magic number {:x} in terminfo header", v), ShortNames => f.write_str("no names exposed, need at least one"), TooManyBools => f.write_str("more boolean properties than libterm knows about"), TooManyNumbers => f.write_str("more number properties than libterm knows about"), TooManyStrings => f.write_str("more string properties than libterm knows about"), InvalidLength => f.write_str("invalid length field value, must be >= -1"), NotUtf8(ref e) => e.fmt(f), NamesMissingNull => f.write_str("names table missing NUL terminator"), StringsMissingNull => f.write_str("string table missing NUL terminator"), } } } impl ::std::convert::From<::std::string::FromUtf8Error> for Error { fn from(v: ::std::string::FromUtf8Error) -> Self { NotUtf8(v.utf8_error()) } } impl ::std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match *self { NotUtf8(ref e) => Some(e), _ => None, } } } pub mod searcher; /// `TermInfo` format parsing. pub mod parser { //! ncurses-compatible compiled terminfo format parsing (term(5)) pub mod compiled; mod names; } pub mod parm; fn cap_for_attr(attr: Attr) -> &'static str { match attr { Attr::Bold => "bold", Attr::Dim => "dim", Attr::Italic(true) => "sitm", Attr::Italic(false) => "ritm", Attr::Underline(true) => "smul", Attr::Underline(false) => "rmul", Attr::Blink => "blink", Attr::Standout(true) => "smso", Attr::Standout(false) => "rmso", Attr::Reverse => "rev", Attr::Secure => "invis", Attr::ForegroundColor(_) => "setaf", Attr::BackgroundColor(_) => "setab", } } /// A Terminal that knows how many colors it supports, with a reference to its /// parsed Terminfo database record. #[derive(Clone, Debug)] pub struct TerminfoTerminal { num_colors: u32, out: T, ti: TermInfo, } impl Terminal for TerminfoTerminal { type Output = T; fn fg(&mut self, color: color::Color) -> Result<()> { let color = self.dim_if_necessary(color); if self.num_colors > color { return self .ti .apply_cap("setaf", &[Param::Number(color as i32)], &mut self.out); } Err(crate::Error::ColorOutOfRange) } fn bg(&mut self, color: color::Color) -> Result<()> { let color = self.dim_if_necessary(color); if self.num_colors > color { return self .ti .apply_cap("setab", &[Param::Number(color as i32)], &mut self.out); } Err(crate::Error::ColorOutOfRange) } fn attr(&mut self, attr: Attr) -> Result<()> { match attr { Attr::ForegroundColor(c) => self.fg(c), Attr::BackgroundColor(c) => self.bg(c), _ => self.ti.apply_cap(cap_for_attr(attr), &[], &mut self.out), } } fn supports_attr(&self, attr: Attr) -> bool { match attr { Attr::ForegroundColor(_) | Attr::BackgroundColor(_) => self.num_colors > 0, _ => { let cap = cap_for_attr(attr); self.ti.strings.get(cap).is_some() } } } fn reset(&mut self) -> Result<()> { self.ti.reset(&mut self.out) } fn supports_reset(&self) -> bool { ["sgr0", "sgr", "op"] .iter() .any(|&cap| self.ti.strings.get(cap).is_some()) } fn supports_color(&self) -> bool { self.num_colors > 0 && self.supports_reset() } fn cursor_up(&mut self) -> Result<()> { self.ti.apply_cap("cuu1", &[], &mut self.out) } fn delete_line(&mut self) -> Result<()> { self.ti.apply_cap("el", &[], &mut self.out) } fn carriage_return(&mut self) -> Result<()> { self.ti.apply_cap("cr", &[], &mut self.out) } fn get_ref(&self) -> &T { &self.out } fn get_mut(&mut self) -> &mut T { &mut self.out } fn into_inner(self) -> T where Self: Sized, { self.out } } impl TerminfoTerminal { /// Create a new TerminfoTerminal with the given TermInfo and Write. pub fn new_with_terminfo(out: T, terminfo: TermInfo) -> TerminfoTerminal { let nc = if terminfo.strings.contains_key("setaf") && terminfo.strings.contains_key("setab") { terminfo.numbers.get("colors").map_or(0, |&n| n) } else { 0 }; TerminfoTerminal { out: out, ti: terminfo, num_colors: nc as u32, } } /// Create a new TerminfoTerminal for the current environment with the given Write. /// /// Returns `None` when the terminfo cannot be found or parsed. pub fn new(out: T) -> Option> { TermInfo::from_env() .map(move |ti| TerminfoTerminal::new_with_terminfo(out, ti)) .ok() } fn dim_if_necessary(&self, color: color::Color) -> color::Color { if color >= self.num_colors && color >= 8 && color < 16 { color - 8 } else { color } } } impl Write for TerminfoTerminal { fn write(&mut self, buf: &[u8]) -> io::Result { self.out.write(buf) } fn flush(&mut self) -> io::Result<()> { self.out.flush() } } term-0.7.0/src/terminfo/parm.rs000064400000000000000000000636650000000000000145130ustar 00000000000000// Copyright 2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Parameterized string expansion use self::Param::*; use self::States::*; use std::iter::repeat; #[derive(Clone, Copy, PartialEq)] enum States { Nothing, Delay, Percent, SetVar, GetVar, PushParam, CharConstant, CharClose, IntConstant(i32), FormatPattern(Flags, FormatState), SeekIfElse(usize), SeekIfElsePercent(usize), SeekIfEnd(usize), SeekIfEndPercent(usize), } #[derive(Copy, PartialEq, Clone)] enum FormatState { Flags, Width, Precision, } /// Types of parameters a capability can use #[allow(missing_docs)] #[derive(Clone)] pub enum Param { Number(i32), Words(String), } impl Default for Param { fn default() -> Self { Param::Number(0) } } /// An error from interpreting a parameterized string. #[derive(Debug, Eq, PartialEq)] pub enum Error { /// Data was requested from the stack, but the stack didn't have enough elements. StackUnderflow, /// The type of the element(s) on top of the stack did not match the type that the operator /// wanted. TypeMismatch, /// An unrecognized format option was used. UnrecognizedFormatOption(char), /// An invalid variable name was used. InvalidVariableName(char), /// An invalid parameter index was used. InvalidParameterIndex(char), /// A malformed character constant was used. MalformedCharacterConstant, /// An integer constant was too large (overflowed an i32) IntegerConstantOverflow, /// A malformed integer constant was used. MalformedIntegerConstant, /// A format width constant was too large (overflowed a usize) FormatWidthOverflow, /// A format precision constant was too large (overflowed a usize) FormatPrecisionOverflow, } impl ::std::fmt::Display for Error { fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { use self::Error::*; match *self { StackUnderflow => f.write_str("not enough elements on the stack"), TypeMismatch => f.write_str("type mismatch"), UnrecognizedFormatOption(_) => f.write_str("unrecognized format option"), InvalidVariableName(_) => f.write_str("invalid variable name"), InvalidParameterIndex(_) => f.write_str("invalid parameter index"), MalformedCharacterConstant => f.write_str("malformed character constant"), IntegerConstantOverflow => f.write_str("integer constant computation overflowed"), MalformedIntegerConstant => f.write_str("malformed integer constant"), FormatWidthOverflow => f.write_str("format width constant computation overflowed"), FormatPrecisionOverflow => { f.write_str("format precision constant computation overflowed") } } } } impl ::std::error::Error for Error {} /// Container for static and dynamic variable arrays #[derive(Default)] pub struct Variables { /// Static variables A-Z sta_vars: [Param; 26], /// Dynamic variables a-z dyn_vars: [Param; 26], } impl Variables { /// Return a new zero-initialized Variables pub fn new() -> Variables { Default::default() } } /// Expand a parameterized capability /// /// # Arguments /// * `cap` - string to expand /// * `params` - vector of params for %p1 etc /// * `vars` - Variables struct for %Pa etc /// /// To be compatible with ncurses, `vars` should be the same between calls to `expand` for /// multiple capabilities for the same terminal. pub fn expand(cap: &[u8], params: &[Param], vars: &mut Variables) -> Result, Error> { let mut state = Nothing; // expanded cap will only rarely be larger than the cap itself let mut output = Vec::with_capacity(cap.len()); let mut stack: Vec = Vec::new(); // Copy parameters into a local vector for mutability let mut mparams = [ Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), Number(0), ]; for (dst, src) in mparams.iter_mut().zip(params.iter()) { *dst = (*src).clone(); } for &c in cap.iter() { let cur = c as char; let mut old_state = state; match state { Nothing => { if cur == '%' { state = Percent; } else if cur == '$' { state = Delay; } else { output.push(c); } } Delay => { old_state = Nothing; if cur == '>' { state = Nothing; } } Percent => { match cur { '%' => { output.push(c); state = Nothing } 'c' => { match stack.pop() { // if c is 0, use 0200 (128) for ncurses compatibility Some(Number(0)) => output.push(128u8), // Don't check bounds. ncurses just casts and truncates. Some(Number(c)) => output.push(c as u8), Some(_) => return Err(Error::TypeMismatch), None => return Err(Error::StackUnderflow), } } 'p' => state = PushParam, 'P' => state = SetVar, 'g' => state = GetVar, '\'' => state = CharConstant, '{' => state = IntConstant(0), 'l' => match stack.pop() { Some(Words(s)) => stack.push(Number(s.len() as i32)), Some(_) => return Err(Error::TypeMismatch), None => return Err(Error::StackUnderflow), }, '+' | '-' | '/' | '*' | '^' | '&' | '|' | 'm' => { match (stack.pop(), stack.pop()) { (Some(Number(y)), Some(Number(x))) => stack.push(Number(match cur { '+' => x + y, '-' => x - y, '*' => x * y, '/' => x / y, '|' => x | y, '&' => x & y, '^' => x ^ y, 'm' => x % y, _ => unreachable!("logic error"), })), (Some(_), Some(_)) => return Err(Error::TypeMismatch), _ => return Err(Error::StackUnderflow), } } '=' | '>' | '<' | 'A' | 'O' => match (stack.pop(), stack.pop()) { (Some(Number(y)), Some(Number(x))) => stack.push(Number( if match cur { '=' => x == y, '<' => x < y, '>' => x > y, 'A' => x > 0 && y > 0, 'O' => x > 0 || y > 0, _ => unreachable!("logic error"), } { 1 } else { 0 }, )), (Some(_), Some(_)) => return Err(Error::TypeMismatch), _ => return Err(Error::StackUnderflow), }, '!' | '~' => match stack.pop() { Some(Number(x)) => stack.push(Number(match cur { '!' if x > 0 => 0, '!' => 1, '~' => !x, _ => unreachable!("logic error"), })), Some(_) => return Err(Error::TypeMismatch), None => return Err(Error::StackUnderflow), }, 'i' => match (&mparams[0], &mparams[1]) { (&Number(x), &Number(y)) => { mparams[0] = Number(x + 1); mparams[1] = Number(y + 1); } (_, _) => return Err(Error::TypeMismatch), }, // printf-style support for %doxXs 'd' | 'o' | 'x' | 'X' | 's' => { if let Some(arg) = stack.pop() { let flags = Flags::default(); let res = format(arg, FormatOp::from_char(cur), flags)?; output.extend(res); } else { return Err(Error::StackUnderflow); } } ':' | '#' | ' ' | '.' | '0'..='9' => { let mut flags = Flags::default(); let mut fstate = FormatState::Flags; match cur { ':' => (), '#' => flags.alternate = true, ' ' => flags.space = true, '.' => fstate = FormatState::Precision, '0'..='9' => { flags.width = cur as usize - '0' as usize; fstate = FormatState::Width; } _ => unreachable!("logic error"), } state = FormatPattern(flags, fstate); } // conditionals '?' | ';' => (), 't' => match stack.pop() { Some(Number(0)) => state = SeekIfElse(0), Some(Number(_)) => (), Some(_) => return Err(Error::TypeMismatch), None => return Err(Error::StackUnderflow), }, 'e' => state = SeekIfEnd(0), c => return Err(Error::UnrecognizedFormatOption(c)), } } PushParam => { // params are 1-indexed stack.push( mparams[match cur.to_digit(10) { Some(d) => d as usize - 1, None => return Err(Error::InvalidParameterIndex(cur)), }] .clone(), ); } SetVar => { if cur >= 'A' && cur <= 'Z' { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'A'; vars.sta_vars[idx as usize] = arg; } else { return Err(Error::StackUnderflow); } } else if cur >= 'a' && cur <= 'z' { if let Some(arg) = stack.pop() { let idx = (cur as u8) - b'a'; vars.dyn_vars[idx as usize] = arg; } else { return Err(Error::StackUnderflow); } } else { return Err(Error::InvalidVariableName(cur)); } } GetVar => { if cur >= 'A' && cur <= 'Z' { let idx = (cur as u8) - b'A'; stack.push(vars.sta_vars[idx as usize].clone()); } else if cur >= 'a' && cur <= 'z' { let idx = (cur as u8) - b'a'; stack.push(vars.dyn_vars[idx as usize].clone()); } else { return Err(Error::InvalidVariableName(cur)); } } CharConstant => { stack.push(Number(i32::from(c))); state = CharClose; } CharClose => { if cur != '\'' { return Err(Error::MalformedCharacterConstant); } } IntConstant(i) => { if cur == '}' { stack.push(Number(i)); state = Nothing; } else if let Some(digit) = cur.to_digit(10) { match i .checked_mul(10) .and_then(|i_ten| i_ten.checked_add(digit as i32)) { Some(i) => { state = IntConstant(i); old_state = Nothing; } None => return Err(Error::IntegerConstantOverflow), } } else { return Err(Error::MalformedIntegerConstant); } } FormatPattern(ref mut flags, ref mut fstate) => { old_state = Nothing; match (*fstate, cur) { (_, 'd') | (_, 'o') | (_, 'x') | (_, 'X') | (_, 's') => { if let Some(arg) = stack.pop() { let res = format(arg, FormatOp::from_char(cur), *flags)?; output.extend(res); // will cause state to go to Nothing old_state = FormatPattern(*flags, *fstate); } else { return Err(Error::StackUnderflow); } } (FormatState::Flags, '#') => { flags.alternate = true; } (FormatState::Flags, '-') => { flags.left = true; } (FormatState::Flags, '+') => { flags.sign = true; } (FormatState::Flags, ' ') => { flags.space = true; } (FormatState::Flags, '0'..='9') => { flags.width = cur as usize - '0' as usize; *fstate = FormatState::Width; } (FormatState::Width, '0'..='9') => { flags.width = match flags .width .checked_mul(10) .and_then(|w| w.checked_add(cur as usize - '0' as usize)) { Some(width) => width, None => return Err(Error::FormatWidthOverflow), } } (FormatState::Width, '.') | (FormatState::Flags, '.') => { *fstate = FormatState::Precision; } (FormatState::Precision, '0'..='9') => { flags.precision = match flags .precision .checked_mul(10) .and_then(|w| w.checked_add(cur as usize - '0' as usize)) { Some(precision) => precision, None => return Err(Error::FormatPrecisionOverflow), } } _ => return Err(Error::UnrecognizedFormatOption(cur)), } } SeekIfElse(level) => { if cur == '%' { state = SeekIfElsePercent(level); } old_state = Nothing; } SeekIfElsePercent(level) => { if cur == ';' { if level == 0 { state = Nothing; } else { state = SeekIfElse(level - 1); } } else if cur == 'e' && level == 0 { state = Nothing; } else if cur == '?' { state = SeekIfElse(level + 1); } else { state = SeekIfElse(level); } } SeekIfEnd(level) => { if cur == '%' { state = SeekIfEndPercent(level); } old_state = Nothing; } SeekIfEndPercent(level) => { if cur == ';' { if level == 0 { state = Nothing; } else { state = SeekIfEnd(level - 1); } } else if cur == '?' { state = SeekIfEnd(level + 1); } else { state = SeekIfEnd(level); } } } if state == old_state { state = Nothing; } } Ok(output) } #[derive(Copy, PartialEq, Clone, Default)] struct Flags { width: usize, precision: usize, alternate: bool, left: bool, sign: bool, space: bool, } #[derive(Copy, Clone)] enum FormatOp { Digit, Octal, Hex, HEX, String, } impl FormatOp { fn from_char(c: char) -> FormatOp { use self::FormatOp::*; match c { 'd' => Digit, 'o' => Octal, 'x' => Hex, 'X' => HEX, 's' => String, _ => panic!("bad FormatOp char"), } } } fn format(val: Param, op: FormatOp, flags: Flags) -> Result, Error> { use self::FormatOp::*; let mut s = match val { Number(d) => { match op { Digit => { if flags.sign { format!("{:+01$}", d, flags.precision) } else if d < 0 { // C doesn't take sign into account in precision calculation. format!("{:01$}", d, flags.precision + 1) } else if flags.space { format!(" {:01$}", d, flags.precision) } else { format!("{:01$}", d, flags.precision) } } Octal => { if flags.alternate { // Leading octal zero counts against precision. format!("0{:01$o}", d, flags.precision.saturating_sub(1)) } else { format!("{:01$o}", d, flags.precision) } } Hex => { if flags.alternate && d != 0 { format!("0x{:01$x}", d, flags.precision) } else { format!("{:01$x}", d, flags.precision) } } HEX => { if flags.alternate && d != 0 { format!("0X{:01$X}", d, flags.precision) } else { format!("{:01$X}", d, flags.precision) } } String => return Err(Error::TypeMismatch), } .into_bytes() } Words(s) => match op { String => { let mut s = s.into_bytes(); if flags.precision > 0 && flags.precision < s.len() { s.truncate(flags.precision); } s } _ => return Err(Error::TypeMismatch), }, }; if flags.width > s.len() { let n = flags.width - s.len(); if flags.left { s.extend(repeat(b' ').take(n)); } else { let mut s_ = Vec::with_capacity(flags.width); s_.extend(repeat(b' ').take(n)); s_.extend(s.into_iter()); s = s_; } } Ok(s) } #[cfg(test)] mod test { use super::Param::{self, Number, Words}; use super::{expand, Variables}; use std::result::Result::Ok; #[test] fn test_basic_setabf() { let s = b"\\E[48;5;%p1%dm"; assert_eq!( expand(s, &[Number(1)], &mut Variables::new()).unwrap(), "\\E[48;5;1m".bytes().collect::>() ); } #[test] fn test_multiple_int_constants() { assert_eq!( expand(b"%{1}%{2}%d%d", &[], &mut Variables::new()).unwrap(), "21".bytes().collect::>() ); } #[test] fn test_op_i() { let mut vars = Variables::new(); assert_eq!( expand( b"%p1%d%p2%d%p3%d%i%p1%d%p2%d%p3%d", &[Number(1), Number(2), Number(3)], &mut vars ), Ok("123233".bytes().collect::>()) ); assert_eq!( expand(b"%p1%d%p2%d%i%p1%d%p2%d", &[], &mut vars), Ok("0011".bytes().collect::>()) ); } #[test] fn test_param_stack_failure_conditions() { let mut varstruct = Variables::new(); let vars = &mut varstruct; fn get_res( fmt: &str, cap: &str, params: &[Param], vars: &mut Variables, ) -> Result, super::Error> { let mut u8v: Vec<_> = fmt.bytes().collect(); u8v.extend(cap.as_bytes().iter().cloned()); expand(&u8v, params, vars) } let caps = ["%d", "%c", "%s", "%Pa", "%l", "%!", "%~"]; for &cap in &caps { let res = get_res("", cap, &[], vars); assert!( res.is_err(), "Op {} succeeded incorrectly with 0 stack entries", cap ); let p = if cap == "%s" || cap == "%l" { Words("foo".to_owned()) } else { Number(97) }; let res = get_res("%p1", cap, &[p], vars); assert!( res.is_ok(), "Op {} failed with 1 stack entry: {}", cap, res.err().unwrap() ); } let caps = ["%+", "%-", "%*", "%/", "%m", "%&", "%|", "%A", "%O"]; for &cap in &caps { let res = expand(cap.as_bytes(), &[], vars); assert!( res.is_err(), "Binop {} succeeded incorrectly with 0 stack entries", cap ); let res = get_res("%{1}", cap, &[], vars); assert!( res.is_err(), "Binop {} succeeded incorrectly with 1 stack entry", cap ); let res = get_res("%{1}%{2}", cap, &[], vars); assert!( res.is_ok(), "Binop {} failed with 2 stack entries: {}", cap, res.err().unwrap() ); } } #[test] fn test_push_bad_param() { assert!(expand(b"%pa", &[], &mut Variables::new()).is_err()); } #[test] fn test_comparison_ops() { let v = [ ('<', [1u8, 0u8, 0u8]), ('=', [0u8, 1u8, 0u8]), ('>', [0u8, 0u8, 1u8]), ]; for &(op, bs) in &v { let s = format!("%{{1}}%{{2}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec![b'0' + bs[0]]); let s = format!("%{{1}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec![b'0' + bs[1]]); let s = format!("%{{2}}%{{1}}%{}%d", op); let res = expand(s.as_bytes(), &[], &mut Variables::new()); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), vec![b'0' + bs[2]]); } } #[test] fn test_conditionals() { let mut vars = Variables::new(); let s = b"\\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m"; let res = expand(s, &[Number(1)], &mut vars); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[31m".bytes().collect::>()); let res = expand(s, &[Number(8)], &mut vars); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[90m".bytes().collect::>()); let res = expand(s, &[Number(42)], &mut vars); assert!(res.is_ok(), res.err().unwrap()); assert_eq!(res.unwrap(), "\\E[38;5;42m".bytes().collect::>()); } #[test] fn test_format() { let mut varstruct = Variables::new(); let vars = &mut varstruct; assert_eq!( expand( b"%p1%s%p2%2s%p3%2s%p4%.2s", &[ Words("foo".to_owned()), Words("foo".to_owned()), Words("f".to_owned()), Words("foo".to_owned()) ], vars ), Ok("foofoo ffo".bytes().collect::>()) ); assert_eq!( expand(b"%p1%:-4.2s", &[Words("foo".to_owned())], vars), Ok("fo ".bytes().collect::>()) ); assert_eq!( expand(b"%p1%d%p1%.3d%p1%5d%p1%:+d", &[Number(1)], vars), Ok("1001 1+1".bytes().collect::>()) ); assert_eq!( expand( b"%p1%o%p1%#o%p2%6.4x%p2%#6.4X", &[Number(15), Number(27)], vars ), Ok("17017 001b0X001B".bytes().collect::>()) ); } } term-0.7.0/src/terminfo/parser/compiled.rs000064400000000000000000000142020000000000000166230ustar 00000000000000// Copyright 2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! ncurses-compatible compiled terminfo format parsing (term(5)) use std::collections::HashMap; use std::io; use std::io::prelude::*; use crate::terminfo::Error::*; use crate::terminfo::TermInfo; use crate::Result; pub use crate::terminfo::parser::names::*; // These are the orders ncurses uses in its compiled format (as of 5.9). Not // sure if portable. fn read_le_u16(r: &mut dyn io::Read) -> io::Result { let mut buf = [0; 2]; r.read_exact(&mut buf) .map(|()| u32::from(u16::from_le_bytes(buf))) } fn read_le_u32(r: &mut dyn io::Read) -> io::Result { let mut buf = [0; 4]; r.read_exact(&mut buf).map(|()| u32::from_le_bytes(buf)) } fn read_byte(r: &mut dyn io::Read) -> io::Result { match r.bytes().next() { Some(s) => s, None => Err(io::Error::new(io::ErrorKind::Other, "end of file")), } } /// Parse a compiled terminfo entry, using long capability names if `longnames` /// is true pub fn parse(file: &mut dyn io::Read, longnames: bool) -> Result { let (bnames, snames, nnames) = if longnames { (boolfnames, stringfnames, numfnames) } else { (boolnames, stringnames, numnames) }; // Check magic number let mut buf = [0; 2]; file.read_exact(&mut buf)?; let magic = u16::from_le_bytes(buf); let read_number = match magic { 0x011A => read_le_u16, 0x021e => read_le_u32, _ => return Err(BadMagic(magic).into()), }; // According to the spec, these fields must be >= -1 where -1 means that the // feature is not // supported. Using 0 instead of -1 works because we skip sections with length // 0. macro_rules! read_nonneg { () => {{ match read_le_u16(file)? as i16 { n if n >= 0 => n as usize, -1 => 0, _ => return Err(InvalidLength.into()), } }}; } let names_bytes = read_nonneg!(); let bools_bytes = read_nonneg!(); let numbers_count = read_nonneg!(); let string_offsets_count = read_nonneg!(); let string_table_bytes = read_nonneg!(); if names_bytes == 0 { return Err(ShortNames.into()); } if bools_bytes > boolnames.len() { return Err(TooManyBools.into()); } if numbers_count > numnames.len() { return Err(TooManyNumbers.into()); } if string_offsets_count > stringnames.len() { return Err(TooManyStrings.into()); } // don't read NUL let mut bytes = Vec::new(); file.take((names_bytes - 1) as u64) .read_to_end(&mut bytes)?; let names_str = match String::from_utf8(bytes) { Ok(s) => s, Err(e) => return Err(NotUtf8(e.utf8_error()).into()), }; let term_names: Vec = names_str.split('|').map(|s| s.to_owned()).collect(); // consume NUL if read_byte(file)? != b'\0' { return Err(NamesMissingNull.into()); } let bools_map = (0..bools_bytes) .filter_map(|i| match read_byte(file) { Err(e) => Some(Err(e)), Ok(1) => Some(Ok((bnames[i], true))), Ok(_) => None, }) .collect::>>()?; if (bools_bytes + names_bytes) % 2 == 1 { read_byte(file)?; // compensate for padding } let numbers_map = (0..numbers_count) .filter_map(|i| match read_number(file) { Ok(0xFFFF) => None, Ok(n) => Some(Ok((nnames[i], n))), Err(e) => Some(Err(e)), }) .collect::>>()?; let string_map: HashMap<&str, Vec> = if string_offsets_count > 0 { let string_offsets = (0..string_offsets_count) .map(|_| { let mut buf = [0; 2]; file.read_exact(&mut buf).map(|()| u16::from_le_bytes(buf)) }) .collect::>>()?; let mut string_table = Vec::new(); file.take(string_table_bytes as u64) .read_to_end(&mut string_table)?; string_offsets .into_iter() .enumerate() .filter(|&(_, offset)| { // non-entry offset != 0xFFFF }) .map(|(i, offset)| { let offset = offset as usize; let name = if snames[i] == "_" { stringfnames[i] } else { snames[i] }; if offset == 0xFFFE { // undocumented: FFFE indicates cap@, which means the capability // is not present // unsure if the handling for this is correct return Ok((name, Vec::new())); } // Find the offset of the NUL we want to go to let nulpos = string_table[offset..string_table_bytes] .iter() .position(|&b| b == 0); match nulpos { Some(len) => Ok((name, string_table[offset..offset + len].to_vec())), None => Err(crate::Error::TerminfoParsing(StringsMissingNull)), } }) .collect::>>()? } else { HashMap::new() }; // And that's all there is to it Ok(TermInfo { names: term_names, bools: bools_map, numbers: numbers_map, strings: string_map, }) } #[cfg(test)] mod test { use super::{boolfnames, boolnames, numfnames, numnames, stringfnames, stringnames}; #[test] fn test_veclens() { assert_eq!(boolfnames.len(), boolnames.len()); assert_eq!(numfnames.len(), numnames.len()); assert_eq!(stringfnames.len(), stringnames.len()); } } term-0.7.0/src/terminfo/parser/names.rs000064400000000000000000000733400000000000000161420ustar 00000000000000#![allow(non_upper_case_globals, missing_docs)] #![cfg_attr(rustfmt, rustfmt_skip)] pub static boolfnames: &[&str] = &["auto_left_margin", "auto_right_margin", "no_esc_ctlc", "ceol_standout_glitch", "eat_newline_glitch", "erase_overstrike", "generic_type", "hard_copy", "has_meta_key", "has_status_line", "insert_null_glitch", "memory_above", "memory_below", "move_insert_mode", "move_standout_mode", "over_strike", "status_line_esc_ok", "dest_tabs_magic_smso", "tilde_glitch", "transparent_underline", "xon_xoff", "needs_xon_xoff", "prtr_silent", "hard_cursor", "non_rev_rmcup", "no_pad_char", "non_dest_scroll_region", "can_change", "back_color_erase", "hue_lightness_saturation", "col_addr_glitch", "cr_cancels_micro_mode", "has_print_wheel", "row_addr_glitch", "semi_auto_right_margin", "cpi_changes_res", "lpi_changes_res", "backspaces_with_bs", "crt_no_scrolling", "no_correctly_working_cr", "gnu_has_meta_key", "linefeed_is_newline", "has_hardware_tabs", "return_does_clr_eol"]; pub static boolnames: &[&str] = &["bw", "am", "xsb", "xhp", "xenl", "eo", "gn", "hc", "km", "hs", "in", "db", "da", "mir", "msgr", "os", "eslok", "xt", "hz", "ul", "xon", "nxon", "mc5i", "chts", "nrrmc", "npc", "ndscr", "ccc", "bce", "hls", "xhpa", "crxm", "daisy", "xvpa", "sam", "cpix", "lpix", "OTbs", "OTns", "OTnc", "OTMT", "OTNL", "OTpt", "OTxr"]; pub static numfnames: &[&str] = &["columns", "init_tabs", "lines", "lines_of_memory", "magic_cookie_glitch", "padding_baud_rate", "virtual_terminal", "width_status_line", "num_labels", "label_height", "label_width", "max_attributes", "maximum_windows", "max_colors", "max_pairs", "no_color_video", "buffer_capacity", "dot_vert_spacing", "dot_horz_spacing", "max_micro_address", "max_micro_jump", "micro_col_size", "micro_line_size", "number_of_pins", "output_res_char", "output_res_line", "output_res_horz_inch", "output_res_vert_inch", "print_rate", "wide_char_size", "buttons", "bit_image_entwining", "bit_image_type", "magic_cookie_glitch_ul", "carriage_return_delay", "new_line_delay", "backspace_delay", "horizontal_tab_delay", "number_of_function_keys"]; pub static numnames: &[&str] = &["cols", "it", "lines", "lm", "xmc", "pb", "vt", "wsl", "nlab", "lh", "lw", "ma", "wnum", "colors", "pairs", "ncv", "bufsz", "spinv", "spinh", "maddr", "mjump", "mcs", "mls", "npins", "orc", "orl", "orhi", "orvi", "cps", "widcs", "btns", "bitwin", "bitype", "UTug", "OTdC", "OTdN", "OTdB", "OTdT", "OTkn"]; pub static stringfnames: &[&str] = &["back_tab", "bell", "carriage_return", "change_scroll_region", "clear_all_tabs", "clear_screen", "clr_eol", "clr_eos", "column_address", "command_character", "cursor_address", "cursor_down", "cursor_home", "cursor_invisible", "cursor_left", "cursor_mem_address", "cursor_normal", "cursor_right", "cursor_to_ll", "cursor_up", "cursor_visible", "delete_character", "delete_line", "dis_status_line", "down_half_line", "enter_alt_charset_mode", "enter_blink_mode", "enter_bold_mode", "enter_ca_mode", "enter_delete_mode", "enter_dim_mode", "enter_insert_mode", "enter_secure_mode", "enter_protected_mode", "enter_reverse_mode", "enter_standout_mode", "enter_underline_mode", "erase_chars", "exit_alt_charset_mode", "exit_attribute_mode", "exit_ca_mode", "exit_delete_mode", "exit_insert_mode", "exit_standout_mode", "exit_underline_mode", "flash_screen", "form_feed", "from_status_line", "init_1string", "init_2string", "init_3string", "init_file", "insert_character", "insert_line", "insert_padding", "key_backspace", "key_catab", "key_clear", "key_ctab", "key_dc", "key_dl", "key_down", "key_eic", "key_eol", "key_eos", "key_f0", "key_f1", "key_f10", "key_f2", "key_f3", "key_f4", "key_f5", "key_f6", "key_f7", "key_f8", "key_f9", "key_home", "key_ic", "key_il", "key_left", "key_ll", "key_npage", "key_ppage", "key_right", "key_sf", "key_sr", "key_stab", "key_up", "keypad_local", "keypad_xmit", "lab_f0", "lab_f1", "lab_f10", "lab_f2", "lab_f3", "lab_f4", "lab_f5", "lab_f6", "lab_f7", "lab_f8", "lab_f9", "meta_off", "meta_on", "newline", "pad_char", "parm_dch", "parm_delete_line", "parm_down_cursor", "parm_ich", "parm_index", "parm_insert_line", "parm_left_cursor", "parm_right_cursor", "parm_rindex", "parm_up_cursor", "pkey_key", "pkey_local", "pkey_xmit", "print_screen", "prtr_off", "prtr_on", "repeat_char", "reset_1string", "reset_2string", "reset_3string", "reset_file", "restore_cursor", "row_address", "save_cursor", "scroll_forward", "scroll_reverse", "set_attributes", "set_tab", "set_window", "tab", "to_status_line", "underline_char", "up_half_line", "init_prog", "key_a1", "key_a3", "key_b2", "key_c1", "key_c3", "prtr_non", "char_padding", "acs_chars", "plab_norm", "key_btab", "enter_xon_mode", "exit_xon_mode", "enter_am_mode", "exit_am_mode", "xon_character", "xoff_character", "ena_acs", "label_on", "label_off", "key_beg", "key_cancel", "key_close", "key_command", "key_copy", "key_create", "key_end", "key_enter", "key_exit", "key_find", "key_help", "key_mark", "key_message", "key_move", "key_next", "key_open", "key_options", "key_previous", "key_print", "key_redo", "key_reference", "key_refresh", "key_replace", "key_restart", "key_resume", "key_save", "key_suspend", "key_undo", "key_sbeg", "key_scancel", "key_scommand", "key_scopy", "key_screate", "key_sdc", "key_sdl", "key_select", "key_send", "key_seol", "key_sexit", "key_sfind", "key_shelp", "key_shome", "key_sic", "key_sleft", "key_smessage", "key_smove", "key_snext", "key_soptions", "key_sprevious", "key_sprint", "key_sredo", "key_sreplace", "key_sright", "key_srsume", "key_ssave", "key_ssuspend", "key_sundo", "req_for_input", "key_f11", "key_f12", "key_f13", "key_f14", "key_f15", "key_f16", "key_f17", "key_f18", "key_f19", "key_f20", "key_f21", "key_f22", "key_f23", "key_f24", "key_f25", "key_f26", "key_f27", "key_f28", "key_f29", "key_f30", "key_f31", "key_f32", "key_f33", "key_f34", "key_f35", "key_f36", "key_f37", "key_f38", "key_f39", "key_f40", "key_f41", "key_f42", "key_f43", "key_f44", "key_f45", "key_f46", "key_f47", "key_f48", "key_f49", "key_f50", "key_f51", "key_f52", "key_f53", "key_f54", "key_f55", "key_f56", "key_f57", "key_f58", "key_f59", "key_f60", "key_f61", "key_f62", "key_f63", "clr_bol", "clear_margins", "set_left_margin", "set_right_margin", "label_format", "set_clock", "display_clock", "remove_clock", "create_window", "goto_window", "hangup", "dial_phone", "quick_dial", "tone", "pulse", "flash_hook", "fixed_pause", "wait_tone", "user0", "user1", "user2", "user3", "user4", "user5", "user6", "user7", "user8", "user9", "orig_pair", "orig_colors", "initialize_color", "initialize_pair", "set_color_pair", "set_foreground", "set_background", "change_char_pitch", "change_line_pitch", "change_res_horz", "change_res_vert", "define_char", "enter_doublewide_mode", "enter_draft_quality", "enter_italics_mode", "enter_leftward_mode", "enter_micro_mode", "enter_near_letter_quality", "enter_normal_quality", "enter_shadow_mode", "enter_subscript_mode", "enter_superscript_mode", "enter_upward_mode", "exit_doublewide_mode", "exit_italics_mode", "exit_leftward_mode", "exit_micro_mode", "exit_shadow_mode", "exit_subscript_mode", "exit_superscript_mode", "exit_upward_mode", "micro_column_address", "micro_down", "micro_left", "micro_right", "micro_row_address", "micro_up", "order_of_pins", "parm_down_micro", "parm_left_micro", "parm_right_micro", "parm_up_micro", "select_char_set", "set_bottom_margin", "set_bottom_margin_parm", "set_left_margin_parm", "set_right_margin_parm", "set_top_margin", "set_top_margin_parm", "start_bit_image", "start_char_set_def", "stop_bit_image", "stop_char_set_def", "subscript_characters", "superscript_characters", "these_cause_cr", "zero_motion", "char_set_names", "key_mouse", "mouse_info", "req_mouse_pos", "get_mouse", "set_a_foreground", "set_a_background", "pkey_plab", "device_type", "code_set_init", "set0_des_seq", "set1_des_seq", "set2_des_seq", "set3_des_seq", "set_lr_margin", "set_tb_margin", "bit_image_repeat", "bit_image_newline", "bit_image_carriage_return", "color_names", "define_bit_image_region", "end_bit_image_region", "set_color_band", "set_page_length", "display_pc_char", "enter_pc_charset_mode", "exit_pc_charset_mode", "enter_scancode_mode", "exit_scancode_mode", "pc_term_options", "scancode_escape", "alt_scancode_esc", "enter_horizontal_hl_mode", "enter_left_hl_mode", "enter_low_hl_mode", "enter_right_hl_mode", "enter_top_hl_mode", "enter_vertical_hl_mode", "set_a_attributes", "set_pglen_inch", "termcap_init2", "termcap_reset", "linefeed_if_not_lf", "backspace_if_not_bs", "other_non_function_keys", "arrow_key_map", "acs_ulcorner", "acs_llcorner", "acs_urcorner", "acs_lrcorner", "acs_ltee", "acs_rtee", "acs_btee", "acs_ttee", "acs_hline", "acs_vline", "acs_plus", "memory_lock", "memory_unlock", "box_chars_1"]; pub static stringnames: &[&str] = &["cbt", "bel", "cr", "csr", "tbc", "clear", "el", "ed", "hpa", "cmdch", "cup", "cud1", "home", "civis", "cub1", "mrcup", "cnorm", "cuf1", "ll", "cuu1", "cvvis", "dch1", "dl1", "dsl", "hd", "smacs", "blink", "bold", "smcup", "smdc", "dim", "smir", "invis", "prot", "rev", "smso", "smul", "ech", "rmacs", "sgr0", "rmcup", "rmdc", "rmir", "rmso", "rmul", "flash", "ff", "fsl", "is1", "is2", "is3", "if", "ich1", "il1", "ip", "kbs", "ktbc", "kclr", "kctab", "kdch1", "kdl1", "kcud1", "krmir", "kel", "ked", "kf0", "kf1", "kf10", "kf2", "kf3", "kf4", "kf5", "kf6", "kf7", "kf8", "kf9", "khome", "kich1", "kil1", "kcub1", "kll", "knp", "kpp", "kcuf1", "kind", "kri", "khts", "kcuu1", "rmkx", "smkx", "lf0", "lf1", "lf10", "lf2", "lf3", "lf4", "lf5", "lf6", "lf7", "lf8", "lf9", "rmm", "smm", "nel", "pad", "dch", "dl", "cud", "ich", "indn", "il", "cub", "cuf", "rin", "cuu", "pfkey", "pfloc", "pfx", "mc0", "mc4", "mc5", "rep", "rs1", "rs2", "rs3", "rf", "rc", "vpa", "sc", "ind", "ri", "sgr", "hts", "wind", "ht", "tsl", "uc", "hu", "iprog", "ka1", "ka3", "kb2", "kc1", "kc3", "mc5p", "rmp", "acsc", "pln", "kcbt", "smxon", "rmxon", "smam", "rmam", "xonc", "xoffc", "enacs", "smln", "rmln", "kbeg", "kcan", "kclo", "kcmd", "kcpy", "kcrt", "kend", "kent", "kext", "kfnd", "khlp", "kmrk", "kmsg", "kmov", "knxt", "kopn", "kopt", "kprv", "kprt", "krdo", "kref", "krfr", "krpl", "krst", "kres", "ksav", "kspd", "kund", "kBEG", "kCAN", "kCMD", "kCPY", "kCRT", "kDC", "kDL", "kslt", "kEND", "kEOL", "kEXT", "kFND", "kHLP", "kHOM", "kIC", "kLFT", "kMSG", "kMOV", "kNXT", "kOPT", "kPRV", "kPRT", "kRDO", "kRPL", "kRIT", "kRES", "kSAV", "kSPD", "kUND", "rfi", "kf11", "kf12", "kf13", "kf14", "kf15", "kf16", "kf17", "kf18", "kf19", "kf20", "kf21", "kf22", "kf23", "kf24", "kf25", "kf26", "kf27", "kf28", "kf29", "kf30", "kf31", "kf32", "kf33", "kf34", "kf35", "kf36", "kf37", "kf38", "kf39", "kf40", "kf41", "kf42", "kf43", "kf44", "kf45", "kf46", "kf47", "kf48", "kf49", "kf50", "kf51", "kf52", "kf53", "kf54", "kf55", "kf56", "kf57", "kf58", "kf59", "kf60", "kf61", "kf62", "kf63", "el1", "mgc", "smgl", "smgr", "fln", "sclk", "dclk", "rmclk", "cwin", "wingo", "hup", "dial", "qdial", "tone", "pulse", "hook", "pause", "wait", "u0", "u1", "u2", "u3", "u4", "u5", "u6", "u7", "u8", "u9", "op", "oc", "initc", "initp", "scp", "setf", "setb", "cpi", "lpi", "chr", "cvr", "defc", "swidm", "sdrfq", "sitm", "slm", "smicm", "snlq", "snrmq", "sshm", "ssubm", "ssupm", "sum", "rwidm", "ritm", "rlm", "rmicm", "rshm", "rsubm", "rsupm", "rum", "mhpa", "mcud1", "mcub1", "mcuf1", "mvpa", "mcuu1", "porder", "mcud", "mcub", "mcuf", "mcuu", "scs", "smgb", "smgbp", "smglp", "smgrp", "smgt", "smgtp", "sbim", "scsd", "rbim", "rcsd", "subcs", "supcs", "docr", "zerom", "csnm", "kmous", "minfo", "reqmp", "getm", "setaf", "setab", "pfxl", "devt", "csin", "s0ds", "s1ds", "s2ds", "s3ds", "smglr", "smgtb", "birep", "binel", "bicr", "colornm", "defbi", "endbi", "setcolor", "slines", "dispc", "smpch", "rmpch", "smsc", "rmsc", "pctrm", "scesc", "scesa", "ehhlm", "elhlm", "elohlm", "erhlm", "ethlm", "evhlm", "sgr1", "slength", "OTi2", "OTrs", "OTnl", "OTbs", "OTko", "OTma", "OTG2", "OTG3", "OTG1", "OTG4", "OTGR", "OTGL", "OTGU", "OTGD", "OTGH", "OTGV", "OTGC", "meml", "memu", "box1"]; term-0.7.0/src/terminfo/searcher.rs000064400000000000000000000063450000000000000153400ustar 00000000000000// Copyright 2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! ncurses-compatible database discovery //! //! Does not support hashed database, only filesystem! use std::env; use std::fs; use std::path::PathBuf; use dirs_next as dirs; /// Return path to database entry for `term` pub fn get_dbpath_for_term(term: &str) -> Option { let mut dirs_to_search = Vec::new(); let first_char = match term.chars().next() { Some(c) => c, None => return None, }; // Find search directory // The terminfo manual says: // // > If the environment variable TERMINFO is set, it is interpreted // > as the pathname of a directory containing the compiled description // > you are working on. Only that directory is searched. // // However, the ncurses manual says: // // > If the environment variable TERMINFO is defined, any program using // > curses checks for a local terminal definition before checking in // > the standard place. // // Given that ncurses is the defacto standard, we follow the ncurses manual. if let Some(dir) = env::var_os("TERMINFO") { dirs_to_search.push(PathBuf::from(dir)); } if let Ok(dirs) = env::var("TERMINFO_DIRS") { for i in dirs.split(':') { if i == "" { dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); } else { dirs_to_search.push(PathBuf::from(i)); } } } else { // Found nothing in TERMINFO_DIRS, use the default paths: // According to /etc/terminfo/README, after looking at // ~/.terminfo, ncurses will search /etc/terminfo, then // /lib/terminfo, and eventually /usr/share/terminfo. // On Haiku the database can be found at /boot/system/data/terminfo if let Some(mut homedir) = dirs::home_dir() { homedir.push(".terminfo"); dirs_to_search.push(homedir) } dirs_to_search.push(PathBuf::from("/etc/terminfo")); dirs_to_search.push(PathBuf::from("/lib/terminfo")); dirs_to_search.push(PathBuf::from("/usr/share/terminfo")); dirs_to_search.push(PathBuf::from("/boot/system/data/terminfo")); } // Look for the terminal in all of the search directories for mut p in dirs_to_search { if fs::metadata(&p).is_ok() { p.push(&first_char.to_string()); p.push(&term); if fs::metadata(&p).is_ok() { return Some(p); } p.pop(); p.pop(); // on some installations the dir is named after the hex of the char // (e.g. OS X) p.push(&format!("{:x}", first_char as usize)); p.push(term); if fs::metadata(&p).is_ok() { return Some(p); } } } None } term-0.7.0/src/win.rs000064400000000000000000000302230000000000000125060ustar 00000000000000// Copyright 2013-2019 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. //! Windows console handling // FIXME (#13400): this is only a tiny fraction of the Windows console api use crate::color; use crate::Attr; use crate::Error; use crate::Result; use crate::Terminal; use std::io; use std::io::prelude::*; use std::ops::Deref; use std::ptr; use winapi::shared::minwindef::{DWORD, WORD}; use winapi::um::consoleapi::{GetConsoleMode, SetConsoleMode}; use winapi::um::fileapi::{CreateFileA, OPEN_EXISTING}; use winapi::um::handleapi::{CloseHandle, INVALID_HANDLE_VALUE}; use winapi::um::wincon::FillConsoleOutputAttribute; use winapi::um::wincon::{ FillConsoleOutputCharacterW, GetConsoleScreenBufferInfo, CONSOLE_SCREEN_BUFFER_INFO, COORD, }; use winapi::um::wincon::{SetConsoleCursorPosition, SetConsoleTextAttribute}; use winapi::um::wincon::{BACKGROUND_INTENSITY, ENABLE_VIRTUAL_TERMINAL_PROCESSING}; use winapi::um::winnt::{FILE_SHARE_WRITE, GENERIC_READ, GENERIC_WRITE, HANDLE}; /// Console info which can be used by a Terminal implementation /// which uses the Win32 Console API. pub struct WinConsoleInfo { def_foreground: color::Color, def_background: color::Color, foreground: color::Color, background: color::Color, reverse: bool, secure: bool, standout: bool, } /// A Terminal implementation which uses the Win32 Console API. pub struct WinConsole { buf: T, info: WinConsoleInfo, } fn color_to_bits(color: color::Color) -> u16 { // magic numbers from mingw-w64's wincon.h let bits = match color % 8 { color::BLACK => 0, color::BLUE => 0x1, color::GREEN => 0x2, color::RED => 0x4, color::YELLOW => 0x2 | 0x4, color::MAGENTA => 0x1 | 0x4, color::CYAN => 0x1 | 0x2, color::WHITE => 0x1 | 0x2 | 0x4, _ => unreachable!(), }; if color >= 8 { bits | 0x8 } else { bits } } fn bits_to_color(bits: u16) -> color::Color { let color = match bits & 0x7 { 0 => color::BLACK, 0x1 => color::BLUE, 0x2 => color::GREEN, 0x4 => color::RED, 0x6 => color::YELLOW, 0x5 => color::MAGENTA, 0x3 => color::CYAN, 0x7 => color::WHITE, _ => unreachable!(), }; color | (bits as u32 & 0x8) // copy the hi-intensity bit } struct HandleWrapper { inner: HANDLE, } impl HandleWrapper { fn new(h: HANDLE) -> HandleWrapper { HandleWrapper { inner: h } } } impl Drop for HandleWrapper { fn drop(&mut self) { if self.inner != INVALID_HANDLE_VALUE { unsafe { CloseHandle(self.inner); } } } } impl Deref for HandleWrapper { type Target = HANDLE; fn deref(&self) -> &HANDLE { &self.inner } } /// Just get a handle to the current console buffer whatever it is fn conout() -> io::Result { let name = b"CONOUT$\0"; let handle = unsafe { CreateFileA( name.as_ptr() as *const i8, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_WRITE, ptr::null_mut(), OPEN_EXISTING, 0, ptr::null_mut(), ) }; if handle == INVALID_HANDLE_VALUE { Err(io::Error::last_os_error()) } else { Ok(HandleWrapper::new(handle)) } } unsafe fn set_flag(handle: HANDLE, flag: DWORD) -> io::Result<()> { let mut curr_mode: DWORD = 0; if GetConsoleMode(handle, &mut curr_mode) == 0 { return Err(io::Error::last_os_error()); } if SetConsoleMode(handle, curr_mode | flag) == 0 { return Err(io::Error::last_os_error()); } return Ok(()); } /// Check if console supports ansi codes (should succeed on Windows 10) pub fn supports_ansi() -> bool { conout() .and_then(|handle| unsafe { set_flag(*handle, ENABLE_VIRTUAL_TERMINAL_PROCESSING) }) .is_ok() } // This test will only pass if it is running in an actual console, probably #[test] fn test_conout() { assert!(conout().is_ok()) } #[rustversion::before(1.36)] unsafe fn get_console_screen_buffer_info(handle: HANDLE) -> io::Result { let mut buffer_info = ::std::mem::uninitialized(); if GetConsoleScreenBufferInfo(handle, &mut buffer_info) == 0 { Err(io::Error::last_os_error()) } else { Ok(buffer_info) } } #[rustversion::since(1.36)] unsafe fn get_console_screen_buffer_info(handle: HANDLE) -> io::Result { let mut buffer_info = ::std::mem::MaybeUninit::uninit(); if GetConsoleScreenBufferInfo(handle, buffer_info.as_mut_ptr()) == 0 { Err(io::Error::last_os_error()) } else { Ok(buffer_info.assume_init()) } } // This test will only pass if it is running in an actual console, probably #[test] fn test_get_console_screen_buffer_info() { let handle = conout().unwrap(); unsafe { let buffer_info = get_console_screen_buffer_info(*handle); assert!(buffer_info.is_ok()); } } impl WinConsoleInfo { /// Returns `Err` whenever console info cannot be retrieved for some /// reason. pub fn from_env() -> io::Result { let fg; let bg; let handle = conout()?; unsafe { let buffer_info = get_console_screen_buffer_info(*handle)?; fg = bits_to_color(buffer_info.wAttributes); bg = bits_to_color(buffer_info.wAttributes >> 4); } Ok(WinConsoleInfo { def_foreground: fg, def_background: bg, foreground: fg, background: bg, reverse: false, secure: false, standout: false, }) } } impl WinConsole { fn apply(&mut self) -> io::Result<()> { let out = conout()?; let _unused = self.buf.flush(); let (mut fg, bg) = if self.info.reverse { (self.info.background, self.info.foreground) } else { (self.info.foreground, self.info.background) }; if self.info.secure { fg = bg; } let mut accum: WORD = 0; accum |= color_to_bits(fg); accum |= color_to_bits(bg) << 4; if self.info.standout { accum |= BACKGROUND_INTENSITY; } else { accum &= BACKGROUND_INTENSITY ^ 0xFF; } unsafe { SetConsoleTextAttribute(*out, accum); } Ok(()) } /// Create a new WinConsole with the given WinConsoleInfo and out pub fn new_with_consoleinfo(out: T, info: WinConsoleInfo) -> WinConsole { WinConsole { buf: out, info } } /// Returns `Err` whenever the terminal cannot be created for some /// reason. pub fn new(out: T) -> io::Result> { let info = WinConsoleInfo::from_env()?; Ok(Self::new_with_consoleinfo(out, info)) } } impl Write for WinConsole { fn write(&mut self, buf: &[u8]) -> io::Result { self.buf.write(buf) } fn flush(&mut self) -> io::Result<()> { self.buf.flush() } } impl Terminal for WinConsole { type Output = T; fn fg(&mut self, color: color::Color) -> Result<()> { self.info.foreground = color; self.apply()?; Ok(()) } fn bg(&mut self, color: color::Color) -> Result<()> { self.info.background = color; self.apply()?; Ok(()) } fn attr(&mut self, attr: Attr) -> Result<()> { match attr { Attr::ForegroundColor(f) => { self.info.foreground = f; self.apply()?; Ok(()) } Attr::BackgroundColor(b) => { self.info.background = b; self.apply()?; Ok(()) } Attr::Reverse => { self.info.reverse = true; self.apply()?; Ok(()) } Attr::Secure => { self.info.secure = true; self.apply()?; Ok(()) } Attr::Standout(v) => { self.info.standout = v; self.apply()?; Ok(()) } _ => Err(Error::NotSupported), } } fn supports_attr(&self, attr: Attr) -> bool { match attr { Attr::ForegroundColor(_) | Attr::BackgroundColor(_) | Attr::Standout(_) | Attr::Reverse | Attr::Secure => true, _ => false, } } fn reset(&mut self) -> Result<()> { self.info.foreground = self.info.def_foreground; self.info.background = self.info.def_background; self.info.reverse = false; self.info.secure = false; self.info.standout = false; self.apply()?; Ok(()) } fn supports_reset(&self) -> bool { true } fn supports_color(&self) -> bool { true } fn cursor_up(&mut self) -> Result<()> { let _unused = self.buf.flush(); let handle = conout()?; unsafe { let buffer_info = get_console_screen_buffer_info(*handle)?; let (x, y) = ( buffer_info.dwCursorPosition.X, buffer_info.dwCursorPosition.Y, ); if y == 0 { // Even though this might want to be a CursorPositionInvalid, on Unix there // is no checking to see if the cursor is already on the first line. // I'm not sure what the ideal behavior is, but I think it'd be silly to have // cursor_up fail in this case. Ok(()) } else { let pos = COORD { X: x, Y: y - 1 }; if SetConsoleCursorPosition(*handle, pos) != 0 { Ok(()) } else { Err(io::Error::last_os_error().into()) } } } } fn delete_line(&mut self) -> Result<()> { let _unused = self.buf.flush(); let handle = conout()?; unsafe { let buffer_info = get_console_screen_buffer_info(*handle)?; let pos = buffer_info.dwCursorPosition; let size = buffer_info.dwSize; let num = (size.X - pos.X) as DWORD; let mut written = 0; // 0x0020u16 is ' ' (space) in UTF-16 (same as ascii) if FillConsoleOutputCharacterW(*handle, 0x0020, num, pos, &mut written) == 0 { return Err(io::Error::last_os_error().into()); } if FillConsoleOutputAttribute(*handle, 0, num, pos, &mut written) == 0 { return Err(io::Error::last_os_error().into()); } // Similar reasoning for not failing as in cursor_up -- it doesn't even make // sense to // me that these APIs could have written 0, unless the terminal is width zero. Ok(()) } } fn carriage_return(&mut self) -> Result<()> { let _unused = self.buf.flush(); let handle = conout()?; unsafe { let buffer_info = get_console_screen_buffer_info(*handle)?; let COORD { X: x, Y: y } = buffer_info.dwCursorPosition; if x == 0 { Err(Error::CursorDestinationInvalid) } else { let pos = COORD { X: 0, Y: y }; if SetConsoleCursorPosition(*handle, pos) != 0 { Ok(()) } else { Err(io::Error::last_os_error().into()) } } } } fn get_ref<'a>(&'a self) -> &'a T { &self.buf } fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf } fn into_inner(self) -> T where Self: Sized, { self.buf } } term-0.7.0/tests/data/dumb000064400000000000000000000004640000000000000135050ustar 00000000000000dumb|80-column dumb ttyP term-0.7.0/tests/data/linux000064400000000000000000000033640000000000000137170ustar 00000000000000}Ilinux|linux console@!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)3=C [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-16color000064400000000000000000000035020000000000000151740ustar 00000000000000+}linux-16color|linux console with 16 colors?!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)Ou{ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%{8}%m%d%?%p1%{7}%>%t;1%e;21%;m[4%p1%{8}%m%d%?%p1%{7}%>%t;5%e;25%;m" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-basic000064400000000000000000000032000000000000000147630ustar 00000000000000}linux-basic|linux console@!%)4EGKMQUY]chmrw| "&*-6?HQZclu{~15;AFHNTZ`flrx~ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-c000064400000000000000000000041100000000000000141250ustar 00000000000000/}linux-c|linux console 1.3.6+ for older ncurses@!%)4EGKMQUY]chmrw| "&*-6?HQZclu{~15;AFHNTZ`flrx~_cmw} [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%?%p1%{9}%>%t%p1%{10}%-%'a'%+%c%e%p1%d%;%p2%{255}%*%{1000}%/%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;%p3%{255}%*%{1000}%/%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;%p4%{255}%*%{1000}%/%Pr%gr%{16}%/%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;%gr%{15}%&%Px%?%gx%{9}%>%t%gx%{10}%-%'a'%+%c%e%gx%d%;[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-c-nc000064400000000000000000000033460000000000000145350ustar 00000000000000+}%linux-c-nc|linux console with color-change@!%)4EGKMQUY]chmrw| "&*-6?HQZclu{~15;AFHNTZ`flrx~ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-koi8000064400000000000000000000034200000000000000145600ustar 000000000000003}Glinux-koi8|linux with koi8 alternate character set@!%)4EGKWYeimy} "(.38<AFJNQZclu~ SW]chjpv|#'1;A [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-koi8r000064400000000000000000000034260000000000000147500ustar 000000000000006}Ilinux-koi8r|linux with koi8-r alternate character set@!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)3=C [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-lat000064400000000000000000000034360000000000000144750ustar 00000000000000>}Ilinux-lat|linux with latin1 or latin2 alternate character set@!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)3=C [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`a fghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-m000064400000000000000000000033520000000000000141460ustar 00000000000000}5linux-m|Linux console no color!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)/ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-nic000064400000000000000000000034220000000000000144610ustar 00000000000000A}<linux-nic|linux with ich/ich1 suppressed for non-curses programs@!%)4EGKWYeimy} $*/48=BFJMV_hqzHLRX]_ekqw}&06 [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux-vt000064400000000000000000000032460000000000000143450ustar 000000000000003}linux-vt|linux console using VT codes for graphics@!%)4EGKWYeimy} %+059>CGKNW`ir{  %+17=CINY^dhqu [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c(0[%p1%dX(K(K[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 MH ++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz~~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux2.2000064400000000000000000000033740000000000000141420ustar 00000000000000}Ilinux2.2|linux 2.2.x console@!%)4EGKWYeimy} "(.38<AFJNQZclu~ UY_ejlrx~%)3=C [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p9%t;11%;mH +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm" AXG0XTU8E0S0ka2kb1kb3kc2term-0.7.0/tests/data/linux2.6000064400000000000000000000033710000000000000141430ustar 00000000000000}?linux2.6|linux 2.6.x console@!%)4EGKWYeimy} #(-16;?CFOXajs| KOU[`bhntz)39 [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;m%?%p9%t%e%;H +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm% !AXG0XTU8E0E3S0ka2kb1kb3kc2term-0.7.0/tests/data/linux2.6.26000064400000000000000000000033750000000000000143750ustar 00000000000000"}?linux2.6.26|linux console w/o bce@!%)4EGKWYeimy} #(-16;?CFOXajs| KOU[`bhntz)39 [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;m%?%p9%t%e%;H +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm% !AXG0XTU8E0E3S0ka2kb1kb3kc2term-0.7.0/tests/data/linux3.0000064400000000000000000000033740000000000000141410ustar 00000000000000}?linux3.0|linux 3.0 kernels@!%)4EGKWYeimy} #(-16;?CFOXajs| KOU[`bhntz)39 [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?1c[?25h[?0c[?25h[?8c[%p1%dX[?5h[?5l$<200/>[@[3~[[A[21~[[B[[C[[D[[E[17~[18~[19~[20~[1~[2~[6~[5~ [%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc]R8[%i%p1%dd7 M[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;m%?%p9%t%e%;H +,-.0`afghijklmno~pqrs_tuvwxyz{|}~[?7h[?7l[4~[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[%i%d;%dR[?6c]R]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x[3%p1%dm[4%p1%dm* !AXG0XTU8E0E3S0ka2kb1kb3kc2term-0.7.0/tests/data/rxvt000064400000000000000000000043550000000000000135640ustar 00000000000000.&n rxvt|rxvt terminal emulator (X Window System)P@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c[3%p1%dm[4%p1%dm(B(0< !&+049>CHLPTX\` "(.4:@FLRX]bhntz[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND3kEND4kEND5kEND6kEND7kHOM3kHOM4kHOM5kHOM6kHOM7kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-16color000064400000000000000000000047010000000000000150420ustar 00000000000000.&nrxvt-16color|rxvt with 16 colors like aixtermP "&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~R [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c%p1%{8}%/%{6}%*%{3}%+[%d%p1%{8}%m%Pa%?%ga%{1}%=%t4%e%ga%{3}%=%t6%e%ga%{4}%=%t1%e%ga%{6}%=%t3%e%ga%d%;m%p1%{8}%/%{6}%*%{4}%+[%d%p1%{8}%m%Pa%?%ga%{1}%=%t4%e%ga%{3}%=%t6%e%ga%{4}%=%t1%e%ga%{6}%=%t3%e%ga%d%;m[%?%p1%{8}%<%t%p1%{30}%+%e%p1%'R'%+%;%dm[%?%p1%{8}%<%t%p1%'('%+%e%p1%{92}%+%;%dm(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-256color000064400000000000000000000045730000000000000151370ustar 00000000000000/&nrxvt-256color|rxvt 2.7.9 with xterm 256-colorsP"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~HL [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-88color000064400000000000000000000045710000000000000150600ustar 00000000000000-&nrxvt-88color|rxvt 2.7.9 with xterm 88-colorsPX@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~HL [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-basic000064400000000000000000000041410000000000000146340ustar 000000000000000&nrxvt-basic|rxvt terminal base (X Window System)P"&*;=AHJQUY]_dirw| #)/5;@EINSW[_cfir{ILNRVZ^b !'-39?EKQW]ciou{ [%i%p1%d;%p2%dr[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h87 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-color000064400000000000000000000042650000000000000147000ustar 000000000000004&n rxvt-color|rxvt terminal emulator (X Window System)P@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c[3%p1%dm[4%p1%dm(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-cygwin000064400000000000000000000043130000000000000150540ustar 00000000000000?&nrxvt-cygwin|rxvt terminal emulator (X Window System) on cygwinP@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} "(.4:@FLRX^djpv|  [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs+,-^0`afghjklmno~pqrs_tuvwxyz{|}~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c[3%p1%dm[4%p1%dm(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-cygwin-native000064400000000000000000000043350000000000000163440ustar 00000000000000S&nrxvt-cygwin-native|rxvt terminal emulator (native MS Window System port) on cygwinP@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} &,28>DJPV\bhntz  [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs+,-^0`afghjklmno~pqrs_tuvwxyz{|~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c[3%p1%dm[4%p1%dm(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/rxvt-xpm000064400000000000000000000042630000000000000143640ustar 000000000000002&n rxvt-xpm|rxvt terminal emulator (X Window System)P@"&*5FHLSU\`dhjot} !'-39?EKPUY^cgkosvy !dgimquy} $*06<BHNTZ`flrx~ [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?25h7[?47h[?47l8[?5h[?5l[?47l=[?1l[?7h[?1;3;4;6l[@[3~[8^[21~[11~[21~[12~[13~[14~[15~[17~[18~[19~[20~[7~[2~[6~[5~>=[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dA>[?7h[?7h[?1;3;4;6l>[?1000l[?25h8[%i%p1%dd7 M[0%?%p6%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;H OwOyOuOqOs``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[8~OM[1~[3$[4~[8$[7$[2$[6$[5$[23~[24~[25~[26~[28~[29~[31~[32~[33~[34~[23$[24$[11^[12^[13^[14^[15^[17^[18^[19^[20^[21^[23^[24^[25^[26^[28^[29^[31^[32^[33^[34^[23@[24@[%i%d;%dR[?1;2c[3%p1%dm[4%p1%dm(B(00 !&+049>CHLPTX\` "(.49>DJPV\bfkosw[3^[3@Ob[8^[8@[7^[7@[2^[2@Od[6^[6@[5^[5@OcOaOxOtOvOrAXXTE3kDC5kDC6kDNkDN5kEND5kEND6kHOM5kHOM6kIC5kIC6kLFT5kNXT5kNXT6kPRV5kPRV6kRIT5kUPkUP5ka2kb1kb3kc2term-0.7.0/tests/data/screen000064400000000000000000000030630000000000000140330ustar 00000000000000*+izscreen|VT 100/ANSI X3.64 virtual terminalP@%)->@DKMY]`fjnpuz #'/7:CLU^gpy8<CHNTYbfp [%i%p1%d;%p2%dr[%i%p1%d;%p2%dH [?25l[?25hM[?1049h[?1049lg)0[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~[1~[2~OD[6~[5~OCOA[?1l>[?1h=E[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc[?1000l[?25h87 M[0%?%p6%t;1%;%?%p1%t;3%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;m%?%p9%t%e%;H ++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[4~[23~[24~[3%p1%dm[4%p1%dm1 !(B(%p1%cAXG0XTU8E0MsS0ka2kb1kb3kc2term-0.7.0/tests/data/screen-256color000064400000000000000000000035700000000000000154070ustar 00000000000000++iscreen-256color|GNU Screen with 256 colorsP%)->@DKMY]`fjnpuz #'/7:CLU^gpy8<CHNTYbf [%i%p1%d;%p2%dr[%i%p1%d;%p2%dH [?25l[?25hM[?1049h[?1049lg)0[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~[1~[2~OD[6~[5~OCOA[?1l>[?1h=E[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dL[%p1%dD[%p1%dC[%p1%dAc[?1000l[?25h87 M[0%?%p6%t;1%;%?%p1%t;3%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;m%?%p9%t%e%;H ++,,--..00``aaffgghhiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~(B)0[4~[23~[24~[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m@ !&+/49>CHNTZ`flrx~(B(%p1%cAXG0XTU8E0S0kDC3kDC4kDC5kDC6kDC7kDNkDN3kDN4kDN5kDN6kDN7kEND5kHOM5kLFT3kLFT4kLFT5kLFT6kLFT7kRIT3kRIT4kRIT5kRIT6kRIT7kUPka2kb1kb3kc2term-0.7.0/tests/data/vt100000064400000000000000000000022460000000000000134300ustar 00000000000000,&vt100|vt100-am|dec vt100 (w/advanced video)P&.7LNRT\dfox '05:?WZ]_f  [%i%p1%d;%p2%dr$<50>$<3>$<50>[%i%p1%d;%p2%dH$<5> $<2>$<2>$<2>$<2>$<2>$<2>$<2>$<2>$<2>$<2>OBOyOPOxOQOROSOtOuOvOlOwODOCOA[?1l>[?1h=pf1pf2pf3pf4[%p1%dB[%p1%dD[%p1%dC[%p1%dA<>[?3;4;5l[?7;8h87 M$<5>[0%?%p1%p6%|%t;1%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;m%?%p9%t%e%;$<2>H OqOsOrOpOn``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~[?7h[?7l(B)0OM$<3>term-0.7.0/tests/data/xterm000064400000000000000000000065240000000000000137200ustar 000000000000000&xterm|xterm terminal emulator (X Window System)P@&*.9JLPWYfjnx|   $(,28>DJNSW\aelsw$'), #*18?GOW_gow'/7>ELS[cks{^cimw [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?12l[?25h[?12;25h(0[?1049h[%p1%dX(B(B[?1049l[?5h$<100/>[?5l[!p[?3;4l>[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~OH[2~OD[6~[5~OCOA[?1l>[?1h=[?1034l[?1034h[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dS[%p1%dL[%p1%dD[%p1%dC[%p1%dT[%p1%dAc[!p[?3;4l>8[%i%p1%dd7 M%?%p9%t(0%e(B%;[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;mH OE``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~[?7h[?7lOFOM[3;2~[2;2~[6;2~[5;2~[23~[24~[15;2~[17;2~[18;2~[19;2~[20;2~[21;2~[23;2~[24;2~[15;5~[17;5~[18;5~[19;5~[20;5~[21;5~[23;5~[24;5~[15;6~[17;6~[18;6~[19;6~[20;6~[21;6~[23;6~[24;6~[15;3~[17;3~[18;3~[19;3~[20;3~[21;3~[23;3~[24;3~[%i%d;%dR[?1;2c[3%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m[4%?%p1%{1}%=%t4%e%p1%{3}%=%t6%e%p1%{4}%=%t1%e%p1%{6}%=%t3%e%p1%d%;m[3%p1%dm[4%p1%dmlm@*0:AHOV]dkry !(/6=DKRY`gnu| !$).38=AFKPUZ`flrx~ !'+05:?DHLP]112]12;%p1%s]52;%p1%s;%p2%s[2 q[%p1%d q[3;3~[3;4~[3;5~[3;6~[3;7~[2;3~[2;4~[2;5~[2;6~[2;7~[6;3~[6;4~[6;5~[6;6~[6;7~[5;3~[5;4~[5;5~[5;6~[5;7~AXG0XTU8CrCsE0E3MsS0SeSskDC3kDC4kDC5kDC6kDC7kDNkDN3kDN4kDN5kDN6kDN7kEND3kEND4kEND5kEND6kEND7kHOM3kHOM4kHOM5kHOM6kHOM7kIC3kIC4kIC5kIC6kIC7kLFT3kLFT4kLFT5kLFT6kLFT7kNXT3kNXT4kNXT5kNXT6kNXT7kPRV3kPRV4kPRV5kPRV6kPRV7kRIT3kRIT4kRIT5kRIT6kRIT7kUPkUP3kUP4kUP5kUP6kUP7ka2kb1kb3kc2term-0.7.0/tests/data/xterm-256color000064400000000000000000000072010000000000000152620ustar 00000000000000%&xterm-256color|xterm with 256 colorsP&*.9JLPWYfjnx|$(,26:>DJPV\`einsw~ '0BEPSUX  '.5<CIOV]dks{#+3;CKS[cjqx nsy} [%i%p1%d;%p2%dr[%i%p1%dG[%i%p1%d;%p2%dH [?25l[?12l[?25h[?12;25h(0[?1049h[%p1%dX(B(B[?1049l[?5h$<100/>[?5l[!p[?3;4l>[3~OBOP[21~OQOROS[15~[17~[18~[19~[20~OH[2~OD[6~[5~OCOA[?1l>[?1h=[?1034l[?1034h[%p1%dP[%p1%dM[%p1%dB[%p1%d@[%p1%dS[%p1%dL[%p1%dD[%p1%dC[%p1%dT[%p1%dA%p1%c[%p2%{1}%-%dbc]104[!p[?3;4l>8[%i%p1%dd7 M%?%p9%t(0%e(B%;[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;mH OE``aaffggiijjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~[?7h[?7lOFOM[3;2~[2;2~[6;2~[5;2~[23~[24~[15;2~[17;2~[18;2~[19;2~[20;2~[21;2~[23;2~[24;2~[15;5~[17;5~[18;5~[19;5~[20;5~[21;5~[23;5~[24;5~[15;6~[17;6~[18;6~[19;6~[20;6~[21;6~[23;6~[24;6~[15;3~[17;3~[18;3~[19;3~[20;3~[21;3~[23;3~[24;3~[%i%d;%dR[?%[;0123456789]c]104]4;%p1%d;rgb:%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\[<[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;mlmIs*0:Zahov} %,3:AHOV]dkry !$'*06;@EJOSX]bglrx~ !'-39?EINSX]bfjnrw|]112]12;%p1%s]52;%p1%s;%p2%s[2 q[%p1%d q[?1006;1000%?%p1%{1}%=%th%el%;[3;3~[3;4~[3;5~[3;6~[3;7~[2;3~[2;4~[2;5~[2;6~[2;7~[6;3~[6;4~[6;5~[6;6~[6;7~[5;3~[5;4~[5;5~[5;6~[5;7~[<%p1%d;%p2%d;%p3%d;%?%p4%tM%em%;AXG0XTU8CrCsE0E3MsS0SeSsTSXMgrbomgsbomkDC3kDC4kDC5kDC6kDC7kDNkDN3kDN4kDN5kDN6kDN7kEND3kEND4kEND5kEND6kEND7kEND8kHOM3kHOM4kHOM5kHOM6kHOM7kHOM8kIC3kIC4kIC5kIC6kIC7kLFT3kLFT4kLFT5kLFT6kLFT7kNXT3kNXT4kNXT5kNXT6kNXT7kPRV3kPRV4kPRV5kPRV6kPRV7kRIT3kRIT4kRIT5kRIT6kRIT7kUPkUP3kUP4kUP5kUP6kUP7ka2kb1kb3kc2rmxxsmxxxmterm-0.7.0/tests/terminfo.rs000064400000000000000000000014400000000000000141060ustar 00000000000000use std::fs; use std::io; use term::terminfo::TermInfo; use term::terminfo::TerminfoTerminal; use term::Terminal; #[test] fn test_parse() { for f in fs::read_dir("tests/data/").unwrap() { let _ = TermInfo::from_path(f.unwrap().path()).unwrap(); } } #[test] fn test_supports_color() { fn supports_color(term: &str) -> bool { let terminfo = TermInfo::from_path(format!("tests/data/{}", term)).unwrap(); let term = TerminfoTerminal::new_with_terminfo(io::stdout(), terminfo); term.supports_color() } assert!(supports_color("linux")); assert!(!supports_color("dumb")); } #[test] fn test_fallback() { TermInfo::from_name("ansi-cargo-test").expect("failed to use fallback"); assert!(TermInfo::from_name("really-bad-terminal").is_err()); }