microcad_lang/model/attribute/
export_command.rs

1// Copyright © 2025 The µcad authors <info@ucad.xyz>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4//! Export attribute.
5
6use crate::{
7    builtin::{ExportError, Exporter},
8    model::Model,
9    rc::RcMut,
10    render::{RenderCache, RenderContext},
11    value::Value,
12};
13use microcad_core::RenderResolution;
14
15/// Export attribute, e.g. `#[export: "output.svg"]`.
16#[derive(Clone)]
17pub struct ExportCommand {
18    /// Filename.
19    pub filename: std::path::PathBuf,
20    /// Resolution
21    pub resolution: RenderResolution,
22    /// Exporter.
23    pub exporter: std::rc::Rc<dyn Exporter>,
24}
25
26impl ExportCommand {
27    /// Export the model. By the settings in the attribute.
28    pub fn export(&self, model: &Model) -> Result<Value, ExportError> {
29        self.exporter.export(model, &self.filename)
30    }
31
32    /// Render the model and export.
33    pub fn render_and_export(&self, model: &Model) -> Result<Value, ExportError> {
34        let render_cache = RcMut::new(RenderCache::default());
35        let mut render_context =
36            RenderContext::new(model, self.resolution.clone(), Some(render_cache), None)?;
37        log::trace!(
38            "Pre-rendered model:\n{}",
39            crate::tree_display::FormatTree(model)
40        );
41
42        use crate::render::RenderWithContext;
43        self.exporter.export(
44            &model.render_with_context(&mut render_context)?,
45            &self.filename,
46        )
47    }
48}
49
50impl From<ExportCommand> for Value {
51    fn from(export_attribute: ExportCommand) -> Self {
52        crate::create_tuple_value!(
53            filename = Value::String(String::from(
54                export_attribute.filename.to_str().expect("PathBuf"),
55            )),
56            id = Value::String(export_attribute.exporter.id().to_string())
57        )
58    }
59}
60
61impl std::fmt::Debug for ExportCommand {
62    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
63        write!(
64            f,
65            "Export: {id:?} => {filename}",
66            id = self.exporter.id(),
67            filename = self.filename.display()
68        )
69    }
70}
71
72impl std::fmt::Display for ExportCommand {
73    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
74        write!(
75            f,
76            "\"{filename}\" with exporter `{id}`",
77            filename = self.filename.display(),
78            id = self.exporter.id(),
79        )
80    }
81}