1use bevy_ecs::{prelude::*, schedule::ScheduleLabel};
2use derive_more::{AsMut, AsRef, Deref, DerefMut};
3use crate::lsp_types::{MarkupContent, MarkupKind};
4
5use crate::lsp_types::{
6 CompletionItem, CompletionItemKind, CompletionItemLabelDetails, CompletionTextEdit,
7 Documentation, InsertTextFormat, TextEdit,
8};
9pub use crate::{
10 systems::{
11 complete_class, complete_properties, keyword_complete,
12 prefix::rdf_lov_undefined_prefix_completion,
13 },
14 util::{token::get_current_cst_token, triple::get_current_triple},
15};
16
17#[derive(ScheduleLabel, Clone, Eq, PartialEq, Debug, Hash)]
19pub struct Label;
20
21#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
23pub struct CompletionRequest(pub Vec<SimpleCompletion>);
24
25pub fn setup_schedule(world: &mut World) {
26 let mut completion = Schedule::new(Label);
27 completion.add_systems((
28 get_current_cst_token,
29 get_current_triple
30 .after(get_current_cst_token)
31 .before(generate_completions),
32 keyword_complete.after(generate_completions),
33 complete_class.after(generate_completions),
34 complete_properties.after(generate_completions),
35 rdf_lov_undefined_prefix_completion.after(generate_completions),
36 ));
37 world.add_schedule(completion);
38}
39
40pub fn generate_completions() {}
41
42#[derive(Debug)]
43pub struct SimpleCompletion {
44 pub kind: CompletionItemKind,
45 pub label: String,
46 pub _is_snippet: bool,
47 pub _label_details: Option<CompletionItemLabelDetails>,
48 pub _documentation: Option<String>,
49 pub _sort_text: Option<String>,
50 pub _filter_text: Option<String>,
51 pub edits: Vec<TextEdit>,
52 pub _commit_char: Option<String>,
53}
54
55impl SimpleCompletion {
56 pub fn new(kind: CompletionItemKind, label: String, edit: TextEdit) -> Self {
57 Self {
58 kind,
59 label,
60 edits: vec![edit],
61 _is_snippet: false,
62 _label_details: None,
63 _documentation: None,
64 _sort_text: None,
65 _filter_text: None,
66 _commit_char: None,
67 }
68 }
69 pub fn as_snippet(mut self) -> Self {
70 self._is_snippet = true;
71 self
72 }
73
74 pub fn label_detail(mut self, detail: impl Into<String>) -> Self {
75 if let Some(ref mut t) = self._label_details {
76 t.detail = Some(detail.into());
77 } else {
78 self._label_details = Some(CompletionItemLabelDetails {
79 detail: Some(detail.into()),
80 description: None,
81 });
82 }
83 self
84 }
85
86 pub fn label_description(mut self, description: impl Into<String>) -> Self {
87 if let Some(ref mut t) = self._label_details {
88 t.description = Some(description.into());
89 } else {
90 self._label_details = Some(CompletionItemLabelDetails {
91 description: Some(description.into()),
92 detail: None,
93 });
94 }
95 self
96 }
97
98 pub fn text_edit(mut self, edit: TextEdit) -> Self {
99 self.edits.push(edit);
100 self
101 }
102
103 pub fn documentation(mut self, documentation: impl Into<String>) -> Self {
104 self._documentation = Some(documentation.into());
105 self
106 }
107
108 pub fn m_documentation<S: Into<String>>(mut self, documentation: Option<S>) -> Self {
109 self._documentation = documentation.map(|x| x.into());
110 self
111 }
112
113 pub fn sort_text(mut self, sort_text: impl Into<String>) -> Self {
114 self._sort_text = Some(sort_text.into());
115 self
116 }
117
118 pub fn filter_text(mut self, filter_text: impl Into<String>) -> Self {
119 self._filter_text = Some(filter_text.into());
120 self
121 }
122
123 pub fn commit_char(mut self, commit_char: impl Into<String>) -> Self {
124 self._commit_char = Some(commit_char.into());
125 self
126 }
127}
128
129impl Into<CompletionItem> for SimpleCompletion {
130 fn into(self) -> CompletionItem {
131 let SimpleCompletion {
132 _is_snippet: is_snippet,
133 _filter_text: filter_text,
134 _sort_text: sort_text,
135 label,
136 _label_details,
137 _documentation: documentation,
138 kind,
139 edits,
140 _commit_char: commit_char,
141 } = self;
142
143 let text_edit = edits
144 .iter()
145 .next()
146 .map(|x| CompletionTextEdit::Edit(x.clone()));
147
148 let additional_text_edits = edits.into_iter().skip(1).collect();
149
150 CompletionItem {
151 label,
152 kind: Some(kind),
153 sort_text,
154 insert_text_format: (kind == CompletionItemKind::SNIPPET || is_snippet)
155 .then_some(InsertTextFormat::SNIPPET),
156 filter_text,
157 label_details: _label_details,
158 documentation: documentation.map(|st| {
159 Documentation::MarkupContent(MarkupContent {
160 kind: MarkupKind::Markdown,
161 value: st,
162 })
163 }),
164 text_edit,
165 additional_text_edits: Some(additional_text_edits),
166 commit_characters: commit_char.map(|x| vec![String::from(x)]),
167 ..Default::default()
168 }
169 }
170}