refactor: 拆分代码结构为 lib.rs 与多模块架构

- 将核心业务逻辑抽离至 lib.rs,精简 main.rs 为纯粹的 CLI 入口
- 将代码按职责拆分为 config、env、runtime、shim 等子模块
- 提高可测试性与代码复用度
This commit is contained in:
2026-08-14 10:36:09 +08:00
parent e52ba67d7e
commit ed5439eaa1
8 changed files with 305 additions and 288 deletions

92
src/config.rs Normal file
View File

@@ -0,0 +1,92 @@
use std::collections::HashMap;
use std::path::PathBuf;
use std::process::Command;
use mlua::{FromLua, Lua, Table, Value};
#[derive(Debug, Clone)]
pub struct ShimConfig {
pub target_path: PathBuf,
pub args: Option<Vec<String>>,
pub envs: Option<HashMap<String, String>>,
}
impl ShimConfig {
/// 根据配置快速构建准备执行的 Command 对象
pub fn to_command(&self) -> Command {
let mut cmd = Command::new(&self.target_path);
if let Some(args) = &self.args {
cmd.args(args);
}
if let Some(envs) = &self.envs {
for (key, val) in envs {
// 直接应用环境变量Lua 端已经处理好字符串拼接或列表合并)
cmd.env(key, val);
}
}
cmd
}
}
/// 实现 FromLua Trait由 mlua 自动处理 Table 转换
impl FromLua for ShimConfig {
fn from_lua(value: Value, _lua: &Lua) -> mlua::Result<Self> {
match value {
Value::Table(table) => {
let path_str: String = table.get("path")?;
let args: Option<Vec<String>> = table.get("args")?;
// 解析 env Table
let mut envs_map = HashMap::new();
if let Ok(env_table) = table.get::<Table>("env") {
// 获取当前系统的路径分隔符Windows 为 ";"Unix 为 ":"
#[cfg(windows)]
let sep = ";";
#[cfg(not(windows))]
let sep = ":";
for pair in env_table.pairs::<String, Value>() {
let (k, v) = pair?;
match v {
// 情况 1: 普通字符串,如 HOME = "C:/path" -> 直接覆盖
Value::String(s) => {
envs_map.insert(k, s.to_str()?.to_string());
}
// 情况 2: 数组 Table如 PATH = { bin_dir, get_env("PATH") }
Value::Table(arr) => {
let paths: Vec<String> = arr
// 将 arr 作为序列(数组)处理,每个元素转为 String
.sequence_values::<String>()
.filter_map(|r| r.ok())
.filter(|s| !s.is_empty()) // 过滤空串,防止生成不必要的连续 ;;
.collect();
let combined = paths.join(sep);
envs_map.insert(k, combined);
}
_ => {}
}
}
}
let envs = if envs_map.is_empty() {
None
} else {
Some(envs_map)
};
Ok(ShimConfig {
target_path: PathBuf::from(path_str),
args,
envs,
})
}
_ => Err(mlua::Error::FromLuaConversionError {
from: value.type_name(),
to: "ShimConfig".into(),
message: Some("Expected a Lua table".to_string()),
}),
}
}
}