forked from
stavola.xyz/mlf
A human-friendly DSL for ATProto Lexicons
1use crate::config::{find_project_root, ConfigError, MlfConfig};
2use std::path::PathBuf;
3
4pub mod code;
5pub mod lexicon;
6pub mod mlf;
7
8/// Run all output configurations from mlf.toml
9pub fn run_all() -> Result<(), std::io::Error> {
10 let current_dir = std::env::current_dir()?;
11
12 let project_root = find_project_root(¤t_dir)
13 .map_err(|e| match e {
14 ConfigError::NotFound => {
15 std::io::Error::new(
16 std::io::ErrorKind::NotFound,
17 "No mlf.toml found. Please create a configuration file or provide explicit arguments."
18 )
19 }
20 _ => std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to load config: {}", e)),
21 })?;
22
23 let config_path = project_root.join("mlf.toml");
24 let config = MlfConfig::load(&config_path)
25 .map_err(|e| std::io::Error::new(std::io::ErrorKind::Other, format!("Failed to load config: {}", e)))?;
26
27 if config.output.is_empty() {
28 println!("No output configurations found in mlf.toml");
29 return Ok(());
30 }
31
32 println!("Running {} output configuration(s)...", config.output.len());
33
34 // Build input path from source directory
35 let source_dir = project_root.join(&config.source.directory);
36 let input_paths = vec![source_dir.clone()];
37
38 let mut errors = Vec::new();
39 let mut success_count = 0;
40
41 for output_config in &config.output {
42 let output_type = &output_config.r#type;
43 let output_dir = PathBuf::from(&output_config.directory);
44
45 println!("\nGenerating {} output to {}...", output_type, output_config.directory);
46
47 let result = match output_type.as_str() {
48 "lexicon" => {
49 lexicon::run(input_paths.clone(), Some(output_dir), Some(source_dir.clone()), false)
50 .map_err(|e| format!("{}", e))
51 }
52 "mlf" => {
53 // For MLF output, we expect JSON lexicons as input
54 // This is a bit different - we'd need JSON input patterns
55 eprintln!(" Warning: MLF generation from TOML config not yet fully implemented");
56 continue;
57 }
58 generator_type => {
59 // Assume it's a code generator (typescript, go, rust, etc.)
60 code::run(Some(generator_type.to_string()), input_paths.clone(), Some(output_dir), Some(source_dir.clone()), false)
61 .map_err(|e| format!("{}", e))
62 }
63 };
64
65 match result {
66 Ok(()) => {
67 success_count += 1;
68 println!(" ✓ Generated {} output successfully", output_type);
69 }
70 Err(e) => {
71 errors.push((output_type.clone(), e));
72 eprintln!(" ✗ Failed to generate {} output", output_type);
73 }
74 }
75 }
76
77 if !errors.is_empty() {
78 eprintln!(
79 "\n{} output(s) generated successfully, {} error(s)",
80 success_count,
81 errors.len()
82 );
83 for (output_type, error) in &errors {
84 eprintln!(" {} - {}", output_type, error);
85 }
86 return Err(std::io::Error::new(
87 std::io::ErrorKind::Other,
88 format!("Failed to generate {} output(s)", errors.len())
89 ));
90 }
91
92 println!("\n✓ Successfully generated all {} output(s)", success_count);
93 Ok(())
94}