{"id":25530,"date":"2024-09-29T18:38:30","date_gmt":"2024-09-29T09:38:30","guid":{"rendered":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25530"},"modified":"2024-09-29T18:38:32","modified_gmt":"2024-09-29T09:38:32","slug":"rust-todo-list","status":"publish","type":"post","link":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25530","title":{"rendered":"Rust Todo-list"},"content":{"rendered":"\n<h3 class=\"wp-block-heading\">1. \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4f5c\u6210\u3068\u4f9d\u5b58\u95a2\u4fc2\u306e\u8ffd\u52a0<\/h3>\n\n\n\n<p>\u307e\u305a\u3001Rust\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\u3057\u3001\u5fc5\u8981\u306a\u30af\u30ec\u30fc\u30c8\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<br><code>argo new advanced_todo_list<br>cd advanced_todo_list<br><\/code><\/pre>\n\n\n\n<p><code>Cargo.toml<\/code>\u306b\u4ee5\u4e0b\u306e\u4f9d\u5b58\u95a2\u4fc2\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">toml\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<br><code>[dependencies]<br>serde = { version = \"1.0\", features = [\"derive\"] }<br>serde_json = \"1.0\"<br>clap = { version = \"4.0\", features = [\"derive\"] }<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">2. \u30b3\u30fc\u30c9\u5168\u4f53\u306e\u5b9f\u88c5<\/h3>\n\n\n\n<p>\u6b21\u306b\u3001<code>src\/main.rs<\/code>\u306b\u4ee5\u4e0b\u306e\u30b3\u30fc\u30c9\u3092\u8a18\u8ff0\u3057\u307e\u3059\u3002<code>clap<\/code>\u3092\u4f7f\u3063\u3066\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570\u3092\u51e6\u7406\u3059\u308b\u3088\u3046\u306b\u5909\u66f4\u3057\u3066\u3044\u307e\u3059\u3002<\/p>\n\n\n\n<pre class=\"wp-block-preformatted\">use clap::{Parser, Subcommand};<br>use serde::{Serialize, Deserialize};<br>use std::fs::OpenOptions;<br>use std::io::{self, Read, Write};<br>use std::time::SystemTime;<br><br>#[derive(Serialize, Deserialize, Debug)]<br>struct TodoItem {<br>    id: usize,<br>    task: String,<br>    description: String,<br>    priority: String, \/\/ e.g., \"High\", \"Medium\", \"Low\"<br>    due_date: Option&lt;String>, \/\/ Due date in \"YYYY-MM-DD\" format<br>    completed: bool,<br>    created_at: SystemTime,<br>}<br><br>impl TodoItem {<br>    fn new(id: usize, task: String, description: String, priority: String, due_date: Option&lt;String>) -> Self {<br>        TodoItem {<br>            id,<br>            task,<br>            description,<br>            priority,<br>            due_date,<br>            completed: false,<br>            created_at: SystemTime::now(),<br>        }<br>    }<br><br>    fn mark_as_completed(&amp;mut self) {<br>        self.completed = true;<br>    }<br>}<br><br>#[derive(Parser)]<br>#[command(name = \"Todo List\")]<br>#[command(about = \"A simple todo list application\", long_about = None)]<br>struct Cli {<br>    #[command(subcommand)]<br>    command: Option&lt;Command>,<br>}<br><br>#[derive(Subcommand)]<br>enum Command {<br>    Add {<br>        task: String,<br>        description: String,<br>        priority: String,<br>        due_date: Option&lt;String>,<br>    },<br>    List,<br>    Edit {<br>        id: usize,<br>    },<br>    Delete {<br>        id: usize,<br>    },<br>    Complete {<br>        id: usize,<br>    },<br>}<br><br>fn load_todos() -> Vec&lt;TodoItem> {<br>    let mut file = match OpenOptions::new().read(true).open(\"todos.json\") {<br>        Ok(file) => file,<br>        Err(_) => return Vec::new(),<br>    };<br>    let mut content = String::new();<br>    file.read_to_string(&amp;mut content).unwrap();<br>    serde_json::from_str(&amp;content).unwrap_or(Vec::new())<br>}<br><br>fn save_todos(todos: &amp;Vec&lt;TodoItem>) {<br>    let content = serde_json::to_string_pretty(todos).unwrap();<br>    let mut file = OpenOptions::new().write(true).create(true).truncate(true).open(\"todos.json\").unwrap();<br>    file.write_all(content.as_bytes()).unwrap();<br>}<br><br>fn add_todo(task: String, description: String, priority: String, due_date: Option&lt;String>) {<br>    let mut todos = load_todos();<br>    let id = if todos.is_empty() { 1 } else { todos.last().unwrap().id + 1 };<br>    let new_todo = TodoItem::new(id, task, description, priority, due_date);<br>    todos.push(new_todo);<br>    save_todos(&amp;todos);<br>    println!(\"Task added!\");<br>}<br><br>fn list_todos() {<br>    let mut todos = load_todos();<br>    todos.sort_by(|a, b| a.priority.cmp(&amp;b.priority)); \/\/ Sort by priority<br><br>    for todo in &amp;todos {<br>        println!(<br>            \"[{}] {} - {} (Priority: {}, Due: {}, Completed: {})\",<br>            todo.id,<br>            todo.task,<br>            todo.description,<br>            todo.priority,<br>            todo.due_date.as_deref().unwrap_or(\"N\/A\"),<br>            if todo.completed { \"Yes\" } else { \"No\" }<br>        );<br>    }<br>}<br><br>fn edit_todo(id: usize) {<br>    let mut todos = load_todos();<br><br>    if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {<br>        println!(\"Editing task: {}\", todo.task);<br><br>        let mut new_description = String::new();<br>        println!(\"Enter new description (leave blank to keep current):\");<br>        io::stdin().read_line(&amp;mut new_description).unwrap();<br>        if !new_description.trim().is_empty() {<br>            todo.description = new_description.trim().to_string();<br>        }<br><br>        let mut new_priority = String::new();<br>        println!(\"Enter new priority (High, Medium, Low, leave blank to keep current):\");<br>        io::stdin().read_line(&amp;mut new_priority).unwrap();<br>        if !new_priority.trim().is_empty() {<br>            todo.priority = new_priority.trim().to_string();<br>        }<br><br>        save_todos(&amp;todos);<br>        println!(\"Task updated!\");<br>    } else {<br>        println!(\"Task not found!\");<br>    }<br>}<br><br>fn delete_todo(id: usize) {<br>    let mut todos = load_todos();<br>    todos.retain(|todo| todo.id != id);<br>    save_todos(&amp;todos);<br>    println!(\"Task deleted!\");<br>}<br><br>fn complete_todo(id: usize) {<br>    let mut todos = load_todos();<br><br>    if let Some(todo) = todos.iter_mut().find(|t| t.id == id) {<br>        todo.mark_as_completed();<br>        save_todos(&amp;todos);<br>        println!(\"Task marked as completed!\");<br>    } else {<br>        println!(\"Task not found!\");<br>    }<br>}<br><br>fn main() {<br>    let args = Cli::parse();<br><br>    match args.command {<br>        Some(Command::Add { task, description, priority, due_date }) => {<br>            add_todo(task, description, priority, due_date);<br>        }<br>        Some(Command::List) => {<br>            list_todos();<br>        }<br>        Some(Command::Edit { id }) => {<br>            edit_todo(id);<br>        }<br>        Some(Command::Delete { id }) => {<br>            delete_todo(id);<br>        }<br>        Some(Command::Complete { id }) => {<br>            complete_todo(id);<br>        }<br>        None => {<br>            println!(\"No command provided. Use --help for available commands.\");<br>        }<br>    }<br>}<br><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">3. \u5b9f\u884c\u65b9\u6cd5<\/h3>\n\n\n\n<p>UTF-8\u3067\u4fdd\u5b58\u3055\u308c\u305f\u3053\u306e\u30d5\u30a1\u30a4\u30eb\u3092\u30b3\u30f3\u30d1\u30a4\u30eb\u3057\u3066\u5b9f\u884c\u3057\u307e\u3059\u3002\u30b3\u30de\u30f3\u30c9\u306e\u4f8b\u306f\u4ee5\u4e0b\u306e\u901a\u308a\u3067\u3059\u3002<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>\u65b0\u3057\u3044\u30bf\u30b9\u30af\u306e\u8ffd\u52a0:bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<code>cargo run -- add \"Buy groceries\" \"Buy milk, eggs, and bread\" \"High\" \"2024-10-10\"<\/code><\/li>\n\n\n\n<li>\u30bf\u30b9\u30af\u306e\u30ea\u30b9\u30c8\u8868\u793a:bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<code>cargo run -- list<\/code><\/li>\n\n\n\n<li>\u30bf\u30b9\u30af\u306e\u7de8\u96c6:bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<code>cargo run -- edit 1<\/code><\/li>\n\n\n\n<li>\u30bf\u30b9\u30af\u306e\u524a\u9664:bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<code>cargo run -- delete 1<\/code><\/li>\n\n\n\n<li>\u30bf\u30b9\u30af\u306e\u5b8c\u4e86:bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308b<code>cargo run -- complete 1<\/code><\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">\u8aac\u660e<\/h3>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong><code>clap<\/code>\u30af\u30ec\u30fc\u30c8<\/strong>\u3092\u4f7f\u7528\u3057\u3066\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u5f15\u6570\u306e\u30d1\u30fc\u30b9\u3092\u884c\u3044\u307e\u3059\u3002\u3053\u308c\u306b\u3088\u308a\u3001\u30bf\u30b9\u30af\u306e\u8ffd\u52a0\u3084\u8868\u793a\u3001\u7de8\u96c6\u3001\u524a\u9664\u3001\u5b8c\u4e86\u306a\u3069\u306e\u64cd\u4f5c\u3092\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3\u304b\u3089\u884c\u3046\u3053\u3068\u304c\u3067\u304d\u307e\u3059\u3002<\/li>\n\n\n\n<li><strong>UTF-8\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0<\/strong>\u3067<code>main.rs<\/code>\u3092\u4fdd\u5b58\u3057\u3001\u30a8\u30f3\u30b3\u30fc\u30c7\u30a3\u30f3\u30b0\u30a8\u30e9\u30fc\u3092\u56de\u907f\u3057\u3066\u3044\u307e\u3059\u3002<\/li>\n<\/ul>\n\n\n\n<p>\u3053\u308c\u3067\u3001\u30bf\u30b9\u30af\u306e\u7ba1\u7406\u3092\u884c\u3046\u305f\u3081\u306e\u30b3\u30de\u30f3\u30c9\u30e9\u30a4\u30f3TODO\u30ea\u30b9\u30c8\u30a2\u30d7\u30ea\u30b1\u30fc\u30b7\u30e7\u30f3\u304c\u5b8c\u6210\u3057\u307e\u3057\u305f\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>1. \u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u306e\u4f5c\u6210\u3068\u4f9d\u5b58\u95a2\u4fc2\u306e\u8ffd\u52a0 \u307e\u305a\u3001Rust\u30d7\u30ed\u30b8\u30a7\u30af\u30c8\u3092\u4f5c\u6210\u3057\u3001\u5fc5\u8981\u306a\u30af\u30ec\u30fc\u30c8\u3092\u8ffd\u52a0\u3057\u307e\u3059\u3002 bash\u30b3\u30fc\u30c9\u3092\u30b3\u30d4\u30fc\u3059\u308bargo new advanced_todo_listcd advanced_todo &hellip; <a href=\"http:\/\/www.tyosuke20xx.com\/blog\/?p=25530\" class=\"more-link\"><span class=\"screen-reader-text\">&#8220;Rust Todo-list&#8221; \u306e<\/span>\u7d9a\u304d\u3092\u8aad\u3080<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[137],"tags":[3,136],"class_list":["post-25530","post","type-post","status-publish","format-standard","hentry","category-rust","tag-programming","tag-rust"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25530","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=25530"}],"version-history":[{"count":1,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25530\/revisions"}],"predecessor-version":[{"id":25531,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25530\/revisions\/25531"}],"wp:attachment":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=25530"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=25530"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=25530"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}