mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Added doc & examples to utilities types
This commit is contained in:
parent
02c2680eaa
commit
e82f0a077d
@ -1,6 +1,9 @@
|
|||||||
//! Direction-related structures.
|
//! Direction-related structures.
|
||||||
//!
|
//!
|
||||||
//! This module defines two main concepts: [Orientation] and [Direction].
|
//! This module defines two main concepts: [`Orientation`] and [`Direction`].
|
||||||
|
//!
|
||||||
|
//! [`Orientation`]: direction::Orientation
|
||||||
|
//! [`Direction`]: direction::Direction
|
||||||
//!
|
//!
|
||||||
//! ### Orientation
|
//! ### Orientation
|
||||||
//!
|
//!
|
||||||
@ -12,8 +15,16 @@
|
|||||||
//! `Direction` is a bit more complex, and can be of two kinds:
|
//! `Direction` is a bit more complex, and can be of two kinds:
|
||||||
//!
|
//!
|
||||||
//! * Absolute direction: left, up, right, or down
|
//! * Absolute direction: left, up, right, or down
|
||||||
//! * Relative direction: front or back.
|
//! * Relative direction: front or back. Its actual direction depends on the
|
||||||
//! Its actual direction depends on the orientation.
|
//! orientation.
|
||||||
|
//!
|
||||||
|
//! Usually, "front" refers to the "forward" direction, or the "next"
|
||||||
|
//! element. For example, for a vertical `LinearLayout`, "front" would refer
|
||||||
|
//! to the "down" direction.
|
||||||
|
//!
|
||||||
|
//! This is mostly relevant when referring to change of focus. Hitting the
|
||||||
|
//! `Tab` key would usually cycle focus in the "front" direction, while
|
||||||
|
//! using the arrow keys would use absolute directions instead.
|
||||||
|
|
||||||
use vec::Vec2;
|
use vec::Vec2;
|
||||||
use XY;
|
use XY;
|
||||||
@ -51,6 +62,17 @@ impl Orientation {
|
|||||||
|
|
||||||
/// Returns a mutable reference to the component of the given vector
|
/// Returns a mutable reference to the component of the given vector
|
||||||
/// corresponding to this orientation.
|
/// corresponding to this orientation.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let o = Orientation::Horizontal;
|
||||||
|
/// let mut xy = XY::new(1, 2);
|
||||||
|
/// *o.get_ref(&mut xy) = 42;
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(42, 2));
|
||||||
|
/// ```
|
||||||
pub fn get_ref<T>(self, v: &mut XY<T>) -> &mut T {
|
pub fn get_ref<T>(self, v: &mut XY<T>) -> &mut T {
|
||||||
match self {
|
match self {
|
||||||
Orientation::Horizontal => &mut v.x,
|
Orientation::Horizontal => &mut v.x,
|
||||||
@ -61,8 +83,8 @@ impl Orientation {
|
|||||||
/// Takes an iterator on sizes, and stack them in the current orientation,
|
/// Takes an iterator on sizes, and stack them in the current orientation,
|
||||||
/// returning the size of the required bounding box.
|
/// returning the size of the required bounding box.
|
||||||
///
|
///
|
||||||
/// For an horizontal view, returns (Sum(x), Max(y)).
|
/// * For an horizontal view, returns `(Sum(x), Max(y))`.
|
||||||
/// For a vertical view, returns (Max(x),Sum(y)).
|
/// * For a vertical view, returns `(Max(x), Sum(y))`.
|
||||||
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(self, iter: T) -> Vec2 {
|
pub fn stack<'a, T: Iterator<Item = &'a Vec2>>(self, iter: T) -> Vec2 {
|
||||||
match self {
|
match self {
|
||||||
Orientation::Horizontal => {
|
Orientation::Horizontal => {
|
||||||
@ -74,7 +96,24 @@ impl Orientation {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `Vec2` with `value` in `self`'s axis.
|
/// Creates a new `Vec2` with `main_axis` in `self`'s axis, and
|
||||||
|
/// `second_axis` for the other axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let o = Orientation::Horizontal;
|
||||||
|
/// let vec = o.make_vec(1, 2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(vec, Vec2::new(1, 2));
|
||||||
|
///
|
||||||
|
/// let o = Orientation::Vertical;
|
||||||
|
/// let vec = o.make_vec(1, 2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(vec, Vec2::new(2, 1));
|
||||||
|
/// ```
|
||||||
pub fn make_vec(self, main_axis: usize, second_axis: usize) -> Vec2 {
|
pub fn make_vec(self, main_axis: usize, second_axis: usize) -> Vec2 {
|
||||||
let mut result = Vec2::zero();
|
let mut result = Vec2::zero();
|
||||||
*self.get_ref(&mut result) = main_axis;
|
*self.get_ref(&mut result) = main_axis;
|
||||||
@ -97,6 +136,9 @@ pub enum Direction {
|
|||||||
|
|
||||||
impl Direction {
|
impl Direction {
|
||||||
/// Returns the relative direction for the given orientation.
|
/// Returns the relative direction for the given orientation.
|
||||||
|
///
|
||||||
|
/// Some combination have no corresponding relative position. For example,
|
||||||
|
/// `Direction::Abs(Up)` means nothing for `Orientation::Horizontal`.
|
||||||
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
|
pub fn relative(self, orientation: Orientation) -> Option<Relative> {
|
||||||
match self {
|
match self {
|
||||||
Direction::Abs(abs) => abs.relative(orientation),
|
Direction::Abs(abs) => abs.relative(orientation),
|
||||||
@ -151,12 +193,11 @@ impl Direction {
|
|||||||
/// Direction relative to an orientation.
|
/// Direction relative to an orientation.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq)]
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
||||||
pub enum Relative {
|
pub enum Relative {
|
||||||
|
// TODO: handle right-to-left? (Arabic, ...)
|
||||||
/// Front relative direction.
|
/// Front relative direction.
|
||||||
///
|
///
|
||||||
/// * Horizontally, this means `Left`
|
/// * Horizontally, this means `Left`
|
||||||
/// * Vertically, this means `Up`
|
/// * Vertically, this means `Up`
|
||||||
///
|
|
||||||
/// TODO: handle right-to-left?
|
|
||||||
Front,
|
Front,
|
||||||
|
|
||||||
/// Back relative direction.
|
/// Back relative direction.
|
||||||
|
@ -4,7 +4,7 @@ use std::sync::Arc;
|
|||||||
/// Atomic counter used by [`ProgressBar`].
|
/// Atomic counter used by [`ProgressBar`].
|
||||||
///
|
///
|
||||||
/// [`ProgressBar`]: ../views/struct.ProgressBar.html
|
/// [`ProgressBar`]: ../views/struct.ProgressBar.html
|
||||||
#[derive(Clone)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Counter(pub Arc<AtomicUsize>);
|
pub struct Counter(pub Arc<AtomicUsize>);
|
||||||
|
|
||||||
impl Counter {
|
impl Counter {
|
||||||
|
@ -5,6 +5,32 @@ use utils::Counter;
|
|||||||
///
|
///
|
||||||
/// Used to monitor a file downloading or other slow IO task
|
/// Used to monitor a file downloading or other slow IO task
|
||||||
/// in a progress bar.
|
/// in a progress bar.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust,no_run
|
||||||
|
/// use std::io::Read;
|
||||||
|
/// use cursive::utils::{Counter, ProgressReader};
|
||||||
|
///
|
||||||
|
/// // Read a file and report the progress
|
||||||
|
/// let file = std::fs::File::open("large_file").unwrap();
|
||||||
|
/// let counter = Counter::new(0);
|
||||||
|
/// let mut reader = ProgressReader::new(counter.clone(), file);
|
||||||
|
///
|
||||||
|
/// std::thread::spawn(move || {
|
||||||
|
/// // Left as an exercise: use an AtomicBool for a stop condition!
|
||||||
|
/// loop {
|
||||||
|
/// let progress = counter.get();
|
||||||
|
/// println!("Read {} bytes so far", progress);
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
///
|
||||||
|
/// // As we read data, the counter will be updated and the control thread
|
||||||
|
/// // will monitor the progress.
|
||||||
|
/// let mut buffer = Vec::new();
|
||||||
|
/// reader.read_to_end(&mut buffer).unwrap();
|
||||||
|
/// ```
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
pub struct ProgressReader<R: Read> {
|
pub struct ProgressReader<R: Read> {
|
||||||
reader: R,
|
reader: R,
|
||||||
counter: Counter,
|
counter: Counter,
|
||||||
|
209
src/vec.rs
209
src/vec.rs
@ -34,6 +34,13 @@ impl<T: PartialOrd> PartialOrd for XY<T> {
|
|||||||
|
|
||||||
impl XY<usize> {
|
impl XY<usize> {
|
||||||
/// Returns a `Vec2` with `usize::max_value()` in each axis.
|
/// Returns a `Vec2` with `usize::max_value()` in each axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// assert!(Vec2::new(9999, 9999) < Vec2::max_value());
|
||||||
|
/// ```
|
||||||
pub fn max_value() -> Self {
|
pub fn max_value() -> Self {
|
||||||
Self::new(usize::max_value(), usize::max_value())
|
Self::new(usize::max_value(), usize::max_value())
|
||||||
}
|
}
|
||||||
@ -41,6 +48,15 @@ impl XY<usize> {
|
|||||||
/// Saturating subtraction. Computes `self - other`, saturating at 0.
|
/// Saturating subtraction. Computes `self - other`, saturating at 0.
|
||||||
///
|
///
|
||||||
/// Never panics.
|
/// Never panics.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let u = Vec2::new(1, 2);
|
||||||
|
/// let v = Vec2::new(2, 1);
|
||||||
|
/// assert_eq!(u.saturating_sub(v), Vec2::new(0, 1));
|
||||||
|
/// ```
|
||||||
pub fn saturating_sub<O: Into<Self>>(&self, other: O) -> Self {
|
pub fn saturating_sub<O: Into<Self>>(&self, other: O) -> Self {
|
||||||
let other = other.into();
|
let other = other.into();
|
||||||
self.zip_map(other, usize::saturating_sub)
|
self.zip_map(other, usize::saturating_sub)
|
||||||
@ -49,12 +65,22 @@ impl XY<usize> {
|
|||||||
/// Saturating addition with a signed vec.
|
/// Saturating addition with a signed vec.
|
||||||
///
|
///
|
||||||
/// Any coordinates saturates to 0.
|
/// Any coordinates saturates to 0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let u = Vec2::new(1, 2);
|
||||||
|
/// let v = XY::<isize>::new(-2, 1);
|
||||||
|
/// assert_eq!(u.saturating_add(v), Vec2::new(0, 3));
|
||||||
|
/// ```
|
||||||
pub fn saturating_add<O: Into<XY<isize>>>(&self, other: O) -> Self {
|
pub fn saturating_add<O: Into<XY<isize>>>(&self, other: O) -> Self {
|
||||||
let other = other.into();
|
let other = other.into();
|
||||||
|
|
||||||
self.zip_map(other, |s, o| {
|
self.zip_map(other, |s, o| {
|
||||||
if o > 0 {
|
if o > 0 {
|
||||||
s + o as usize
|
s.saturating_add(o as usize)
|
||||||
} else {
|
} else {
|
||||||
s.saturating_sub((-o) as usize)
|
s.saturating_sub((-o) as usize)
|
||||||
}
|
}
|
||||||
@ -62,6 +88,15 @@ impl XY<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Term-by-term integer division that rounds up.
|
/// Term-by-term integer division that rounds up.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let u = Vec2::new(1, 6);
|
||||||
|
/// let v = Vec2::new(2, 3);
|
||||||
|
/// assert_eq!(u.div_up(v), Vec2::new(1, 2));
|
||||||
|
/// ```
|
||||||
pub fn div_up<O>(&self, other: O) -> Self
|
pub fn div_up<O>(&self, other: O) -> Self
|
||||||
where
|
where
|
||||||
O: Into<Self>,
|
O: Into<Self>,
|
||||||
@ -74,6 +109,15 @@ impl XY<usize> {
|
|||||||
/// Returns `None` if `self.x < other.x || self.y < other.y`.
|
/// Returns `None` if `self.x < other.x || self.y < other.y`.
|
||||||
///
|
///
|
||||||
/// Never panics.
|
/// Never panics.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let xy = Vec2::new(1, 2);
|
||||||
|
/// assert_eq!(xy.checked_sub((1, 1)), Some(Vec2::new(0, 1)));
|
||||||
|
/// assert_eq!(xy.checked_sub((2, 2)), None);
|
||||||
|
/// ```
|
||||||
pub fn checked_sub<O: Into<Self>>(&self, other: O) -> Option<Self> {
|
pub fn checked_sub<O: Into<Self>>(&self, other: O) -> Option<Self> {
|
||||||
let other = other.into();
|
let other = other.into();
|
||||||
if self.fits(other) {
|
if self.fits(other) {
|
||||||
@ -84,6 +128,18 @@ impl XY<usize> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a `XY<isize>` from `self`.
|
/// Returns a `XY<isize>` from `self`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let v: XY<isize> = Vec2::new(1, 2).signed().map(|i| i - 5);
|
||||||
|
/// assert_eq!(v, XY::new(-4, -3));
|
||||||
|
///
|
||||||
|
/// let u = Vec2::new(3, 4);
|
||||||
|
/// assert_eq!(u.saturating_add(v), Vec2::new(0, 1));
|
||||||
|
/// ```
|
||||||
pub fn signed(self) -> XY<isize> {
|
pub fn signed(self) -> XY<isize> {
|
||||||
self.into()
|
self.into()
|
||||||
}
|
}
|
||||||
@ -95,6 +151,16 @@ impl<T: Ord> XY<T> {
|
|||||||
/// Shortcut for `self.x <= other.x && self.y <= other.y`.
|
/// Shortcut for `self.x <= other.x && self.y <= other.y`.
|
||||||
///
|
///
|
||||||
/// If this returns `true`, then `other - self` will not underflow.
|
/// If this returns `true`, then `other - self` will not underflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::new(1, 2);
|
||||||
|
/// assert!(v.fits_in((1, 2)));
|
||||||
|
/// assert!(v.fits_in((3, 3)));
|
||||||
|
/// assert!(!v.fits_in((2, 1)));
|
||||||
|
/// ```
|
||||||
pub fn fits_in<O: Into<Self>>(&self, other: O) -> bool {
|
pub fn fits_in<O: Into<Self>>(&self, other: O) -> bool {
|
||||||
let other = other.into();
|
let other = other.into();
|
||||||
self.x <= other.x && self.y <= other.y
|
self.x <= other.x && self.y <= other.y
|
||||||
@ -105,12 +171,29 @@ impl<T: Ord> XY<T> {
|
|||||||
/// Shortcut for `self.x >= other.x && self.y >= other.y`.
|
/// Shortcut for `self.x >= other.x && self.y >= other.y`.
|
||||||
///
|
///
|
||||||
/// If this returns `true`, then `self - other` will not underflow.
|
/// If this returns `true`, then `self - other` will not underflow.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::new(1, 2);
|
||||||
|
/// assert!(v.fits((1, 2)));
|
||||||
|
/// assert!(v.fits((0, 0)));
|
||||||
|
/// assert!(!v.fits((2, 1)));
|
||||||
|
/// ```
|
||||||
pub fn fits<O: Into<Self>>(&self, other: O) -> bool {
|
pub fn fits<O: Into<Self>>(&self, other: O) -> bool {
|
||||||
let other = other.into();
|
let other = other.into();
|
||||||
self.x >= other.x && self.y >= other.y
|
self.x >= other.x && self.y >= other.y
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new Vec2 that is a maximum per coordinate.
|
/// Returns a new Vec2 that is a maximum per coordinate.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// assert_eq!(Vec2::max((1, 2), (3, 1)), Vec2::new(3, 2));
|
||||||
|
/// ```
|
||||||
pub fn max<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
|
pub fn max<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
|
||||||
let a = a.into();
|
let a = a.into();
|
||||||
let b = b.into();
|
let b = b.into();
|
||||||
@ -118,6 +201,13 @@ impl<T: Ord> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new Vec2 that is no larger than any input in both dimensions.
|
/// Returns a new Vec2 that is no larger than any input in both dimensions.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// assert_eq!(Vec2::min((1, 2), (3, 1)), Vec2::new(1, 1));
|
||||||
|
/// ```
|
||||||
pub fn min<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
|
pub fn min<A: Into<XY<T>>, B: Into<XY<T>>>(a: A, b: B) -> Self {
|
||||||
let a = a.into();
|
let a = a.into();
|
||||||
let b = b.into();
|
let b = b.into();
|
||||||
@ -125,11 +215,15 @@ impl<T: Ord> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the minimum of `self` and `other`.
|
/// Returns the minimum of `self` and `other`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `Vec2::min(self, other)`.
|
||||||
pub fn or_min<O: Into<XY<T>>>(self, other: O) -> Self {
|
pub fn or_min<O: Into<XY<T>>>(self, other: O) -> Self {
|
||||||
Self::min(self, other)
|
Self::min(self, other)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the maximum of `self` and `other`.
|
/// Returns the maximum of `self` and `other`.
|
||||||
|
///
|
||||||
|
/// This is equivalent to `Vec2::max(self, other)`.
|
||||||
pub fn or_max<O: Into<XY<T>>>(self, other: O) -> Self {
|
pub fn or_max<O: Into<XY<T>>>(self, other: O) -> Self {
|
||||||
Self::max(self, other)
|
Self::max(self, other)
|
||||||
}
|
}
|
||||||
@ -165,16 +259,39 @@ impl<T: Ord + Add<Output = T> + Clone> XY<T> {
|
|||||||
|
|
||||||
impl<T: Zero + Clone> XY<T> {
|
impl<T: Zero + Clone> XY<T> {
|
||||||
/// Returns a vector with the X component of self, and y=0.
|
/// Returns a vector with the X component of self, and y=0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.keep_x(), XY::new(1, 0));
|
||||||
|
/// ```
|
||||||
pub fn keep_x(&self) -> Self {
|
pub fn keep_x(&self) -> Self {
|
||||||
Self::new(self.x.clone(), T::zero())
|
Self::new(self.x.clone(), T::zero())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector with the Y component of self, and x=0.
|
/// Returns a vector with the Y component of self, and x=0.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.keep_y(), XY::new(0, 2));
|
||||||
|
/// ```
|
||||||
pub fn keep_y(&self) -> Self {
|
pub fn keep_y(&self) -> Self {
|
||||||
Self::new(T::zero(), self.y.clone())
|
Self::new(T::zero(), self.y.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Alias for `Self::new(0,0)`.
|
/// Alias for `Self::new(0,0)`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// assert_eq!(Vec2::zero(), Vec2::new(0, 0));
|
||||||
|
/// ```
|
||||||
pub fn zero() -> Self {
|
pub fn zero() -> Self {
|
||||||
Self::new(T::zero(), T::zero())
|
Self::new(T::zero(), T::zero())
|
||||||
}
|
}
|
||||||
@ -184,6 +301,15 @@ impl<'a, T> From<&'a XY<T>> for XY<T>
|
|||||||
where
|
where
|
||||||
T: Clone,
|
T: Clone,
|
||||||
{
|
{
|
||||||
|
/// Clone a XY
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(String::from("a"), String::from("ab"));
|
||||||
|
/// assert_eq!(XY::from(&xy), xy);
|
||||||
|
/// ```
|
||||||
fn from(t: &'a XY<T>) -> Self {
|
fn from(t: &'a XY<T>) -> Self {
|
||||||
t.clone()
|
t.clone()
|
||||||
}
|
}
|
||||||
@ -194,6 +320,15 @@ impl<T> From<T> for XY<isize>
|
|||||||
where
|
where
|
||||||
T: Into<XY<usize>>,
|
T: Into<XY<usize>>,
|
||||||
{
|
{
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let u = Vec2::new(1, 2);
|
||||||
|
/// let v: XY<isize> = XY::from(u);
|
||||||
|
/// assert_eq!(v, XY::new(1, 2));
|
||||||
|
/// ```
|
||||||
fn from(t: T) -> Self {
|
fn from(t: T) -> Self {
|
||||||
let other = t.into();
|
let other = t.into();
|
||||||
Self::new(other.x as isize, other.y as isize)
|
Self::new(other.x as isize, other.y as isize)
|
||||||
@ -201,24 +336,52 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl From<(i32, i32)> for XY<usize> {
|
impl From<(i32, i32)> for XY<usize> {
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy: XY<isize> = XY::from((-1i32, -2i32));
|
||||||
|
/// assert_eq!(xy, XY::new(-1, -2));
|
||||||
|
/// ```
|
||||||
fn from((x, y): (i32, i32)) -> Self {
|
fn from((x, y): (i32, i32)) -> Self {
|
||||||
(x as usize, y as usize).into()
|
(x as usize, y as usize).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(u32, u32)> for XY<usize> {
|
impl From<(u32, u32)> for XY<usize> {
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::from((1u32, 2u32));
|
||||||
|
/// assert_eq!(v, Vec2::new(1, 2));
|
||||||
|
/// ```
|
||||||
fn from((x, y): (u32, u32)) -> Self {
|
fn from((x, y): (u32, u32)) -> Self {
|
||||||
(x as usize, y as usize).into()
|
(x as usize, y as usize).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(u8, u8)> for XY<usize> {
|
impl From<(u8, u8)> for XY<usize> {
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::from((1u8, 2u8));
|
||||||
|
/// assert_eq!(v, Vec2::new(1, 2));
|
||||||
|
/// ```
|
||||||
fn from((x, y): (u8, u8)) -> Self {
|
fn from((x, y): (u8, u8)) -> Self {
|
||||||
(x as usize, y as usize).into()
|
(x as usize, y as usize).into()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<(u16, u16)> for XY<usize> {
|
impl From<(u16, u16)> for XY<usize> {
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::from((1u16, 2u16));
|
||||||
|
/// assert_eq!(v, Vec2::new(1, 2));
|
||||||
|
/// ```
|
||||||
fn from((x, y): (u16, u16)) -> Self {
|
fn from((x, y): (u16, u16)) -> Self {
|
||||||
(x as usize, y as usize).into()
|
(x as usize, y as usize).into()
|
||||||
}
|
}
|
||||||
@ -232,6 +395,13 @@ where
|
|||||||
{
|
{
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy + (2, 3), XY::new(3, 5));
|
||||||
|
/// ```
|
||||||
fn add(self, other: O) -> Self {
|
fn add(self, other: O) -> Self {
|
||||||
self.zip_map(other.into(), Add::add)
|
self.zip_map(other.into(), Add::add)
|
||||||
}
|
}
|
||||||
@ -244,6 +414,13 @@ where
|
|||||||
{
|
{
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy - (1, 0), XY::new(0, 2));
|
||||||
|
/// ```
|
||||||
fn sub(self, other: O) -> Self {
|
fn sub(self, other: O) -> Self {
|
||||||
self.zip_map(other.into(), Sub::sub)
|
self.zip_map(other.into(), Sub::sub)
|
||||||
}
|
}
|
||||||
@ -252,6 +429,13 @@ where
|
|||||||
impl<T: Clone + Div<Output = T>> Div<T> for XY<T> {
|
impl<T: Clone + Div<Output = T>> Div<T> for XY<T> {
|
||||||
type Output = Self;
|
type Output = Self;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 4);
|
||||||
|
/// assert_eq!(xy / 2, XY::new(0, 2));
|
||||||
|
/// ```
|
||||||
fn div(self, other: T) -> Self {
|
fn div(self, other: T) -> Self {
|
||||||
self.map(|s| s / other.clone())
|
self.map(|s| s / other.clone())
|
||||||
}
|
}
|
||||||
@ -260,6 +444,13 @@ impl<T: Clone + Div<Output = T>> Div<T> for XY<T> {
|
|||||||
impl Mul<usize> for XY<usize> {
|
impl Mul<usize> for XY<usize> {
|
||||||
type Output = Vec2;
|
type Output = Vec2;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::vec::Vec2;
|
||||||
|
/// let v = Vec2::new(1, 2);
|
||||||
|
/// assert_eq!(v * 2, Vec2::new(2, 4));
|
||||||
|
/// ```
|
||||||
fn mul(self, other: usize) -> Vec2 {
|
fn mul(self, other: usize) -> Vec2 {
|
||||||
self.map(|s| s * other)
|
self.map(|s| s * other)
|
||||||
}
|
}
|
||||||
@ -271,6 +462,14 @@ where
|
|||||||
{
|
{
|
||||||
type Output = XY<T::Output>;
|
type Output = XY<T::Output>;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let u = XY::new(1, 2);
|
||||||
|
/// let v = XY::new(2, 3);
|
||||||
|
/// assert_eq!(u * v, XY::new(2, 6));
|
||||||
|
/// ```
|
||||||
fn mul(self, other: XY<T>) -> Self::Output {
|
fn mul(self, other: XY<T>) -> Self::Output {
|
||||||
self.zip_map(other, |s, o| s * o)
|
self.zip_map(other, |s, o| s * o)
|
||||||
}
|
}
|
||||||
@ -281,6 +480,14 @@ where
|
|||||||
{
|
{
|
||||||
type Output = XY<T::Output>;
|
type Output = XY<T::Output>;
|
||||||
|
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let u = XY::new(2, 3);
|
||||||
|
/// let v = XY::new(1, 2);
|
||||||
|
/// assert_eq!(u / v, XY::new(2, 1));
|
||||||
|
/// ```
|
||||||
fn div(self, other: XY<T>) -> Self::Output {
|
fn div(self, other: XY<T>) -> Self::Output {
|
||||||
self.zip_map(other, |s, o| s / o)
|
self.zip_map(other, |s, o| s / o)
|
||||||
}
|
}
|
||||||
|
323
src/xy.rs
323
src/xy.rs
@ -14,6 +14,7 @@ impl<T> IntoIterator for XY<T> {
|
|||||||
type Item = T;
|
type Item = T;
|
||||||
type IntoIter = iter::Chain<iter::Once<T>, iter::Once<T>>;
|
type IntoIter = iter::Chain<iter::Once<T>, iter::Once<T>>;
|
||||||
|
|
||||||
|
/// Iterate over x, then y.
|
||||||
fn into_iter(self) -> Self::IntoIter {
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
iter::once(self.x).chain(iter::once(self.y))
|
iter::once(self.x).chain(iter::once(self.y))
|
||||||
}
|
}
|
||||||
@ -26,11 +27,30 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Swaps the x and y values.
|
/// Swaps the x and y values.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.swap(), XY::new(2, 1));
|
||||||
|
/// ```
|
||||||
pub fn swap(self) -> Self {
|
pub fn swap(self) -> Self {
|
||||||
XY::new(self.y, self.x)
|
XY::new(self.y, self.x)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns `f(self.x, self.y)`
|
/// Returns `f(self.x, self.y)`
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy.fold(std::ops::Add::add), 3);
|
||||||
|
/// assert_eq!(xy.fold(std::ops::Mul::mul), 2);
|
||||||
|
/// assert_eq!(xy.fold(|x, y| x < y), true);
|
||||||
|
/// ```
|
||||||
pub fn fold<U, F>(self, f: F) -> U
|
pub fn fold<U, F>(self, f: F) -> U
|
||||||
where
|
where
|
||||||
F: FnOnce(T, T) -> U,
|
F: FnOnce(T, T) -> U,
|
||||||
@ -39,6 +59,16 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `XY` by applying `f` to `x` and `y`.
|
/// Creates a new `XY` by applying `f` to `x` and `y`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy.map(|v| v * 2), XY::new(2, 4));
|
||||||
|
/// assert_eq!(xy.map(|v| v > 1), XY::new(false, true));
|
||||||
|
/// ```
|
||||||
pub fn map<U, F>(self, f: F) -> XY<U>
|
pub fn map<U, F>(self, f: F) -> XY<U>
|
||||||
where
|
where
|
||||||
F: Fn(T) -> U,
|
F: Fn(T) -> U,
|
||||||
@ -49,6 +79,17 @@ impl<T> XY<T> {
|
|||||||
/// Applies `f` on axis where `condition` is true.
|
/// Applies `f` on axis where `condition` is true.
|
||||||
///
|
///
|
||||||
/// Carries over `self` otherwise.
|
/// Carries over `self` otherwise.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// let cond = XY::new(true, false);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy.map_if(cond, |v| v * 3), XY::new(3, 2));
|
||||||
|
///
|
||||||
|
/// ```
|
||||||
pub fn map_if<F>(self, condition: XY<bool>, f: F) -> Self
|
pub fn map_if<F>(self, condition: XY<bool>, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: Fn(T) -> T,
|
F: Fn(T) -> T,
|
||||||
@ -59,6 +100,16 @@ impl<T> XY<T> {
|
|||||||
/// Applies `f` on axis where `condition` is true.
|
/// Applies `f` on axis where `condition` is true.
|
||||||
///
|
///
|
||||||
/// Returns `None` otherwise.
|
/// Returns `None` otherwise.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// let cond = XY::new(true, false);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy.run_if(cond, |v| v * 3), XY::new(Some(3), None));
|
||||||
|
/// ```
|
||||||
pub fn run_if<F, U>(self, condition: XY<bool>, f: F) -> XY<Option<U>>
|
pub fn run_if<F, U>(self, condition: XY<bool>, f: F) -> XY<Option<U>>
|
||||||
where
|
where
|
||||||
F: Fn(T) -> U,
|
F: Fn(T) -> U,
|
||||||
@ -67,6 +118,14 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `XY` by applying `f` to `x`, and carrying `y` over.
|
/// Creates a new `XY` by applying `f` to `x`, and carrying `y` over.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.map_x(|x| x * 10), XY::new(10, 2));
|
||||||
|
/// ```
|
||||||
pub fn map_x<F>(self, f: F) -> Self
|
pub fn map_x<F>(self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnOnce(T) -> T,
|
F: FnOnce(T) -> T,
|
||||||
@ -75,6 +134,14 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new `XY` by applying `f` to `y`, and carrying `x` over.
|
/// Creates a new `XY` by applying `f` to `y`, and carrying `x` over.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.map_y(|y| y * 10), XY::new(1, 20));
|
||||||
|
/// ```
|
||||||
pub fn map_y<F>(self, f: F) -> Self
|
pub fn map_y<F>(self, f: F) -> Self
|
||||||
where
|
where
|
||||||
F: FnOnce(T) -> T,
|
F: FnOnce(T) -> T,
|
||||||
@ -83,21 +150,65 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Destructure self into a pair.
|
/// Destructure self into a pair.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// let (x, y) = xy.pair();
|
||||||
|
/// assert_eq!((x, y), (1, 2));
|
||||||
|
/// ```
|
||||||
pub fn pair(self) -> (T, T) {
|
pub fn pair(self) -> (T, T) {
|
||||||
(self.x, self.y)
|
(self.x, self.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return a `XY` with references to this one's values.
|
/// Return a `XY` with references to this one's values.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// fn longer(xy: &XY<String>, l: usize) -> XY<bool> {
|
||||||
|
/// // `XY::map` takes ownership
|
||||||
|
/// // So we need to get a XY<&String> from a &XY<String>
|
||||||
|
/// let by_ref: XY<&String> = xy.as_ref();
|
||||||
|
/// by_ref.map(|s| s.len() > l)
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// let xy = XY::new(String::from("a"), String::from("bbb"));
|
||||||
|
///
|
||||||
|
/// assert_eq!(longer(&xy, 2), XY::new(false, true));
|
||||||
|
/// ```
|
||||||
pub fn as_ref(&self) -> XY<&T> {
|
pub fn as_ref(&self) -> XY<&T> {
|
||||||
XY::new(&self.x, &self.y)
|
XY::new(&self.x, &self.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an iterator that returns references to `x`, then `y`.
|
/// Creates an iterator that returns references to `x`, then `y`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// let vec: Vec<bool> = xy.iter().map(|&i| i > 1).collect();
|
||||||
|
/// assert_eq!(vec, vec![false, true]);
|
||||||
|
/// ```
|
||||||
pub fn iter(&self) -> iter::Chain<iter::Once<&T>, iter::Once<&T>> {
|
pub fn iter(&self) -> iter::Chain<iter::Once<&T>, iter::Once<&T>> {
|
||||||
iter::once(&self.x).chain(iter::once(&self.y))
|
iter::once(&self.x).chain(iter::once(&self.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a reference to the value on the given axis.
|
/// Returns a reference to the value on the given axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// assert_eq!(xy.get(Orientation::Horizontal), &1);
|
||||||
|
/// assert_eq!(xy.get(Orientation::Vertical), &2);
|
||||||
|
/// ```
|
||||||
pub fn get(&self, o: Orientation) -> &T {
|
pub fn get(&self, o: Orientation) -> &T {
|
||||||
match o {
|
match o {
|
||||||
Orientation::Horizontal => &self.x,
|
Orientation::Horizontal => &self.x,
|
||||||
@ -106,6 +217,17 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a mutable reference to the value on the given axis.
|
/// Returns a mutable reference to the value on the given axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let mut xy = XY::new(1, 2);
|
||||||
|
/// *xy.get_mut(Orientation::Horizontal) = 10;
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(10, 2));
|
||||||
|
/// ```
|
||||||
pub fn get_mut(&mut self, o: Orientation) -> &mut T {
|
pub fn get_mut(&mut self, o: Orientation) -> &mut T {
|
||||||
match o {
|
match o {
|
||||||
Orientation::Horizontal => &mut self.x,
|
Orientation::Horizontal => &mut self.x,
|
||||||
@ -114,16 +236,49 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` of tuples made by zipping `self` and `other`.
|
/// Returns a new `XY` of tuples made by zipping `self` and `other`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(1, 2);
|
||||||
|
/// let b = XY::new(true, false);
|
||||||
|
/// assert_eq!(a.zip(b), XY::new((1, true), (2, false)));
|
||||||
|
/// ```
|
||||||
pub fn zip<U>(self, other: XY<U>) -> XY<(T, U)> {
|
pub fn zip<U>(self, other: XY<U>) -> XY<(T, U)> {
|
||||||
XY::new((self.x, other.x), (self.y, other.y))
|
XY::new((self.x, other.x), (self.y, other.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` of tuples made by zipping `self`, `a` and `b`.
|
/// Returns a new `XY` of tuples made by zipping `self`, `a` and `b`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(1, 2);
|
||||||
|
/// let b = XY::new(true, false);
|
||||||
|
/// let c = XY::new("x", "y");
|
||||||
|
/// assert_eq!(a.zip3(b, c), XY::new((1, true, "x"), (2, false, "y")));
|
||||||
|
/// ```
|
||||||
pub fn zip3<U, V>(self, a: XY<U>, b: XY<V>) -> XY<(T, U, V)> {
|
pub fn zip3<U, V>(self, a: XY<U>, b: XY<V>) -> XY<(T, U, V)> {
|
||||||
XY::new((self.x, a.x, b.x), (self.y, a.y, b.y))
|
XY::new((self.x, a.x, b.x), (self.y, a.y, b.y))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` of tuples made by zipping `self`, `a`, `b` and `c`.
|
/// Returns a new `XY` of tuples made by zipping `self`, `a`, `b` and `c`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(1, 2);
|
||||||
|
/// let b = XY::new(true, false);
|
||||||
|
/// let c = XY::new("x", "y");
|
||||||
|
/// let d = XY::new(vec![1], vec![2, 3, 4]);
|
||||||
|
/// assert_eq!(
|
||||||
|
/// XY::zip4(a, b, c, d),
|
||||||
|
/// XY::new((1, true, "x", vec![1]), (2, false, "y", vec![2, 3, 4]))
|
||||||
|
/// );
|
||||||
|
/// ```
|
||||||
pub fn zip4<U, V, W>(
|
pub fn zip4<U, V, W>(
|
||||||
self, a: XY<U>, b: XY<V>, c: XY<W>,
|
self, a: XY<U>, b: XY<V>, c: XY<W>,
|
||||||
) -> XY<(T, U, V, W)> {
|
) -> XY<(T, U, V, W)> {
|
||||||
@ -131,6 +286,27 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` of tuples made by zipping `self`, `a`, `b`, `c` and `d`.
|
/// Returns a new `XY` of tuples made by zipping `self`, `a`, `b`, `c` and `d`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(1, 2);
|
||||||
|
/// let b = XY::new(true, false);
|
||||||
|
/// let c = XY::new("x", "y");
|
||||||
|
/// let d = XY::new(vec![1], vec![2, 3, 4]);
|
||||||
|
/// let e = XY::new('a', 'b');
|
||||||
|
///
|
||||||
|
/// let xy: XY<Option<char>> = XY::zip5(a, b, c, d, e)
|
||||||
|
/// .map(|(a, b, c, d, e)| {
|
||||||
|
/// if b && d.contains(&a) {
|
||||||
|
/// Some(e)
|
||||||
|
/// } else {
|
||||||
|
/// c.chars().next()
|
||||||
|
/// }
|
||||||
|
/// });
|
||||||
|
/// assert_eq!(xy, XY::new(Some('a'), Some('y')));
|
||||||
|
/// ```
|
||||||
pub fn zip5<U, V, W, Z>(
|
pub fn zip5<U, V, W, Z>(
|
||||||
self, a: XY<U>, b: XY<V>, c: XY<W>, d: XY<Z>,
|
self, a: XY<U>, b: XY<V>, c: XY<W>, d: XY<Z>,
|
||||||
) -> XY<(T, U, V, W, Z)> {
|
) -> XY<(T, U, V, W, Z)> {
|
||||||
@ -138,6 +314,16 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` by calling `f` on `self` and `other` for each axis.
|
/// Returns a new `XY` by calling `f` on `self` and `other` for each axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new((1, 10), (2, 20));
|
||||||
|
/// let b = XY::new(true, false);
|
||||||
|
/// let xy = a.zip_map(b, |(a1, a2), b| if b { a1 } else { a2 });
|
||||||
|
/// assert_eq!(xy, XY::new(1, 20));
|
||||||
|
/// ```
|
||||||
pub fn zip_map<U, V, F>(self, other: XY<U>, f: F) -> XY<V>
|
pub fn zip_map<U, V, F>(self, other: XY<U>, f: F) -> XY<V>
|
||||||
where
|
where
|
||||||
F: Fn(T, U) -> V,
|
F: Fn(T, U) -> V,
|
||||||
@ -146,6 +332,16 @@ impl<T> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// For each axis, keep the element from `self` if `keep` is `true`.
|
/// For each axis, keep the element from `self` if `keep` is `true`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(1, 2);
|
||||||
|
/// let cond = XY::new(true, false);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy.keep(cond), XY::new(Some(1), None));
|
||||||
|
/// ```
|
||||||
pub fn keep(self, keep: XY<bool>) -> XY<Option<T>> {
|
pub fn keep(self, keep: XY<bool>) -> XY<Option<T>> {
|
||||||
keep.select(self)
|
keep.select(self)
|
||||||
}
|
}
|
||||||
@ -153,6 +349,16 @@ impl<T> XY<T> {
|
|||||||
|
|
||||||
impl<T: Clone> XY<T> {
|
impl<T: Clone> XY<T> {
|
||||||
/// Returns a new `XY` with the axis `o` set to `value`.
|
/// Returns a new `XY` with the axis `o` set to `value`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let xy = XY::new(1, 2).with_axis(Orientation::Horizontal, 42);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(42, 2));
|
||||||
|
/// ```
|
||||||
pub fn with_axis(&self, o: Orientation, value: T) -> Self {
|
pub fn with_axis(&self, o: Orientation, value: T) -> Self {
|
||||||
let mut new = self.clone();
|
let mut new = self.clone();
|
||||||
*o.get_ref(&mut new) = value;
|
*o.get_ref(&mut new) = value;
|
||||||
@ -160,6 +366,17 @@ impl<T: Clone> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new `XY` with the axis `o` set to the value from `other`.
|
/// Returns a new `XY` with the axis `o` set to the value from `other`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let other = XY::new(3, 4);
|
||||||
|
/// let xy = XY::new(1, 2).with_axis_from(Orientation::Horizontal, &other);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(3, 2));
|
||||||
|
/// ```
|
||||||
pub fn with_axis_from(&self, o: Orientation, other: &Self) -> Self {
|
pub fn with_axis_from(&self, o: Orientation, other: &Self) -> Self {
|
||||||
let mut new = self.clone();
|
let mut new = self.clone();
|
||||||
new.set_axis_from(o, other);
|
new.set_axis_from(o, other);
|
||||||
@ -167,66 +384,158 @@ impl<T: Clone> XY<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the axis `o` on `self` to the value from `other`.
|
/// Sets the axis `o` on `self` to the value from `other`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// # use cursive::direction::Orientation;
|
||||||
|
/// let mut xy = XY::new(1, 2);
|
||||||
|
/// let other = XY::new(3, 4);
|
||||||
|
/// xy.set_axis_from(Orientation::Horizontal, &other);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(3, 2));
|
||||||
|
/// ```
|
||||||
pub fn set_axis_from(&mut self, o: Orientation, other: &Self) {
|
pub fn set_axis_from(&mut self, o: Orientation, other: &Self) {
|
||||||
*o.get_ref(self) = o.get(other);
|
*o.get_ref(self) = o.get(other);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Creates a `XY` with both `x` and `y` set to `value`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::both_from(42);
|
||||||
|
///
|
||||||
|
/// assert_eq!(xy, XY::new(42, 42));
|
||||||
|
/// ```
|
||||||
|
pub fn both_from(value: T) -> Self {
|
||||||
|
let x = value.clone();
|
||||||
|
let y = value;
|
||||||
|
XY::new(x, y)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> XY<Option<T>> {
|
impl<T> XY<Option<T>> {
|
||||||
/// Returns a new `XY` by calling `unwrap_or` on each axis.
|
/// Returns a new `XY` by calling `unwrap_or` on each axis.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let xy = XY::new(Some(1), None);
|
||||||
|
/// assert_eq!(xy.unwrap_or(XY::new(10, 20)), XY::new(1, 20));
|
||||||
|
/// ```
|
||||||
pub fn unwrap_or(self, other: XY<T>) -> XY<T> {
|
pub fn unwrap_or(self, other: XY<T>) -> XY<T> {
|
||||||
self.zip_map(other, Option::unwrap_or)
|
self.zip_map(other, Option::unwrap_or)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl XY<bool> {
|
impl XY<bool> {
|
||||||
|
// Could also be called "either"
|
||||||
/// Returns `true` if any of `x` or `y` is `true`.
|
/// Returns `true` if any of `x` or `y` is `true`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// assert_eq!(XY::new(true, false).any(), true);
|
||||||
|
/// assert_eq!(XY::new(false, false).any(), false);
|
||||||
|
/// assert_eq!(XY::new('a', 'b').map(|c| c == 'a').any(), true);
|
||||||
|
/// ```
|
||||||
pub fn any(self) -> bool {
|
pub fn any(self) -> bool {
|
||||||
use std::ops::BitOr;
|
use std::ops::BitOr;
|
||||||
self.fold(BitOr::bitor)
|
self.fold(BitOr::bitor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Could also be called "all"
|
||||||
/// Returns `true` if both `x` and `y` are `true`.
|
/// Returns `true` if both `x` and `y` are `true`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// assert_eq!(XY::new(true, false).both(), false);
|
||||||
|
/// assert_eq!(XY::new(true, true).both(), true);
|
||||||
|
/// assert_eq!(XY::new("abc", "de").map(|s| s.len() > 2).both(), false);
|
||||||
|
/// ```
|
||||||
pub fn both(self) -> bool {
|
pub fn both(self) -> bool {
|
||||||
use std::ops::BitAnd;
|
use std::ops::BitAnd;
|
||||||
self.fold(BitAnd::bitand)
|
self.fold(BitAnd::bitand)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For each axis, keeps elements from `other` if `self` is `true`.
|
/// For each axis, keeps elements from `other` if `self` is `true`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let choice = XY::new(true, false);
|
||||||
|
/// let values = XY::new(1, 2);
|
||||||
|
/// let selection = choice.select(values);
|
||||||
|
///
|
||||||
|
/// assert_eq!(selection, XY::new(Some(1), None));
|
||||||
|
/// ```
|
||||||
pub fn select<T>(self, other: XY<T>) -> XY<Option<T>> {
|
pub fn select<T>(self, other: XY<T>) -> XY<Option<T>> {
|
||||||
self.zip_map(other, |keep, o| if keep { Some(o) } else { None })
|
self.zip_map(other, |keep, o| if keep { Some(o) } else { None })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// For each axis, selects `if_true` if `self` is true, else `if_false`.
|
/// For each axis, selects `if_true` if `self` is true, else `if_false`.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let choice = XY::new(true, false);
|
||||||
|
/// let values = XY::new(1, 2);
|
||||||
|
/// let fallback = XY::new(3, 4);
|
||||||
|
/// let selection = choice.select_or(values, fallback);
|
||||||
|
///
|
||||||
|
/// assert_eq!(selection, XY::new(1, 4));
|
||||||
|
/// ```
|
||||||
pub fn select_or<T>(self, if_true: XY<T>, if_false: XY<T>) -> XY<T> {
|
pub fn select_or<T>(self, if_true: XY<T>, if_false: XY<T>) -> XY<T> {
|
||||||
self.select(if_true).unwrap_or(if_false)
|
self.select(if_true).unwrap_or(if_false)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a term-by-term AND operation.
|
/// Returns a term-by-term AND operation.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(true, false);
|
||||||
|
/// let b = XY::new(true, true);
|
||||||
|
/// assert_eq!(a.and(b), XY::new(true, false));
|
||||||
|
/// ```
|
||||||
pub fn and(self, other: Self) -> Self {
|
pub fn and(self, other: Self) -> Self {
|
||||||
self.zip_map(other, |s, o| s && o)
|
self.zip_map(other, |s, o| s && o)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a term-by-term OR operation.
|
/// Returns a term-by-term OR operation.
|
||||||
|
///
|
||||||
|
/// # Examples
|
||||||
|
///
|
||||||
|
/// ```rust
|
||||||
|
/// # use cursive::XY;
|
||||||
|
/// let a = XY::new(true, false);
|
||||||
|
/// let b = XY::new(true, true);
|
||||||
|
/// assert_eq!(a.or(b), XY::new(true, true));
|
||||||
|
/// ```
|
||||||
pub fn or(self, other: Self) -> Self {
|
pub fn or(self, other: Self) -> Self {
|
||||||
self.zip_map(other, |s, o| s || o)
|
self.zip_map(other, |s, o| s || o)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Copy> XY<T> {
|
|
||||||
/// Creates a `XY` with both `x` and `y` set to `value`.
|
|
||||||
pub fn both_from(value: T) -> Self {
|
|
||||||
XY::new(value, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T> From<(T, T)> for XY<T> {
|
impl<T> From<(T, T)> for XY<T> {
|
||||||
|
/// A pair is assumed to be (x, y)
|
||||||
fn from((x, y): (T, T)) -> Self {
|
fn from((x, y): (T, T)) -> Self {
|
||||||
XY::new(x, y)
|
XY::new(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T, U> From<(XY<T>, XY<U>)> for XY<(T, U)> {
|
impl<T, U> From<(XY<T>, XY<U>)> for XY<(T, U)> {
|
||||||
|
/// Easily zip a pair of XY into a XY of pair
|
||||||
fn from((t, u): (XY<T>, XY<U>)) -> Self {
|
fn from((t, u): (XY<T>, XY<U>)) -> Self {
|
||||||
t.zip(u)
|
t.zip(u)
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user