format.rs

 1use collections::HashMap;
 2use schemars::{JsonSchema, json_schema};
 3use serde::Deserialize;
 4use serde_json_lenient::Value;
 5use std::borrow::Cow;
 6
 7#[derive(Deserialize)]
 8pub struct VsSnippetsFile {
 9    #[serde(flatten)]
10    pub(crate) snippets: HashMap<String, VsCodeSnippet>,
11}
12
13impl VsSnippetsFile {
14    pub fn generate_json_schema() -> Value {
15        let schema = schemars::generate::SchemaSettings::draft07()
16            .into_generator()
17            .root_schema_for::<Self>();
18
19        serde_json_lenient::to_value(schema).unwrap()
20    }
21}
22
23impl JsonSchema for VsSnippetsFile {
24    fn schema_name() -> Cow<'static, str> {
25        "VsSnippetsFile".into()
26    }
27
28    fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
29        let snippet_schema = generator.subschema_for::<VsCodeSnippet>();
30        json_schema!({
31            "type": "object",
32            "additionalProperties": snippet_schema
33        })
34    }
35}
36
37#[derive(Deserialize, JsonSchema)]
38#[serde(untagged)]
39pub(crate) enum ListOrDirect {
40    Single(String),
41    List(Vec<String>),
42}
43
44impl From<ListOrDirect> for Vec<String> {
45    fn from(list: ListOrDirect) -> Self {
46        match list {
47            ListOrDirect::Single(entry) => vec![entry],
48            ListOrDirect::List(entries) => entries,
49        }
50    }
51}
52
53impl std::fmt::Display for ListOrDirect {
54    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
55        write!(
56            f,
57            "{}",
58            match self {
59                Self::Single(v) => v.to_owned(),
60                Self::List(v) => v.join("\n"),
61            }
62        )
63    }
64}
65
66#[derive(Deserialize, JsonSchema)]
67pub(crate) struct VsCodeSnippet {
68    /// The snippet prefix used to decide whether a completion menu should be shown.
69    pub(crate) prefix: Option<ListOrDirect>,
70
71    /// The snippet content. Use `$1` and `${1:defaultText}` to define cursor positions and `$0` for final cursor position.
72    pub(crate) body: ListOrDirect,
73
74    /// The snippet description displayed inside the completion menu.
75    pub(crate) description: Option<ListOrDirect>,
76}