Skip to content

Commit 28489b4

Browse files
MarkShawn2020claude
andcommitted
feat(statusbar): 支持脚本配置状态栏
- 重构 StatusBar 组件支持双模式:内置/脚本 - 添加 ANSI 颜色代码解析支持 - 新增 execute_statusbar_script 等 Rust 命令 - 在设置中添加 StatusBar 配置项 - 创建默认 statusbar.sh 脚本模板 脚本通过 stdin 接收 JSON 上下文,stdout 第一行作为状态栏内容 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 84c96c5 commit 28489b4

3 files changed

Lines changed: 427 additions & 40 deletions

File tree

src-tauri/src/lib.rs

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3656,6 +3656,119 @@ fn has_previous_statusline() -> bool {
36563656
get_lovstudio_dir().join("statusline").join("_previous.sh").exists()
36573657
}
36583658

3659+
/// Context passed to Lovcode statusbar script
3660+
#[derive(Debug, Serialize, Deserialize)]
3661+
pub struct StatusBarContext {
3662+
pub app_name: String,
3663+
pub version: String,
3664+
pub projects_count: usize,
3665+
pub features_count: usize,
3666+
pub today_lines_added: usize,
3667+
pub today_lines_deleted: usize,
3668+
pub timestamp: String,
3669+
pub home_dir: String,
3670+
}
3671+
3672+
/// Execute Lovcode's GUI statusbar script and return output
3673+
#[tauri::command]
3674+
fn execute_statusbar_script(script_path: String, context: StatusBarContext) -> Result<String, String> {
3675+
use std::io::Write;
3676+
use std::process::{Command, Stdio};
3677+
3678+
// Expand ~ to home dir
3679+
let home = dirs::home_dir().unwrap_or_default();
3680+
let expanded_path = if script_path.starts_with("~") {
3681+
script_path.replacen("~", &home.to_string_lossy(), 1)
3682+
} else {
3683+
script_path
3684+
};
3685+
3686+
let path = std::path::Path::new(&expanded_path);
3687+
if !path.exists() {
3688+
return Err(format!("Script not found: {}", expanded_path));
3689+
}
3690+
3691+
// Serialize context to JSON
3692+
let context_json = serde_json::to_string(&context).map_err(|e| e.to_string())?;
3693+
3694+
// Determine how to execute the script
3695+
#[cfg(unix)]
3696+
let mut child = Command::new(&expanded_path)
3697+
.stdin(Stdio::piped())
3698+
.stdout(Stdio::piped())
3699+
.stderr(Stdio::piped())
3700+
.spawn()
3701+
.map_err(|e| format!("Failed to spawn script: {}", e))?;
3702+
3703+
#[cfg(windows)]
3704+
let mut child = Command::new("powershell")
3705+
.args(["-ExecutionPolicy", "Bypass", "-File", &expanded_path])
3706+
.stdin(Stdio::piped())
3707+
.stdout(Stdio::piped())
3708+
.stderr(Stdio::piped())
3709+
.spawn()
3710+
.map_err(|e| format!("Failed to spawn script: {}", e))?;
3711+
3712+
// Write context JSON to stdin
3713+
if let Some(mut stdin) = child.stdin.take() {
3714+
stdin.write_all(context_json.as_bytes()).ok();
3715+
}
3716+
3717+
// Wait for output with timeout
3718+
let output = child
3719+
.wait_with_output()
3720+
.map_err(|e| format!("Script execution failed: {}", e))?;
3721+
3722+
// Get first line of stdout
3723+
let stdout = String::from_utf8_lossy(&output.stdout);
3724+
let first_line = stdout.lines().next().unwrap_or("").to_string();
3725+
3726+
Ok(first_line)
3727+
}
3728+
3729+
/// Get Lovcode statusbar settings from workspace.json
3730+
#[tauri::command]
3731+
fn get_statusbar_settings() -> Result<Option<serde_json::Value>, String> {
3732+
let settings_path = get_lovstudio_dir().join("statusbar-settings.json");
3733+
if !settings_path.exists() {
3734+
return Ok(None);
3735+
}
3736+
let content = fs::read_to_string(&settings_path).map_err(|e| e.to_string())?;
3737+
let settings: serde_json::Value = serde_json::from_str(&content).map_err(|e| e.to_string())?;
3738+
Ok(Some(settings))
3739+
}
3740+
3741+
/// Save Lovcode statusbar settings
3742+
#[tauri::command]
3743+
fn save_statusbar_settings(settings: serde_json::Value) -> Result<(), String> {
3744+
let settings_path = get_lovstudio_dir().join("statusbar-settings.json");
3745+
let content = serde_json::to_string_pretty(&settings).map_err(|e| e.to_string())?;
3746+
fs::write(&settings_path, content).map_err(|e| e.to_string())
3747+
}
3748+
3749+
/// Write Lovcode statusbar script to ~/.lovstudio/lovcode/statusbar/
3750+
#[tauri::command]
3751+
fn write_lovcode_statusbar_script(name: String, content: String) -> Result<String, String> {
3752+
let statusbar_dir = get_lovstudio_dir().join("statusbar");
3753+
fs::create_dir_all(&statusbar_dir).map_err(|e| e.to_string())?;
3754+
3755+
let script_path = statusbar_dir.join(format!("{}.sh", name));
3756+
fs::write(&script_path, &content).map_err(|e| e.to_string())?;
3757+
3758+
// Make executable on Unix
3759+
#[cfg(unix)]
3760+
{
3761+
use std::os::unix::fs::PermissionsExt;
3762+
let mut perms = fs::metadata(&script_path)
3763+
.map_err(|e| e.to_string())?
3764+
.permissions();
3765+
perms.set_mode(0o755);
3766+
fs::set_permissions(&script_path, perms).map_err(|e| e.to_string())?;
3767+
}
3768+
3769+
Ok(script_path.to_string_lossy().to_string())
3770+
}
3771+
36593772
/// Remove installed statusline template
36603773
#[tauri::command]
36613774
fn remove_statusline_template(name: String) -> Result<(), String> {
@@ -7184,6 +7297,10 @@ pub fn run() {
71847297
apply_statusline,
71857298
restore_previous_statusline,
71867299
has_previous_statusline,
7300+
execute_statusbar_script,
7301+
get_statusbar_settings,
7302+
save_statusbar_settings,
7303+
write_lovcode_statusbar_script,
71877304
remove_statusline_template,
71887305
open_in_editor,
71897306
open_file_at_line,

0 commit comments

Comments
 (0)