typst_analyzer_analysis/completion/
markup.rs1use std::collections::HashMap;
25
26use tower_lsp::lsp_types::{CompletionItem, CompletionItemKind, InsertTextFormat, MarkupContent};
27
28use crate::{get_images, typ_logger};
29
30use super::generic::TypCmpItem;
31
32pub fn items() -> Vec<CompletionItem> {
33 let mut items = Vec::new();
34 items.append(&mut headers());
35 items
36}
37
38pub fn constructors() -> Vec<CompletionItem> {
39 let mut items = Vec::new();
40 let constructor: Vec<(&str, &str, String)> = vec![
42 ("Paragraph break", "parbreak", "parbreak()\n".to_owned()),
43 ("Strong emphasis", "strong", "*${1:Text}*".to_owned()),
44 ("Strong emphasis", "bold", "*${1:Text}*".to_owned()),
45 ("Emphasis", "emph", "_${1:Text}_".to_owned()),
46 ("Raw text", "raw", "`${1:Text}`".to_owned()),
47 ("Link", "link", "https://${1:URL}/".to_owned()),
48 ("Label", "label", "<${1:Text}>".to_owned()),
49 ("Reference", "ref", "@${1:Text}".to_owned()),
50 ("Bullet list", "bullet-list", "- ${1:Text}".to_owned()),
51 ("Numbered list", "numbered-list", "+ ${1:Text}".to_owned()),
52 (
53 "Term list",
54 "terms",
55 "/ ${1:Term}: ${2:Description}".to_owned(),
56 ),
57 ("Line break", "linebreak", "\\".to_owned()),
58 ("Smart quote", "smartquote", "'${1:Text}'".to_owned()),
59 ("Code expression", "Scripting", "#${1:Code}".to_owned()),
60 ("Comment", "line-comment", "// ${1:Text}".to_owned()),
61 ("Comment", "block-comment", "/*\n ${1:Text} \n*/".to_owned()),
62 ];
63 for ctx in constructor {
64 let item = TypCmpItem {
65 label: ctx.1.to_owned(),
66 label_details: "markup",
67 kind: CompletionItemKind::CONSTRUCTOR,
68 documentation: ctx.0,
69 insert_text: ctx.2.to_owned(),
70 };
71 items.push(item);
72 }
73 TypCmpItem::get_cmp(items)
74}
75
76fn get_headers() -> HashMap<String, String> {
77 let mut cmp_item = HashMap::new();
78 let mut item = "=".to_owned();
79
80 for num in 1..7 {
82 let label = format!("h{}", num); cmp_item.insert(label, item.clone());
84 item.push('='); }
86 cmp_item
87}
88
89#[test]
90fn header_test() {
91 let mut expected = HashMap::new();
92 expected.insert("h1".to_owned(), "=".to_owned());
93 expected.insert("h2".to_owned(), "==".to_owned());
94 expected.insert("h3".to_owned(), "===".to_owned());
95 expected.insert("h4".to_owned(), "====".to_owned());
96 expected.insert("h5".to_owned(), "=====".to_owned());
97 expected.insert("h6".to_owned(), "======".to_owned());
98
99 let result = get_headers();
100
101 assert_eq!(
102 result, expected,
103 "The generated HashMap does not match the expected output."
104 );
105}
106
107fn headers() -> Vec<CompletionItem> {
108 let header = get_headers();
109 let mut header_items = Vec::new();
110 for (key, val) in header {
111 let num: usize = key[1..].parse().unwrap_or(0);
112 header_items.push(CompletionItem {
113 label: key.to_owned(),
114 label_details: Some(tower_lsp::lsp_types::CompletionItemLabelDetails {
115 detail: Some("Header".to_owned()),
116 description: None,
117 }),
118 kind: Some(CompletionItemKind::CONSTRUCTOR),
119 documentation: Some(tower_lsp::lsp_types::Documentation::MarkupContent(
120 MarkupContent {
121 kind: tower_lsp::lsp_types::MarkupKind::Markdown,
122 value: format!("level {} heading", num),
123 },
124 )),
125 insert_text: Some(format!("{} ", val)),
126 insert_text_format: Some(InsertTextFormat::PLAIN_TEXT),
127 ..Default::default()
128 });
129 }
130 header_items
131}
132
133pub fn typ_image_cmp() -> Result<Vec<CompletionItem>, anyhow::Error> {
134 let mut items = Vec::new();
135 let images = get_images()?;
136 typ_logger!("image: {:#?}", images);
137 for item in images {
138 let image = item.to_string_lossy().to_string();
139 let item = TypCmpItem {
140 label: "image".to_owned(),
141 label_details: "markup",
142 kind: CompletionItemKind::FILE,
143 documentation: "Image",
144 insert_text: format!("#image(\"{}\", width: 100%)", image),
145 };
146 typ_logger!("image: {}", image);
147 items.push(item);
148 }
149 Ok(TypCmpItem::get_cmp(items))
150}