Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
use super::collections_search_text::search_text; ← from collections.search-text ^1.0.0 · built alongside by fune
use super::todo_item::{todo_from_value, todos_to_value, Todo}; ← from todo.item ^1.0.0 · built alongside by fune
use super::todo_item_validate_draft::trim_space;
use super::todo_normalise_tags::normalise_tags; ← from todo.normalise-tags ^1.0.0 · built alongside by fune
/// The todos a list shows for its view, tag and search box, in input order.
///
/// The tag is normalised like stored tags, so "#Home" finds "home"; one that
/// normalises to nothing matches no todo. The search covers the title, the
/// notes and the tags joined with spaces (collections.search-text).
///
/// # Panics
/// Panics on an unknown view.
pub fn filter_todos(todos: &[Todo], filter: &TodoFilter) -> Vec<Todo> {
let view = filter.view.as_str();
if view != "all" && view != "active" && view != "completed" {
panic!("unknown view \"{}\": expected all, active or completed", view);
}
let wanted: Option<String> = match &filter.tag {
None => None,
Some(tag) => match normalise_tags(&[tag.clone()]).into_iter().next() {
None => return Vec::new(),
Some(t) => Some(t),
},
};
let kept: Vec<&Todo> = todos
.iter()
.filter(|t| !(view == "active" && t.done) && !(view == "completed" && !t.done))
.filter(|t| wanted.as_ref().map_or(true, |w| t.tags.contains(w)))
.collect();
let query = trim_space(&filter.query);
if query.is_empty() {
return kept.into_iter().cloned().collect();
}
let records: Vec<Value> = kept
.iter()
.enumerate()
.map(|(i, t)| {
Value::obj(vec![
("i", Value::Int(i as i64)),
("title", Value::str(&t.title)),
("notes", t.notes.as_deref().map(Value::str).unwrap_or(Value::Null)),
("tags", Value::Str(t.tags.join(" "))),
])
})
.collect();
let fields = vec!["title".to_string(), "notes".to_string(), "tags".to_string()];
search_text(&records, &fields, query)
.iter()
.map(|r| kept[r.get("i").as_i64() as usize].clone())
.collect()
}
pub fn todo_filter_from_value(v: &Value) -> TodoFilter {
TodoFilter {
view: v.get("view").as_str().to_string(),
tag: if v.get("tag").is_null() { None } else { Some(v.get("tag").as_str().to_string()) },
query: v.get("query").as_str().to_string(),
}
}
pub fn fune_vector(args: &[Value]) -> Value {
let todos: Vec<Todo> = args[0].as_arr().iter().map(todo_from_value).collect();
todos_to_value(&filter_todos(&todos, &todo_filter_from_value(&args[1])))
}