楼主: 苏印
14 0

Rust 命令行待办工具 [推广有奖]

  • 0关注
  • 0粉丝

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
10 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-9-15
最后登录
2018-9-15

楼主
苏印 发表于 2025-11-16 13:23:00 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

Rust项目实战- 命令行待办工具全解析

一、项目概述

1.1 项目背景

Rust 兼备内存安全与高效性能。此项目利用 Rust 构建命令行待办工具,不仅发挥 Rust 的性能优势,而且通过合理的设计满足日常待办管理的需求,后续增加了优先级管理和关键词搜索功能,进一步提高了工具的实用性。

1.2 核心功能

基础功能: 添加、查看、标记完成、删除待办,数据以 JSON 格式保存在本地文件中,确保持久化,重启工具数据不会丢失。

todo.json

新增功能:
优先级管理:提供 Low/Medium/High 三个级别的优先级,添加待办时可以指定优先级,查看待办时按照优先级降序排列。
关键词搜索:增加搜索命令,根据关键词筛选待办内容,搜索不区分大小写,结果按优先级排序显示。

1.3 技术栈

基础语法: 变量、函数、结构体、枚举、循环、条件判断。

第三方库:

clap
:解析命令行参数,支持子命令和可选参数配置。
serde
+
serde_json
:实现 JSON 数据的序列化与反序列化,用于待办数据的读写。
chrono
:处理时间,记录待办创建时间,支持时间格式转换。

标准库: 文件 IO(

std::fs
)用于读写本地文件,
std::path
处理文件路径,错误处理(
Result
类型)应对各种异常情况。

二、环境准备

2.1 安装依赖工具

工具 版本要求 安装方法 验证命令
Rust 工具链 1.70+ 官网下载
rustup-init
,默认安装
rustc --version

三、项目初始化与配置

3.1 创建项目

打开终端,运行以下命令创建 Rust 项目:
cargo new rust_todo_cli
cd rust_todo_cli

生成的初始目录结构如下:
rust_todo_cli/
├─ src/
│ └─ main.rs # 主程序文件,处理命令行交互逻辑
└─ Cargo.toml # 项目配置文件,管理依赖与项目信息

3.2 配置依赖

修改

Cargo.toml
文件,在
[dependencies]
下添加所需的第三方库依赖:
[package]
name = "rust_todo_cli"
version = "0.1.0"
edition = "2021"

[dependencies]
# 命令行参数解析(支持子命令与参数配置)
clap = { version = "4.0", features = ["derive"] }
# JSON 序列化/反序列化(处理待办数据存储)
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
# 时间处理(记录待办创建时间)
chrono = { version = "0.4", features = ["serde", "std"] }

3.3 模块导出配置

新建

src/lib.rs
文件,用于导出自定义模块,便于
main.rs
调用:
// src/lib.rs
pub mod todo; // 导出 todo 模块,包含待办数据结构与核心操作

四、核心代码实现

4.1 待办数据结构与核心操作(src/todo.rs)

use chrono::{DateTime, Local, Utc};
use serde::{Deserialize, Serialize};
use std::fmt;
use std::fs;
use std::path::Path;
use std::str::FromStr;

// 待办优先级枚举(支持排序、序列化、命令行参数解析)
#[derive(Debug, Serialize, Deserialize, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum Priority {
    Low,    // 低优先级
    Medium, // 中优先级(默认)
    High,   // 高优先级
}

// 待办任务状态:未完成/已完成
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
pub enum TodoStatus {
    Pending,   // 未完成
    Completed, // 已完成
}

// 待办任务结构体(包含优先级字段)
#[derive(Debug, Serialize, Deserialize, Clone)]
pub struct Todo {
    pub id: usize,                // 唯一序号(用于标记/删除)
    pub content: String,          // 任务内容
    pub created_at: DateTime, // 创建时间(UTC 时间,避免时区问题)
    pub status: TodoStatus,       // 任务状态
    pub priority: Priority,       // 任务优先级
}

// 待办列表(封装待办的核心操作)
#[derive(Debug, Serialize, Deserialize)]
pub struct TodoList {
    pub todos: Vec, // 存储所有待办
}

