Skip to main content

maya_mel/maya/
model.rs

1//! Detailed Maya fact model types.
2//!
3//! Most users can stay on [`crate::maya`] entry points and inspect
4//! [`crate::maya::model::MayaTopLevelFacts`]. Reach for this module when you
5//! need the full set of Maya-specific item, hybrid, promotion, or
6//! selective-collection data types.
7
8use mel_parser::{LightCommandSurface, ParseOptions};
9use mel_sema::{CommandKind, CommandMode};
10use mel_syntax::{SourceView, TextRange};
11
12#[derive(Debug, Clone, PartialEq, Eq, Default)]
13/// Top-level Maya facts collected from a full parse.
14///
15/// The result is intentionally coarse-grained: each top-level item is either a
16/// proc, a command-style statement promoted into Maya-aware form, or an
17/// unclassified statement span.
18pub struct MayaTopLevelFacts {
19    pub items: Vec<MayaTopLevelItem>,
20}
21
22#[derive(Debug, Clone, PartialEq, Eq, Default)]
23pub struct MayaLightTopLevelFacts {
24    pub items: Vec<MayaLightTopLevelItem>,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
28pub enum MayaSelectivePassthrough {
29    #[default]
30    TargetOnly,
31    IncludeOtherCommands,
32}
33
34#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
35pub struct MayaSelectiveOptions {
36    pub passthrough: MayaSelectivePassthrough,
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq)]
40pub enum MayaTrackedSetAttrAttr {
41    B,
42    St,
43    Stp,
44    Ftn,
45    Fn,
46    F,
47}
48
49pub trait MayaSelectiveSetAttrSelector {
50    fn classify(&self, attr_path: &str) -> Option<MayaTrackedSetAttrAttr>;
51}
52
53impl<F> MayaSelectiveSetAttrSelector for F
54where
55    F: Fn(&str) -> Option<MayaTrackedSetAttrAttr>,
56{
57    fn classify(&self, attr_path: &str) -> Option<MayaTrackedSetAttrAttr> {
58        self(attr_path)
59    }
60}
61
62#[derive(Debug, Clone, Copy, Default)]
63pub struct DefaultMayaSelectiveSetAttrSelector;
64
65impl MayaSelectiveSetAttrSelector for DefaultMayaSelectiveSetAttrSelector {
66    fn classify(&self, attr_path: &str) -> Option<MayaTrackedSetAttrAttr> {
67        let suffix = attr_path.rsplit('.').next()?;
68        match suffix {
69            "b" => Some(MayaTrackedSetAttrAttr::B),
70            "st" => Some(MayaTrackedSetAttrAttr::St),
71            "stp" => Some(MayaTrackedSetAttrAttr::Stp),
72            "ftn" => Some(MayaTrackedSetAttrAttr::Ftn),
73            "fn" => Some(MayaTrackedSetAttrAttr::Fn),
74            "f" => Some(MayaTrackedSetAttrAttr::F),
75            _ => None,
76        }
77    }
78}
79
80#[derive(Debug, Clone, PartialEq, Eq)]
81pub enum MayaSelectiveItem {
82    Requires(MayaSelectiveRequires),
83    File(MayaSelectiveFile),
84    CreateNode(MayaSelectiveCreateNode),
85    SetAttr(MayaSelectiveSetAttr),
86    OtherCommand {
87        head_range: TextRange,
88        span: TextRange,
89    },
90}
91
92pub trait MayaSelectiveItemSink {
93    fn on_item(&mut self, item: MayaSelectiveItem);
94}
95
96impl<F> MayaSelectiveItemSink for F
97where
98    F: FnMut(MayaSelectiveItem),
99{
100    fn on_item(&mut self, item: MayaSelectiveItem) {
101        self(item);
102    }
103}
104
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct MayaSelectiveRequires {
107    pub head_range: TextRange,
108    pub argument_ranges: Vec<TextRange>,
109    pub span: TextRange,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq)]
113pub struct MayaSelectiveFile {
114    pub head_range: TextRange,
115    pub path_range: Option<TextRange>,
116    pub span: TextRange,
117}
118
119#[derive(Debug, Clone, PartialEq, Eq)]
120pub struct MayaSelectiveCreateNode {
121    pub head_range: TextRange,
122    pub node_type_range: Option<TextRange>,
123    pub name_range: Option<TextRange>,
124    pub parent_range: Option<TextRange>,
125    pub span: TextRange,
126}
127
128#[derive(Debug, Clone, PartialEq, Eq)]
129pub struct MayaSelectiveSetAttr {
130    pub head_range: TextRange,
131    pub attr_path_range: Option<TextRange>,
132    pub type_name_range: Option<TextRange>,
133    pub tracked_attr: Option<MayaTrackedSetAttrAttr>,
134    pub opaque_tail: Option<TextRange>,
135    pub span: TextRange,
136}
137
138#[derive(Debug, Clone, Copy, PartialEq, Eq)]
139pub enum MayaPromotionKind {
140    FullParse,
141    LightSynthesized,
142    OpaqueTailPromoted,
143    PolicyPromoted,
144    CustomDeciderPromoted,
145}
146
147#[derive(Debug, Clone, PartialEq, Eq, Default)]
148pub enum MayaPromotionPolicy {
149    #[default]
150    OpaqueTailOnly,
151    ByCommandName(Vec<String>),
152    Always,
153}
154
155#[derive(Debug, Clone, PartialEq, Eq)]
156pub struct MayaPromotionError {
157    pub command_span: TextRange,
158    pub head: Option<String>,
159    pub message: String,
160}
161
162#[derive(Debug, Clone, PartialEq, Eq)]
163pub struct MayaPromotionDiagnostic {
164    pub command_span: TextRange,
165    pub head: Option<String>,
166    pub attempted_kind: MayaPromotionKind,
167    pub message: String,
168}
169
170#[derive(Debug, Clone, PartialEq, Eq)]
171pub struct MayaCommandValidationDiagnostic {
172    pub command_span: TextRange,
173    pub head: Option<String>,
174    pub message: String,
175}
176
177#[derive(Debug, Clone, PartialEq, Eq, Default)]
178pub struct MayaHybridTopLevelReport {
179    pub facts: MayaTopLevelFacts,
180    pub promotion_diagnostics: Vec<MayaPromotionDiagnostic>,
181    pub validation_diagnostics: Vec<MayaCommandValidationDiagnostic>,
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, Default)]
185pub struct MayaPromotionOptions {
186    pub policy: MayaPromotionPolicy,
187    pub parse_options: ParseOptions,
188}
189
190#[derive(Debug, Clone, Copy, PartialEq, Eq)]
191pub struct MayaPromotionCandidate<'a> {
192    pub command: &'a LightCommandSurface,
193    pub raw_head: &'a str,
194    pub canonical_name: Option<&'a str>,
195}
196
197pub trait MayaPromotionDecider {
198    fn should_promote(&self, candidate: MayaPromotionCandidate<'_>) -> bool;
199}
200
201impl<F> MayaPromotionDecider for F
202where
203    F: for<'a> Fn(MayaPromotionCandidate<'a>) -> bool,
204{
205    fn should_promote(&self, candidate: MayaPromotionCandidate<'_>) -> bool {
206        self(candidate)
207    }
208}
209
210#[derive(Debug, Clone, Copy, Default)]
211pub struct NoopPromotionDecider;
212
213impl MayaPromotionDecider for NoopPromotionDecider {
214    fn should_promote(&self, _: MayaPromotionCandidate<'_>) -> bool {
215        false
216    }
217}
218
219#[derive(Debug, Clone, PartialEq, Eq)]
220/// A top-level item observed while collecting Maya facts from a full parse.
221pub enum MayaTopLevelItem {
222    Command(Box<MayaTopLevelCommand>),
223    Proc {
224        name: String,
225        is_global: bool,
226        span: TextRange,
227    },
228    Other {
229        span: TextRange,
230    },
231}
232
233#[derive(Debug, Clone, PartialEq, Eq)]
234pub enum MayaLightTopLevelItem {
235    Command(Box<MayaLightTopLevelCommand>),
236    Proc {
237        name: Option<String>,
238        is_global: bool,
239        span: TextRange,
240    },
241    Other {
242        span: TextRange,
243    },
244}
245
246#[derive(Debug, Clone, PartialEq, Eq)]
247/// Maya-specific view of a top-level command statement.
248///
249/// This keeps the original shell-like surface in [`Self::raw_items`] while also
250/// attaching optional normalized and specialized forms.
251pub struct MayaTopLevelCommand {
252    pub head: String,
253    pub captured: bool,
254    pub raw_items: Vec<MayaRawShellItem>,
255    pub normalized: Option<MayaNormalizedCommand>,
256    pub specialized: Option<MayaSpecializedCommand>,
257    pub promotion_kind: MayaPromotionKind,
258    pub span: TextRange,
259}
260
261#[derive(Debug, Clone, PartialEq, Eq)]
262pub struct MayaLightTopLevelCommand {
263    pub head: String,
264    pub captured: bool,
265    pub prefix_items: Vec<MayaRawShellItem>,
266    pub opaque_tail: Option<TextRange>,
267    pub specialized: Option<MayaLightSpecializedCommand>,
268    pub span: TextRange,
269}
270
271#[derive(Debug, Clone, PartialEq, Eq)]
272/// Lossless raw shell item captured from a command-style invocation.
273pub struct MayaRawShellItem {
274    /// Surface classification for this shell item.
275    pub kind: MayaRawShellItemKind,
276    /// Lossless source span for the full raw item surface as it appeared in the command.
277    pub span: TextRange,
278    pub(crate) text_range: Option<TextRange>,
279}
280
281#[derive(Debug, Clone, Copy, PartialEq, Eq)]
282/// Surface classification for a raw shell item.
283pub enum MayaRawShellItemKind {
284    Flag,
285    Numeric,
286    BareWord,
287    QuotedString,
288    Variable,
289    GroupedExpr,
290    BraceList,
291    VectorLiteral,
292    Capture,
293}
294
295#[derive(Debug, Clone, PartialEq, Eq)]
296pub struct MayaPositionalArg {
297    pub item: MayaRawShellItem,
298}
299
300#[derive(Debug, Clone, PartialEq, Eq)]
301pub struct MayaNormalizedFlag {
302    pub source_range: TextRange,
303    pub canonical_name: Option<String>,
304    pub args: Vec<MayaPositionalArg>,
305    pub span: TextRange,
306}
307
308#[derive(Debug, Clone, PartialEq, Eq)]
309pub struct MayaLightFlag {
310    pub source_range: TextRange,
311    pub canonical_name: Option<String>,
312    pub args: Vec<MayaPositionalArg>,
313    pub span: TextRange,
314}
315
316impl MayaRawShellItem {
317    /// Returns the lexical text span used to derive [`Self::value_text`], when this item kind has one.
318    ///
319    /// This range is distinct from [`Self::span`]: `span` covers the full raw item surface,
320    /// while `text_range` points at the slice that backs value extraction for literal-like words.
321    #[must_use]
322    pub fn text_range(&self) -> Option<TextRange> {
323        self.text_range
324    }
325
326    /// Returns the lossless source text for the full raw item surface.
327    #[must_use]
328    pub fn source_text<'a>(&self, source: SourceView<'a>) -> &'a str {
329        source.display_slice(self.span)
330    }
331
332    /// Returns the lexical value text for literal-like words.
333    ///
334    /// This accessor uses [`Self::text_range`] and may further normalize the sliced text by kind,
335    /// such as stripping the surrounding quotes from quoted strings.
336    #[must_use]
337    pub fn value_text<'a>(&self, source: SourceView<'a>) -> Option<&'a str> {
338        let text = source.slice(self.text_range?);
339        match self.kind {
340            MayaRawShellItemKind::Numeric | MayaRawShellItemKind::BareWord => Some(text),
341            MayaRawShellItemKind::QuotedString => text
342                .strip_prefix('"')
343                .and_then(|text| text.strip_suffix('"')),
344            MayaRawShellItemKind::Flag
345            | MayaRawShellItemKind::Variable
346            | MayaRawShellItemKind::GroupedExpr
347            | MayaRawShellItemKind::BraceList
348            | MayaRawShellItemKind::VectorLiteral
349            | MayaRawShellItemKind::Capture => None,
350        }
351    }
352
353    /// Returns the preferred consumer-facing text for this shell item.
354    ///
355    /// Literal-like words use [`Self::value_text`] so downstream consumers can read decoded
356    /// values without stripping quotes manually. Other shell surfaces fall back to full
357    /// source-preserving text.
358    #[must_use]
359    pub fn preferred_text<'a>(&self, source: SourceView<'a>) -> &'a str {
360        self.value_text(source)
361            .unwrap_or_else(|| self.source_text(source))
362    }
363}
364
365impl MayaPositionalArg {
366    #[must_use]
367    pub fn preferred_text<'a>(&self, source: SourceView<'a>) -> &'a str {
368        self.item.preferred_text(source)
369    }
370}
371
372impl MayaNormalizedFlag {
373    #[must_use]
374    pub fn source_text<'a>(&self, source: SourceView<'a>) -> &'a str {
375        source.display_slice(self.source_range)
376    }
377
378    #[must_use]
379    pub fn preferred_name<'a>(&'a self, source: SourceView<'a>) -> &'a str {
380        self.canonical_name
381            .as_deref()
382            .unwrap_or_else(|| self.source_text(source))
383    }
384
385    #[must_use]
386    pub fn matches_name(&self, source: SourceView<'_>, canonical: &str, short: &str) -> bool {
387        self.canonical_name.as_deref() == Some(canonical)
388            || self.source_text(source) == short
389            || self.source_text(source).trim_start_matches('-') == short.trim_start_matches('-')
390    }
391}
392
393impl MayaLightFlag {
394    #[must_use]
395    pub fn source_text<'a>(&self, source: SourceView<'a>) -> &'a str {
396        source.display_slice(self.source_range)
397    }
398
399    #[must_use]
400    pub fn preferred_name<'a>(&'a self, source: SourceView<'a>) -> &'a str {
401        self.canonical_name
402            .as_deref()
403            .unwrap_or_else(|| self.source_text(source))
404    }
405
406    #[must_use]
407    pub fn matches_name(&self, source: SourceView<'_>, canonical: &str, short: &str) -> bool {
408        self.canonical_name.as_deref() == Some(canonical)
409            || self.source_text(source) == short
410            || self.source_text(source).trim_start_matches('-') == short.trim_start_matches('-')
411    }
412}
413
414#[derive(Debug, Clone, PartialEq, Eq)]
415pub enum MayaNormalizedCommandItem {
416    Flag(MayaNormalizedFlag),
417    Positional(MayaPositionalArg),
418}
419
420#[derive(Debug, Clone, PartialEq, Eq)]
421/// Generic normalized command representation before Maya-specific specialization.
422pub struct MayaNormalizedCommand {
423    pub head: String,
424    pub(crate) head_range: TextRange,
425    pub schema_name: String,
426    pub kind: CommandKind,
427    pub mode: CommandMode,
428    pub items: Vec<MayaNormalizedCommandItem>,
429    pub span: TextRange,
430}
431
432#[derive(Debug, Clone, PartialEq, Eq)]
433/// Maya-specific structured command variants derived from a top-level command.
434pub enum MayaSpecializedCommand {
435    Requires(MayaRequiresCommand),
436    CurrentUnit(MayaCurrentUnitCommand),
437    FileInfo(MayaFileInfoCommand),
438    CreateNode(MayaCreateNodeCommand),
439    Rename(MayaRenameCommand),
440    Select(MayaSelectCommand),
441    SetAttr(MayaSetAttrCommand),
442    AddAttr(Box<MayaAddAttrCommand>),
443    ConnectAttr(MayaConnectAttrCommand),
444    Relationship(MayaRelationshipCommand),
445    File(MayaFileCommand),
446}
447
448#[derive(Debug, Clone, PartialEq, Eq)]
449pub enum MayaLightSpecializedCommand {
450    Requires(MayaLightRequiresCommand),
451    CurrentUnit(MayaLightCurrentUnitCommand),
452    FileInfo(MayaLightFileInfoCommand),
453    CreateNode(MayaLightCreateNodeCommand),
454    Rename(MayaLightRenameCommand),
455    Select(MayaLightSelectCommand),
456    SetAttr(MayaLightSetAttrCommand),
457    AddAttr(Box<MayaLightAddAttrCommand>),
458    ConnectAttr(MayaLightConnectAttrCommand),
459    Relationship(MayaLightRelationshipCommand),
460    File(MayaLightFileCommand),
461}
462
463#[derive(Debug, Clone, PartialEq, Eq)]
464pub struct MayaRequiresCommand {
465    pub plugin_name: Option<MayaRawShellItem>,
466    pub plugin_version: Option<MayaRawShellItem>,
467    pub option_items: Vec<MayaRawShellItem>,
468    pub requirements: Vec<MayaRawShellItem>,
469    pub flags: Vec<MayaNormalizedFlag>,
470    pub span: TextRange,
471}
472
473#[derive(Debug, Clone, PartialEq, Eq)]
474pub struct MayaLightRequiresCommand {
475    pub plugin_name: Option<MayaRawShellItem>,
476    pub plugin_version: Option<MayaRawShellItem>,
477    pub option_items: Vec<MayaRawShellItem>,
478    pub requirements: Vec<MayaRawShellItem>,
479    pub flags: Vec<MayaLightFlag>,
480    pub opaque_tail: Option<TextRange>,
481    pub span: TextRange,
482}
483
484#[derive(Debug, Clone, PartialEq, Eq)]
485pub struct MayaCurrentUnitCommand {
486    pub linear: Option<MayaRawShellItem>,
487    pub angle: Option<MayaRawShellItem>,
488    pub time: Option<MayaRawShellItem>,
489    pub flags: Vec<MayaNormalizedFlag>,
490    pub span: TextRange,
491}
492
493#[derive(Debug, Clone, PartialEq, Eq)]
494pub struct MayaLightCurrentUnitCommand {
495    pub linear: Option<MayaRawShellItem>,
496    pub angle: Option<MayaRawShellItem>,
497    pub time: Option<MayaRawShellItem>,
498    pub flags: Vec<MayaLightFlag>,
499    pub opaque_tail: Option<TextRange>,
500    pub span: TextRange,
501}
502
503#[derive(Debug, Clone, PartialEq, Eq)]
504pub struct MayaFileInfoCommand {
505    pub key: Option<MayaRawShellItem>,
506    pub value: Option<MayaRawShellItem>,
507    pub flags: Vec<MayaNormalizedFlag>,
508    pub span: TextRange,
509}
510
511#[derive(Debug, Clone, PartialEq, Eq)]
512pub struct MayaLightFileInfoCommand {
513    pub key: Option<MayaRawShellItem>,
514    pub value: Option<MayaRawShellItem>,
515    pub flags: Vec<MayaLightFlag>,
516    pub opaque_tail: Option<TextRange>,
517    pub span: TextRange,
518}
519
520#[derive(Debug, Clone, PartialEq, Eq)]
521pub struct MayaCreateNodeCommand {
522    pub node_type: Option<MayaRawShellItem>,
523    pub name: Option<MayaRawShellItem>,
524    pub parent: Option<MayaRawShellItem>,
525    pub shared: bool,
526    pub flags: Vec<MayaNormalizedFlag>,
527    pub span: TextRange,
528}
529
530#[derive(Debug, Clone, PartialEq, Eq)]
531pub struct MayaLightCreateNodeCommand {
532    pub node_type: Option<MayaRawShellItem>,
533    pub name: Option<MayaRawShellItem>,
534    pub parent: Option<MayaRawShellItem>,
535    pub shared: bool,
536    pub flags: Vec<MayaLightFlag>,
537    pub opaque_tail: Option<TextRange>,
538    pub span: TextRange,
539}
540
541#[derive(Debug, Clone, PartialEq, Eq)]
542pub struct MayaRenameCommand {
543    pub uuid: Option<MayaRawShellItem>,
544    pub source: Option<MayaRawShellItem>,
545    pub target: Option<MayaRawShellItem>,
546    pub flags: Vec<MayaNormalizedFlag>,
547    pub span: TextRange,
548}
549
550#[derive(Debug, Clone, PartialEq, Eq)]
551pub struct MayaLightRenameCommand {
552    pub uuid: Option<MayaRawShellItem>,
553    pub source: Option<MayaRawShellItem>,
554    pub target: Option<MayaRawShellItem>,
555    pub flags: Vec<MayaLightFlag>,
556    pub opaque_tail: Option<TextRange>,
557    pub span: TextRange,
558}
559
560#[derive(Debug, Clone, PartialEq, Eq)]
561pub struct MayaSelectCommand {
562    pub no_expand: bool,
563    pub targets: Vec<MayaRawShellItem>,
564    pub flags: Vec<MayaNormalizedFlag>,
565    pub span: TextRange,
566}
567
568#[derive(Debug, Clone, PartialEq, Eq)]
569pub struct MayaLightSelectCommand {
570    pub no_expand: bool,
571    pub targets: Vec<MayaRawShellItem>,
572    pub flags: Vec<MayaLightFlag>,
573    pub opaque_tail: Option<TextRange>,
574    pub span: TextRange,
575}
576
577#[derive(Debug, Clone, PartialEq, Eq)]
578pub struct MayaSetAttrCommand {
579    pub attr_path: Option<MayaRawShellItem>,
580    pub type_name: Option<MayaRawShellItem>,
581    pub value_kind: MayaSetAttrValueKind,
582    pub values: Vec<MayaRawShellItem>,
583    pub flags: Vec<MayaNormalizedFlag>,
584    pub span: TextRange,
585}
586
587#[derive(Debug, Clone, PartialEq, Eq)]
588pub struct MayaLightSetAttrCommand {
589    pub attr_path: Option<MayaRawShellItem>,
590    pub type_name: Option<MayaRawShellItem>,
591    pub value_kind: MayaSetAttrValueKind,
592    pub prefix_values: Vec<MayaRawShellItem>,
593    pub flags: Vec<MayaLightFlag>,
594    pub opaque_tail: Option<TextRange>,
595    pub span: TextRange,
596}
597
598#[derive(Debug, Clone, Copy, PartialEq, Eq)]
599pub enum MayaSetAttrValueKind {
600    TypedNumbers,
601    String,
602    StringArray,
603    Int32Array,
604    ComponentList,
605    OpaqueTyped,
606    MatrixXform,
607    DataReferenceEdits,
608    Unknown,
609}
610
611#[derive(Debug, Clone, PartialEq, Eq)]
612pub struct MayaAddAttrCommand {
613    pub short_name: Option<MayaRawShellItem>,
614    pub long_name: Option<MayaRawShellItem>,
615    pub parent: Option<MayaRawShellItem>,
616    pub number_of_children: Option<MayaRawShellItem>,
617    pub nice_name: Option<MayaRawShellItem>,
618    pub default_value: Option<MayaRawShellItem>,
619    pub min_value: Option<MayaRawShellItem>,
620    pub max_value: Option<MayaRawShellItem>,
621    pub soft_min_value: Option<MayaRawShellItem>,
622    pub soft_max_value: Option<MayaRawShellItem>,
623    pub enum_name: Option<MayaRawShellItem>,
624    pub attribute_type: Option<MayaRawShellItem>,
625    pub data_type: Option<MayaRawShellItem>,
626    pub flags: Vec<MayaNormalizedFlag>,
627    pub tail: Vec<MayaRawShellItem>,
628    pub tail_kind: MayaAddAttrTailKind,
629    pub span: TextRange,
630}
631
632#[derive(Debug, Clone, PartialEq, Eq)]
633pub struct MayaLightAddAttrCommand {
634    pub short_name: Option<MayaRawShellItem>,
635    pub long_name: Option<MayaRawShellItem>,
636    pub parent: Option<MayaRawShellItem>,
637    pub number_of_children: Option<MayaRawShellItem>,
638    pub nice_name: Option<MayaRawShellItem>,
639    pub default_value: Option<MayaRawShellItem>,
640    pub min_value: Option<MayaRawShellItem>,
641    pub max_value: Option<MayaRawShellItem>,
642    pub soft_min_value: Option<MayaRawShellItem>,
643    pub soft_max_value: Option<MayaRawShellItem>,
644    pub enum_name: Option<MayaRawShellItem>,
645    pub attribute_type: Option<MayaRawShellItem>,
646    pub data_type: Option<MayaRawShellItem>,
647    pub flags: Vec<MayaLightFlag>,
648    pub tail: Vec<MayaRawShellItem>,
649    pub tail_kind: MayaAddAttrTailKind,
650    pub opaque_tail: Option<TextRange>,
651    pub span: TextRange,
652}
653
654#[derive(Debug, Clone, Copy, PartialEq, Eq)]
655pub enum MayaAddAttrTailKind {
656    None,
657    Numeric,
658    String,
659    Mixed,
660}
661
662#[derive(Debug, Clone, PartialEq, Eq)]
663pub struct MayaConnectAttrCommand {
664    pub source_attr: Option<MayaRawShellItem>,
665    pub target_attr: Option<MayaRawShellItem>,
666    pub next_available: bool,
667    pub lock_arg: Option<MayaRawShellItem>,
668    pub flags: Vec<MayaNormalizedFlag>,
669    pub span: TextRange,
670}
671
672#[derive(Debug, Clone, PartialEq, Eq)]
673pub struct MayaLightConnectAttrCommand {
674    pub source_attr: Option<MayaRawShellItem>,
675    pub target_attr: Option<MayaRawShellItem>,
676    pub next_available: bool,
677    pub lock_arg: Option<MayaRawShellItem>,
678    pub flags: Vec<MayaLightFlag>,
679    pub opaque_tail: Option<TextRange>,
680    pub span: TextRange,
681}
682
683#[derive(Debug, Clone, PartialEq, Eq)]
684pub struct MayaRelationshipCommand {
685    pub relationship: Option<MayaRawShellItem>,
686    pub members: Vec<MayaRawShellItem>,
687    pub flags: Vec<MayaNormalizedFlag>,
688    pub span: TextRange,
689}
690
691#[derive(Debug, Clone, PartialEq, Eq)]
692pub struct MayaLightRelationshipCommand {
693    pub relationship: Option<MayaRawShellItem>,
694    pub members: Vec<MayaRawShellItem>,
695    pub flags: Vec<MayaLightFlag>,
696    pub opaque_tail: Option<TextRange>,
697    pub span: TextRange,
698}
699
700#[derive(Debug, Clone, PartialEq, Eq)]
701pub struct MayaFileCommand {
702    pub path: Option<MayaRawShellItem>,
703    pub namespace: Option<MayaRawShellItem>,
704    pub reference_node: Option<MayaRawShellItem>,
705    pub file_type: Option<MayaRawShellItem>,
706    pub options: Option<MayaRawShellItem>,
707    pub is_reference: bool,
708    pub flags: Vec<MayaNormalizedFlag>,
709    pub span: TextRange,
710}
711
712#[derive(Debug, Clone, PartialEq, Eq)]
713pub struct MayaLightFileCommand {
714    pub path: Option<MayaRawShellItem>,
715    pub namespace: Option<MayaRawShellItem>,
716    pub reference_node: Option<MayaRawShellItem>,
717    pub file_type: Option<MayaRawShellItem>,
718    pub options: Option<MayaRawShellItem>,
719    pub is_reference: bool,
720    pub flags: Vec<MayaLightFlag>,
721    pub opaque_tail: Option<TextRange>,
722    pub span: TextRange,
723}