Feature suggestion: @if and @for syntax inside of column![]

Hey there. Awesome project.

One thing that I noticed is that view instantly becomes spaghetti as soon as your tree is not static, because you have to break up columns/rows and build them manually. I’ve seen this issue where you expressed dislike against a DSL for view, and I mostly agree (even though I wouldn’t mind a DSL), but I would still suggest some minor syntax features for the column! (and other alike macros).

Example of usage:


columnxx![
    button("Start recording").on_press(Message::StartRecording),

    @if let Some(last) = app.last_rec => {
        text(format!("Updates handled {}", app.updates_handled)).size(12)
    },

    button("Add Progressbar").on_press(Message::AddProgressBar),

    @for (_, prog) in &app.progresses => {
        progress_bar(0.0..=1.0, *prog)
    },
]

Prototype to play around with:

macro_rules! columnxx {
    ($($t:tt)*) => {
        Column::with_children(vecs!($($t)*))
    };
}

macro_rules! vecs {
    (cont $vec:ident @if let $cond:pat = $expr:expr => { $single:expr }, $($other:tt)*) => {
        if let $cond = $expr {
            $vec.push($single.into());
        }
        vecs!(cont $vec $($other)*);
    };
    (cont $vec:ident @if $cond:expr => { $single:expr }, $($other:tt)*) => {
        if $cond {
            $vec.push($single.into());
        }
        vecs!(cont $vec $($other)*);
    };
    (cont $vec:ident @for $var:pat in $rng:expr => { $single:expr }, $($other:tt)*) => {
        for $var in $rng {
            $vec.push($single.into());
        }
        vecs!(cont $vec $($other)*);
    };
    (cont $vec:ident @flat $all:expr, $($other:tt)*) => {
        for el in $all {
            $vec.push(el.into());
        }
        vecs!(cont $vec $($other)*);
    };
    (cont $vec:ident) => {};
    (cont $vec:ident $single:expr, $($other:tt)*) => {
        $vec.push($single.into());
        vecs!(cont $vec $($other)*);
    };
    ($($tt:tt)*) => {{
        let mut vec = std::vec![];
        vecs!(cont vec $($tt)*);
        vec
    }};
}

FWIW the @if can already be expressed on master by just using an Option:

column![
    button("Start recording").on_press(Message::StartRecording),

    if let Some(last) = app.last_rec {
        Some(text(format!("Updates handled {}", app.updates_handled)).size(12))
    } else {
        None
    }
]
2 Likes

Oh I see, interesting. Makes sense but I’ll keep my suggestion here with a loop too.