1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
//! A widget based terminal ui rendering library.
//!
//! This crate provides an abstraction over terminal manipulation in the form of the [`Widget`]
//! trait. It also provides some default widgets available in [`widgets`].
//!
//! While this crate was built for the  [`requestty`] crate and other crates which implement the
//! [`Prompt`] trait in [`requestty`], it can be used otherwise as well.
//!
//! [`requestty`]: https://crates.io/crates/requestty
//! [`Prompt`]: https://docs.rs/requestty/0.1.1/requestty/prompt/trait.Prompt.html
//!
//! # Backends
//!
//! This crate currently supports 2 backends:
//! - [`crossterm`](https://crates.io/crates/crossterm)
//! - [`termion`](https://crates.io/crates/termion)
//!
//! The different backends can be enabled using the features of the same name.
#![deny(
    missing_docs,
    missing_debug_implementations,
    unreachable_pub,
    broken_intra_doc_links
)]
#![warn(rust_2018_idioms)]
#![cfg_attr(docsrs, feature(doc_cfg))]

pub use error::{ErrorKind, Result};
pub use input::{Input, OnEsc, Prompt, Validation};
pub use widgets::Widget;

pub mod backend;
mod char_input;
mod error;
pub mod events;
mod input;
pub mod layout;
mod prompt;
mod select;
mod string_input;
pub mod style;
mod text;
pub mod widgets;

/// Some characters used in the `requestty` crate.
#[allow(missing_docs)]
pub mod symbols {
    /// `'❯' U+276F`
    pub const ARROW: char = '❯';
    /// `'›' U+203A`
    pub const SMALL_ARROW: char = '›';
    /// `'✔' U+2714`
    pub const TICK: char = '✔';
    /// `'·' U+00B7`
    pub const MIDDLE_DOT: char = '·';
    /// `'✖' U+2716`
    pub const CROSS: char = '✖';
    /// `'┐' U+2510`
    pub const BOX_LIGHT_TOP_RIGHT: char = '┐';
    /// `'┌' U+250C`
    pub const BOX_LIGHT_TOP_LEFT: char = '┌';
    /// `'┘' U+2518`
    pub const BOX_LIGHT_BOTTOM_RIGHT: char = '┘';
    /// `'└' U+2514`
    pub const BOX_LIGHT_BOTTOM_LEFT: char = '└';
    /// `'─' U+2500`
    pub const BOX_LIGHT_HORIZONTAL: char = '─';
    /// `'│' U+2502`
    pub const BOX_LIGHT_VERTICAL: char = '│';
}

#[doc(hidden)]
pub mod features {
    #[cfg(feature = "crossterm")]
    pub const SNAPSHOT_PATH: &str = "crossterm-snapshots";

    // XXX: Only works when crossterm and termion are the only two available backends
    //
    // Instead of directly checking for termion, we check for not crossterm so that compiling
    // (documentation) with both features enabled will not error
    #[cfg(not(feature = "crossterm"))]
    pub const SNAPSHOT_PATH: &str = "termion-snapshots";
}

/// A testing utility to assert visual equality with [`TestBackend`](backend::TestBackend).
///
/// It is a simple wrapper around [`insta::assert_display_snapshot`] which puts the snapshots in
/// `$CARGO_MANIFEST_DIR/{crossterm/termion}-snapshots`.
///
/// [`insta::assert_display_snapshot`]: https://docs.rs/insta/1.7.1/insta/macro.assert_display_snapshot.html
#[cfg(any(feature = "crossterm", feature = "termion"))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "crossterm", feature = "termion"))))]
#[macro_export]
macro_rules! assert_backend_snapshot {
    ($value:expr, @$snapshot:literal) => {
        $crate::assert_backend_snapshot_impl!(::insta::assert_display_snapshot!($value, @$snapshot))
    };
    ($name:expr, $value:expr) => {
        $crate::assert_backend_snapshot_impl!(::insta::assert_display_snapshot!($name, $value))
    };
    ($value:expr) => {
        $crate::assert_backend_snapshot_impl!(::insta::assert_display_snapshot!($value))
    };

}

#[doc(hidden)]
#[macro_export]
macro_rules! assert_backend_snapshot_impl {
    ($($tt:tt)*) => {{
        ::insta::with_settings!({
            snapshot_path => ::std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join($crate::features::SNAPSHOT_PATH)
        }, {
            $($tt)*
        })
    }}
}

#[cfg(test)]
mod test_consts {
    /// ASCII placeholder text with 470 characters
    pub(crate) static LOREM: &str = "Lorem ipsum dolor sit amet, consectetuer \
        adipiscing elit. Aenean commodo ligula e get dolor. Aenean massa. Cum sociis \
        natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. \
        Donec quam felis, ultricies nec, pellentesque eu, pretium quis, sem. Nulla \
        consequat massa quis enim. Donec pede justo, fringilla vel, aliquet nec, \
        vulputate eget, arcu. In enim justo, rhoncus ut, imperdiet a, venenatis vitae, \
        justo. Nullam dictum felis eu pede mollis pretium.";

    /// Unicode placeholder text with 470 characters
    pub(crate) static UNICODE: &str = "ǹɕǶǽũ ȥűǷŀȷÂǦǨÏNJ ýǡƎƭǃÁžƖţŝŬœĶ ɳƙŁŵŃŋŗ dzÆŅɜŴô ħIJǗɧÝÙĝɸÿ \
        ǝƬDŽƫɌñÄç ɎƷɔȲƧ éďŅǒƿŅ üIJƪɮúǚijǓɔÏǙǟ ǃóıÄ×ȤøŌɘŬ ȃŜʈǑƱļ ȶė÷ƝȣŞýş óɭǽƎȮ ŏŀƔȾřŞȩ \
        ĚïƝƦʀƕĥǡǎÌʅ ĻɠȞīĈưĭÓĢÑ LJĦƷűǐ¾đ ŊǂȘŰƒ ēɄɟɍƬč ɼ·ȄĶȸŦɉ ţĥŐʼnŭ ãɹƠƲɼŒǜ ȹúƄdžȆ ȡǞȐǖŁƀ \
        ėýŭȇȹı ɹûØùž ïȕĆßĀȭ ÍȖȟũȍ ȼƦŚɀʆ ĖDZŞȅŎ ţÎǓŏï ȃāÖćźȀȿ Īŝłƒťƌȇ ǘůńNJļ ǂȄȐǐǻ Ȳɵ¾ǕÉ \
        ɛȃǾȚDZÚ ķĘƄɜÉ êɷƐŻɌ ɐțǼÏƐȄ òɫɥƸâɈ ĄȫĞîĖƿſú¹ ǐȊÜÉį ȬDzɩŎǩĮ ĂȷĎǶŐ ÍɼƔÌűÉĎƣ ÃÜȯƪLJ \
        ȋDzŹǀŊȻ Ɍ¾ȓƃĝ êɊDŽɕÈ ÿ¸ȧȣíÚɁƺ ȏǖŷȡȬ ȍǕȁɜğʆ ƨɺȨƠŇȱƕ ȊÑļɧģŷIJ ʈźçƣƑ ƀǼŌéǔÀ ȊŅɂƵǝ¾ \
        ēɩīűŃɖąɔɳ ȁõıĚņ ȦɂȄƄȥɣŴűǎǃ";
}