mirror of
https://github.com/FliegendeWurst/cursive.git
synced 2024-11-23 17:35:00 +00:00
Add immut! macros
This commit is contained in:
parent
44d9cd5552
commit
333392e034
@ -103,12 +103,14 @@ pub mod event;
|
||||
#[macro_use]
|
||||
pub mod view;
|
||||
|
||||
#[macro_use]
|
||||
pub mod utils;
|
||||
|
||||
pub mod align;
|
||||
pub mod direction;
|
||||
pub mod menu;
|
||||
pub mod rect;
|
||||
pub mod theme;
|
||||
pub mod utils;
|
||||
pub mod vec;
|
||||
pub mod views;
|
||||
|
||||
|
135
src/utils/immutify.rs
Normal file
135
src/utils/immutify.rs
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
|
||||
// TODO: replace the 3 macros with 3 functions once they work correctly with
|
||||
// reference arguments.
|
||||
// (The returned closure must implement the for<'a> Fn(T, U<'a>)...
|
||||
|
||||
|
||||
// TODO: replace the 3 macros/functions with a generic function when it can
|
||||
// accept any number of arguments.
|
||||
|
||||
/// Wraps a `FnMut` into a `Fn`
|
||||
///
|
||||
/// This can be used to use a `FnMut` when a callack expects a `Fn`.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If the resulting `Fn` is called recursively, subsequent calls will be
|
||||
/// no-ops.
|
||||
pub fn immutify<F: FnMut(&mut Cursive)>(
|
||||
f: F,
|
||||
) -> impl for<'s> Fn(&'s mut Cursive) {
|
||||
let callback = RefCell::new(f);
|
||||
move |s| {
|
||||
// Here's the weird trick: if we're already borrowed,
|
||||
// just ignored the callback.
|
||||
if let Ok(mut f) = callback.try_borrow_mut() {
|
||||
// Beeeaaah that's ugly.
|
||||
// Why do we need to manually dereference here?
|
||||
(&mut *f)(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
/// Macro to wrap a `FnMut` with 1 argument into a `Fn`.
|
||||
///
|
||||
/// This can wrap any `FnMut` with a single arguments (for example `&mut Cursive`).
|
||||
///
|
||||
/// See [`immut2!`] and [`immut3!`] to support a different number of arguments.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If this function tries to call itself recursively (for example by
|
||||
/// triggering an event in `Cursive`), the second call will be a no-op.
|
||||
/// Enabling recursive calls would break the `FnMut` contract.
|
||||
///
|
||||
/// In addition, due to weird interaction between Higher-rank trait bounds and
|
||||
/// closures, you should use the result from the macro directly, and not
|
||||
/// assign it to a variable.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[macro_use]
|
||||
/// # extern crate cursive;
|
||||
/// # use cursive::Cursive;
|
||||
/// # fn main() {
|
||||
/// # let mut siv = Cursive::dummy();
|
||||
/// let mut i = 0;
|
||||
/// // `Cursive::add_global_callback` takes a `Fn(&mut Cursive)`
|
||||
/// siv.add_global_callback('q', immut1!(move |s: &mut Cursive| {
|
||||
/// // But here we mutate the environment! Crazy!
|
||||
/// i += 1;
|
||||
/// if i == 5 {
|
||||
/// s.quit();
|
||||
/// }
|
||||
/// }));
|
||||
/// # }
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! immut1 {
|
||||
($f:expr) => {{
|
||||
let callback = ::std::cell::RefCell::new($f);
|
||||
move |s| {
|
||||
if let Ok(mut f) = callback.try_borrow_mut() {
|
||||
(&mut *f)(s)
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro to wrap a `FnMut` with 2 arguments into a `Fn`.
|
||||
///
|
||||
/// This can wrap any `FnMut` with two arguments.
|
||||
///
|
||||
/// See [`immut1!`] and [`immut3!`] to support a different number of arguments.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If this function tries to call itself recursively (for example by
|
||||
/// triggering an event in `Cursive`), the second call will be a no-op.
|
||||
/// Enabling recursive calls would break the `FnMut` contract.
|
||||
///
|
||||
/// In addition, due to weird interaction between Higher-rank trait bounds and
|
||||
/// closures, you should use the result from the macro directly, and not
|
||||
/// assign it to a variable.
|
||||
#[macro_export]
|
||||
macro_rules! immut2 {
|
||||
($f:expr) => {{
|
||||
let callback = ::std::cell::RefCell::new($f);
|
||||
move |s, t| {
|
||||
if let Ok(mut f) = callback.try_borrow_mut() {
|
||||
(&mut *f)(s, t)
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro to wrap a `FnMut` with 3 arguments into a `Fn`.
|
||||
///
|
||||
/// This can wrap any `FnMut` with three arguments.
|
||||
///
|
||||
/// See [`immut1!`] and [`immut2!`] to support a different number of arguments.
|
||||
///
|
||||
/// # Note
|
||||
///
|
||||
/// If this function tries to call itself recursively (for example by
|
||||
/// triggering an event in `Cursive`), the second call will be a no-op.
|
||||
/// Enabling recursive calls would break the `FnMut` contract.
|
||||
///
|
||||
/// In addition, due to weird interaction between Higher-rank trait bounds and
|
||||
/// closures, you should use the result from the macro directly, and not
|
||||
/// assign it to a variable.
|
||||
#[macro_export]
|
||||
macro_rules! immut3 {
|
||||
($f:expr) => {{
|
||||
let callback = ::std::cell::RefCell::new($f);
|
||||
move |s, t, u| {
|
||||
if let Ok(mut f) = callback.try_borrow_mut() {
|
||||
(&mut *f)(s, t, u)
|
||||
}
|
||||
}
|
||||
}};
|
||||
}
|
@ -1,6 +1,8 @@
|
||||
//! Toolbox to make text layout easier.
|
||||
|
||||
mod counter;
|
||||
#[macro_use]
|
||||
mod immutify;
|
||||
pub mod lines;
|
||||
pub mod markup;
|
||||
mod reader;
|
||||
|
@ -236,16 +236,7 @@ impl EditView {
|
||||
where
|
||||
F: FnMut(&mut Cursive, &str, usize) + 'static,
|
||||
{
|
||||
let callback = RefCell::new(callback);
|
||||
// Here's the weird trick: if we're already borrowed,
|
||||
// just ignored the callback.
|
||||
self.set_on_edit(move |s, text, cursor| {
|
||||
if let Ok(mut f) = callback.try_borrow_mut() {
|
||||
// Beeeaaah that's ugly.
|
||||
// Why do we need to manually dereference here?
|
||||
(&mut *f)(s, text, cursor);
|
||||
}
|
||||
});
|
||||
self.set_on_edit(immut3!(callback));
|
||||
}
|
||||
|
||||
/// Sets a callback to be called whenever the content is modified.
|
||||
|
Loading…
Reference in New Issue
Block a user