use super::node::Node;
use super::prose::{children_slots, Slot};
pub fn iter_with_parent_visit<'a>(
nodes: &'a [Node],
visit: &mut dyn FnMut(&[Slot<'a>], usize, &'a Node),
) {
let top: Vec<Slot<'a>> = nodes.iter().map(Some).collect();
visit_seq(&top, visit);
}
fn visit_seq<'a>(seq: &[Slot<'a>], visit: &mut dyn FnMut(&[Slot<'a>], usize, &'a Node)) {
for (i, &slot) in seq.iter().enumerate() {
let Some(node) = slot else { continue };
visit(seq, i, node);
let children = children_slots(node);
if !children.is_empty() {
visit_seq(&children, visit);
}
}
}
pub fn next_group_arg<'a>(parent: &[Slot<'a>], idx: usize) -> Option<&'a super::node::GroupNode> {
let next = parent.get(idx + 1).copied().flatten()?;
match next {
Node::Group(g) => Some(g),
_ => None,
}
}
pub fn group_text(group: &super::node::GroupNode) -> String {
let mut out = String::new();
for child in &group.nodelist {
if let Node::Chars(c) = child {
out.push_str(&c.chars);
}
}
out.trim().to_string()
}
pub fn macro_args_text<'a>(
macro_node: &super::node::MacroNode,
parent: &[Slot<'a>],
idx: usize,
) -> String {
for arg in ¯o_node.args {
if let Some(Node::Group(g)) = arg {
return group_text(g);
}
}
if let Some(sibling) = next_group_arg(parent, idx) {
return group_text(sibling);
}
String::new()
}