use std::{ env, path::PathBuf };
fn main()
{
println!( "cargo:rerun-if-changed=unilang.commands.yaml" );
println!( "cargo:rerun-if-changed=build.rs" );
if env::var( "CARGO_FEATURE_CLI" ).is_ok()
{
generate_static_commands();
}
}
fn generate_static_commands()
{
let out_dir = env::var( "OUT_DIR" )
.expect( "OUT_DIR environment variable not set" );
let yaml_content = std::fs::read_to_string( "unilang.commands.yaml" )
.expect( "Failed to read unilang.commands.yaml" );
let mut commands : Vec< serde_yaml::Value > = serde_yaml::from_str( &yaml_content )
.expect( "Failed to parse unilang.commands.yaml" );
for command in &mut commands
{
if let Some( args ) = command.get_mut( "arguments" ).and_then( | v | v.as_sequence_mut() )
{
for arg in args
{
if let Some( map ) = arg.as_mapping_mut()
{
transform_argument_attributes( map );
}
}
}
}
let temp_yaml_path = PathBuf::from( &out_dir ).join( "commands.yaml" );
let transformed_yaml = serde_yaml::to_string( &commands )
.expect( "Failed to serialize transformed commands" );
std::fs::write( &temp_yaml_path, transformed_yaml )
.expect( "Failed to write transformed commands" );
let config = unilang::multi_yaml::AggregationConfig
{
base_dir : PathBuf::from( &out_dir ),
modules : vec!
[
unilang::multi_yaml::ModuleConfig
{
name : "claude_storage".to_string(),
yaml_path : "commands.yaml".to_string(),
prefix : None,
enabled : true,
},
],
global_prefix : None,
detect_conflicts : true,
env_overrides : std::collections::HashMap::new(),
conflict_resolution : unilang::multi_yaml::ConflictResolutionStrategy::Fail,
auto_discovery : false,
discovery_patterns : vec![],
namespace_isolation : unilang::multi_yaml::NamespaceIsolation
{
enabled : false,
separator : ".".to_string(),
strict_mode : false,
},
};
let mut aggregator = unilang::multi_yaml::MultiYamlAggregator::new( config );
match aggregator.aggregate()
{
Ok( () ) =>
{
if !aggregator.conflicts().is_empty()
{
eprintln!( "ERROR: Command conflicts detected:" );
for conflict in aggregator.conflicts()
{
eprintln!( " - Command '{}' in modules: {:?}", conflict.command_name, conflict.modules );
}
panic!( "Build failed due to command conflicts" );
}
let mut registry_source = aggregator.generate_static_registry_source();
if !registry_source.contains( "show_version_in_help:" )
{
registry_source = registry_source.replace(
" auto_help_enabled: true,\n",
" auto_help_enabled: true,\n show_version_in_help: true,\n"
);
registry_source = registry_source.replace(
" auto_help_enabled: false,\n",
" auto_help_enabled: false,\n show_version_in_help: true,\n"
);
}
let output_path = PathBuf::from( &out_dir ).join( "static_commands.rs" );
std::fs::write( &output_path, ®istry_source )
.expect( "Failed to write static_commands.rs" );
let command_count = commands.len();
println!( "cargo:warning=Generated static command registry with {command_count} commands" );
}
Err( e ) =>
{
panic!( "Failed to aggregate commands: {e}" );
}
}
}
fn transform_argument_attributes( arg_map : &mut serde_yaml::Mapping )
{
let optional = arg_map
.remove( serde_yaml::Value::String( "optional".to_string() ) )
.and_then( | v | v.as_bool() )
.unwrap_or( false );
let default_val = arg_map
.remove( serde_yaml::Value::String( "default".to_string() ) )
.and_then( | v | match v
{
serde_yaml::Value::String( s ) => Some( s ),
serde_yaml::Value::Number( n ) => Some( n.to_string() ),
serde_yaml::Value::Bool( b ) => Some( b.to_string() ),
_ => None,
});
let mut attributes = serde_yaml::Mapping::new();
attributes.insert
(
serde_yaml::Value::String( "optional".to_string() ),
serde_yaml::Value::Bool( optional )
);
attributes.insert
(
serde_yaml::Value::String( "sensitive".to_string() ),
serde_yaml::Value::Bool( false )
);
attributes.insert
(
serde_yaml::Value::String( "interactive".to_string() ),
serde_yaml::Value::Bool( false )
);
attributes.insert
(
serde_yaml::Value::String( "multiple".to_string() ),
serde_yaml::Value::Bool( false )
);
if let Some( default_str ) = default_val
{
attributes.insert
(
serde_yaml::Value::String( "default".to_string() ),
serde_yaml::Value::String( default_str )
);
}
arg_map.insert
(
serde_yaml::Value::String( "attributes".to_string() ),
serde_yaml::Value::Mapping( attributes )
);
}