Eliminate ~500 lines of duplicate code across 31 files by extracting shared functions, helpers, and consolidating repeated patterns. Highlights: - Toast helpers (toast_info/success/warning/error) on AppStateRest - push_event() helper for turn-event queue (19 callers consolidated) - log_write_edit_tool() shared fn (turn.rs + engine.rs ~50 lines saved) - resolve_api_key() shared fn (spawn.rs + provider.rs) - LSP call_positional() helper on LspClient - lsp_cursor_params() shared schema for 4 tool files -overlay_block() helper for consistent overlay title/border styling - cycle_selected_index(), path_not_found/a_directory() helpers - mark_dirty(), save_settings() on AppStateRest - Remove redundant Err(e) => Err(e) arms in LSP tools - Consolidate generate_workspace_tree (turn.rs → workspace.rs) - Simplify background-review wrapper args in auto/mod.rs Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
79 lines
2.7 KiB
Rust
79 lines
2.7 KiB
Rust
//! Tool for marking tasks as finished in the session's todo list.
|
|
use super::super::{Tool, ToolCtx};
|
|
use anyhow::{anyhow, Result};
|
|
use serde_json::{json, Value};
|
|
use std::path::PathBuf;
|
|
|
|
/// Tool that marks tasks as finished in the session's todo.md.
|
|
pub struct Todofinish;
|
|
|
|
impl Tool for Todofinish {
|
|
fn name(&self) -> &'static str { "todofinish" }
|
|
|
|
fn description(&self) -> &'static str {
|
|
"Mark tasks as finished in the session todo list (todo.md). You can mark all tasks as finished by leaving the 'task_index' empty, or specify a 1-based index to finish a specific task."
|
|
}
|
|
|
|
fn parameters(&self) -> Value {
|
|
json!({
|
|
"type": "object",
|
|
"properties": {
|
|
"task_index": {
|
|
"type": "integer",
|
|
"description": "Optional 1-based index of the task to mark as finished. If omitted, ALL unfinished tasks will be marked as finished."
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
fn run(&self, ctx: &ToolCtx, args: &Value) -> Result<String> {
|
|
let path: PathBuf = ctx.session_dir.join("todo.md");
|
|
if !path.exists() {
|
|
return Ok("No todo.md found in session directory. Nothing to finish.".to_string());
|
|
}
|
|
|
|
let content =
|
|
std::fs::read_to_string(&path).map_err(|e| anyhow!("failed to read todo.md: {e}"))?;
|
|
|
|
let task_index = args.get("task_index").and_then(serde_json::Value::as_i64);
|
|
|
|
let mut new_content = String::new();
|
|
let mut task_count = 0;
|
|
let mut modified = false;
|
|
|
|
for line in content.lines() {
|
|
if line.trim_start().starts_with("- [ ]") {
|
|
task_count += 1;
|
|
if let Some(target) = task_index {
|
|
if task_count == target {
|
|
new_content.push_str(&line.replacen("- [ ]", "- [x]", 1));
|
|
modified = true;
|
|
} else {
|
|
new_content.push_str(line);
|
|
}
|
|
} else {
|
|
// Mark all as finished
|
|
new_content.push_str(&line.replacen("- [ ]", "- [x]", 1));
|
|
modified = true;
|
|
}
|
|
} else {
|
|
new_content.push_str(line);
|
|
}
|
|
new_content.push('\n');
|
|
}
|
|
|
|
if !modified {
|
|
return Ok("No unfinished tasks found or index out of bounds.".to_string());
|
|
}
|
|
|
|
std::fs::write(&path, new_content)
|
|
.map_err(|e| anyhow!("failed to write to todo.md: {e}"))?;
|
|
|
|
if let Some(idx) = task_index {
|
|
Ok(format!("Successfully marked task {idx} as finished."))
|
|
} else {
|
|
Ok("Successfully marked ALL tasks as finished.".to_string())
|
|
}
|
|
}
|
|
}
|