Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发
<img src="public/icons/css.svg" width="60" alt="CSS">
<img src="public/icons/go.svg" width="60" alt="Go">
<img src="public/icons/groovy.svg" width="60" alt="Groovy">
<img src="public/icons/haskell.svg" width="60" alt="Haskell">
<img src="public/icons/html.svg" width="60" alt="HTML">
<img src="public/icons/java.svg" width="60" alt="Java">
<img src="public/icons/javascript-browser.svg" width="60" alt="JavaScript (Browser)">
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "codeforge",
"private": true,
"version": "25.0.3",
"version": "25.0.4",
"type": "module",
"scripts": {
"dev": "vite",
Expand Down
5 changes: 5 additions & 0 deletions public/icons/haskell.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src-tauri/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "CodeForge"
version = "25.0.3"
version = "25.0.4"
description = "CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发者、学生和编程爱好者设计。"
authors = ["devlive-community"]
edition = "2024"
Expand Down
80 changes: 80 additions & 0 deletions src-tauri/src/examples/haskell.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
-- Haskell示例代码 - CodeForge 代码执行环境

import Data.List (intercalate)

main :: IO ()
main = do
putStrLn "🎉 欢迎使用 CodeForge!"
putStrLn "Welcome to CodeForge!"
putStrLn ""

putStrLn "========================================="
putStrLn " CodeForge Haskell "
putStrLn "========================================="
putStrLn ""

-- 基本输出示例
putStrLn "✅ Haskell运行成功! (Haskell is working!)"
putStrLn "⚡ 这是Haskell程序 (This is Haskell program)"
putStrLn ""

-- 变量操作
let name = "CodeForge"
version = "Haskell"
number1 = 10
number2 = 20
result = number1 + number2

putStrLn "🔢 简单计算 (Simple calculation):"
putStrLn $ show number1 ++ " + " ++ show number2 ++ " = " ++ show result
putStrLn ""

-- 字符串操作
putStrLn "📝 字符串操作 (String operations):"
putStrLn $ "平台名称 (Platform): " ++ name
putStrLn $ "语言版本 (Language): " ++ version
putStrLn $ "完整信息 (Full info): " ++ name ++ " - " ++ version
putStrLn ""

-- 列表操作
putStrLn "🍎 列表示例 (List example):"
let fruits = ["苹果", "香蕉", "橙子", "葡萄"]
mapM_ (\(i, fruit) -> putStrLn $ show (i + 1) ++ ". " ++ fruit) (zip [0..] fruits)
putStrLn ""

-- 条件判断
let score = 85
putStrLn "📊 成绩评估 (Score evaluation):"
putStrLn $ evaluateScore score
putStrLn ""

-- 循环示例
putStrLn "🔄 循环输出 (Loop output):"
mapM_ (\i -> putStrLn $ "第 " ++ show i ++ " 次输出 (Output #" ++ show i ++ "): Hello from CodeForge!") [1..5]
putStrLn ""

-- 递归示例 (模拟while循环)
putStrLn "🔁 递归示例 (Recursion example):"
countDown 3
putStrLn ""

putStrLn "🎯 CodeForge Haskell代码执行完成!"
putStrLn "🎯 CodeForge Haskell execution completed!"
putStrLn ""
putStrLn "感谢使用 CodeForge 代码执行环境! 🚀"
putStrLn "Thank you for using CodeForge! 🚀"

-- 评估分数的函数
evaluateScore :: Int -> String
evaluateScore score
| score >= 90 = "优秀! (Excellent!)"
| score >= 80 = "良好! (Good!)"
| score >= 60 = "及格 (Pass)"
| otherwise = "需要努力 (Need improvement)"

-- 递归倒计数函数 (模拟while循环)
countDown :: Int -> IO ()
countDown 0 = return ()
countDown n = do
putStrLn $ "递归循环: 第 " ++ show (4 - n) ++ " 次"
countDown (n - 1)
99 changes: 99 additions & 0 deletions src-tauri/src/plugins/haskell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use super::{LanguagePlugin, PluginConfig};
use std::vec;

pub struct HaskellPlugin;

impl LanguagePlugin for HaskellPlugin {
fn get_order(&self) -> i32 {
25
}

fn get_language_name(&self) -> &'static str {
"Haskell"
}

fn get_language_key(&self) -> &'static str {
"haskell"
}

