use kiutils_sexpr::{Atom, Node}; pub fn head(node: &Node) -> Option<&str> { let Node::List { items, .. } = node else { return None; }; items.first().and_then(symbol) } pub fn symbol(node: &Node) -> Option<&str> { match node { Node::Atom { atom: Atom::Symbol(s), .. } => Some(s.as_str()), Node::Atom { atom: Atom::Quoted(s), .. } => Some(s.as_str()), _ => None, } } pub fn children<'a>(node: &'a Node) -> &'a [Node] { match node { Node::List { items, .. } => items, _ => &[], } } pub fn find_list<'a>(parent: &'a Node, head_name: &str) -> Option<&'a Node> { children(parent) .iter() .find(|n| head(n) == Some(head_name)) } pub fn find_lists<'a>(parent: &'a Node, head_name: &str) -> Vec<&'a Node> { children(parent) .iter() .filter(|n| head(n) == Some(head_name)) .collect() } pub fn arg<'a>(list_node: &'a Node, index: usize) -> Option<&'a Node> { children(list_node).get(index + 1) } pub fn arg_f64(list_node: &Node, index: usize) -> Option { arg(list_node, index).and_then(as_f64) } pub fn arg_str<'a>(list_node: &'a Node, index: usize) -> Option<&'a str> { arg(list_node, index).and_then(symbol) } pub fn as_f64(node: &Node) -> Option { symbol(node).and_then(|s| s.parse::().ok()) } pub fn xy_from<'a>(list_node: &'a Node, head_name: &str) -> Option<(f64, f64)> { let l = find_list(list_node, head_name)?; Some((arg_f64(l, 0)?, arg_f64(l, 1)?)) }