diff options
author | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
---|---|---|
committer | Norbert Preining <norbert@preining.info> | 2021-05-23 03:00:39 +0000 |
commit | f1261b349e875b842745b63258c3e338cb1fe3bf (patch) | |
tree | b5d402b3e80818cde2c079a42249f3dcb9732247 /support/texlab/src/outline.rs | |
parent | 58aa1ac09b1d9e4769d0a0661cf12e2b2db41b14 (diff) |
CTAN sync 202105230300
Diffstat (limited to 'support/texlab/src/outline.rs')
-rw-r--r-- | support/texlab/src/outline.rs | 437 |
1 files changed, 0 insertions, 437 deletions
diff --git a/support/texlab/src/outline.rs b/support/texlab/src/outline.rs deleted file mode 100644 index 07ffaee09f..0000000000 --- a/support/texlab/src/outline.rs +++ /dev/null @@ -1,437 +0,0 @@ -use crate::{ - feature::DocumentView, - protocol::{MarkupContent, MarkupKind, Options, Position, Range, RangeExt, Uri}, - syntax::{latex, SyntaxNode}, - workspace::{Document, DocumentContent}, -}; -use std::{borrow::Cow, collections::HashSet, path::Path}; -use titlecase::titlecase; -use OutlineContextItem::*; - -#[derive(Debug, Clone, Copy)] -pub struct OutlineSection<'a> { - pub document: &'a Document, - pub item: &'a latex::Section, -} - -pub struct Outline<'a> { - sections: Vec<OutlineSection<'a>>, -} - -impl<'a> Outline<'a> { - pub fn find(&'a self, uri: &Uri, pos: Position) -> Option<&'a latex::Section> { - self.sections - .iter() - .filter(|section| section.document.uri == *uri) - .rev() - .find(|section| { - let table = section.document.content.as_latex().unwrap(); - table[section.item.parent].end() <= pos - }) - .map(|sec| sec.item) - } - - pub fn analyze(view: &'a DocumentView, options: &Options, current_dir: &Path) -> Self { - let mut finder = OutlineSectionFinder::default(); - let doc = view - .snapshot - .parent(&view.current.uri, options, current_dir) - .map(|parent| { - view.related - .iter() - .find(|doc| doc.uri == parent.uri) - .unwrap() - }) - .unwrap_or(&view.current); - - finder.analyze(view, doc); - Self { - sections: finder.sections, - } - } -} - -#[derive(Debug, Clone, Copy)] -enum OutlineItem<'a> { - Section(&'a latex::Section), - Include(&'a latex::Include), -} - -#[derive(Debug, Default)] -struct OutlineSectionFinder<'a> { - visited: HashSet<&'a Uri>, - sections: Vec<OutlineSection<'a>>, -} - -impl<'a> OutlineSectionFinder<'a> { - fn analyze(&mut self, view: &'a DocumentView, doc: &'a Document) { - if !self.visited.insert(&doc.uri) { - return; - } - - if let DocumentContent::Latex(table) = &doc.content { - let mut items = Vec::new(); - for section in &table.sections { - items.push(OutlineItem::Section(section)); - } - for include in &table.includes { - items.push(OutlineItem::Include(include)); - } - items.sort_by_key(|item| match item { - OutlineItem::Include(include) => table[include.parent].start(), - OutlineItem::Section(section) => table[section.parent].start(), - }); - - for item in items { - match item { - OutlineItem::Section(item) => { - let section = OutlineSection { - document: doc, - item, - }; - self.sections.push(section); - } - OutlineItem::Include(item) => { - for doc in &view.related { - for targets in &item.all_targets { - if targets.contains(&doc.uri) { - self.analyze(view, doc); - break; - } - } - } - } - } - } - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone, Copy)] -pub enum OutlineCaptionKind { - Figure, - Table, - Listing, - Algorithm, -} - -impl OutlineCaptionKind { - pub fn as_str(self) -> &'static str { - match self { - Self::Figure => "Figure", - Self::Table => "Table", - Self::Listing => "Listing", - Self::Algorithm => "Algorithm", - } - } - - pub fn parse(env_name: &str) -> Option<Self> { - match env_name { - "figure" | "subfigure" => Some(Self::Figure), - "table" | "subtable" => Some(Self::Table), - "listing" | "lstlisting" => Some(Self::Listing), - "algorithm" => Some(Self::Algorithm), - _ => None, - } - } -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub enum OutlineContextItem { - Section { - prefix: Cow<'static, str>, - text: String, - }, - Caption { - kind: Option<OutlineCaptionKind>, - text: String, - }, - Theorem { - kind: String, - description: Option<String>, - }, - Equation, - Item, -} - -#[derive(Debug, PartialEq, Eq, Clone)] -pub struct OutlineContext { - pub range: Range, - pub number: Option<String>, - pub item: OutlineContextItem, -} - -impl OutlineContext { - pub fn reference(&self) -> String { - match &self.number { - Some(number) => match &self.item { - Section { prefix, text } => format!("{} {} ({})", prefix, number, text), - Caption { kind: None, text } => format!("{} {}", number, text), - Caption { - kind: Some(kind), - text, - } => format!("{} {}: {}", kind.as_str(), number, text), - Theorem { - kind, - description: None, - } => format!("{} {}", kind, number), - Theorem { - kind, - description: Some(description), - } => format!("{} {} ({})", kind, number, description), - Equation => format!("Equation ({})", number), - Item => format!("Item {}", number), - }, - None => match &self.item { - Section { prefix, text } => format!("{} ({})", prefix, text), - Caption { kind: None, text } => text.clone(), - Caption { - kind: Some(kind), - text, - } => format!("{}: {}", kind.as_str(), text), - Theorem { - kind, - description: None, - } => kind.into(), - Theorem { - kind, - description: Some(description), - } => format!("{} ({})", kind, description), - Equation => "Equation".into(), - Item => "Item".into(), - }, - } - } - - pub fn detail(&self) -> Option<String> { - match &self.item { - Section { .. } | Theorem { .. } | Equation | Item => Some(self.reference()), - Caption { - kind: Some(kind), .. - } => { - let result = match &self.number { - Some(number) => format!("{} {}", kind.as_str(), number), - None => kind.as_str().to_owned(), - }; - Some(result) - } - Caption { .. } => None, - } - } - - pub fn documentation(&self) -> MarkupContent { - MarkupContent { - kind: MarkupKind::PlainText, - value: self.reference(), - } - } - - pub fn parse(view: &DocumentView, outline: &Outline, label: latex::Label) -> Option<Self> { - if let DocumentContent::Latex(table) = &view.current.content { - Self::find_caption(view, table, label) - .or_else(|| Self::find_theorem(view, table, label)) - .or_else(|| Self::find_equation(view, table, label)) - .or_else(|| Self::find_item(view, table, label)) - .or_else(|| Self::find_section(view, outline, table, label)) - } else { - None - } - } - - fn find_caption( - view: &DocumentView, - table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<Self> { - let label_range = table[label.parent].range(); - let caption_env = table - .environments - .iter() - .filter(|env| !env.is_root(&table)) - .find(|env| env.range(&table).contains(label_range.start))?; - - let caption = table - .captions - .iter() - .find(|cap| table.is_direct_child(*caption_env, table[cap.parent].start()))?; - - let caption_text = table.print_group_content( - caption.parent, - latex::GroupKind::Group, - caption.arg_index, - )?; - - let caption_kind = caption_env - .left - .name(&table) - .map(latex::Token::text) - .and_then(OutlineCaptionKind::parse); - - Some(Self { - range: caption_env.range(&table), - number: Self::find_number(view, table, label), - item: Caption { - kind: caption_kind, - text: caption_text, - }, - }) - } - - fn find_theorem( - view: &DocumentView, - main_table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<Self> { - let label_range = main_table[label.parent].range(); - let env = main_table - .environments - .iter() - .find(|env| env.range(&main_table).contains(label_range.start))?; - - let env_name = env.left.name(&main_table).map(latex::Token::text)?; - - for doc in &view.related { - if let DocumentContent::Latex(table) = &doc.content { - for def in &table.theorem_definitions { - if env_name == def.name(&table).text() { - let kind = table - .print_group_content( - def.parent, - latex::GroupKind::Group, - def.arg_index + 1, - ) - .unwrap_or_else(|| titlecase(&env_name)); - - let description = main_table.print_group_content( - env.left.parent, - latex::GroupKind::Options, - 0, - ); - - return Some(Self { - range: env.range(&main_table), - number: Self::find_number(view, main_table, label), - item: Theorem { kind, description }, - }); - } - } - } - } - None - } - - fn find_equation( - view: &DocumentView, - table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<Self> { - let label_range = table[label.parent].range(); - table - .environments - .iter() - .filter(|env| env.left.is_math(&table)) - .map(|env| env.range(&table)) - .find(|range| range.contains(label_range.start)) - .map(|range| Self { - range, - number: Self::find_number(view, table, label), - item: Equation, - }) - } - - fn find_item( - view: &DocumentView, - table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<Self> { - let label_range = table[label.parent].range(); - struct LatexItemNode { - item: latex::Item, - range: Range, - } - - let enumeration = table - .environments - .iter() - .filter(|env| env.left.is_enum(&table)) - .find(|env| env.range(&table).contains(label_range.start))?; - - let mut item_nodes: Vec<_> = table - .items - .iter() - .filter(|item| table.is_enum_item(*enumeration, **item)) - .map(|item| LatexItemNode { - item: *item, - range: Range::default(), - }) - .collect(); - - for i in 0..item_nodes.len() { - let start = table[item_nodes[i].item.parent].start(); - let end = item_nodes - .get(i + 1) - .map(|node| table[node.item.parent].start()) - .unwrap_or_else(|| table[enumeration.right.parent].start()); - item_nodes[i].range = Range::new(start, end); - } - - let node = item_nodes - .iter() - .find(|node| node.range.contains(label_range.start))?; - - let number = node - .item - .name(&table) - .or_else(|| Self::find_number(view, table, label)); - - Some(Self { - range: enumeration.range(&table), - number, - item: Item, - }) - } - - fn find_section( - view: &DocumentView, - outline: &Outline, - table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<Self> { - let label_range = table[label.parent].range(); - let section = outline.find(&view.current.uri, label_range.start)?; - Some(Self { - range: table[section.parent].range(), - number: Self::find_number(view, table, label), - item: Section { - prefix: section.prefix.clone(), - text: table.print_group_content( - section.parent, - latex::GroupKind::Group, - section.arg_index, - )?, - }, - }) - } - - pub fn find_number( - view: &DocumentView, - table: &latex::SymbolTable, - label: latex::Label, - ) -> Option<String> { - let label_names = label.names(&table); - if label_names.len() != 1 { - return None; - } - - for doc in &view.related { - if let DocumentContent::Latex(table) = &doc.content { - for numbering in &table.label_numberings { - if numbering.name(&table).text() == label_names[0].text() { - return Some(numbering.number.clone()); - } - } - } - } - None - } -} |