cursive-extras 0.13.4

Extra views for the Cursive TUI library as well some helper functions and macros
Documentation
/// Convenience macro that updates the specified `StatusView` reference with an error message and returns
/// from the current callback if an error happens, returns the `Ok` value otherwise
///
/// # Example
/// ```
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(
///     hlayout!(
///         Dialog::text("Yes")
///             .button("Quit", Cursive::quit)
///             .title("Error Reporting example")
///         StatusView::new().with_name("status")
///     )
/// );
/// root.set_fps(30);
/// root.set_global_callback(Event::Refresh, |root| {
///     let error: Result<&str, &str> = Err("Error: Houston, we have a problem!");
///     let mut status = root.find_name::<StatusView>("status").expect("StatusView does not exist!");
///     report_error!(status, error);
///     status.update();
/// });
/// root.run();
/// ```
#[macro_export]
macro_rules! report_error {
    ($status_view:expr, $res_val:expr) => {
        match $res_val {
            Ok(v) => v,
            Err(error) => {
                $status_view.report_error(error);
                return;
            }
        }
    }
}

/// Convenience macro that makes `SelectView`s easier to create
///
/// # Example
/// ```
/// let sv = select_view! {
///     "yes" => true,
///     "no" => false
/// }.on_submit(|r, _| r.quit());
///
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(Dialog::around(sv).title("Select View"));
/// root.run();
/// ```
#[macro_export]
macro_rules! select_view {
    ($($label:expr => $item:expr), *) => {
        {
            let mut temp_sv = $crate::siv::views::SelectView::new();
            $( temp_sv.add_item($label, $item); )*
            temp_sv
        }
    };

    ($($label:expr), *) => {
        select_view!($($label => $label), *)
    }
}

/// Convenience macro that makes `AdvancedSelectView`s easier to create
///
/// # Example
/// ```
/// let adv_sv = adv_select_view! {
///     "yes" => true,
///     "no" => false
/// }.on_submit(|r, _| r.quit());
///
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(Dialog::around(adv_sv).title("Advanced Select View"));
/// root.run();
/// ```
#[cfg(feature = "advanced")]
#[macro_export]
macro_rules! adv_select_view {
    ($($label:expr => $item:expr), *) => {
        {
            let mut temp_sv = $crate::AdvancedSelectView::new();
            $( temp_sv.add_item($label, $item); )*
            temp_sv
        }
    };

    ($($label:expr), *) => {
        adv_select_view!($($label => $label), *)
    }
}

/// Convenience macro to generate a `TabDialog` view
#[cfg(feature = "tabs")]
#[macro_export]
macro_rules! tabs {
    ($($title:expr => $view:expr), *) => {
        $crate::TabDialog::new()
            $( .tab($title, $view) ) *
    }
}

/// Convenience macro to generate a `TabLayer` view
#[cfg(feature = "tabs")]
#[macro_export]
macro_rules! tab_layer {
    ($($title:expr => $view:expr), *) => {
        $crate::TabLayer::new()
            $( .tab($title, $view) ) *
    }
}

/// Convenience macro that creates a horizontal layout of views
///
///  # Example
/// ```
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(
///     Dialog::around(
///         hlayout!(
///             TextView::new("Yes "),
///             TextView::new("No")
///         )
///     )
///     .button("Quit", Cursive::quit)
/// );
/// root.run();
/// ```
#[macro_export]
macro_rules! hlayout {
    ($($view:expr), *) => {
        $crate::siv::views::LinearLayout::horizontal()
            $( .child($view) )*
    };
}

/// Convenience macro that creates a vertical layout of views
///
///  # Example
/// ```
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(
///     Dialog::around(
///         vlayout!(
///             TextView::new("Yes "),
///             TextView::new("No")
///         )
///     )
///     .button("Quit", Cursive::quit)
/// );
/// root.run();
/// ```
#[macro_export]
macro_rules! vlayout {
    ($($view:expr), *) => {
        $crate::siv::views::LinearLayout::vertical()
            $( .child($view) )*
    };
}

/// Convenience macro that wraps a view in a `CircularFocus` that wraps the arrow keys
#[macro_export]
macro_rules! c_focus {
    ($view:expr) => {
        $crate::siv::views::CircularFocus::new($view).wrap_arrows()
    }
}

/// Convenience macro that generates a settings view using sub-views wrapped in a `Dialog` view
///
///  # Example
/// ```
/// let mut root = cursive::default();
/// root.add_fullscreen_layer(
///     settings!(
///         "Settings Example", // title
///         Cursive::quit, // callback if "Save" is selected
///         TextView::new("Option:"), // views
///         EditView::new()
///     )
/// );
/// root.run();
/// ```
#[macro_export]
macro_rules! settings {
    ($title:expr, $save_cb:expr, $($view:expr), *) => {
        $crate::__settings_internal!($title, "Save", $save_cb $(, $view)*)
    };
}

/// Same as the `settings!` macro, but allows for a custom confirmation text to be defined as well
#[macro_export]
macro_rules! settings_cb {
    ($title:expr, $c_bt:expr, $save_cb:expr, $($view:expr), *) => {
        $crate::__settings_internal!($title, $c_bt, $save_cb $(, $view)*)
    };
}

#[macro_export(local_inner_macros)]
#[doc(hidden)]
macro_rules! __settings_internal {
    ($title:expr, $c_bt:expr, $save_cb:expr, $($view:expr), *) => {
        {
            use $crate::siv::{
                traits::{With as _, Scrollable as _},
                views::{Dialog, OnEventView},
                event::{Key, Event}
            };

            $crate::c_focus!(
                Dialog::around(
                    $crate::vlayout!($($view), *)
                        .scrollable()
                        .scroll_x(true)
                )
                    .dismiss_button("Back")
                    .button($c_bt, $save_cb)
                    .title($title)
                    .wrap_with(OnEventView::new)
                    .on_event(Event::Key(Key::Esc), |r| {
                        if r.screen().len() <= 1 {
                            r.quit();
                        }
                        else {
                            r.pop_layer();
                        }
                    })
            )
        }
    };
}