From ca2e9c013aa70d22b6fb19b8870b2ac56376148e Mon Sep 17 00:00:00 2001 From: Jun Wu Date: Tue, 4 Feb 2020 07:20:03 -0800 Subject: [PATCH] termwiz: do not depend on derive_builder derive_builder has some extra dependencies that take a while to compile. The builder feature can be expressed via a 30-line macro. So let's do that to make termwiz compile faster. --- termwiz/Cargo.toml | 1 - termwiz/src/caps/mod.rs | 197 +++++++++++++-------------------- termwiz/src/lib.rs | 1 + termwiz/src/lineedit/mod.rs | 16 +-- termwiz/src/macros.rs | 30 +++++ termwiz/src/render/terminfo.rs | 22 +--- 6 files changed, 121 insertions(+), 146 deletions(-) create mode 100644 termwiz/src/macros.rs diff --git a/termwiz/Cargo.toml b/termwiz/Cargo.toml index 9291c6223..11de735fd 100644 --- a/termwiz/Cargo.toml +++ b/termwiz/Cargo.toml @@ -14,7 +14,6 @@ readme = "README.md" base64 = "0.10" bitflags = "1.0" cassowary = {version="0.3", optional=true} -derive_builder = "0.7" anyhow = "1.0" filedescriptor = { version="0.7", path = "../filedescriptor" } fnv = {version="1.0", optional=true} diff --git a/termwiz/src/caps/mod.rs b/termwiz/src/caps/mod.rs index cd2852366..9a780c938 100644 --- a/termwiz/src/caps/mod.rs +++ b/termwiz/src/caps/mod.rs @@ -52,74 +52,74 @@ //! With all this in mind, this module presents a `Capabilities` struct //! that holds information about a terminal. The `new_from_env` method //! implements some heuristics (a fancy word for guessing) to compute -//! the terminal capabilities, but also offers a `ProbeHintsBuilder` +//! the terminal capabilities, but also offers a `ProbeHints` //! that can be used by the embedding application to override those choices. +use crate::builder; use anyhow::Error; -use derive_builder::*; use semver::Version; use std::env::var; use terminfo::{self, capability as cap}; -/// Use the `ProbeHintsBuilder` to configure an instance of -/// the `ProbeHints` struct. `ProbeHints` are passed to the `Capabilities` -/// constructor to influence the effective set of terminal capabilities. -#[derive(Debug, Default, Builder, Clone)] -#[builder(default)] -pub struct ProbeHints { - /// The contents of the TERM environment variable - term: Option, +builder! { + /// Use the `ProbeHints` to configure an instance of + /// the `ProbeHints` struct. `ProbeHints` are passed to the `Capabilities` + /// constructor to influence the effective set of terminal capabilities. + #[derive(Debug, Default, Clone)] + pub struct ProbeHints { + /// The contents of the TERM environment variable + term: Option, - /// The contents of the COLORTERM environment variable. - /// - colorterm: Option, + /// The contents of the COLORTERM environment variable. + /// + colorterm: Option, - /// The contents of the TERM_PROGRAM environment variable - term_program: Option, + /// The contents of the TERM_PROGRAM environment variable + term_program: Option, - /// Override the choice of the number of colors - color_level: Option, + /// Override the choice of the number of colors + color_level: Option, - /// The contents of the TERM_PROGRAM_VERSION environment variable - term_program_version: Option, + /// The contents of the TERM_PROGRAM_VERSION environment variable + term_program_version: Option, - /// Definitively set whether hyperlinks are supported. - /// The default is to assume yes as this is mostly harmless. - hyperlinks: Option, + /// Definitively set whether hyperlinks are supported. + /// The default is to assume yes as this is mostly harmless. + hyperlinks: Option, - /// Configure whether sixel graphics are supported. - sixel: Option, + /// Configure whether sixel graphics are supported. + sixel: Option, - /// Configure whether iTerm2 style graphics embedding is supported - /// See - iterm2_image: Option, + /// Configure whether iTerm2 style graphics embedding is supported + /// See + iterm2_image: Option, - /// Specify whether `bce`, background color erase, is supported. - bce: Option, + /// Specify whether `bce`, background color erase, is supported. + bce: Option, - /// The contents of the COLORTERM_BCE environment variable - /// - colorterm_bce: Option, + /// The contents of the COLORTERM_BCE environment variable + /// + colorterm_bce: Option, - /// A loaded terminfo database entry - terminfo_db: Option, + /// A loaded terminfo database entry + terminfo_db: Option, - /// Whether bracketed paste mode is supported - bracketed_paste: Option, + /// Whether bracketed paste mode is supported + bracketed_paste: Option, - /// Whether mouse support is present and should be used - mouse_reporting: Option, + /// Whether mouse support is present and should be used + mouse_reporting: Option, + } } -impl ProbeHintsBuilder { - pub fn new_from_env() -> ProbeHintsBuilder { - let mut hints = ProbeHintsBuilder::default(); - hints.term(var("TERM").ok()); - hints.colorterm(var("COLORTERM").ok()); - hints.colorterm_bce(var("COLORTERM_BCE").ok()); - hints.term_program(var("TERM_PROGRAM").ok()); - hints.term_program_version(var("TERM_PROGRAM_VERSION").ok()); - hints.terminfo_db(terminfo::Database::from_env().ok()); - hints +impl ProbeHints { + pub fn new_from_env() -> Self { + ProbeHints::default() + .term(var("TERM").ok()) + .colorterm(var("COLORTERM").ok()) + .colorterm_bce(var("COLORTERM_BCE").ok()) + .term_program(var("TERM_PROGRAM").ok()) + .term_program_version(var("TERM_PROGRAM_VERSION").ok()) + .terminfo_db(terminfo::Database::from_env().ok()) } } @@ -164,11 +164,7 @@ impl Capabilities { /// This function inspects the environment variables to build /// up configuration hints. pub fn new_from_env() -> Result { - Self::new_with_hints( - ProbeHintsBuilder::new_from_env() - .build() - .map_err(Error::msg)?, - ) + Self::new_with_hints(ProbeHints::new_from_env()) } /// Build a `Capabilities` object based on the provided `ProbeHints` object. @@ -330,8 +326,7 @@ mod test { #[test] fn empty_hint() { - let caps = - Capabilities::new_with_hints(ProbeHintsBuilder::default().build().unwrap()).unwrap(); + let caps = Capabilities::new_with_hints(ProbeHints::default()).unwrap(); assert_eq!(caps.color_level(), ColorLevel::Sixteen); assert_eq!(caps.sixel(), false); @@ -342,65 +337,45 @@ mod test { #[test] fn bce() { - let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .colorterm_bce(Some("1".into())) - .build() - .unwrap(), - ) - .unwrap(); + let caps = + Capabilities::new_with_hints(ProbeHints::default().colorterm_bce(Some("1".into()))) + .unwrap(); assert_eq!(caps.bce(), true); } #[test] fn bce_terminfo() { - let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .terminfo_db(Some(load_terminfo())) - .build() - .unwrap(), - ) - .unwrap(); + let caps = + Capabilities::new_with_hints(ProbeHints::default().terminfo_db(Some(load_terminfo()))) + .unwrap(); assert_eq!(caps.bce(), true); } #[test] fn terminfo_color() { - let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .terminfo_db(Some(load_terminfo())) - .build() - .unwrap(), - ) - .unwrap(); + let caps = + Capabilities::new_with_hints(ProbeHints::default().terminfo_db(Some(load_terminfo()))) + .unwrap(); assert_eq!(caps.color_level(), ColorLevel::TrueColor); } #[test] fn term_but_not_colorterm() { - let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .term(Some("xterm-256color".into())) - .build() - .unwrap(), - ) - .unwrap(); + let caps = + Capabilities::new_with_hints(ProbeHints::default().term(Some("xterm-256color".into()))) + .unwrap(); assert_eq!(caps.color_level(), ColorLevel::TwoFiftySix); } #[test] fn colorterm_but_no_term() { - let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .colorterm(Some("24bit".into())) - .build() - .unwrap(), - ) - .unwrap(); + let caps = + Capabilities::new_with_hints(ProbeHints::default().colorterm(Some("24bit".into()))) + .unwrap(); assert_eq!(caps.color_level(), ColorLevel::TrueColor); } @@ -408,34 +383,28 @@ mod test { #[test] fn term_and_colorterm() { let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term(Some("xterm-256color".into())) // bogus value - .colorterm(Some("24bot".into())) - .build() - .unwrap(), + .colorterm(Some("24bot".into())), ) .unwrap(); assert_eq!(caps.color_level(), ColorLevel::TwoFiftySix); let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term(Some("xterm-256color".into())) - .colorterm(Some("24bit".into())) - .build() - .unwrap(), + .colorterm(Some("24bit".into())), ) .unwrap(); assert_eq!(caps.color_level(), ColorLevel::TrueColor); let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term(Some("xterm-256color".into())) - .colorterm(Some("truecolor".into())) - .build() - .unwrap(), + .colorterm(Some("truecolor".into())), ) .unwrap(); @@ -445,41 +414,33 @@ mod test { #[test] fn iterm2_image() { let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term_program(Some("iTerm.app".into())) - .term_program_version(Some("1.0.0".into())) - .build() - .unwrap(), + .term_program_version(Some("1.0.0".into())), ) .unwrap(); assert_eq!(caps.iterm2_image(), false); let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term_program(Some("iTerm.app".into())) - .term_program_version(Some("2.9.0".into())) - .build() - .unwrap(), + .term_program_version(Some("2.9.0".into())), ) .unwrap(); assert_eq!(caps.iterm2_image(), false); let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term_program(Some("iTerm.app".into())) - .term_program_version(Some("2.9.20150512".into())) - .build() - .unwrap(), + .term_program_version(Some("2.9.20150512".into())), ) .unwrap(); assert_eq!(caps.iterm2_image(), true); let caps = Capabilities::new_with_hints( - ProbeHintsBuilder::default() + ProbeHints::default() .term_program(Some("iTerm.app".into())) - .term_program_version(Some("3.2.0beta5".into())) - .build() - .unwrap(), + .term_program_version(Some("3.2.0beta5".into())), ) .unwrap(); assert_eq!(caps.iterm2_image(), true); diff --git a/termwiz/src/lib.rs b/termwiz/src/lib.rs index ff43b52b2..3aa0cd38f 100644 --- a/termwiz/src/lib.rs +++ b/termwiz/src/lib.rs @@ -46,6 +46,7 @@ pub mod input; pub mod istty; pub mod keymap; pub mod lineedit; +mod macros; mod readbuf; pub mod render; pub mod surface; diff --git a/termwiz/src/lineedit/mod.rs b/termwiz/src/lineedit/mod.rs index 84aae0da3..8de200607 100644 --- a/termwiz/src/lineedit/mod.rs +++ b/termwiz/src/lineedit/mod.rs @@ -34,12 +34,11 @@ //! Ctrl-W | Delete word leading up to cursor //! Alt-b, Alt-Left | Move the cursor backwards one word //! Alt-f, Alt-Right | Move the cursor forwards one word -use crate::caps::{Capabilities, ProbeHintsBuilder}; +use crate::caps::{Capabilities, ProbeHints}; use crate::cell::unicode_column_width; use crate::input::{InputEvent, KeyCode, KeyEvent, Modifiers}; use crate::surface::{Change, Position}; use crate::terminal::{new_terminal, Terminal}; -use anyhow::Error; use unicode_segmentation::GraphemeCursor; mod actions; @@ -118,14 +117,12 @@ impl LineEditor { /// editor: /// /// ```no_run - /// use termwiz::caps::{Capabilities, ProbeHintsBuilder}; + /// use termwiz::caps::{Capabilities, ProbeHints}; /// use termwiz::terminal::new_terminal; /// use anyhow::Error; /// // Disable mouse input in the line editor - /// let hints = ProbeHintsBuilder::new_from_env() - /// .mouse_reporting(Some(false)) - /// .build() - /// .map_err(Error::msg)?; + /// let hints = ProbeHints::new_from_env() + /// .mouse_reporting(Some(false)); /// let caps = Capabilities::new_with_hints(hints)?; /// let terminal = new_terminal(caps)?; /// # Ok::<(), Error>(()) @@ -561,10 +558,7 @@ impl LineEditor { /// Create a `Terminal` with the recommended settings, and use that /// to create a `LineEditor` instance. pub fn line_editor() -> anyhow::Result> { - let hints = ProbeHintsBuilder::new_from_env() - .mouse_reporting(Some(false)) - .build() - .map_err(Error::msg)?; + let hints = ProbeHints::new_from_env().mouse_reporting(Some(false)); let caps = Capabilities::new_with_hints(hints)?; let terminal = new_terminal(caps)?; Ok(LineEditor::new(terminal)) diff --git a/termwiz/src/macros.rs b/termwiz/src/macros.rs new file mode 100644 index 000000000..c76e98331 --- /dev/null +++ b/termwiz/src/macros.rs @@ -0,0 +1,30 @@ +#[doc(hidden)] +#[macro_export] +macro_rules! builder { + ( + $( #[ $( $meta:tt )* ] )* + $vis:vis struct $name:ident { + $( + $( #[doc=$doc:expr] )* + $field:ident : $type:ty, + )* + } + ) => { + $( #[ $( $meta )* ] )* + $vis struct $name { + $( + $( #[doc=$doc] )* + $field : $type, + )* + } + + impl $name { + $( + pub fn $field(mut self, value: $type) -> Self { + self.$field = value; + self + } + )* + } + } +} diff --git a/termwiz/src/render/terminfo.rs b/termwiz/src/render/terminfo.rs index 7fbc5e233..114bf8eb0 100644 --- a/termwiz/src/render/terminfo.rs +++ b/termwiz/src/render/terminfo.rs @@ -671,7 +671,7 @@ impl TerminfoRenderer { #[cfg(all(test, unix))] mod test { use super::*; - use crate::caps::ProbeHintsBuilder; + use crate::caps::ProbeHints; use crate::color::{AnsiColor, ColorAttribute, RgbColor}; use crate::escape::parser::Parser; use crate::escape::{Action, Esc, EscCode}; @@ -692,25 +692,15 @@ mod test { // Load our own compiled data so that the tests have an // environment that doesn't vary machine by machine. let data = include_bytes!("../../data/xterm-256color"); - Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .terminfo_db(Some( - terminfo::Database::from_buffer(data.as_ref()).unwrap(), - )) - .build() - .unwrap(), - ) + Capabilities::new_with_hints(ProbeHints::default().terminfo_db(Some( + terminfo::Database::from_buffer(data.as_ref()).unwrap(), + ))) .unwrap() } fn no_terminfo_all_enabled() -> Capabilities { - Capabilities::new_with_hints( - ProbeHintsBuilder::default() - .color_level(Some(ColorLevel::TrueColor)) - .build() - .unwrap(), - ) - .unwrap() + Capabilities::new_with_hints(ProbeHints::default().color_level(Some(ColorLevel::TrueColor))) + .unwrap() } struct FakeTty {