Skip to content

Commit b912dad

Browse files
authored
Merge pull request #71 from qianmoQ/dev-25.0.6
feat: 支持自定义语言插件
2 parents 71ba16a + 43b4f88 commit b912dad

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+688
-99
lines changed

src-tauri/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ tauri-build = { version = "2", features = [] }
1414
chrono = { version = "0.4.41", features = ["serde"] }
1515

1616
[dependencies]
17-
tauri = { version = "2.9", features = ["devtools"] }
17+
tauri = { version = "2.9", features = ["devtools", "protocol-asset"] }
1818
tauri-plugin-opener = "2.5"
1919
tauri-plugin-shell = "2.0"
2020
tauri-plugin-dialog = "2.4"

src-tauri/src/config.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ pub struct AppConfig {
4141
pub keep_log_days: Option<u32>,
4242
pub theme: Option<String>,
4343
pub plugins: Option<Vec<PluginConfig>>,
44+
pub custom_plugins: Option<Vec<PluginConfig>>,
4445
pub editor: Option<EditorConfig>,
4546
pub environment_mirror: Option<EnvironmentMirrorConfig>,
4647
pub github: Option<GithubConfig>,
@@ -54,6 +55,7 @@ impl Default for AppConfig {
5455
keep_log_days: Some(30),
5556
theme: Some("system".to_string()),
5657
plugins: Some(vec![]),
58+
custom_plugins: Some(vec![]),
5759
editor: Some(EditorConfig {
5860
indent_with_tab: Some(true),
5961
tab_size: Some(2),
@@ -238,6 +240,7 @@ impl ConfigManager {
238240
keep_log_days: Some(30),
239241
theme: Some("system".to_string()),
240242
plugins: Self::get_default_plugins_config(app_handle),
243+
custom_plugins: Some(vec![]),
241244
editor: Some(EditorConfig {
242245
indent_with_tab: Some(true),
243246
tab_size: Some(2),
@@ -279,6 +282,11 @@ impl ConfigManager {
279282
self.config.log_directory = path;
280283
self.save_config()
281284
}
285+
286+
pub fn update_config(&mut self, new_config: AppConfig) -> Result<(), String> {
287+
self.config = new_config;
288+
self.save_config()
289+
}
282290
}
283291

284292
// 初始化配置
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
use crate::config::{get_app_config_internal, get_config_manager};
2+
use crate::execution::PluginManagerState;
3+
use crate::plugins::PluginConfig;
4+
use crate::plugins::custom::CustomPlugin;
5+
use log::info;
6+
use std::fs;
7+
use tauri::{AppHandle, Emitter, State, command};
8+
9+
#[command]
10+
pub async fn add_custom_plugin(
11+
config: PluginConfig,
12+
app_handle: AppHandle,
13+
plugin_manager: State<'_, PluginManagerState>,
14+
) -> Result<(), String> {
15+
{
16+
let mut guard = get_config_manager()?;
17+
if let Some(config_manager) = guard.as_mut() {
18+
let mut app_config = config_manager.get_config().clone();
19+
20+
let mut custom_plugins = app_config.custom_plugins.unwrap_or_default();
21+
22+
if custom_plugins.iter().any(|p| p.language == config.language) {
23+
return Err(format!("自定义插件 {} 已存在", config.language));
24+
}
25+
26+
custom_plugins.push(config.clone());
27+
app_config.custom_plugins = Some(custom_plugins);
28+
29+
config_manager.update_config(app_config)?;
30+
} else {
31+
return Err("配置管理器未初始化".to_string());
32+
}
33+
}
34+
35+
let mut manager = plugin_manager.lock().await;
36+
let custom_plugin = CustomPlugin::new(config.clone());
37+
manager.register_plugin(config.language.clone(), Box::new(custom_plugin));
38+
39+
app_handle.emit("config-updated", ()).ok();
40+
info!("自定义插件 {} 已添加", config.language);
41+
42+
Ok(())
43+
}
44+
45+
#[command]
46+
pub async fn update_custom_plugin(
47+
config: PluginConfig,
48+
app_handle: AppHandle,
49+
plugin_manager: State<'_, PluginManagerState>,
50+
) -> Result<(), String> {
51+
{
52+
let mut guard = get_config_manager()?;
53+
if let Some(config_manager) = guard.as_mut() {
54+
let mut app_config = config_manager.get_config().clone();
55+
56+
let mut custom_plugins = app_config.custom_plugins.unwrap_or_default();
57+
58+
if let Some(index) = custom_plugins
59+
.iter()
60+
.position(|p| p.language == config.language)
61+
{
62+
custom_plugins[index] = config.clone();
63+
} else {
64+
return Err(format!("自定义插件 {} 不存在", config.language));
65+
}
66+
67+
app_config.custom_plugins = Some(custom_plugins);
68+
69+
config_manager.update_config(app_config)?;
70+
} else {
71+
return Err("配置管理器未初始化".to_string());
72+
}
73+
}
74+
75+
let mut manager = plugin_manager.lock().await;
76+
manager.unregister_plugin(&config.language);
77+
let custom_plugin = CustomPlugin::new(config.clone());
78+
manager.register_plugin(config.language.clone(), Box::new(custom_plugin));
79+
80+
app_handle.emit("config-updated", ()).ok();
81+
info!("自定义插件 {} 已更新", config.language);
82+
83+
Ok(())
84+
}
85+
86+
#[command]
87+
pub async fn remove_custom_plugin(
88+
language: String,
89+
app_handle: AppHandle,
90+
plugin_manager: State<'_, PluginManagerState>,
91+
) -> Result<(), String> {
92+
{
93+
let mut guard = get_config_manager()?;
94+
if let Some(config_manager) = guard.as_mut() {
95+
let mut app_config = config_manager.get_config().clone();
96+
97+
let mut custom_plugins = app_config.custom_plugins.unwrap_or_default();
98+
99+
custom_plugins.retain(|p| p.language != language);
100+
101+
app_config.custom_plugins = Some(custom_plugins);
102+
103+
config_manager.update_config(app_config)?;
104+
} else {
105+
return Err("配置管理器未初始化".to_string());
106+
}
107+
}
108+
109+
let mut manager = plugin_manager.lock().await;
110+
manager.unregister_plugin(&language);
111+
112+
app_handle.emit("config-updated", ()).ok();
113+
info!("自定义插件 {} 已移除", language);
114+
115+
Ok(())
116+
}
117+
118+
#[command]
119+
pub async fn get_custom_plugins() -> Result<Vec<PluginConfig>, String> {
120+
let app_config = get_app_config_internal()?;
121+
Ok(app_config.custom_plugins.unwrap_or_default())
122+
}
123+
124+
#[command]
125+
pub async fn save_custom_icon(
126+
language: String,
127+
icon_data: Vec<u8>,
128+
file_extension: String,
129+
) -> Result<String, String> {
130+
let home_dir = dirs::home_dir().ok_or("无法获取用户主目录")?;
131+
let icons_dir = home_dir.join(".codeforge").join("custom-icons");
132+
133+
fs::create_dir_all(&icons_dir).map_err(|e| format!("创建图标目录失败: {}", e))?;
134+
135+
let icon_path = icons_dir.join(format!("{}.{}", language, file_extension));
136+
137+
fs::write(&icon_path, icon_data).map_err(|e| format!("保存图标文件失败: {}", e))?;
138+
139+
info!("自定义图标已保存: {:?}", icon_path);
140+
141+
Ok(icon_path.to_string_lossy().to_string())
142+
}

src-tauri/src/main.rs

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
mod cache;
77
mod config;
8+
mod custom_plugin_commands;
89
mod env_commands;
910
mod env_manager;
1011
mod env_providers;
@@ -19,6 +20,10 @@ mod update;
1920
mod utils;
2021

2122
use crate::cache::{clear_all_cache, clear_plugins_cache, get_cache_info};
23+
use crate::custom_plugin_commands::{
24+
add_custom_plugin, get_custom_plugins, remove_custom_plugin, save_custom_icon,
25+
update_custom_plugin,
26+
};
2227
use crate::env_commands::{
2328
EnvironmentManagerState, download_and_install_version, get_environment_info,
2429
get_supported_environment_languages, switch_environment_version, uninstall_environment_version,
@@ -70,7 +75,20 @@ fn main() {
7075
eprintln!("Failed to initialize config: {}", e);
7176
}
7277

73-
// 第二步:初始化日志系统
78+
// 第二步:加载自定义插件
79+
use tauri::Manager;
80+
if let Some(plugin_manager_state) = app.try_state::<ExecutionPluginManagerState>() {
81+
if let Ok(mut manager) = plugin_manager_state.try_lock() {
82+
if let Ok(app_config) = config::get_app_config_internal() {
83+
if let Some(custom_plugins) = app_config.custom_plugins {
84+
manager.load_custom_plugins(custom_plugins);
85+
info!("初始化 -> 已加载自定义插件");
86+
}
87+
}
88+
}
89+
}
90+
91+
// 第三步:初始化日志系统
7492
if let Err(e) = logger::setup_logger(app.handle()) {
7593
eprintln!("Failed to setup logger: {}", e);
7694
}
@@ -115,6 +133,12 @@ fn main() {
115133
get_app_config,
116134
update_app_config,
117135
get_config_path,
136+
// 自定义插件相关命令
137+
add_custom_plugin,
138+
update_custom_plugin,
139+
remove_custom_plugin,
140+
get_custom_plugins,
141+
save_custom_icon,
118142
// 缓存相关命令
119143
get_cache_info,
120144
clear_plugins_cache,

src-tauri/src/plugins/applescript.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl LanguagePlugin for AppleScriptPlugin {
4242
template: Some(String::from("-- 在这里输入 AppleScript 代码")),
4343
timeout: Some(45),
4444
console_type: Some(String::from("console")),
45+
icon_path: None,
4546
}
4647
}
4748

src-tauri/src/plugins/c.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl LanguagePlugin for CPlugin {
6767
template: Some(String::from("// 在这里输入 C 代码")),
6868
timeout: Some(30),
6969
console_type: Some(String::from("console")),
70+
icon_path: None,
7071
}
7172
}
7273

src-tauri/src/plugins/cangjie.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ impl LanguagePlugin for CangjiePlugin {
8686
)),
8787
timeout: Some(30),
8888
console_type: Some(String::from("console")),
89+
icon_path: None,
8990
}
9091
}
9192

src-tauri/src/plugins/clojure.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ impl LanguagePlugin for ClojurePlugin {
4242
template: Some(String::from(";; 在这里输入 Clojure 代码")),
4343
timeout: Some(45),
4444
console_type: Some(String::from("console")),
45+
icon_path: None,
4546
}
4647
}
4748

src-tauri/src/plugins/cpp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ impl LanguagePlugin for CppPlugin {
6767
template: Some(String::from("// 在这里输入 C++ 代码")),
6868
timeout: Some(30),
6969
console_type: Some(String::from("console")),
70+
icon_path: None,
7071
}
7172
}
7273

0 commit comments

Comments
 (0)