// 优先级相关方法(图标转换、文字描述、默认值、命令行解析)
impl Priority {
    // 优先级转图标(用于友好显示)
    pub fn to_icon(&self) -> &str {
        match self {
            Priority::Low => "????",
```

Priority::Medium => "中等",
Priority::High => "高",
}
}
// 优先级转换为文字描述(用于终端输出)
pub fn to_str(&self) -> &str {
match self {
Priority::Low => "低",
Priority::Medium => "中等",
Priority::High => "高",
}
}
}
// 实现 Display 特性(枚举转换为字符串,支持 clap 命令行参数显示)
impl fmt::Display for Priority {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Priority::Low => write!(f, "Low"),
Priority::Medium => write!(f, "Medium"),
Priority::High => write!(f, "High"),
}
}
}
// 实现 FromStr 特性(字符串转换为枚举,支持 clap 解析用户输入)
impl FromStr for Priority {
type Err = String;
fn from_str(s: &str) -> Result {
match s.to_lowercase().as_str() {
"low" => Ok(Priority::Low),
"medium" => Ok(Priority::Medium),
"high" => Ok(Priority::High),
_ => Err(format!(
"无效的优先级:{}!仅支持 Low/Medium/High(不区分大小写)",
s
)),
}
}
}
// 为优先级实现默认值(默认为中等优先级)
impl Default for Priority {
fn default() -> Self {
Priority::Medium
}
}
// 待办列表核心操作实现
impl TodoList {
// 1. 从本地文件加载待办列表(文件不存在则返回空列表)
pub fn load_from_file(file_path: &str) -> Result> {
if !Path::new(file_path).exists() {
return Ok(Self { todos: Vec::new() });
}
let content = fs::read_to_string(file_path)?;
let todo_list: Self = serde_json::from_str(&content)?;
Ok(todo_list)
}
// 2. 保存待办列表到本地文件(JSON 格式,带缩进便于阅读)
pub fn save_to_file(&self, file_path: &str) -> Result<(), Box> {
let content = serde_json::to_string_pretty(self)?;
fs::write(file_path, content)?;
Ok(())
}
// 3. 添加新待办(支持指定优先级,默认为中等优先级)
pub fn add_todo(&mut self, content: String, priority: Priority) {
let new_id = self.todos.last().map(|t| t.id + 1).unwrap_or(1);
let new_todo = Todo {
id: new_id,
content,
created_at: Utc::now(),
status: TodoStatus::Pending,
priority,
};
self.todos.push(new_todo);
}
// 4. 标记待办为已完成(通过 ID 查找,未找到则返回错误)
pub fn complete_todo(&mut self, todo_id: usize) -> Result<(), String> {
let todo = self
.todos
.iter_mut()
.find(|t| t.id == todo_id)

.ok_or_else(|| format!("未能找到 ID 为 {} 的待办事项", todo_id))?

todo.status = TodoStatus::Completed;

Ok(())

}

// 5. 移除待办事项(通过 ID 过滤,找不到则返回错误)

pub fn delete_todo(&mut self, todo_id: usize) -> Result<(), String> {

let initial_len = self.todos.len();

self.todos.retain(|t| t.id != todo_id);

if self.todos.len() == initial_len {

return Err(format!("未能找到 ID 为 {} 的待办事项", todo_id));

}

Ok(())

}

// 6. 展示所有待办事项(按优先级降序排列,包含状态、优先级、时间信息)

pub fn display(&self) {

if self.todos.is_empty() {

println!("???? 暂无待办事项,快来添加一个吧!");

return;

}

let mut sorted_todos = self.todos.clone();

// 按优先级降序排列(High > Medium > Low)

sorted_todos.sort_by(|a, b| b.priority.cmp(&a.priority));

println!("???? 你的待办列表(总计 {} 项任务,按优先级排列):", sorted_todos.len());

for todo in sorted_todos {

let status_icon = match todo.status {

TodoStatus::Pending => "????",

TodoStatus::Completed => "????",

};

let priority_icon = todo.priority.to_icon();

let priority_str = todo.priority.to_str();

// UTC 时间转换为本地时间

let local_time = todo.created_at.with_timezone(&Local);

let time_str = local_time.format("%Y-%m-%d %H:%M:%S").to_string();

println!(

"{} {} ID: {} | 内容: {} | 优先级: {} | 创建时间: {}",

status_icon, priority_icon, todo.id, todo.content, priority_str, time_str

);

}

}

// 7. 关键词搜索待办事项(忽略大小写,返回匹配结果)

pub fn search(&self, keyword: &str) -> Vec<Todo> {

let lower_keyword = keyword.to_lowercase();

self.todos

.iter()

.filter(|todo| todo.content.to_lowercase().contains(&lower_keyword))

.cloned()

.collect()

}

// 8. 展示搜索结果(按优先级排序,无结果时提供友好提示信息)

pub fn display_search_results(&self, keyword: &str) {

let results = self.search(keyword);

if results.is_empty() {

println!("???? 未发现包含关键词「{}」的待办事项", keyword);

return;

}

let mut sorted_results = results;

sorted_results.sort_by(|a, b| b.priority.cmp(&a.priority));

println!(

"???? 共找到 {} 项包含关键词「{}」的待办事项:",

sorted_results.len(),

keyword

);

for todo in sorted_results {

let status_icon = match todo.status {

TodoStatus::Pending => "????",

TodoStatus::Completed => "????",

};

let priority_icon = todo.priority.to_icon();

let priority_str = todo.priority.to_str();
let local_time = todo.created_at.with_timezone(&Local);
let time_str = local_time.format("%Y-%m-%d %H:%M:%S").to_string();
println!(
"{} {} ID: {} | 内容: {} | 优先级: {} | 创建时间: {}",
status_icon, priority_icon, todo.id, todo.content, priority_str, time_str
);
}
}
}
4.2 命令行交互逻辑(src/main.rs)
use clap::Parser;
use rust_todo_cli::todo::{Priority, TodoList};
// 定义命令行参数结构(支持 add/list/complete/delete/search 子命令)
#[derive(Parser, Debug)]
#[command(author, version, about = "Rust 命令行待办工具(支持优先级+搜索)", long_about = None)]
enum TodoCommand {
/// 添加新待办(示例:todo add "买牛奶" -p High)
Add {
/// 待办任务内容
content: String,
/// 任务优先级(可选,默认 中等)
#[arg(short = 'p', long = "priority", default_value_t = Priority::Medium)]
priority: Priority,
},
/// 查看所有待办(按优先级排序)
List,
/// 标记待办为已完成(示例:todo complete 1)
Complete {
/// 待办ID
id: usize,
},
/// 删除待办(示例:todo delete 1)
Delete {
/// 待办ID
id: usize,
},
/// 搜索待办(示例:todo search "Rust")
Search {
/// 搜索关键词(不区分大小写)
keyword: String,
},
}
// 本地待办数据存储路径(当前目录下的 todo.json)
const TODO_FILE_PATH: &str = "todo.json";
fn main() {
// 解析命令行参数
let command = TodoCommand::parse();
// 加载本地待办列表(处理加载错误)
let mut todo_list = match TodoList::load_from_file(TODO_FILE_PATH) {
Ok(list) => list,
Err(e) => {
eprintln!("? 加载待办列表失败:{}", e);
return;
}
};
// 根据不同命令执行对应操作
match command {
TodoCommand::Add { content, priority } => {
todo_list.add_todo(content.clone(), priority);
if todo_list.save_to_file(TODO_FILE_PATH).is_ok() {
println!(
"? 成功添加待办:{} | 优先级:{}",
content, priority.to_str()
);
} else {
eprintln!("? 保存待办失败,请重新尝试!");
}
}
TodoCommand::List => {
todo_list.display();
}
TodoCommand::Complete { id } => {
match todo_list.complete_todo(id) {
Ok(_) => {
if todo_list.save_to_file(TODO_FILE_PATH).is_ok() {
println!("? 成功标记 ID {} 为已完成!", id);
} else {
eprintln!("? 保存状态失败,请重新尝试!");
}
}
Err(e) => eprintln!("? 标记失败:{}", e),
}
}
TodoCommand::Delete { id } => {
match todo_list.delete_todo(id) {
Ok(_) => {
if todo_list.save_to_file(TODO_FILE_PATH).is_ok() {
println!("? 成功删除 ID {} 的待办!", id);
} else {
    
eprintln!("? 未能保存删除结果,请再次尝试!");
    }
    }
    Err(e) => eprintln!("? 删除失败:{}", e),
    }
    }
    TodoCommand::Search { keyword } => {
        todo_list.display_search_results(&keyword);
    }
    }
    }
    五、项目运行与测试
    5.1 基本命令格式
    所有指令需在
    
rust_todo_cli
项目文件夹下执行,格式为
cargo run -- 子命令 参数
,各项功能对应的命令如下: 功能 命令实例 描述 添加任务
cargo run -- add "买牛奶"
添加默认优先级(中等)的任务 添加特定优先级任务
cargo run -- add "完成 Rust 项目" -p High
添加高优先级任务 查看任务
cargo run -- list
显示所有任务,按优先级降序排列 标记完成
cargo run -- complete 1
标记 ID 为 1 的任务为已完成 删除任务
cargo run -- delete 1
删除 ID 为 1 的任务 搜索任务
cargo run -- search "Rust"
搜索内容包含 “Rust” 的任务,不区分大小写 5.2 完整测试流程 步骤 1:添加不同优先级任务 # 添加高优先级任务 cargo run -- add "完成 Rust 命令行工具开发" -p High # 添加中优先级任务(默认) cargo run -- add "学习 Rust 序列化库 serde" # 添加低优先级任务 cargo run -- add "整理项目文档" -p Low 执行后终端输出: ? 成功添加任务:完成 Rust 命令行工具开发 | 优先级:高 ? 成功添加任务:学习 Rust 序列化库 serde | 优先级:中 ? 成功添加任务:整理项目文档 | 优先级:低 步骤 2:查看任务列表(验证优先级排序) 执行查看命令:
cargo run -- list
输出结果(按优先级 高 > 中 > 低 排序,含状态、优先级图标与时间):
???? 你的待办列表(共 3 个任务,按优先级排序):
???? ???? ID: 1 | 内容: 完成 Rust 命令行工具开发 | 优先级: 高 | 创建时间: 2025-11-04 19:53:27
???? ???? ID: 2 | 内容: 学习 Rust 序列化库 serde | 优先级: 中 | 创建时间: 2025-11-04 19:55:35
???? ???? ID: 3 | 内容: 整理项目文档 | 优先级: 低 | 创建时间: 2025-11-04 19:55:45
说明 :状态图标 “????” 表示未完成,优先级图标 “????/????/????” 对应高 / 中 / 低优先级,时间已转换为本地时区。 步骤 3:标记任务为已完成 执行标记命令(标记 ID=2 的任务):
cargo run -- complete 2
输出结果:
? 成功标记 ID 2 为已完成!
再次查看任务(
cargo run -- list
),ID=2 的状态图标变为 “????”:
???? 你的待办列表(共 3 个任务,按优先级排序):
???? ???? ID: 1 | 内容: 完成 Rust 命令行工具开发 | 优先级: 高 | 创建时间: 2025-11-04 19:53:27
???? ???? ID: 2 | 内容: 学习 Rust 序列化库 serde | 优先级: 中 | 创建时间: 2025-11-04 19:55:35
???? ???? ID: 3 | 内容: 整理项目文档 | 优先级: 低 | 创建时间: 2025-11-04 19:55:45
步骤 4:测试搜索功能(不区分大小写) 场景 1:搜索包含 “Rust” 的任务 执行搜索命令:
cargo run -- search "Rust"
输出结果(匹配 ID=1 和 ID=2 的任务):
???? 找到 2 个包含关键词「Rust」的待办任务:
???? ???? ID: 1 | 内容: 完成 Rust 命令行工具开发 | 优先级: 高 | 创建时间: 2025-11-04 19:53:27
???? ???? ID: 2 | 内容: 学习 Rust 序列化库 serde | 优先级: 中 | 创建时间: 2025-11-04 19:55:35
场景 2:搜索小写关键词 “rust”(验证不区分大小写) 执行搜索命令:
cargo run -- search "rust"
输出结果与场景 1 一致,说明搜索不区分大小写。 场景 3:搜索不存在的关键词(如 “Java”) 执行搜索命令:
cargo run -- search "Java"
输出友好提示:
???? 未找到包含关键词「Java」的待办任务
步骤 5:删除任务 执行删除命令(删除 ID=3 的低优先级任务):
cargo run -- delete 3
输出结果:
? 成功删除 ID 3 的待办!
查看任务(
cargo run -- list
),ID=3 的任务已移除:
你的待办列表(共 2 个任务,按优先级排序):
???? ???? ID: 1 | 内容: 完成 Rust 命令行工具开发 | 优先级: 高 | 创建时间: 2025-11-04 19:53:27
???? ???? ID: 2 | 内容: 学习 Rust 序列化库 serde | 优先级: 中 | 创建时间: 2025-11-04 19:55:35
5.3 数据持久化验证 任务数据存储在项目根目录的
todo.json
文件中,打开文件可查看 JSON 格式的持久化数据(带缩进,便于人类阅读):
{
  "todos": [
    {
      "id": 1,
      "content": "完成 Rust 命令行工具开发",
      "created_at": "2025-11-04T11:53:27.248706900Z",
      "status": "Pending",
      "priority": "High"
    },
    {
      "id": 2,
      "content": "学习 Rust 序列化库 serde",
      "created_at": "2025-11-04T11:55:35.909026300Z",
      "status": "Completed",
      "priority": "Medium"
    }
  ]
}
关键验证点 : 重启终端或电脑后,重新执行
cargo run -- list
,数据依然存在; 新增 / 删除 / 标记操作后,
todo.json
会自动更新,确保数据与操作一致。 六、常见问题与解决方案 常见问题 原因分析 解决方案 执行
cargo run
报错 “找不到 todo 模块” 未创建
src/lib.rs
或未导出
todo
模块 确保
src/lib.rs
中存在
pub mod todo;
代码 添加任务时优先级参数不生效 优先级参数值拼写错误(如
--priority high
写成
--priority hight
) 优先级参数仅支持
Low
/
Medium
/
High
(不区分大小写),检查拼写是否正确 搜索结果为空但任务存在 关键词与任务内容完全不匹配,或存在特殊字符(如空格、符号) 简化关键词(如用 “Rust” 代替 “Rust 开发”),或检查任务内容是否包含目标关键词
todo.json
文件损坏导致加载失败 手动修改
todo.json
时格式错误(如缺少逗号、引号不匹配) 删除损坏的
todo.json
文件,重新添加任务(或从备份恢复正确的 JSON 格式) 终端显示乱码(如图标不显示) 终端不支持 Unicode 字符(如 Windows 旧版 CMD) 改用 Windows Terminal 或 PowerShell,或在
todo.rs
中替换图标为文字(如 “高” 代替 “????”) 七、项目总结 7.1 核心技术收获 Rust 语法实践

:理解结构体、枚举、trait(如

Default
/
PartialOrd
)、错误处理(
Result
类别、
?
运算符)的实际运用; 第三方库的应用 :了解
clap
命令行解析、
serde
JSON 序列化、
chrono
时间处理的主要 API; 工程化思路 :通过模块划分(
todo.rs
封装关键逻辑、
main.rs
管理交互)实现代码分离,通过 JSON 持久化保障数据安全。

7.2 工具应用场景 此工具适合开发者日常任务管理,特别是需要划分任务重要性(如 “紧急开发需求” 为高优先级、“文档整理” 为低优先级)的情况,命令行操作便捷且无需图形界面,可以融入终端工作流程。 通过本项目的构建与改进,不仅能够强化 Rust 基础,还能培养从需求分析到实现的全面开发观念,为未来更复杂的 Rust 项目(如网络服务、桌面应用程序)奠定基础。 欲获取更多相关信息,请参阅 旋武开源社区

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:completed features datetime Complete Version

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-28 21:31