usage/spec/
complete.rs

1use kdl::{KdlEntry, KdlNode};
2use serde::{Deserialize, Serialize};
3
4use crate::error::UsageErr;
5use crate::spec::context::ParsingContext;
6use crate::spec::helpers::NodeHelper;
7use crate::spec::is_false;
8
9#[derive(Debug, Default, Clone, Serialize, Deserialize)]
10pub struct SpecComplete {
11    pub name: String,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub run: Option<String>,
14    #[serde(skip_serializing_if = "is_false")]
15    pub descriptions: bool,
16    #[serde(skip_serializing_if = "Option::is_none")]
17    pub type_: Option<String>,
18}
19
20impl SpecComplete {
21    pub(crate) fn parse(ctx: &ParsingContext, node: &NodeHelper) -> Result<Self, UsageErr> {
22        let mut config = Self::default();
23        node.ensure_arg_len(1..=1)?;
24        config.name = node.arg(0)?.ensure_string()?.to_string().to_lowercase();
25        for (k, v) in node.props() {
26            match k {
27                "run" => {
28                    if config.type_.is_some() {
29                        bail_parse!(ctx, v.entry.span(), "can set run or type, not both")
30                    }
31                    config.run = Some(v.ensure_string()?.to_string())
32                }
33                "descriptions" => config.descriptions = v.ensure_bool()?,
34                "type" => {
35                    if config.run.is_some() {
36                        bail_parse!(ctx, v.entry.span(), "can set run or type, not both")
37                    }
38                    config.type_ = Some(v.ensure_string()?.to_string())
39                }
40                k => bail_parse!(ctx, v.entry.span(), "unsupported complete key {k}"),
41            }
42        }
43        Ok(config)
44    }
45}
46
47impl From<&SpecComplete> for KdlNode {
48    fn from(complete: &SpecComplete) -> Self {
49        let mut node = KdlNode::new("complete");
50        node.push(KdlEntry::new(complete.name.clone()));
51        if let Some(run) = &complete.run {
52            node.push(KdlEntry::new_prop("run", run.clone()));
53        }
54        if let Some(type_) = &complete.type_ {
55            node.push(KdlEntry::new_prop("type", type_.clone()));
56        }
57        if complete.descriptions {
58            node.push(KdlEntry::new_prop("descriptions", "true".to_string()));
59        }
60        node
61    }
62}