diff --git a/README.md b/README.md
index 08bf79a..22b51d9 100644
--- a/README.md
+++ b/README.md
@@ -24,6 +24,7 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发

+

@@ -39,6 +40,7 @@ CodeForge 是一款轻量级、高性能的桌面代码执行器,专为开发

+

diff --git a/public/icons/cangjie.svg b/public/icons/cangjie.svg
new file mode 100644
index 0000000..8c770d3
--- /dev/null
+++ b/public/icons/cangjie.svg
@@ -0,0 +1,5 @@
+
+
\ No newline at end of file
diff --git a/public/icons/r.svg b/public/icons/r.svg
new file mode 100644
index 0000000..23c270b
--- /dev/null
+++ b/public/icons/r.svg
@@ -0,0 +1,14 @@
+
\ No newline at end of file
diff --git a/src-tauri/src/examples/cangjie.cj b/src-tauri/src/examples/cangjie.cj
new file mode 100644
index 0000000..058f02c
--- /dev/null
+++ b/src-tauri/src/examples/cangjie.cj
@@ -0,0 +1,79 @@
+// 仓颉示例代码 - CodeForge 代码执行环境
+
+main(): Unit {
+ println("🎉 欢迎使用 CodeForge!")
+ println("Welcome to CodeForge!")
+ println("")
+
+ println("=========================================")
+ println(" CodeForge Cangjie ")
+ println("=========================================")
+ println("")
+
+ // 基本输出示例
+ println("✅ 仓颉运行成功! (Cangjie is working!)")
+ println("⚡ 这是仓颉程序 (This is Cangjie program)")
+ println("")
+
+ // 变量操作
+ let name = "CodeForge"
+ let version = "Cangjie"
+ let number1 = 10
+ let number2 = 20
+ let result = number1 + number2
+
+ println("🔢 简单计算 (Simple calculation):")
+ println("${number1} + ${number2} = ${result}")
+ println("")
+
+ // 字符串操作和插值
+ println("📝 字符串操作 (String operations):")
+ println("平台名称 (Platform): ${name}")
+ println("语言版本 (Language): ${version}")
+ println("完整信息 (Full info): ${name} - ${version}")
+ println("")
+
+ // 数组操作
+ println("🍎 数组示例 (Array example):")
+ let fruits = ["苹果", "香蕉", "橙子", "葡萄"]
+ for (i in 0..fruits.size) {
+ println("${i + 1}. ${fruits[i]}")
+ }
+ println("")
+
+ // 条件判断
+ let score = 85
+ println("📊 成绩评估 (Score evaluation):")
+ if (score >= 90) {
+ println("优秀! (Excellent!)")
+ } else if (score >= 80) {
+ println("良好! (Good!)")
+ } else if (score >= 60) {
+ println("及格 (Pass)")
+ } else {
+ println("需要努力 (Need improvement)")
+ }
+ println("")
+
+ // 循环示例
+ println("🔄 循环输出 (Loop output):")
+ for (i in 1..6) {
+ println("第 ${i} 次输出 (Output #${i}): Hello from CodeForge!")
+ }
+ println("")
+
+ // while循环示例
+ println("🔁 While循环示例 (While loop example):")
+ var counter = 1
+ while (counter <= 3) {
+ println("While循环: 第 ${counter} 次")
+ counter += 1
+ }
+ println("")
+
+ println("🎯 CodeForge 仓颉代码执行完成!")
+ println("🎯 CodeForge Cangjie execution completed!")
+ println("")
+ println("感谢使用 CodeForge 代码执行环境! 🚀")
+ println("Thank you for using CodeForge! 🚀")
+}
diff --git a/src-tauri/src/examples/r.r b/src-tauri/src/examples/r.r
new file mode 100644
index 0000000..4c86c78
--- /dev/null
+++ b/src-tauri/src/examples/r.r
@@ -0,0 +1,323 @@
+# R 示例代码 - CodeForge 代码执行环境
+
+cat("欢迎使用 CodeForge!\n")
+cat("Welcome to CodeForge!\n\n")
+
+cat("=========================================\n")
+cat(" CodeForge R \n")
+cat("=========================================\n\n")
+
+# 基本输出示例
+cat("R 运行成功! (R is working!)\n")
+cat("这是 R 程序 (This is R program)\n\n")
+
+# 变量操作
+name <- "CodeForge"
+version <- "R"
+number1 <- 10
+number2 <- 20
+result <- number1 + number2
+
+cat("简单计算 (Simple calculation):\n")
+cat(sprintf("%d + %d = %d\n", number1, number2, result))
+cat("\n")
+
+# 字符串操作
+cat("字符串操作 (String operations):\n")
+cat(sprintf("平台名称 (Platform): %s\n", name))
+cat(sprintf("语言版本 (Language): %s\n", version))
+cat(sprintf("完整信息 (Full info): %s - %s\n", name, version))
+cat("\n")
+
+# 向量操作
+cat("向量示例 (Vector example):\n")
+fruits <- c("苹果", "香蕉", "橙子", "葡萄")
+for (i in 1:length(fruits)) {
+ cat(sprintf("%d. %s\n", i, fruits[i]))
+}
+cat("\n")
+
+# 数值向量
+numbers <- c(1, 2, 3, 4, 5)
+cat("数值向量示例 (Numeric vector example):\n")
+cat("原向量:", numbers, "\n")
+cat("向量和:", sum(numbers), "\n")
+cat("向量平均值:", mean(numbers), "\n")
+cat("向量长度:", length(numbers), "\n\n")
+
+# 条件判断
+score <- 85
+cat("成绩评估 (Score evaluation):\n")
+if (score >= 90) {
+ cat("优秀! (Excellent!)\n")
+} else if (score >= 80) {
+ cat("良好! (Good!)\n")
+} else if (score >= 60) {
+ cat("及格 (Pass)\n")
+} else {
+ cat("需要努力 (Need improvement)\n")
+}
+cat("\n")
+
+# 循环示例
+cat("循环输出 (Loop output):\n")
+for (i in 1:5) {
+ cat(sprintf("第 %d 次输出 (Output #%d): Hello from CodeForge!\n", i, i))
+}
+cat("\n")
+
+# while循环
+cat("While循环示例 (While loop example):\n")
+counter <- 1
+while (counter <= 3) {
+ cat(sprintf("While循环: 第 %d 次\n", counter))
+ counter <- counter + 1
+}
+cat("\n")
+
+# 函数定义
+greet_user <- function(user_name) {
+ return(paste("Hello,", user_name, "!"))
+}
+
+add_numbers <- function(a, b) {
+ return(a + b)
+}
+
+fibonacci <- function(n) {
+ if (n <= 1) return(n)
+ return(fibonacci(n - 1) + fibonacci(n - 2))
+}
+
+cat("函数示例 (Function example):\n")
+cat(greet_user("CodeForge用户"), "\n")
+cat("函数计算 5 + 3 =", add_numbers(5, 3), "\n\n")
+
+# 递归示例
+cat("递归示例 (Recursion example):\n")
+fib_n <- 7
+fib_result <- fibonacci(fib_n)
+cat(sprintf("斐波那契数列第%d项: %d\n", fib_n, fib_result))
+cat("\n")
+
+# 列表操作
+cat("列表示例 (List example):\n")
+person_list <- list(
+ name = "张三",
+ age = 25,
+ height = 175.5,
+ hobbies = c("读书", "游泳", "编程")
+)
+
+cat("姓名:", person_list$name, "\n")
+cat("年龄:", person_list$age, "\n")
+cat("身高:", person_list$height, "cm\n")
+cat("爱好:", paste(person_list$hobbies, collapse = ", "), "\n\n")
+
+# 数据框操作
+cat("数据框示例 (Data frame example):\n")
+students <- data.frame(
+ 姓名 = c("张三", "李四", "王五"),
+ 成绩 = c(85, 92, 78),
+ 年龄 = c(20, 21, 19),
+ stringsAsFactors = FALSE
+)
+
+cat("学生数据框:\n")
+print(students)
+cat("\n")
+
+# 数据框统计
+cat("数据框统计 (Data frame statistics):\n")
+cat("平均成绩:", mean(students$成绩), "\n")
+cat("最高成绩:", max(students$成绩), "\n")
+cat("最低成绩:", min(students$成绩), "\n")
+cat("成绩标准差:", sd(students$成绩), "\n\n")
+
+# 矩阵操作
+cat("矩阵示例 (Matrix example):\n")
+matrix_data <- matrix(c(1, 2, 3, 4, 5, 6), nrow = 2, ncol = 3)
+cat("矩阵:\n")
+print(matrix_data)
+
+cat("矩阵维度:", dim(matrix_data), "\n")
+cat("矩阵行数:", nrow(matrix_data), "\n")
+cat("矩阵列数:", ncol(matrix_data), "\n\n")
+
+# 数学函数
+cat("数学函数示例 (Math function examples):\n")
+angle <- 45
+radians <- angle * pi / 180
+cat(sprintf("sin(%.0f°) = %.4f\n", angle, sin(radians)))
+cat(sprintf("cos(%.0f°) = %.4f\n", angle, cos(radians)))
+cat("sqrt(16) =", sqrt(16), "\n")
+cat("log(10) =", log(10), "\n")
+cat("exp(1) =", exp(1), "\n\n")
+
+# 统计函数
+cat("统计函数示例 (Statistical function examples):\n")
+sample_data <- c(5, 2, 8, 1, 9, 3, 7, 4, 6)
+cat("数据:", paste(sample_data, collapse = ", "), "\n")
+cat("均值:", mean(sample_data), "\n")
+cat("中位数:", median(sample_data), "\n")
+cat("标准差:", sd(sample_data), "\n")
+cat("方差:", var(sample_data), "\n")
+cat("最小值:", min(sample_data), "\n")
+cat("最大值:", max(sample_data), "\n")
+cat("四分位数:\n")
+print(quantile(sample_data))
+cat("\n")
+
+# 字符串处理
+cat("字符串处理示例 (String processing examples):\n")
+text <- "CodeForge R Example"
+cat("原字符串:", text, "\n")
+cat("字符串长度:", nchar(text), "\n")
+cat("大写:", toupper(text), "\n")
+cat("小写:", tolower(text), "\n")
+cat("子字符串:", substr(text, 1, 9), "\n")
+cat("替换:", gsub("R", "Programming", text), "\n\n")
+
+# 逻辑运算
+cat("逻辑运算示例 (Logical operations example):\n")
+a <- TRUE
+b <- FALSE
+cat("a =", a, ", b =", b, "\n")
+cat("a & b =", a & b, "(AND)\n")
+cat("a | b =", a | b, "(OR)\n")
+cat("!a =", !a, "(NOT)\n\n")
+
+# 向量化操作
+cat("向量化操作示例 (Vectorized operations example):\n")
+vec1 <- c(1, 2, 3, 4, 5)
+vec2 <- c(2, 4, 6, 8, 10)
+cat("向量1:", paste(vec1, collapse = ", "), "\n")
+cat("向量2:", paste(vec2, collapse = ", "), "\n")
+cat("向量相加:", paste(vec1 + vec2, collapse = ", "), "\n")
+cat("向量相乘:", paste(vec1 * vec2, collapse = ", "), "\n")
+cat("向量平方:", paste(vec1^2, collapse = ", "), "\n\n")
+
+# 条件筛选
+cat("条件筛选示例 (Conditional filtering example):\n")
+test_scores <- c(85, 92, 78, 96, 73, 88, 91)
+cat("所有成绩:", paste(test_scores, collapse = ", "), "\n")
+high_scores <- test_scores[test_scores >= 90]
+cat("高分(>=90):", paste(high_scores, collapse = ", "), "\n")
+low_scores <- test_scores[test_scores < 80]
+cat("低分(<80):", paste(low_scores, collapse = ", "), "\n\n")
+
+# 排序操作
+cat("排序操作示例 (Sorting operations example):\n")
+unsorted_data <- c(5, 2, 8, 1, 9, 3)
+cat("原数据:", paste(unsorted_data, collapse = ", "), "\n")
+sorted_asc <- sort(unsorted_data)
+cat("升序:", paste(sorted_asc, collapse = ", "), "\n")
+sorted_desc <- sort(unsorted_data, decreasing = TRUE)
+cat("降序:", paste(sorted_desc, collapse = ", "), "\n\n")
+
+# 因子操作
+cat("因子示例 (Factor example):\n")
+grades <- c("A", "B", "C", "A", "B", "A", "C", "B")
+grade_factor <- factor(grades, levels = c("A", "B", "C"))
+cat("原始等级:", paste(grades, collapse = ", "), "\n")
+cat("因子等级:", paste(as.character(grade_factor), collapse = ", "), "\n")
+cat("等级计数:\n")
+print(table(grade_factor))
+cat("\n")
+
+# 缺失值处理
+cat("缺失值处理示例 (Missing value handling example):\n")
+data_with_na <- c(1, 2, NA, 4, 5, NA, 7)
+cat("包含NA的数据:", paste(data_with_na, collapse = ", "), "\n")
+cat("是否为NA:", paste(is.na(data_with_na), collapse = ", "), "\n")
+clean_data <- data_with_na[!is.na(data_with_na)]
+cat("清理后的数据:", paste(clean_data, collapse = ", "), "\n")
+cat("NA数量:", sum(is.na(data_with_na)), "\n\n")
+
+# apply函数族示例
+cat("apply函数族示例 (apply family example):\n")
+test_matrix <- matrix(1:12, nrow = 3, ncol = 4)
+cat("测试矩阵:\n")
+print(test_matrix)
+cat("行求和 (Row sums):", apply(test_matrix, 1, sum), "\n")
+cat("列求和 (Column sums):", apply(test_matrix, 2, sum), "\n\n")
+
+# lapply示例
+cat("lapply示例 (lapply example):\n")
+number_list <- list(a = 1:5, b = 6:10, c = 11:15)
+list_means <- lapply(number_list, mean)
+cat("各组平均值:\n")
+print(list_means)
+cat("\n")
+
+# 随机数生成
+cat("随机数生成示例 (Random number generation example):\n")
+set.seed(123) # 设置随机种子以获得可重复结果
+random_normal <- rnorm(5, mean = 0, sd = 1)
+cat("正态分布随机数:", paste(round(random_normal, 2), collapse = ", "), "\n")
+random_uniform <- runif(5, min = 0, max = 10)
+cat("均匀分布随机数:", paste(round(random_uniform, 2), collapse = ", "), "\n")
+random_integers <- sample(1:100, 5)
+cat("随机整数:", paste(random_integers, collapse = ", "), "\n\n")
+
+# 日期和时间
+cat("日期时间示例 (Date and time example):\n")
+current_date <- Sys.Date()
+current_time <- Sys.time()
+cat("当前日期:", as.character(current_date), "\n")
+cat("当前时间:", as.character(current_time), "\n")
+cat("格式化日期:", format(current_date, "%Y年%m月%d日"), "\n\n")
+
+# 简单的数据分析
+cat("数据分析示例 (Data analysis example):\n")
+analysis_data <- c(23, 45, 56, 78, 32, 67, 89, 12, 34, 56, 78, 90, 23, 45)
+cat("分析数据:", paste(analysis_data, collapse = ", "), "\n")
+cat("描述性统计:\n")
+cat(" 样本数:", length(analysis_data), "\n")
+cat(" 均值:", round(mean(analysis_data), 2), "\n")
+cat(" 中位数:", median(analysis_data), "\n")
+cat(" 标准差:", round(sd(analysis_data), 2), "\n")
+cat(" 最小值:", min(analysis_data), "\n")
+cat(" 最大值:", max(analysis_data), "\n")
+cat(" 范围:", max(analysis_data) - min(analysis_data), "\n\n")
+
+# 相关性分析
+cat("相关性分析示例 (Correlation analysis example):\n")
+x_values <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+y_values <- c(2, 4, 6, 8, 10, 12, 14, 16, 18, 20)
+correlation <- cor(x_values, y_values)
+cat("x值:", paste(x_values, collapse = ", "), "\n")
+cat("y值:", paste(y_values, collapse = ", "), "\n")
+cat("相关系数:", round(correlation, 4), "\n\n")
+
+# 线性回归示例
+cat("线性回归示例 (Linear regression example):\n")
+# 使用更现实的数据,添加一些噪声
+set.seed(42)
+x_reg <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
+y_reg <- 2 * x_reg + 1 + rnorm(10, mean = 0, sd = 0.5) # 添加噪声
+lm_model <- lm(y_reg ~ x_reg)
+cat("x值:", paste(x_reg, collapse = ", "), "\n")
+cat("y值:", paste(round(y_reg, 2), collapse = ", "), "\n")
+cat("回归摘要:\n")
+cat("系数:\n")
+print(coef(lm_model))
+cat("R平方:", round(summary(lm_model)$r.squared, 4), "\n\n")
+
+# 环境信息
+cat("环境信息示例 (Environment info example):\n")
+cat("R版本:", R.version.string, "\n")
+cat("平台:", R.version$platform, "\n")
+cat("工作目录:", getwd(), "\n")
+cat("搜索路径长度:", length(search()), "\n\n")
+
+# 内存使用
+cat("内存使用示例 (Memory usage example):\n")
+cat("对象数量:", length(ls()), "\n")
+memory_info <- gc()
+cat("内存清理完成\n\n")
+
+cat("CodeForge R 代码执行完成!\n")
+cat("CodeForge R execution completed!\n\n")
+cat("感谢使用 CodeForge 代码执行环境!\n")
+cat("Thank you for using CodeForge!\n")
\ No newline at end of file
diff --git a/src-tauri/src/plugins/cangjie.rs b/src-tauri/src/plugins/cangjie.rs
new file mode 100644
index 0000000..aea8844
--- /dev/null
+++ b/src-tauri/src/plugins/cangjie.rs
@@ -0,0 +1,97 @@
+use super::{LanguagePlugin, PluginConfig};
+use std::vec;
+
+pub struct CangjiePlugin;
+
+impl LanguagePlugin for CangjiePlugin {
+ fn get_order(&self) -> i32 {
+ 24
+ }
+
+ fn get_language_name(&self) -> &'static str {
+ "Cangjie"
+ }
+
+ fn get_language_key(&self) -> &'static str {
+ "cangjie"
+ }
+
+ fn get_file_extension(&self) -> String {
+ self.get_config()
+ .map(|config| config.extension.clone())
+ .unwrap_or_else(|| "cj".to_string())
+ }
+
+ fn get_version_args(&self) -> Vec<&'static str> {
+ vec!["--version"]
+ }
+
+ fn get_path_command(&self) -> String {
+ "which cjc".to_string()
+ }
+
+ fn get_command(
+ &self,
+ _file_path: Option<&str>,
+ _is_version: bool,
+ _file_name: Option
,
+ ) -> String {
+ if _is_version {
+ let cjc_command = if self.get_execute_home().is_some() {
+ "./cjc"
+ } else {
+ "cjc"
+ };
+
+ return cjc_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 {
+ let cjc_command = if self.get_execute_home().is_some() {
+ "./cjc"
+ } else {
+ "cjc"
+ };
+
+ let cmd = format!("{} {}", cjc_command, file_path);
+
+ vec!["-c".to_string(), cmd]
+ }
+
+ fn get_default_config(&self) -> PluginConfig {
+ PluginConfig {
+ enabled: true,
+ language: String::from("cangjie"),
+ before_compile: Some(String::from("cjc $filename -o main")),
+ extension: String::from("cj"),
+ execute_home: None,
+ run_command: Some(String::from("main")),
+ after_compile: Some(String::from("rm -f main")),
+ template: Some(String::from(
+ "// 在这里输入仓颉代码\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(|| "cjc".to_string())
+ }
+}
diff --git a/src-tauri/src/plugins/manager.rs b/src-tauri/src/plugins/manager.rs
index 7467f58..6344962 100644
--- a/src-tauri/src/plugins/manager.rs
+++ b/src-tauri/src/plugins/manager.rs
@@ -1,6 +1,7 @@
use super::{LanguagePlugin, PluginConfig};
use crate::plugins::applescript::AppleScriptPlugin;
use crate::plugins::c::CPlugin;
+use crate::plugins::cangjie::CangjiePlugin;
use crate::plugins::clojure::ClojurePlugin;
use crate::plugins::cpp::CppPlugin;
use crate::plugins::css::CssPlugin;
@@ -16,6 +17,7 @@ use crate::plugins::nodejs::NodeJSPlugin;
use crate::plugins::php::PHPPlugin;
use crate::plugins::python2::Python2Plugin;
use crate::plugins::python3::Python3Plugin;
+use crate::plugins::r::RPlugin;
use crate::plugins::ruby::RubyPlugin;
use crate::plugins::rust::RustPlugin;
use crate::plugins::scala::ScalaPlugin;
@@ -56,6 +58,8 @@ impl PluginManager {
plugins.insert("css".to_string(), Box::new(CssPlugin));
plugins.insert("svg".to_string(), Box::new(SvgPlugin));
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(
"javascript-nodejs".to_string(),
Box::new(JavaScriptNodeJsPlugin),
diff --git a/src-tauri/src/plugins/mod.rs b/src-tauri/src/plugins/mod.rs
index 240c69a..a845ae6 100644
--- a/src-tauri/src/plugins/mod.rs
+++ b/src-tauri/src/plugins/mod.rs
@@ -371,6 +371,7 @@ pub trait LanguagePlugin: Send + Sync {
// 重新导出子模块
pub mod applescript;
pub mod c;
+pub mod cangjie;
pub mod clojure;
pub mod cpp;
pub mod css;
@@ -387,6 +388,7 @@ pub mod nodejs;
pub mod php;
pub mod python2;
pub mod python3;
+pub mod r;
pub mod ruby;
pub mod rust;
pub mod scala;
diff --git a/src-tauri/src/plugins/r.rs b/src-tauri/src/plugins/r.rs
new file mode 100644
index 0000000..fc158b3
--- /dev/null
+++ b/src-tauri/src/plugins/r.rs
@@ -0,0 +1,61 @@
+use super::{LanguagePlugin, PluginConfig};
+use std::vec;
+
+pub struct RPlugin;
+
+impl LanguagePlugin for RPlugin {
+ fn get_order(&self) -> i32 {
+ 23
+ }
+
+ fn get_language_name(&self) -> &'static str {
+ "R"
+ }
+
+ fn get_language_key(&self) -> &'static str {
+ "r"
+ }
+
+ fn get_file_extension(&self) -> String {
+ self.get_config()
+ .map(|config| config.extension.clone())
+ .unwrap_or_else(|| "r".to_string())
+ }
+
+ fn get_version_args(&self) -> Vec<&'static str> {
+ vec!["--version"]
+ }
+
+ fn get_path_command(&self) -> String {
+ "which R".to_string()
+ }
+
+ fn get_execute_args(&self, file_path: &str) -> Vec {
+ let cmd = format!("R --vanilla --slave -f {}", file_path);
+
+ vec!["-c".to_string(), cmd]
+ }
+
+ fn get_default_config(&self) -> PluginConfig {
+ PluginConfig {
+ enabled: true,
+ language: String::from("r"),
+ before_compile: None,
+ extension: String::from("r"),
+ execute_home: None,
+ run_command: Some(String::from("bash")),
+ after_compile: None,
+ template: Some(String::from(
+ "# 在这里输入 R 代码\n# R - 统计计算和图形的语言和环境",
+ )),
+ 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(|| "R".to_string())
+ }
+}
diff --git a/src/composables/useCodeMirrorEditor.ts b/src/composables/useCodeMirrorEditor.ts
index fbb2af8..3cfb0c0 100644
--- a/src/composables/useCodeMirrorEditor.ts
+++ b/src/composables/useCodeMirrorEditor.ts
@@ -15,6 +15,7 @@ import {kotlin, 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'
+import {r} from "@codemirror/legacy-modes/mode/r"
import {
abcdef,
abyss,
@@ -178,6 +179,7 @@ export function useCodeMirrorEditor(props: Props)
case 'java':
return java()
case 'rust':
+ case 'cangjie':
return rust()
case 'c':
case 'cpp':
@@ -209,6 +211,8 @@ export function useCodeMirrorEditor(props: Props)
return xml()
case 'php':
return php()
+ case 'r':
+ return StreamLanguage.define(r)
default:
return null
}