use super::args::{CliArgs, Commands, OutputFormat};
use crate::notebook::{NotebookFormat, NotebookDeserializer, NotebookUI};
use crate::api::Yufmath;
use std::path::Path;
pub fn run_command(args: CliArgs) -> Result<(), Box<dyn std::error::Error>> {
match args.command {
Some(Commands::Notepad { file, title, terminal }) => {
run_notepad_command(file, title, terminal)?;
}
Some(Commands::Interactive) => {
crate::cli::run_interactive()?;
}
Some(Commands::Compute { expression }) => {
let yuf = Yufmath::new();
let result = yuf.compute(&expression)?;
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Simplify { expression }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let simplified = yuf.simplify(&expr)?;
let result = yuf.format(&simplified);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Diff { expression, variable }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let derivative = yuf.diff(&expr, &variable)?;
let result = yuf.format(&derivative);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Integrate { expression, variable }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let integral = yuf.integrate(&expr, &variable)?;
let result = yuf.format(&integral);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Solve { equation, variable }) => {
let yuf = Yufmath::new();
let eq = yuf.parse(&equation)?;
let solutions = yuf.solve(&eq, &variable)?;
for (i, solution) in solutions.iter().enumerate() {
let result = yuf.format(solution);
println!("解 {}: {}", i + 1, format_output(&result, &args.format));
}
}
Some(Commands::Factor { expression }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let factored = yuf.factor(&expr)?;
let result = yuf.format(&factored);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Expand { expression }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let expanded = yuf.expand(&expr)?;
let result = yuf.format(&expanded);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Limit { expression, variable, point }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let point_expr = yuf.parse(&point)?;
let limit = yuf.limit(&expr, &variable, &point_expr)?;
let result = yuf.format(&limit);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Series { expression, variable, point, order }) => {
let yuf = Yufmath::new();
let expr = yuf.parse(&expression)?;
let point_expr = yuf.parse(&point)?;
let series = yuf.series(&expr, &variable, &point_expr, order)?;
let result = yuf.format(&series);
println!("{}", format_output(&result, &args.format));
}
Some(Commands::Batch { ref input, ref output }) => {
run_batch_command(input, output.as_deref(), &args)?;
}
None => {
crate::cli::run_interactive()?;
}
}
Ok(())
}
fn run_notepad_command(file: Option<String>, title: Option<String>, terminal: bool) -> Result<(), Box<dyn std::error::Error>> {
let notebook = if let Some(file_path) = file {
let path = Path::new(&file_path);
if path.exists() {
println!("正在加载笔记本: {}", file_path);
NotebookDeserializer::load_from_file(path)?
} else {
let notebook_title = title.unwrap_or_else(|| {
path.file_stem()
.and_then(|s| s.to_str())
.unwrap_or("新笔记本")
.to_string()
});
println!("正在创建新笔记本: {} ({})", notebook_title, file_path);
let mut notebook = NotebookFormat::create_template(¬ebook_title);
crate::notebook::NotebookSerializer::save_to_file(&mut notebook, path)?;
notebook
}
} else {
let notebook_title = title.unwrap_or_else(|| "临时笔记本".to_string());
println!("正在创建临时笔记本: {}", notebook_title);
NotebookFormat::create_template(¬ebook_title)
};
if terminal {
let mut ui = NotebookUI::with_notebook(notebook);
ui.run()?;
} else {
println!("正在启动图形界面...");
if !has_display() {
eprintln!("警告:未检测到图形环境,将使用终端界面");
eprintln!("提示:");
eprintln!(" - 确保在图形桌面环境中运行");
eprintln!(" - 如果使用 SSH,请使用 -X 或 -Y 参数启用 X11 转发");
eprintln!(" - 或者使用 --terminal 参数强制使用终端界面");
let mut ui = NotebookUI::with_notebook(notebook);
ui.run()?;
} else {
let mut gui_ui = crate::notebook::NotebookGUI::new();
match gui_ui.set_notebook(notebook) {
Ok(_) => {
match gui_ui.run() {
Ok(_) => {
println!("图形界面已关闭");
}
Err(e) => {
eprintln!("图形界面运行错误: {}", e);
}
}
}
Err(e) => {
eprintln!("图形界面设置失败: {}", e);
}
}
}
}
Ok(())
}
fn run_batch_command(input: &str, output: Option<&str>, args: &CliArgs) -> Result<(), Box<dyn std::error::Error>> {
use std::fs;
use std::io::Write;
let input_content = fs::read_to_string(input)?;
let lines: Vec<&str> = input_content.lines().collect();
let yuf = Yufmath::new();
let mut results = Vec::new();
for (line_num, line) in lines.iter().enumerate() {
let line = line.trim();
if line.is_empty() || line.starts_with('#') {
continue; }
match yuf.compute(line) {
Ok(result) => {
let formatted = format_output(&result, &args.format);
results.push(format!("输入 {}: {}", line_num + 1, line));
results.push(format!("输出 {}: {}", line_num + 1, formatted));
if !args.quiet {
println!("输入 {}: {}", line_num + 1, line);
println!("输出 {}: {}", line_num + 1, formatted);
}
}
Err(e) => {
let error_msg = format!("错误 {}: {}", line_num + 1, e);
results.push(error_msg.clone());
if !args.quiet {
eprintln!("{}", error_msg);
}
}
}
}
if let Some(output_path) = output {
let mut file = fs::File::create(output_path)?;
for result in results {
writeln!(file, "{}", result)?;
}
if !args.quiet {
println!("结果已保存到: {}", output_path);
}
}
Ok(())
}
fn format_output(result: &str, format: &OutputFormat) -> String {
match format {
OutputFormat::Standard => result.to_string(),
OutputFormat::Latex => {
if result.starts_with('$') && result.ends_with('$') {
result.to_string()
} else {
format!("${result}$")
}
}
OutputFormat::Mathml => {
format!("<math><mrow>{}</mrow></math>", result)
}
}
}
fn has_display() -> bool {
std::env::var("DISPLAY").is_ok() ||
std::env::var("WAYLAND_DISPLAY").is_ok() ||
cfg!(target_os = "windows") ||
cfg!(target_os = "macos")
}