fn get_file_extension(&self) -> String {
self.get_config()
.map(|config| config.extension.clone())
.unwrap_or_else(|| "hs".to_string())
}

fn get_version_args(&self) -> Vec<&'static str> {
vec!["--version"]
}

fn get_path_command(&self) -> String {
"which ghc".to_string()
}

fn get_command(
&self,
_file_path: Option<&str>,
_is_version: bool,
_file_name: Option<String>,
) -> String {
if _is_version {
let ghc_command = if self.get_execute_home().is_some() {
"./ghc"
} else {
"ghc"
};

return ghc_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 {
// 执行代码但没有文件名时,返回原始命令让框架处理 $filename 替换
run_cmd.clone()
};
}
}
self.get_default_command()
}

fn get_execute_args(&self, file_path: &str) -> Vec<String> {
let ghc_command = if self.get_execute_home().is_some() {
"./ghc"
} else {
"ghc"
};

// 对于 Haskell,通常先编译再运行
// 这里假设编译后的可执行文件名为 main
let cmd = format!("{} {} -o main && ./main", ghc_command, file_path);

vec!["-c".to_string(), cmd]
}

fn get_default_config(&self) -> PluginConfig {
PluginConfig {
enabled: true,
language: String::from("haskell"),
before_compile: Some(String::from("ghc $filename -o /tmp/main")),
extension: String::from("hs"),
execute_home: None,
run_command: Some(String::from("/tmp/main")),
after_compile: Some(String::from("rm -f /tmp/main /tmp/main.hi /tmp/main.o")),
template: Some(String::from(
"-- 在这里输入 Haskell 代码\n-- Haskell - 纯函数式编程语言\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(|| "./main".to_string())
}
}
2 changes: 2 additions & 0 deletions src-tauri/src/plugins/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use crate::plugins::cpp::CppPlugin;
use crate::plugins::css::CssPlugin;
use crate::plugins::go::GoPlugin;
use crate::plugins::groovy::GroovyPlugin;
use crate::plugins::haskell::HaskellPlugin;
use crate::plugins::html::HtmlPlugin;
use crate::plugins::java::JavaPlugin;
use crate::plugins::javascript_browser::JavaScriptBrowserPlugin;
Expand Down Expand Up @@ -60,6 +61,7 @@ impl PluginManager {
plugins.insert("php".to_string(), Box::new(PHPPlugin));
plugins.insert("r".to_string(), Box::new(RPlugin));
plugins.insert("cangjie".to_string(), Box::new(CangjiePlugin));
plugins.insert("haskell".to_string(), Box::new(HaskellPlugin));
plugins.insert(
"javascript-nodejs".to_string(),
Box::new(JavaScriptNodeJsPlugin),
Expand Down
1 change: 1 addition & 0 deletions src-tauri/src/plugins/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -377,6 +377,7 @@ pub mod cpp;
pub mod css;
pub mod go;
pub mod groovy;
pub mod haskell;
pub mod html;
pub mod java;
pub mod javascript_browser;
Expand Down
2 changes: 1 addition & 1 deletion src-tauri/tauri.conf.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "CodeForge",
"version": "25.0.3",
"version": "25.0.4",
"identifier": "org.devlive.codeforge",
"build": {
"beforeDevCommand": "pnpm dev",
Expand Down
3 changes: 3 additions & 0 deletions src/composables/useCodeMirrorEditor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {clojure} from '@codemirror/legacy-modes/mode/clojure'
import {ruby} from '@codemirror/legacy-modes/mode/ruby'
import {groovy} from '@codemirror/legacy-modes/mode/groovy'
import {r} from "@codemirror/legacy-modes/mode/r"
import {haskell} from "@codemirror/legacy-modes/mode/haskell"
import {
abcdef,
abyss,
Expand Down Expand Up @@ -213,6 +214,8 @@ export function useCodeMirrorEditor(props: Props)
return php()
case 'r':
return StreamLanguage.define(r)
case 'haskell':
return StreamLanguage.define(haskell)
default:
return null
}
Expand Down
Loading