use crate::functions::{
FuncArg, FuncArgType, FunctionArgs, FunctionCtx, FunctionRet, NadiFunctions, NodeFunction,
NodeFunction_TO,
};
use crate::plugins::NadiPlugin;
use crate::prelude::*;
use crate::return_on_err;
use abi_stable::sabi_trait::TD_CanDowncast;
use abi_stable::std_types::{RString, RVec, Tuple2};
use nadi_plugin::node_func;
pub struct AttrsMod;
impl NadiPlugin for AttrsMod {
fn name(&self) -> RString {
"ATTRS".into()
}
fn register(&self, nf: &mut NadiFunctions) {
nf.register_node_function(
"ATTRS",
NodeFunction_TO::from_value(LoadAttrs, TD_CanDowncast),
);
nf.register_alias(
"ATTRS.load_attrs".to_string(),
"load_attrs".to_string(),
::nadi_core::tasks::FunctionType::Node,
);
nf.register_node_function(
"ATTRS",
NodeFunction_TO::from_value(PrintAllAttrs, TD_CanDowncast),
);
nf.register_alias(
"ATTRS.print_all_attrs".to_string(),
"print_all_attrs".to_string(),
::nadi_core::tasks::FunctionType::Node,
);
nf.register_node_function(
"ATTRS",
NodeFunction_TO::from_value(PrintAttrsNode, TD_CanDowncast),
);
nf.register_alias(
"ATTRS.print_attrs".to_string(),
"print_attrs".to_string(),
::nadi_core::tasks::FunctionType::Node,
);
}
}
#[derive(Debug, Clone)]
pub struct LoadAttrs;
impl NodeFunction for LoadAttrs {
fn name(&self) -> RString {
"load_attrs".into()
}
fn help(&self) -> RString {
"Loads attrs from file for all nodes based on the given template
# Arguments
- `filename`: Template for the filename to load node attributes from
- `verbose`: print verbose message
The template will be rendered for each node, and that filename from the
rendered template will be used to load the attributes.
# Errors
The function will error out in following conditions:
- Template for filename is not given,
- The template couldn't be rendered,
- There was error loading attributes from the file.
"
.into()
}
fn args(&self) -> RVec<FuncArg> {
vec![FuncArg {
name: "filename".into(),
ty: "PathBuf".into(),
help: "Template for the filename to load node attributes from".into(),
category: FuncArgType::Arg,
}]
.into()
}
fn call_mut(&self, node: &mut NodeInner, ctx: &FunctionCtx) -> FunctionRet {
let templ: Template = match ctx.arg_kwarg(0, "filename") {
Some(Ok(a)) => a,
Some(Err(e)) => return FunctionRet::Error(e.into()),
None => return FunctionRet::Error("Text template not given".into()),
};
let verbose: bool = match ctx.arg_kwarg(1, "verbose") {
Some(Ok(a)) => a,
Some(Err(e)) => return FunctionRet::Error(e.into()),
None => false,
};
let filepath = match templ.render(node) {
Ok(f) => f,
Err(e) => return FunctionRet::Error(e.to_string().into()),
};
if verbose {
eprintln!("Loadin Attributes from: {filepath}");
}
if let Err(e) = node.load_attr(&filepath) {
FunctionRet::Error(RString::from(e.to_string()))
} else {
FunctionRet::None
}
}
fn code(&self) -> RString {
"".into()
}
}
#[derive(Debug, Clone)]
pub struct PrintAllAttrs;
impl NodeFunction for PrintAllAttrs {
fn name(&self) -> RString {
"print_all_attrs".into()
}
fn help(&self) -> RString {
"Print all attrs in a node
No arguments and no errors, it'll just print all the attributes in a node with
`node::attr=val` format, where,
- node is node name
- attr is attribute name
- val is attribute value (string representation)
"
.into()
}
fn args(&self) -> RVec<FuncArg> {
vec![].into()
}
fn call(&self, node: &NodeInner, _ctx: &FunctionCtx) -> FunctionRet {
for Tuple2(k, v) in node.attr_map() {
println!("{}::{k} = {}", node.name(), v);
}
FunctionRet::None
}
fn code(&self) -> RString {
"".into()
}
}
#[node_func(name = false)]
fn print_attrs(node: &NodeInner, #[args] attrs: FunctionArgs, name: bool) -> FunctionRet {
let attrs = return_on_err!(attrs
.iter()
.map(|t| String::try_from_attr(&t.attribute().map_err(|e| e.to_string())?))
.collect::<Result<Vec<String>, String>>());
for a in attrs {
if let Some(v) = node.attr(&a) {
if name {
print!("{}::", node.name());
}
println!("{a} = {}", v);
}
}
FunctionRet::None
}