summaryrefslogtreecommitdiff
path: root/support/texlab/src/outline.rs
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2021-05-23 03:00:39 +0000
committerNorbert Preining <norbert@preining.info>2021-05-23 03:00:39 +0000
commitf1261b349e875b842745b63258c3e338cb1fe3bf (patch)
treeb5d402b3e80818cde2c079a42249f3dcb9732247 /support/texlab/src/outline.rs
parent58aa1ac09b1d9e4769d0a0661cf12e2b2db41b14 (diff)
CTAN sync 202105230300
Diffstat (limited to 'support/texlab/src/outline.rs')
-rw-r--r--support/texlab/src/outline.rs437
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
- }
-}