Skip to main content

aam_core/commands/
import.rs

1//! `@import` directive — merges another `.aam` file into the current document.
2//!
3//! # Syntax
4//! ```text
5//! @import path/to/file.aam
6//! @import "path/to/file.aam"
7//! ```
8//!
9//! # Semantics
10//! Unlike `@derive`, `@import` uses `merge_content` which means **later** values
11//! overwrite earlier ones. If the same key appears in both the current document
12//! and the imported file, the imported value **wins** (last-write semantics).
13
14use crate::aaml::AAML;
15use crate::commands::Command;
16use crate::error::AamlError;
17use crate::pipeline::utils::resolve_relative_path;
18
19/// Command handler for the `@import` directive.
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21pub struct ImportCommand;
22
23impl Command for ImportCommand {
24    fn name(&self) -> &'static str {
25        "import"
26    }
27
28    /// Reads the file at the given path and merges its content into `aaml`.
29    ///
30    /// # Errors
31    /// - [`AamlError::ParseError`] — path argument is empty.
32    /// - [`AamlError::IoError`] — a file cannot be read.
33    /// - Any parse error from the imported file.
34    fn execute(&self, aaml: &mut AAML, args: &str) -> Result<(), AamlError> {
35        let raw_path = args.trim();
36        if raw_path.is_empty() {
37            return Err(AamlError::ParseError {
38                line: 0,
39                content: args.to_string(),
40                details: "Import path cannot be empty".to_string(),
41                diagnostics: Some(Box::new(crate::error::ErrorDiagnostics::new(
42                    "Missing import path",
43                    "@import directive requires a file path",
44                    "Use format: @import \"path/to/file.aam\"",
45                ))),
46            });
47        }
48
49        let path = AAML::unwrap_quotes(raw_path);
50        let resolved = resolve_relative_path(path, aaml.source_dir.as_deref());
51        aaml.merge_file(resolved)
52    }
53}