diff --git a/.gitignore b/.gitignore
index df87552..87c437b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,3 +29,4 @@ pnpm-lock.yaml
go.mod
.RData
.Rhistory
+program
diff --git a/README.md b/README.md
index 9a2bbe2..ba0117c 100644
--- a/README.md
+++ b/README.md
@@ -39,6 +39,8 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发
+
+
diff --git a/public/icons/objective-c.svg b/public/icons/objective-c.svg
new file mode 100644
index 0000000..0af8491
--- /dev/null
+++ b/public/icons/objective-c.svg
@@ -0,0 +1,6 @@
+
\ No newline at end of file
diff --git a/public/icons/objective-cpp.svg b/public/icons/objective-cpp.svg
new file mode 100644
index 0000000..7bfb08d
--- /dev/null
+++ b/public/icons/objective-cpp.svg
@@ -0,0 +1,9 @@
+
+
\ No newline at end of file
diff --git a/src-tauri/src/examples/objective-c.m b/src-tauri/src/examples/objective-c.m
new file mode 100644
index 0000000..9c42492
--- /dev/null
+++ b/src-tauri/src/examples/objective-c.m
@@ -0,0 +1,73 @@
+#import
+
+int main(int argc, const char * argv[]) {
+ @autoreleasepool {
+ printf("🎉 欢迎使用 CodeForge!\n");
+ printf("Welcome to CodeForge!\n");
+ printf("\n");
+
+ printf("=========================================\n");
+ printf(" CodeForge Objective-C \n");
+ printf("=========================================\n");
+ printf("\n");
+
+ printf("✅ Objective-C运行成功! (Objective-C is working!)\n");
+ printf("⚡ 这是Objective-C程序 (This is Objective-C program)\n");
+ printf("\n");
+
+ int number1 = 10;
+ int number2 = 20;
+ int result = number1 + number2;
+
+ printf("🔢 简单计算 (Simple calculation):\n");
+ printf("%d + %d = %d\n", number1, number2, result);
+ printf("\n");
+
+ printf("📝 字符串操作 (String operations):\n");
+ printf("平台名称 (Platform): CodeForge\n");
+ printf("语言版本 (Language): Objective-C\n");
+ printf("完整信息 (Full info): CodeForge - Objective-C\n");
+ printf("\n");
+
+ printf("🍎 数组示例 (Array example):\n");
+ NSArray *fruits = @[@"苹果", @"香蕉", @"橙子", @"葡萄"];
+ for (int i = 0; i < fruits.count; i++) {
+ printf("%d. %s\n", i + 1, [fruits[i] UTF8String]);
+ }
+ printf("\n");
+
+ int score = 85;
+ printf("📊 成绩评估 (Score evaluation):\n");
+ if (score >= 90) {
+ printf("优秀! (Excellent!)\n");
+ } else if (score >= 80) {
+ printf("良好! (Good!)\n");
+ } else if (score >= 60) {
+ printf("及格 (Pass)\n");
+ } else {
+ printf("需要努力 (Need improvement)\n");
+ }
+ printf("\n");
+
+ printf("🔄 循环输出 (Loop output):\n");
+ for (int i = 1; i <= 5; i++) {
+ printf("第 %d 次输出 (Output #%d): Hello from CodeForge!\n", i, i);
+ }
+ printf("\n");
+
+ printf("🔁 While循环示例 (While loop example):\n");
+ int counter = 1;
+ while (counter <= 3) {
+ printf("While循环: 第 %d 次\n", counter);
+ counter++;
+ }
+ printf("\n");
+
+ printf("🎯 CodeForge Objective-C代码执行完成!\n");
+ printf("🎯 CodeForge Objective-C execution completed!\n");
+ printf("\n");
+ printf("感谢使用 CodeForge 代码执行环境! 🚀\n");
+ printf("Thank you for using CodeForge! 🚀\n");
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/src-tauri/src/examples/objective-cpp.mm b/src-tauri/src/examples/objective-cpp.mm
new file mode 100644
index 0000000..c4420cb
--- /dev/null
+++ b/src-tauri/src/examples/objective-cpp.mm
@@ -0,0 +1,85 @@
+#import
+#include
+#include
+#include
+
+int main(int argc, const char * argv[]) {
+ @autoreleasepool {
+ printf("🎉 欢迎使用 CodeForge!\n");
+ printf("Welcome to CodeForge!\n");
+ printf("\n");
+
+ printf("=========================================\n");
+ printf(" CodeForge Objective-C++ \n");
+ printf("=========================================\n");
+ printf("\n");
+
+ printf("✅ Objective-C++运行成功! (Objective-C++ is working!)\n");
+ printf("⚡ 这是Objective-C++程序 (This is Objective-C++ program)\n");
+ printf("\n");
+
+ int number1 = 10;
+ int number2 = 20;
+ int result = number1 + number2;
+
+ printf("🔢 简单计算 (Simple calculation):\n");
+ printf("%d + %d = %d\n", number1, number2, result);
+ printf("\n");
+
+ printf("📝 字符串操作 (String operations):\n");
+ std::string cppName = "CodeForge";
+ std::string cppVersion = "Objective-C++";
+ printf("平台名称 (Platform): %s\n", cppName.c_str());
+ printf("语言版本 (Language): %s\n", cppVersion.c_str());
+ printf("完整信息 (Full info): %s - %s\n", cppName.c_str(), cppVersion.c_str());
+ printf("\n");
+
+ printf("🍎 数组示例 (Array example - Objective-C):\n");
+ NSArray *fruits = @[@"苹果", @"香蕉", @"橙子", @"葡萄"];
+ for (int i = 0; i < fruits.count; i++) {
+ printf("%d. %s\n", i + 1, [fruits[i] UTF8String]);
+ }
+ printf("\n");
+
+ printf("🍇 Vector示例 (Vector example - C++):\n");
+ std::vector colors = {"红色", "蓝色", "绿色", "黄色"};
+ for (size_t i = 0; i < colors.size(); i++) {
+ printf("%zu. %s\n", i + 1, colors[i].c_str());
+ }
+ printf("\n");
+
+ int score = 85;
+ printf("📊 成绩评估 (Score evaluation):\n");
+ if (score >= 90) {
+ printf("优秀! (Excellent!)\n");
+ } else if (score >= 80) {
+ printf("良好! (Good!)\n");
+ } else if (score >= 60) {
+ printf("及格 (Pass)\n");
+ } else {
+ printf("需要努力 (Need improvement)\n");
+ }
+ printf("\n");
+
+ printf("🔄 循环输出 (Loop output):\n");
+ for (int i = 1; i <= 5; i++) {
+ printf("第 %d 次输出 (Output #%d): Hello from CodeForge!\n", i, i);
+ }
+ printf("\n");
+
+ printf("🔁 While循环示例 (While loop example):\n");
+ int counter = 1;
+ while (counter <= 3) {
+ printf("While循环: 第 %d 次\n", counter);
+ counter++;
+ }
+ printf("\n");
+
+ printf("🎯 CodeForge Objective-C++代码执行完成!\n");
+ printf("🎯 CodeForge Objective-C++ execution completed!\n");
+ printf("\n");
+ printf("感谢使用 CodeForge 代码执行环境! 🚀\n");
+ printf("Thank you for using CodeForge! 🚀\n");
+ }
+ return 0;
+}
\ No newline at end of file
diff --git a/src-tauri/src/plugin.rs b/src-tauri/src/plugin.rs
index 9c7431a..bf51bab 100644
--- a/src-tauri/src/plugin.rs
+++ b/src-tauri/src/plugin.rs
@@ -1,12 +1,42 @@
use crate::plugins::{LanguageInfo, PluginManager};
use log::{debug, error, info};
+use regex::Regex;
use std::process::Command;
use tauri::State;
use tokio::sync::Mutex;
pub type PluginManagerState = Mutex;
-// 通用的环境信息获取函数
+fn extract_version(output: &str) -> String {
+ let output = output.trim();
+
+ let version_patterns = vec![
+ r"(?i)version\s+([0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9]+)?)",
+ r"(?i)version\s+([0-9]+\.[0-9]+(?:\.[0-9]+)?)",
+ r"\bv?([0-9]+\.[0-9]+\.[0-9]+(?:-[a-zA-Z0-9]+)?)\b",
+ r"\bv?([0-9]+\.[0-9]+(?:\.[0-9]+)?)\b",
+ r#""([0-9]+\.[0-9]+\.[0-9]+)""#,
+ ];
+
+ for pattern in version_patterns {
+ if let Ok(re) = Regex::new(pattern) {
+ if let Some(cap) = re.captures(output) {
+ if let Some(version) = cap.get(1) {
+ return version.as_str().to_string();
+ }
+ }
+ }
+ }
+
+ if let Some(first_line) = output.lines().next() {
+ if !first_line.is_empty() {
+ return first_line.to_string();
+ }
+ }
+
+ output.to_string()
+}
+
#[tauri::command]
pub async fn get_info(
language: String,
@@ -44,20 +74,27 @@ pub async fn get_info(
.arg(plugin.get_path_command())
.output();
- let mut version = String::from_utf8_lossy(&version_out.stdout)
+ let mut raw_version = String::from_utf8_lossy(&version_out.stdout)
.trim()
.to_string();
- if version.is_empty() {
+ if raw_version.is_empty() {
info!(
"获取环境 -> 调用插件 [ {} ] 版本为空,通过 stderr 获取",
language
);
- version = String::from_utf8_lossy(&version_out.stderr)
+ raw_version = String::from_utf8_lossy(&version_out.stderr)
.trim()
.to_string();
}
+ let version = extract_version(&raw_version);
+ let final_version = if version.is_empty() {
+ raw_version
+ } else {
+ version
+ };
+
let path = if let Ok(path_out) = path_result {
if path_out.status.success() {
String::from_utf8_lossy(&path_out.stdout).trim().to_string()
@@ -71,7 +108,7 @@ pub async fn get_info(
info!("获取环境 -> 调用插件 [ {} ] 完成", language);
return Ok(LanguageInfo {
installed: true,
- version,
+ version: final_version,
path,
language: plugin.get_language_name().to_string(),
});
@@ -90,7 +127,6 @@ pub async fn get_info(
})
}
-// 获取支持的语言列表
#[tauri::command]
pub async fn get_supported_languages(
plugin_manager: State<'_, PluginManagerState>,
diff --git a/src-tauri/src/plugins/manager.rs b/src-tauri/src/plugins/manager.rs
index 111cdf6..933e565 100644
--- a/src-tauri/src/plugins/manager.rs
+++ b/src-tauri/src/plugins/manager.rs
@@ -16,6 +16,8 @@ use crate::plugins::javascript_nodejs::JavaScriptNodeJsPlugin;
use crate::plugins::kotlin::KotlinPlugin;
use crate::plugins::lua::LuaPlugin;
use crate::plugins::nodejs::NodeJSPlugin;
+use crate::plugins::objective_c::ObjectiveCPlugin;
+use crate::plugins::objective_cpp::ObjectiveCppPlugin;
use crate::plugins::php::PHPPlugin;
use crate::plugins::python2::Python2Plugin;
use crate::plugins::python3::Python3Plugin;
@@ -64,6 +66,8 @@ impl PluginManager {
plugins.insert("cangjie".to_string(), Box::new(CangjiePlugin));
plugins.insert("haskell".to_string(), Box::new(HaskellPlugin));
plugins.insert("lua".to_string(), Box::new(LuaPlugin));
+ plugins.insert("objective-c".to_string(), Box::new(ObjectiveCPlugin));
+ plugins.insert("objective-cpp".to_string(), Box::new(ObjectiveCppPlugin));
plugins.insert(
"javascript-nodejs".to_string(),
Box::new(JavaScriptNodeJsPlugin),
diff --git a/src-tauri/src/plugins/mod.rs b/src-tauri/src/plugins/mod.rs
index 1715f53..61159c8 100644
--- a/src-tauri/src/plugins/mod.rs
+++ b/src-tauri/src/plugins/mod.rs
@@ -387,6 +387,8 @@ pub mod kotlin;
pub mod lua;
pub mod manager;
pub mod nodejs;
+pub mod objective_c;
+pub mod objective_cpp;
pub mod php;
pub mod python2;
pub mod python3;
diff --git a/src-tauri/src/plugins/objective_c.rs b/src-tauri/src/plugins/objective_c.rs
new file mode 100644
index 0000000..d37a17b
--- /dev/null
+++ b/src-tauri/src/plugins/objective_c.rs
@@ -0,0 +1,85 @@
+use super::{LanguagePlugin, PluginConfig};
+use std::vec;
+
+pub struct ObjectiveCPlugin;
+
+impl LanguagePlugin for ObjectiveCPlugin {
+ fn get_order(&self) -> i32 {
+ 27
+ }
+
+ fn get_language_name(&self) -> &'static str {
+ "Objective-C"
+ }
+
+ fn get_language_key(&self) -> &'static str {
+ "objective-c"
+ }
+
+ fn get_file_extension(&self) -> String {
+ self.get_config()
+ .map(|config| config.extension.clone())
+ .unwrap_or_else(|| "m".to_string())
+ }
+
+ fn get_version_args(&self) -> Vec<&'static str> {
+ vec!["--version"]
+ }
+
+ fn get_path_command(&self) -> String {
+ "which clang".to_string()
+ }
+
+ fn get_command(
+ &self,
+ _file_path: Option<&str>,
+ _is_version: bool,
+ _file_name: Option,
+ ) -> String {
+ if _is_version {
+ let clang_command = if self.get_execute_home().is_some() {
+ "./clang"
+ } else {
+ "clang"
+ };
+
+ return clang_command.to_string();
+ }
+
+ if let Some(config) = self.get_config() {
+ if let Some(run_cmd) = &config.run_command {
+ return if let Some(file_name) = _file_name {
+ run_cmd.replace("$filename", &file_name)
+ } else {
+ run_cmd.clone()
+ };
+ }
+ }
+ self.get_default_command()
+ }
+
+ fn get_default_config(&self) -> PluginConfig {
+ PluginConfig {
+ enabled: true,
+ language: String::from("objective-c"),
+ before_compile: Some(String::from(
+ "clang -framework Foundation $filename -o program",
+ )),
+ extension: String::from("m"),
+ execute_home: None,
+ run_command: Some(String::from("./program")),
+ after_compile: Some(String::from("rm -f program")),
+ template: Some(String::from(
+ "// Objective-C 示例代码 - CodeForge 代码执行环境\n\n",
+ )),
+ timeout: Some(30),
+ console_type: Some(String::from("console")),
+ }
+ }
+
+ fn get_default_command(&self) -> String {
+ self.get_config()
+ .and_then(|config| config.run_command.clone())
+ .unwrap_or_else(|| "./program".to_string())
+ }
+}
diff --git a/src-tauri/src/plugins/objective_cpp.rs b/src-tauri/src/plugins/objective_cpp.rs
new file mode 100644
index 0000000..231af12
--- /dev/null
+++ b/src-tauri/src/plugins/objective_cpp.rs
@@ -0,0 +1,85 @@
+use super::{LanguagePlugin, PluginConfig};
+use std::vec;
+
+pub struct ObjectiveCppPlugin;
+
+impl LanguagePlugin for ObjectiveCppPlugin {
+ fn get_order(&self) -> i32 {
+ 28
+ }
+
+ fn get_language_name(&self) -> &'static str {
+ "Objective-C++"
+ }
+
+ fn get_language_key(&self) -> &'static str {
+ "objective-cpp"
+ }
+
+ fn get_file_extension(&self) -> String {
+ self.get_config()
+ .map(|config| config.extension.clone())
+ .unwrap_or_else(|| "mm".to_string())
+ }
+
+ fn get_version_args(&self) -> Vec<&'static str> {
+ vec!["--version"]
+ }
+
+ fn get_path_command(&self) -> String {
+ "which clang++".to_string()
+ }
+
+ fn get_command(
+ &self,
+ _file_path: Option<&str>,
+ _is_version: bool,
+ _file_name: Option,
+ ) -> String {
+ if _is_version {
+ let clang_command = if self.get_execute_home().is_some() {
+ "./clang++"
+ } else {
+ "clang++"
+ };
+
+ return clang_command.to_string();
+ }
+
+ if let Some(config) = self.get_config() {
+ if let Some(run_cmd) = &config.run_command {
+ return if let Some(file_name) = _file_name {
+ run_cmd.replace("$filename", &file_name)
+ } else {
+ run_cmd.clone()
+ };
+ }
+ }
+ self.get_default_command()
+ }
+
+ fn get_default_config(&self) -> PluginConfig {
+ PluginConfig {
+ enabled: true,
+ language: String::from("objective-cpp"),
+ before_compile: Some(String::from(
+ "clang++ -framework Foundation $filename -o program",
+ )),
+ extension: String::from("mm"),
+ execute_home: None,
+ run_command: Some(String::from("./program")),
+ after_compile: Some(String::from("rm -f program")),
+ template: Some(String::from(
+ "// Objective-C++ 示例代码 - CodeForge 代码执行环境\n\n",
+ )),
+ timeout: Some(30),
+ console_type: Some(String::from("console")),
+ }
+ }
+
+ fn get_default_command(&self) -> String {
+ self.get_config()
+ .and_then(|config| config.run_command.clone())
+ .unwrap_or_else(|| "./program".to_string())
+ }
+}
diff --git a/src/composables/useCodeMirrorEditor.ts b/src/composables/useCodeMirrorEditor.ts
index f6dfb07..1971fa7 100644
--- a/src/composables/useCodeMirrorEditor.ts
+++ b/src/composables/useCodeMirrorEditor.ts
@@ -11,7 +11,7 @@ import {xml} from '@codemirror/lang-xml'
import {php} from '@codemirror/lang-php'
import {shell} from '@codemirror/legacy-modes/mode/shell'
import {swift} from '@codemirror/legacy-modes/mode/swift'
-import {kotlin, scala} from '@codemirror/legacy-modes/mode/clike'
+import {kotlin, objectiveC, objectiveCpp, scala} from '@codemirror/legacy-modes/mode/clike'
import {clojure} from '@codemirror/legacy-modes/mode/clojure'
import {ruby} from '@codemirror/legacy-modes/mode/ruby'
import {groovy} from '@codemirror/legacy-modes/mode/groovy'
@@ -219,6 +219,10 @@ export function useCodeMirrorEditor(props: Props)
return StreamLanguage.define(haskell)
case 'lua':
return StreamLanguage.define(lua)
+ case 'objective-c':
+ return StreamLanguage.define(objectiveC)
+ case 'objective-cpp':
+ return StreamLanguage.define(objectiveCpp)
default:
return null
}
@@ -287,7 +291,6 @@ export function useCodeMirrorEditor(props: Props)
}
}
- // 其余代码完全保持不变...
const loadEditorConfig = async () => {
try {
const globalConfig = await invoke('get_app_config')
diff --git a/src/composables/useStatusBar.ts b/src/composables/useStatusBar.ts
index 4f6e256..63244ba 100644
--- a/src/composables/useStatusBar.ts
+++ b/src/composables/useStatusBar.ts
@@ -1,6 +1,6 @@
-import { type Ref } from 'vue'
-import { CheckCircle, Loader2, XCircle } from 'lucide-vue-next'
-import { EnvInfo } from '../types/app.ts'
+import {type Ref} from 'vue'
+import {CheckCircle, Loader2, XCircle} from 'lucide-vue-next'
+import {EnvInfo} from '../types/app.ts'
export function useStatusBar(envInfo: Ref, isLoading: Ref)
{
@@ -31,14 +31,14 @@ export function useStatusBar(envInfo: Ref, isLoading: Ref)
// 计算状态文本
const getStatusText = () => {
if (isLoading.value) {
- return `${ envInfo.value.language }: 检查环境中...`
+ return `${envInfo.value.language}: 检查环境中...`
}
if (envInfo.value.installed) {
- return `${ envInfo.value.language }: ${ envInfo.value.version }`
+ return `${envInfo.value.language}: ${envInfo.value.version || '--'}`
}
else {
- return `${ envInfo.value.language }: 环境未安装`
+ return `${envInfo.value.language}: 环境未安装`
}
}