lang_jsonld/
lib.rs

1#![doc(
2    html_logo_url = "https://ajuvercr.github.io/semantic-web-lsp/assets/icons/favicon.png",
3    html_favicon_url = "https://ajuvercr.github.io/semantic-web-lsp/assets/icons/favicon.ico"
4)]
5use bevy_ecs::prelude::*;
6use chumsky::prelude::Simple;
7use lsp_core::{
8    components::DynLang,
9    lang::{Lang, LangHelper},
10    prelude::*,
11    CreateEvent,
12};
13use lsp_types::SemanticTokenType;
14use ropey::Rope;
15
16pub mod ecs;
17pub mod lang;
18use crate::{
19    ecs::{highlight_named_nodes, keyword_highlight, setup_parse},
20    lang::parser::Json,
21};
22
23pub fn setup_world(world: &mut World) {
24    let mut semantic_token_dict = world.resource_mut::<SemanticTokensDict>();
25    JsonLd::LEGEND_TYPES.iter().for_each(|lt| {
26        if !semantic_token_dict.contains_key(lt) {
27            let l = semantic_token_dict.0.len();
28            semantic_token_dict.insert(lt.clone(), l);
29        }
30    });
31    world.observe(|trigger: Trigger<CreateEvent>, mut commands: Commands| {
32        match &trigger.event().language_id {
33            Some(x) if x == "jsonld" => {
34                commands
35                    .entity(trigger.entity())
36                    .insert(JsonLd)
37                    .insert(DynLang(Box::new(JsonLdHelper)));
38                return;
39            }
40            _ => {}
41        }
42        // pass
43        if trigger.event().url.as_str().ends_with(".jsonld") {
44            commands
45                .entity(trigger.entity())
46                .insert(JsonLd)
47                .insert(DynLang(Box::new(JsonLdHelper)));
48            return;
49        }
50    });
51
52    world.schedule_scope(SemanticLabel, |_, schedule| {
53        use semantic::*;
54        schedule.add_systems((
55            highlight_named_nodes
56                .before(keyword_highlight)
57                .after(basic_semantic_tokens),
58            keyword_highlight
59                .before(semantic_tokens_system)
60                .after(basic_semantic_tokens),
61        ));
62    });
63
64    world.schedule_scope(DiagnosticsLabel, |_, schedule| {
65        use diagnostics::*;
66        schedule.add_systems(publish_diagnostics::<JsonLd>);
67    });
68
69    setup_parse(world);
70}
71
72#[derive(Debug, Component)]
73pub struct JsonLd;
74
75impl Lang for JsonLd {
76    type Token = Token;
77
78    type TokenError = Simple<char>;
79
80    type Element = Json;
81
82    type ElementError = Simple<Token>;
83
84    const PATTERN: Option<&'static str> = None;
85
86    const LANG: &'static str = "jsonld";
87    const CODE_ACTION: bool = false;
88    const HOVER: bool = true;
89
90    const TRIGGERS: &'static [&'static str] = &["@", "\""];
91    const LEGEND_TYPES: &'static [SemanticTokenType] = &[
92        SemanticTokenType::VARIABLE,
93        SemanticTokenType::STRING,
94        SemanticTokenType::NUMBER,
95        SemanticTokenType::KEYWORD,
96        SemanticTokenType::PROPERTY,
97        SemanticTokenType::ENUM_MEMBER,
98    ];
99}
100
101#[derive(Debug)]
102pub struct JsonLdHelper;
103impl LangHelper for JsonLdHelper {
104    fn get_relevant_text(
105        &self,
106        token: &Spanned<Token>,
107        rope: &Rope,
108    ) -> (String, std::ops::Range<usize>) {
109        let r = token.span();
110        match token.value() {
111            Token::Str(st, _) => (st.clone(), r.start + 1..r.end - 1),
112            _ => (self._get_relevant_text(token, rope), r.clone()),
113        }
114    }
115
116    fn keyword(&self) -> &[&'static str] {
117        &[]
118    }
119}