commit
f9699953e7
11 changed files with 4392 additions and 0 deletions
@ -0,0 +1,13 @@ |
|||||||
|
{ |
||||||
|
"version": "0.2.0", |
||||||
|
"configurations": [ |
||||||
|
{ |
||||||
|
"type": "lldb", |
||||||
|
"request": "launch", |
||||||
|
"name": "Debug", |
||||||
|
"program": "${workspaceFolder}/target/debug/text_editor", |
||||||
|
"args": [], |
||||||
|
"cwd": "${workspaceFolder}" |
||||||
|
} |
||||||
|
] |
||||||
|
} |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,23 @@ |
|||||||
|
[package] |
||||||
|
name = "text_editor" |
||||||
|
version = "0.1.0" |
||||||
|
edition = "2024" |
||||||
|
|
||||||
|
[dependencies] |
||||||
|
# GUI框架 |
||||||
|
egui = "0.31.1" # 用于界面 |
||||||
|
eframe = "0.31.1" # 用于应用框架 |
||||||
|
# 文件系统操作 |
||||||
|
walkdir = "2.4" |
||||||
|
# 文本处理 |
||||||
|
regex = "1.10" |
||||||
|
# Windows特定功能 |
||||||
|
windows = { version = "0.61.1", features = [ |
||||||
|
"Win32_Foundation", |
||||||
|
"Win32_UI_WindowsAndMessaging", |
||||||
|
"Win32_UI_Shell", |
||||||
|
"Win32_Storage_FileSystem", |
||||||
|
] } |
||||||
|
|
||||||
|
serde = { version = "1.0", features = ["derive"] } |
||||||
|
serde_json = "1.0" |
Binary file not shown.
@ -0,0 +1,150 @@ |
|||||||
|
use eframe::egui; |
||||||
|
use serde_json::{Value, to_string_pretty}; |
||||||
|
use std::path::{Path, PathBuf}; |
||||||
|
use walkdir::WalkDir; |
||||||
|
|
||||||
|
pub struct TextEditorApp { |
||||||
|
current_dir: String, |
||||||
|
files: Vec<PathBuf>, |
||||||
|
selected_file: Option<PathBuf>, |
||||||
|
file_content: String, |
||||||
|
} |
||||||
|
|
||||||
|
impl Default for TextEditorApp { |
||||||
|
fn default() -> Self { |
||||||
|
Self { |
||||||
|
current_dir: String::from("C:\\"), // 默认目录
|
||||||
|
files: Vec::new(), |
||||||
|
selected_file: None, |
||||||
|
file_content: String::new(), |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl eframe::App for TextEditorApp { |
||||||
|
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) { |
||||||
|
egui::TopBottomPanel::top("top_panel").show(ctx, |ui| { |
||||||
|
ui.heading("轻量文本编辑器"); |
||||||
|
}); |
||||||
|
|
||||||
|
egui::CentralPanel::default().show(ctx, |ui| { |
||||||
|
ui.horizontal(|ui| { |
||||||
|
// 左侧资源管理器面板
|
||||||
|
egui::SidePanel::left("explorer_panel") |
||||||
|
.resizable(true) |
||||||
|
.default_width(200.0) |
||||||
|
.show_inside(ui, |ui| { |
||||||
|
ui.heading("资源管理器"); |
||||||
|
|
||||||
|
// 目录输入框
|
||||||
|
ui.horizontal(|ui| { |
||||||
|
ui.label("目录:"); |
||||||
|
ui.text_edit_singleline(&mut self.current_dir); |
||||||
|
if ui.button("加载").clicked() { |
||||||
|
self.load_directory(); |
||||||
|
} |
||||||
|
}); |
||||||
|
|
||||||
|
// 文件列表
|
||||||
|
egui::ScrollArea::vertical().show(ui, |ui| { |
||||||
|
let mut clicked_file = None; |
||||||
|
|
||||||
|
for file in &self.files { |
||||||
|
let display_name = file |
||||||
|
.file_name() |
||||||
|
.and_then(|n| n.to_str()) |
||||||
|
.unwrap_or_default(); |
||||||
|
|
||||||
|
if ui |
||||||
|
.selectable_label( |
||||||
|
self.selected_file.as_ref() == Some(file), |
||||||
|
display_name, |
||||||
|
) |
||||||
|
.clicked() |
||||||
|
{ |
||||||
|
clicked_file = Some(file.clone()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if let Some(file) = clicked_file { |
||||||
|
self.selected_file = Some(file.clone()); |
||||||
|
self.load_file_content(&file); |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
// 右侧文本编辑面板
|
||||||
|
egui::CentralPanel::default().show_inside(ui, |ui| { |
||||||
|
ui.heading("文本编辑器"); |
||||||
|
|
||||||
|
// 文本编辑区域
|
||||||
|
egui::ScrollArea::both().show(ui, |ui| { |
||||||
|
ui.text_edit_multiline(&mut self.file_content); |
||||||
|
}); |
||||||
|
|
||||||
|
// 转换按钮
|
||||||
|
ui.with_layout(egui::Layout::bottom_up(egui::Align::LEFT), |ui| { |
||||||
|
ui.horizontal(|ui| { |
||||||
|
if ui.button("转换为大写").clicked() { |
||||||
|
self.convert_to_uppercase(); |
||||||
|
} |
||||||
|
if ui.button("转换为小写").clicked() { |
||||||
|
self.convert_to_lowercase(); |
||||||
|
} |
||||||
|
if ui.button("格式化JSON").clicked() { |
||||||
|
self.format_json(); |
||||||
|
} |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
}); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
impl TextEditorApp { |
||||||
|
fn load_directory(&mut self) { |
||||||
|
self.files.clear(); |
||||||
|
self.selected_file = None; |
||||||
|
self.file_content.clear(); |
||||||
|
|
||||||
|
let path = Path::new(&self.current_dir); |
||||||
|
if path.is_dir() { |
||||||
|
for entry in WalkDir::new(path) |
||||||
|
.max_depth(1) |
||||||
|
.into_iter() |
||||||
|
.filter_map(|e| e.ok()) |
||||||
|
{ |
||||||
|
if entry.file_type().is_file() { |
||||||
|
self.files.push(entry.path().to_path_buf()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fn load_file_content(&mut self, file_path: &Path) { |
||||||
|
self.file_content = std::fs::read_to_string(file_path).unwrap_or_default(); |
||||||
|
} |
||||||
|
|
||||||
|
fn convert_to_uppercase(&mut self) { |
||||||
|
self.file_content = self.file_content.to_uppercase(); |
||||||
|
} |
||||||
|
|
||||||
|
fn convert_to_lowercase(&mut self) { |
||||||
|
self.file_content = self.file_content.to_lowercase(); |
||||||
|
} |
||||||
|
|
||||||
|
fn format_json(&mut self) { |
||||||
|
match serde_json::from_str::<Value>(&self.file_content) { |
||||||
|
Ok(parsed) => { |
||||||
|
if let Ok(formatted) = to_string_pretty(&parsed) { |
||||||
|
self.file_content = formatted; |
||||||
|
} |
||||||
|
} |
||||||
|
Err(e) => { |
||||||
|
// 可以在这里添加错误处理,比如显示错误消息
|
||||||
|
println!("JSON 格式化错误: {}", e); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,25 @@ |
|||||||
|
use std::path::{Path, PathBuf}; |
||||||
|
use walkdir::WalkDir; |
||||||
|
|
||||||
|
pub fn list_files_in_dir(path: &str) -> Vec<PathBuf> { |
||||||
|
let mut files = Vec::new(); |
||||||
|
let path = Path::new(path); |
||||||
|
|
||||||
|
if path.is_dir() { |
||||||
|
for entry in WalkDir::new(path) |
||||||
|
.max_depth(1) |
||||||
|
.into_iter() |
||||||
|
.filter_map(|e| e.ok()) |
||||||
|
{ |
||||||
|
if entry.file_type().is_file() { |
||||||
|
files.push(entry.path().to_path_buf()); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
files |
||||||
|
} |
||||||
|
|
||||||
|
pub fn read_file_content(file_path: &Path) -> Option<String> { |
||||||
|
std::fs::read_to_string(file_path).ok() |
||||||
|
} |
@ -0,0 +1,44 @@ |
|||||||
|
mod app; |
||||||
|
use app::TextEditorApp; |
||||||
|
use eframe::egui; |
||||||
|
|
||||||
|
fn main() -> eframe::Result<()> { |
||||||
|
let options = eframe::NativeOptions { |
||||||
|
viewport: egui::ViewportBuilder::default() |
||||||
|
.with_inner_size([1000.0, 600.0]) |
||||||
|
.with_min_inner_size([400.0, 300.0]), |
||||||
|
..Default::default() |
||||||
|
}; |
||||||
|
|
||||||
|
eframe::run_native( |
||||||
|
"轻量文本编辑器", |
||||||
|
options, |
||||||
|
Box::new(|cc| { |
||||||
|
// 使用系统字体
|
||||||
|
let mut fonts = egui::FontDefinitions::default(); |
||||||
|
|
||||||
|
// 添加中文字体
|
||||||
|
fonts.font_data.insert( |
||||||
|
"msyh".to_owned(), |
||||||
|
egui::FontData::from_static(include_bytes!("C:\\Windows\\Fonts\\msyh.ttc")), |
||||||
|
); |
||||||
|
|
||||||
|
// 或者使用系统已安装的字体
|
||||||
|
fonts |
||||||
|
.families |
||||||
|
.entry(egui::FontFamily::Proportional) |
||||||
|
.or_default() |
||||||
|
.insert(0, "Microsoft YaHei".to_owned()); |
||||||
|
|
||||||
|
fonts |
||||||
|
.families |
||||||
|
.entry(egui::FontFamily::Monospace) |
||||||
|
.or_default() |
||||||
|
.push("Microsoft YaHei".to_owned()); |
||||||
|
|
||||||
|
cc.egui_ctx.set_fonts(fonts); |
||||||
|
|
||||||
|
Ok(Box::new(TextEditorApp::default())) |
||||||
|
}), |
||||||
|
) |
||||||
|
} |
@ -0,0 +1,22 @@ |
|||||||
|
use regex::Regex; |
||||||
|
use serde_json::{Value, to_string_pretty}; |
||||||
|
|
||||||
|
pub fn to_uppercase(text: &str) -> String { |
||||||
|
text.to_uppercase() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn to_lowercase(text: &str) -> String { |
||||||
|
text.to_lowercase() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn format_json(text: &str) -> Option<String> { |
||||||
|
match serde_json::from_str::<Value>(text) { |
||||||
|
Ok(parsed) => to_string_pretty(&parsed).ok(), |
||||||
|
Err(_) => None, |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub fn extract_emails(text: &str) -> Vec<String> { |
||||||
|
let re = Regex::new(r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b").unwrap(); |
||||||
|
re.find_iter(text).map(|m| m.as_str().to_string()).collect() |
||||||
|
} |
Loading…
Reference in new issue