1. プロジェクトの作成と依存関係の追加
まず、Rustプロジェクトを作成し、必要なクレートを追加します。
bashコードをコピーするargo new advanced_todo_list
cd advanced_todo_list
Cargo.tomlに以下の依存関係を追加します。
tomlコードをコピーする[dependencies]
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
clap = { version = "4.0", features = ["derive"] }
2. コード全体の実装
次に、src/main.rsに以下のコードを記述します。clapを使ってコマンドライン引数を処理するように変更しています。
use clap::{Parser, Subcommand};
use serde::{Serialize, Deserialize};
use std::fs::OpenOptions;
use std::io::{self, Read, Write};
use std::time::SystemTime;
#[derive(Serialize, Deserialize, Debug)]
struct TodoItem {
id: usize,
task: String,
description: String,
priority: String, // e.g., "High", "Medium", "Low"
due_date: Option<String>, // Due date in "YYYY-MM-DD" format
completed: bool,
created_at: SystemTime,
}
impl TodoItem {
fn new(id: usize, task: String, description: String, priority: String, due_date: Option<String>) -> Self {
TodoItem {
id,
task,
description,
priority,
due_date,
completed: false,
created_at: SystemTime::now(),
}
}
fn mark_as_completed(&mut self) {
self.completed = true;
}
}
#[derive(Parser)]
#[command(name = "Todo List")]
#[command(about = "A simple todo list application", long_about = None)]
struct Cli {
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Subcommand)]
enum Command {
Add {
task: String,
description: String,
priority: String,
due_date: Option<String>,
},
List,
Edit {
id: usize,
},
Delete {
id: usize,
},
Complete {
id: usize,
},
}
fn load_todos() -> Vec<TodoItem> {
let mut file = match OpenOptions::new().read(true).open("todos.json") {
Ok(file) => file,
Err(_) => return Vec::new(),
};
let mut content = String::new();
file.read_to_string(&mut content).unwrap();
serde_json::from_str(&content).unwrap_or(Vec::new())
}
fn save_todos(todos: &Vec<TodoItem>) {
let content = serde_json::to_string_pretty(todos).unwrap();
let mut file = OpenOptions::new().write(true).create(true).truncate(true).open("todos.json").unwrap();
file.write_all(content.as_bytes()).unwrap();
}
fn add_todo(task: String, description: String, priority: String, due_date: Option<String>) {
let mut todos = load_todos();
let id = if todos.is_empty() { 1 } else { todos.last().unwrap().id + 1 };
let new_todo = TodoItem::new(id, task, description, priority, due_date);
todos.push(new_todo);
save_todos(&todos);
println!("Task added!");
}
fn list_todos() {
let mut todos = load_todos();
todos.sort_by(|a, b| a.priority.cmp(&b.priority)); // Sort by priority
for todo in &todos {
println!(
"[{}] {} - {} (Priority: {}, Due: {}, Completed: {})",
todo.id,
todo.task,
todo.description,
todo.priority,
todo.due_date.as_deref().unwrap_or("N/A"),
if todo.completed { "Yes" } else { "No" }
);
}
}
fn edit_todo(id: usize) {
let mut todos = load_todos();
if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {
println!("Editing task: {}", todo.task);
let mut new_description = String::new();
println!("Enter new description (leave blank to keep current):");
io::stdin().read_line(&mut new_description).unwrap();
if !new_description.trim().is_empty() {
todo.description = new_description.trim().to_string();
}
let mut new_priority = String::new();
println!("Enter new priority (High, Medium, Low, leave blank to keep current):");
io::stdin().read_line(&mut new_priority).unwrap();
if !new_priority.trim().is_empty() {
todo.priority = new_priority.trim().to_string();
}
save_todos(&todos);
println!("Task updated!");
} else {
println!("Task not found!");
}
}
fn delete_todo(id: usize) {
let mut todos = load_todos();
todos.retain(|todo| todo.id != id);
save_todos(&todos);
println!("Task deleted!");
}
fn complete_todo(id: usize) {
let mut todos = load_todos();
if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {
todo.mark_as_completed();
save_todos(&todos);
println!("Task marked as completed!");
} else {
println!("Task not found!");
}
}
fn main() {
let args = Cli::parse();
match args.command {
Some(Command::Add { task, description, priority, due_date }) => {
add_todo(task, description, priority, due_date);
}
Some(Command::List) => {
list_todos();
}
Some(Command::Edit { id }) => {
edit_todo(id);
}
Some(Command::Delete { id }) => {
delete_todo(id);
}
Some(Command::Complete { id }) => {
complete_todo(id);
}
None => {
println!("No command provided. Use --help for available commands.");
}
}
}
3. 実行方法
UTF-8で保存されたこのファイルをコンパイルして実行します。コマンドの例は以下の通りです。
- 新しいタスクの追加:bashコードをコピーする
cargo run -- add "Buy groceries" "Buy milk, eggs, and bread" "High" "2024-10-10" - タスクのリスト表示:bashコードをコピーする
cargo run -- list - タスクの編集:bashコードをコピーする
cargo run -- edit 1 - タスクの削除:bashコードをコピーする
cargo run -- delete 1 - タスクの完了:bashコードをコピーする
cargo run -- complete 1
説明
clapクレートを使用してコマンドライン引数のパースを行います。これにより、タスクの追加や表示、編集、削除、完了などの操作をコマンドラインから行うことができます。- UTF-8エンコーディングで
main.rsを保存し、エンコーディングエラーを回避しています。
これで、タスクの管理を行うためのコマンドラインTODOリストアプリケーションが完成しました。

