diff options
author | Norbert Preining <norbert@preining.info> | 2019-12-03 03:01:24 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2019-12-03 03:01:24 +0000 |
commit | b8d4bb76703bcb15578e2b23c5d256532180b894 (patch) | |
tree | bedd1df7a00521a2bd986b3c0289d6556a59e39b /support/texlab/src/completion/data.rs | |
parent | 02e4625a78a5029e8b5dc2a4ec70193b232f497e (diff) |
CTAN sync 201912030301
Diffstat (limited to 'support/texlab/src/completion/data.rs')
-rw-r--r-- | support/texlab/src/completion/data.rs | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/support/texlab/src/completion/data.rs b/support/texlab/src/completion/data.rs new file mode 100644 index 0000000000..827b99bac1 --- /dev/null +++ b/support/texlab/src/completion/data.rs @@ -0,0 +1,125 @@ +use crate::syntax::*; +use crate::workspace::Document; +use itertools::Itertools; +use lsp_types::{MarkupContent, MarkupKind}; +use once_cell::sync::Lazy; +use serde::{Deserialize, Serialize}; +use std::sync::Arc; + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Database { + pub components: Vec<Component>, + pub metadata: Vec<Metadata>, +} + +impl Database { + pub fn find(&self, name: &str) -> Option<&Component> { + self.components.iter().find(|component| { + component + .file_names + .iter() + .any(|file_name| file_name == name) + }) + } + + pub fn contains(&self, short_name: &str) -> bool { + let sty = format!("{}.sty", short_name); + let cls = format!("{}.cls", short_name); + self.find(&sty).is_some() || self.find(&cls).is_some() + } + + pub fn kernel(&self) -> &Component { + self.components + .iter() + .find(|component| component.file_names.is_empty()) + .unwrap() + } + + pub fn related_components(&self, documents: &[Arc<Document>]) -> Vec<&Component> { + let mut start_components = vec![self.kernel()]; + for document in documents { + if let SyntaxTree::Latex(tree) = &document.tree { + tree.components + .iter() + .flat_map(|file| self.find(file)) + .for_each(|component| start_components.push(component)) + } + } + + let mut all_components = Vec::new(); + for component in start_components { + all_components.push(component); + component + .references + .iter() + .flat_map(|file| self.find(&file)) + .for_each(|component| all_components.push(component)) + } + + all_components + .into_iter() + .unique_by(|component| &component.file_names) + .collect() + } + + pub fn exists(&self, file_name: &str) -> bool { + self.components + .iter() + .any(|component| component.file_names.iter().any(|f| f == file_name)) + } + + pub fn documentation(&self, name: &str) -> Option<MarkupContent> { + let metadata = self + .metadata + .iter() + .find(|metadata| metadata.name == name)?; + + let desc = metadata.description.to_owned()?; + Some(MarkupContent { + kind: MarkupKind::PlainText, + value: desc, + }) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Component { + pub file_names: Vec<String>, + pub references: Vec<String>, + pub commands: Vec<Command>, + pub environments: Vec<String>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Command { + pub name: String, + pub image: Option<String>, + pub glyph: Option<String>, + pub parameters: Vec<Parameter>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Parameter(pub Vec<Argument>); + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Argument { + pub name: String, + pub image: Option<String>, +} + +#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct Metadata { + pub name: String, + pub caption: Option<String>, + pub description: Option<String>, +} + +const JSON: &str = include_str!("data.json"); + +pub static DATABASE: Lazy<Database> = Lazy::new(|| serde_json::from_str(JSON).unwrap()); |