1use serde_json::Value;
4
5#[derive(Debug, Clone, Copy)]
7#[allow(dead_code)]
8pub enum CompletionItemKind {
9 Text = 1,
10 Method = 2,
11 Function = 3,
12 Constructor = 4,
13 Field = 5,
14 Variable = 6,
15 Class = 7,
16 Interface = 8,
17 Module = 9,
18 Property = 10,
19 Unit = 11,
20 Value = 12,
21 Enum = 13,
22 Keyword = 14,
23 Snippet = 15,
24 Color = 16,
25 File = 17,
26 Reference = 18,
27}
28
29pub fn get_ssml_completions() -> Vec<Value> {
31 vec![
32 create_completion_item(
33 "speak",
34 CompletionItemKind::Snippet,
35 "SSML root element",
36 "<speak>$1</speak>",
37 ),
38 create_completion_item(
39 "voice",
40 CompletionItemKind::Snippet,
41 "Voice selection element",
42 "<voice name=\"${1:kokoro-en}\">$2</voice>",
43 ),
44 create_completion_item(
45 "prosody",
46 CompletionItemKind::Snippet,
47 "Prosody control (rate, pitch, volume)",
48 "<prosody rate=\"${1:1.0}\" pitch=\"${2:0}\" volume=\"${3:0}\">$4</prosody>",
49 ),
50 create_completion_item(
51 "break",
52 CompletionItemKind::Snippet,
53 "Insert pause",
54 "<break time=\"${1:500ms}\"/>",
55 ),
56 create_completion_item(
57 "emphasis",
58 CompletionItemKind::Snippet,
59 "Emphasis level control",
60 "<emphasis level=\"${1:moderate}\">$2</emphasis>",
61 ),
62 create_completion_item(
63 "say-as",
64 CompletionItemKind::Snippet,
65 "Control interpretation",
66 "<say-as interpret-as=\"${1:cardinal}\">$2</say-as>",
67 ),
68 create_completion_item(
69 "phoneme",
70 CompletionItemKind::Snippet,
71 "Phonetic pronunciation",
72 "<phoneme alphabet=\"${1:ipa}\" ph=\"${2:pronunciation}\">$3</phoneme>",
73 ),
74 create_completion_item(
75 "sub",
76 CompletionItemKind::Snippet,
77 "Substitute pronunciation",
78 "<sub alias=\"${1:alias}\">$2</sub>",
79 ),
80 ]
81}
82
83pub fn get_voice_completions() -> Vec<Value> {
85 vec![
86 create_simple_completion(
87 "kokoro-en",
88 CompletionItemKind::Value,
89 "Kokoro English voice",
90 ),
91 create_simple_completion(
92 "kokoro-ja",
93 CompletionItemKind::Value,
94 "Kokoro Japanese voice",
95 ),
96 create_simple_completion(
97 "kokoro-zh",
98 CompletionItemKind::Value,
99 "Kokoro Chinese voice",
100 ),
101 create_simple_completion("en-us-male", CompletionItemKind::Value, "English US Male"),
102 create_simple_completion(
103 "en-us-female",
104 CompletionItemKind::Value,
105 "English US Female",
106 ),
107 ]
108}
109
110pub fn get_emphasis_levels() -> Vec<Value> {
112 vec![
113 create_simple_completion("strong", CompletionItemKind::Keyword, "Strong emphasis"),
114 create_simple_completion("moderate", CompletionItemKind::Keyword, "Moderate emphasis"),
115 create_simple_completion("reduced", CompletionItemKind::Keyword, "Reduced emphasis"),
116 create_simple_completion("none", CompletionItemKind::Keyword, "No emphasis"),
117 ]
118}
119
120pub fn get_interpret_as_types() -> Vec<Value> {
122 vec![
123 create_simple_completion("cardinal", CompletionItemKind::Keyword, "Cardinal number"),
124 create_simple_completion("ordinal", CompletionItemKind::Keyword, "Ordinal number"),
125 create_simple_completion("characters", CompletionItemKind::Keyword, "Spell out"),
126 create_simple_completion("date", CompletionItemKind::Keyword, "Date format"),
127 create_simple_completion("time", CompletionItemKind::Keyword, "Time format"),
128 create_simple_completion("telephone", CompletionItemKind::Keyword, "Phone number"),
129 ]
130}
131
132fn create_completion_item(
134 label: &str,
135 kind: CompletionItemKind,
136 detail: &str,
137 insert_text: &str,
138) -> Value {
139 serde_json::json!({
140 "label": label,
141 "kind": kind as u32,
142 "detail": detail,
143 "insertText": insert_text,
144 "insertTextFormat": 2, "documentation": {
146 "kind": "markdown",
147 "value": format!("**{}**\n\n{}", label, detail)
148 }
149 })
150}
151
152fn create_simple_completion(label: &str, kind: CompletionItemKind, detail: &str) -> Value {
154 serde_json::json!({
155 "label": label,
156 "kind": kind as u32,
157 "detail": detail,
158 "insertText": label,
159 "insertTextFormat": 1 })
161}
162
163#[cfg(test)]
164mod tests {
165 use super::*;
166
167 #[test]
168 fn test_ssml_completions() {
169 let completions = get_ssml_completions();
170 assert!(!completions.is_empty());
171 assert!(completions.iter().any(|c| c["label"] == "speak"));
172 assert!(completions.iter().any(|c| c["label"] == "voice"));
173 assert!(completions.iter().any(|c| c["label"] == "prosody"));
174 }
175
176 #[test]
177 fn test_voice_completions() {
178 let completions = get_voice_completions();
179 assert!(!completions.is_empty());
180 assert!(completions.iter().any(|c| c["label"] == "kokoro-en"));
181 }
182
183 #[test]
184 fn test_emphasis_levels() {
185 let levels = get_emphasis_levels();
186 assert_eq!(levels.len(), 4);
187 assert!(levels.iter().any(|l| l["label"] == "strong"));
188 assert!(levels.iter().any(|l| l["label"] == "moderate"));
189 }
190
191 #[test]
192 fn test_interpret_as_types() {
193 let types = get_interpret_as_types();
194 assert!(!types.is_empty());
195 assert!(types.iter().any(|t| t["label"] == "cardinal"));
196 assert!(types.iter().any(|t| t["label"] == "date"));
197 }
198}