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::todo_item::Todo; ← from todo.item ^1.0.0 · built alongside by fune
use super::todo_item_validate_draft::is_iso_date;
use super::todo_item_validate_todo::{todos_from_value, todos_to_value};
use super::todo_list_add_todo::require_utc_now; ← addTodo, another function of this group · built into the same file, even by a slim install
use super::todo_list_update_todo::index_of_todo; ← updateTodo, another function of this group · built into the same file, even by a slim install
use super::todo_next_occurrence::next_occurrence; ← from todo.next-occurrence ^1.0.0 · built alongside by fune
/// Refuse a today that is not a real YYYY-MM-DD date, whether or not a repeat needs it.
pub fn require_today(today: &str) {
if !is_iso_date(today) {
panic!("today must be a date like 2026-09-28");
}
}
/// Complete one open todo. A one-off is done at `now`; a repeating one stays
/// open and rolls forward to its next occurrence (todo.next-occurrence).
pub fn complete_todo(todo: &Todo, now: &str, today: &str) -> Todo {
let mut next = todo.clone();
match (&todo.recurrence, todo.due.as_deref()) {
(None, _) => {
next.done = true;
next.completed_at = Some(now.to_string());
}
(Some(_), None) => panic!("repeating todo \"{}\" has no due date", todo.id),
(Some(rule), Some(due)) => {
next.done = false;
next.completed_at = None;
next.due = Some(next_occurrence(rule, due, today));
}
}
next
}
/// Tick or untick one todo. Reopening clears the completion time.
///
/// # Panics
/// On an unknown id, a `now` that is not a UTC timestamp or a `today` that is
/// not a date.
pub fn toggle_todo(todos: &[Todo], id: &str, now: &str, today: &str) -> Vec<Todo> {
let at = index_of_todo(todos, id);
require_utc_now(now);
require_today(today);
let mut out = todos.to_vec();
if out[at].done {
out[at].done = false;
out[at].completed_at = None;
} else {
out[at] = complete_todo(&todos[at], now, today);
}
out
}
pub fn fune_vector(args: &[Value]) -> Value {
let todos = todos_from_value(&args[0]);
todos_to_value(&toggle_todo(&todos, args[1].as_str(), args[2].as_str(), args[3].as_str()))
}