If I am being honest this is the kind of site I quietly hope my own work will someday resemble, and a stop at shadowglowcorner extended that aspirational feeling, finding work that models what I want to produce is part of why I read carefully and this site has been performing that modelling function for me lately consistently.
Glad to find a site whose links lead somewhere worth going rather than back to itself for SEO juice, and a stop at silverpetalstore kept that generous outbound feel, citing other peoples work with real respect rather than just for ranking signals is a sign of an honest operation worth supporting going forward.
Well crafted post, the structure flows naturally from one point to the next without forcing transitions, and a stop at silverpetalcollective kept the same flow going, you can tell when a writer has thought about how their content reads rather than just what it contains and this is one of those examples.
Now wishing more sites covered topics with this level of care, and a look at velvetorchidmarket extended that wish across more subjects, the rarity of careful coverage on most topics is a problem and this site is one of the small antidotes to that broader pattern of casual or surface treatment of complex subjects.
Skipped the TLDR thinking I would read everything anyway, and ended up enjoying the path through the full post, and a stop at urbanpickcorner similarly rewarded the patient read, summaries are useful but the journey through good writing is part of what makes the destination feel earned rather than just delivered cleanly.
Started reading without much expectation and ended on a high note, and a look at velvetorchidmarket continued that arc, content that builds rather than peaks early is a sign of a writer who knows how to structure a piece for sustained reader engagement rather than relying on a strong hook to do all the work.
Appreciate how nothing here feels copied or pieced together from other places, the voice is consistent and the tone stays human, and after I checked ambergrovecrafts I noticed the same style holds, which is a small detail but it makes the whole experience feel personal rather than like another generic site.
Now adjusting my mental model of how the topic fits into the broader landscape, and a look at neonbuycorner extended that adjustment, content that affects my structural understanding rather than just my factual knowledge is content with deeper impact and this site is providing those structural updates at a meaningful rate consistently across topics.
Strong recommendation, anyone interested in this topic owes themselves a visit, and a stop at echopinecollective extends that recommendation across more of the site, this is the kind of resource that makes me more optimistic about the state of the open web than I usually am these days actually for once which is genuinely refreshing.
Saving the link for sure, this one is a keeper, and a look at digitaldealcorner confirmed I should bookmark the entire site rather than just this page, the consistency across what I have seen so far suggests there is a lot more here worth coming back for soon when I have more time.
Appreciate the work that went into laying this out so clearly, every section earns its place without filler, and a look at nextgentrendzone confirmed the same care, definitely the kind of place that deserves a return visit when the topic comes up again later in the future or for any related question.
Bookmarked the page and the homepage too because clearly there is more to explore here, and a quick stop at velvetcrestmarket only made that more obvious, this is the kind of place I want to dig through over a weekend rather than rushing through during a coffee break tomorrow morning before getting back to work.
Reading this gave me the rare experience of fully agreeing with all the conclusions, and a stop at stylishgoodscorner continued that agreement pattern, content that aligns with my existing views without seeming designed to do so is just content that happens to be reasonable and this site reads as reasonable rather than ideological mostly.
However measured this site clears the bar I set for sites I take seriously, and a stop at hyperdealhub continued clearing that bar, the metrics I use for site quality are admittedly informal but they are consistent and this site has cleared them on multiple measurements across multiple visits which is meaningful for my evaluation.
A modest masterpiece in its own quiet way, and a look at bluecrestemporium confirmed the same quiet quality across the rest of the site, calling something a masterpiece is usually overstating but for content this carefully crafted the word feels appropriate even if the writers themselves would probably resist the label honestly.
Generally my attention drifts on long posts but this one held it through the end, and a stop at epiccartcenter earned the same sustained focus, content that defeats my drift tendency is content with substantive pulling power and this site has demonstrated that pulling power across multiple pieces in a session that has now run quite long actually.
Now considering the post as evidence that careful blog writing is still possible, and a look at copperwindessentials extended that evidence, the broader question of whether the modern web can sustain quality writing has obvious empirical answers in sites like this one and seeing them is reassuring even when they remain a minority overall today.
Most of my reading time goes to a small number of trusted sources and this one is now joining that group, and a stop at infinitybuyhub reinforced the group membership, the few sites that earn a place in my regular rotation are sites I expect ongoing returns from and this one has earned that elevated position consistently.
Honest opinion is that this is the kind of post that builds long term trust with readers, and a look at neonpickmarket reinforced that perception, the slow accumulation of trust through consistent quality is the only sustainable way to build a real audience and this site is clearly playing that long game.
Recommended without reservation for anyone interested in the topic at any level of expertise, and a look at perfectbuycorner only strengthens that recommendation, this site clearly knows how to serve readers across a range of backgrounds without watering down the content or talking past anyone in the audience which is genuinely impressive to see.
Honestly enjoyed reading this more than I expected to when I first clicked through, and a stop at crystalbloommarket kept that pleasant surprise going, sometimes you stumble onto a site that just clicks with how you like to read and this is one of those for me right now today which is great.