mirror of
https://github.com/latex-lsp/texlab.git
synced 2025-08-04 10:49:55 +00:00
Add symbol support for thmtools package (#897)
This commit is contained in:
parent
365c04050c
commit
f24f35f2a6
17 changed files with 200 additions and 21 deletions
|
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- Add symbol support for `thmtools` package ([#894](https://github.com/latex-lsp/texlab/issues/894))
|
||||
|
||||
### Changed
|
||||
|
||||
- Show inlay hints for labels after the command instead of inside the argument ([#890](https://github.com/latex-lsp/texlab/issues/890))
|
||||
|
|
|
@ -223,13 +223,11 @@ impl Semantics {
|
|||
fn process_theorem_definition(&mut self, theorem_def: latex::TheoremDefinition) {
|
||||
let Some(name) = theorem_def.name().and_then(|name| name.key()) else { return };
|
||||
|
||||
let Some(description) = theorem_def
|
||||
.heading()
|
||||
.and_then(|group| group.content_text()) else { return };
|
||||
let Some(heading) = theorem_def.heading() else { return };
|
||||
|
||||
self.theorem_definitions.push(TheoremDefinition {
|
||||
name: Span::from(&name),
|
||||
heading: description,
|
||||
heading,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,7 +138,8 @@ impl<'a> Parser<'a> {
|
|||
CommandName::AcronymDefinition => self.acronym_definition(),
|
||||
CommandName::AcronymDeclaration => self.acronym_declaration(),
|
||||
CommandName::AcronymReference => self.acronym_reference(),
|
||||
CommandName::TheoremDefinition => self.theorem_definition(),
|
||||
CommandName::TheoremDefinitionAmsThm => self.theorem_definition_amsthm(),
|
||||
CommandName::TheoremDefinitionThmTools => self.theorem_definition_thmtools(),
|
||||
CommandName::ColorReference => self.color_reference(),
|
||||
CommandName::ColorDefinition => self.color_definition(),
|
||||
CommandName::ColorSetDefinition => self.color_set_definition(),
|
||||
|
@ -978,8 +979,8 @@ impl<'a> Parser<'a> {
|
|||
self.builder.finish_node();
|
||||
}
|
||||
|
||||
fn theorem_definition(&mut self) {
|
||||
self.builder.start_node(THEOREM_DEFINITION.into());
|
||||
fn theorem_definition_amsthm(&mut self) {
|
||||
self.builder.start_node(THEOREM_DEFINITION_AMSTHM.into());
|
||||
self.eat();
|
||||
self.trivia();
|
||||
|
||||
|
@ -1002,6 +1003,22 @@ impl<'a> Parser<'a> {
|
|||
self.builder.finish_node();
|
||||
}
|
||||
|
||||
fn theorem_definition_thmtools(&mut self) {
|
||||
self.builder.start_node(THEOREM_DEFINITION_THMTOOLS.into());
|
||||
self.eat();
|
||||
self.trivia();
|
||||
|
||||
if self.lexer.peek() == Some(Token::LBrack) {
|
||||
self.brack_group_key_value();
|
||||
}
|
||||
|
||||
if self.lexer.peek() == Some(Token::LCurly) {
|
||||
self.curly_group_word();
|
||||
}
|
||||
|
||||
self.builder.finish_node();
|
||||
}
|
||||
|
||||
fn color_reference(&mut self) {
|
||||
self.builder.start_node(COLOR_REFERENCE.into());
|
||||
self.eat();
|
||||
|
|
|
@ -67,9 +67,8 @@ pub fn classify(name: &str, config: &SyntaxConfig) -> CommandName {
|
|||
| "Glsentrylong" | "glsentrylongpl" | "Glsentrylongpl" | "glsentryshort"
|
||||
| "Glsentryshort" | "glsentryshortpl" | "Glsentryshortpl" | "glsentryfullpl"
|
||||
| "Glsentryfullpl" => CommandName::AcronymReference,
|
||||
"newtheorem" | "newtheorem*" | "declaretheorem" | "declaretheorem*" => {
|
||||
CommandName::TheoremDefinition
|
||||
}
|
||||
"newtheorem" | "newtheorem*" => CommandName::TheoremDefinitionAmsThm,
|
||||
"declaretheorem" | "declaretheorem*" => CommandName::TheoremDefinitionThmTools,
|
||||
"color" | "colorbox" | "textcolor" | "pagecolor" => CommandName::ColorReference,
|
||||
"definecolor" => CommandName::ColorDefinition,
|
||||
"definecolorset" => CommandName::ColorSetDefinition,
|
||||
|
|
|
@ -111,7 +111,8 @@ pub enum CommandName {
|
|||
AcronymDefinition,
|
||||
AcronymDeclaration,
|
||||
AcronymReference,
|
||||
TheoremDefinition,
|
||||
TheoremDefinitionAmsThm,
|
||||
TheoremDefinitionThmTools,
|
||||
ColorReference,
|
||||
ColorDefinition,
|
||||
ColorSetDefinition,
|
||||
|
|
|
@ -5,7 +5,7 @@ input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definit
|
|||
---
|
||||
ROOT@0..31
|
||||
PREAMBLE@0..31
|
||||
THEOREM_DEFINITION@0..31
|
||||
THEOREM_DEFINITION_AMSTHM@0..31
|
||||
COMMAND_NAME@0..11 "\\newtheorem"
|
||||
CURLY_GROUP_WORD@11..16
|
||||
L_CURLY@11..12 "{"
|
||||
|
|
|
@ -5,7 +5,7 @@ input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definit
|
|||
---
|
||||
ROOT@0..21
|
||||
PREAMBLE@0..21
|
||||
THEOREM_DEFINITION@0..21
|
||||
THEOREM_DEFINITION_AMSTHM@0..21
|
||||
COMMAND_NAME@0..11 "\\newtheorem"
|
||||
CURLY_GROUP_WORD@11..16
|
||||
L_CURLY@11..12 "{"
|
||||
|
|
|
@ -5,7 +5,7 @@ input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definit
|
|||
---
|
||||
ROOT@0..21
|
||||
PREAMBLE@0..21
|
||||
THEOREM_DEFINITION@0..21
|
||||
THEOREM_DEFINITION_AMSTHM@0..21
|
||||
COMMAND_NAME@0..11 "\\newtheorem"
|
||||
CURLY_GROUP_WORD@11..16
|
||||
L_CURLY@11..12 "{"
|
||||
|
|
|
@ -5,7 +5,7 @@ input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definit
|
|||
---
|
||||
ROOT@0..26
|
||||
PREAMBLE@0..26
|
||||
THEOREM_DEFINITION@0..26
|
||||
THEOREM_DEFINITION_AMSTHM@0..26
|
||||
COMMAND_NAME@0..11 "\\newtheorem"
|
||||
CURLY_GROUP_WORD@11..16
|
||||
L_CURLY@11..12 "{"
|
||||
|
|
|
@ -5,7 +5,7 @@ input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definit
|
|||
---
|
||||
ROOT@0..16
|
||||
PREAMBLE@0..16
|
||||
THEOREM_DEFINITION@0..16
|
||||
THEOREM_DEFINITION_AMSTHM@0..16
|
||||
COMMAND_NAME@0..11 "\\newtheorem"
|
||||
CURLY_GROUP_WORD@11..16
|
||||
L_CURLY@11..12 "{"
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
source: crates/parser/src/latex.rs
|
||||
expression: root
|
||||
input_file: crates/parser/src/test_data/latex/theorem_definition/theorem_definition_thmtools.txt
|
||||
---
|
||||
ROOT@0..41
|
||||
PREAMBLE@0..41
|
||||
THEOREM_DEFINITION_THMTOOLS@0..41
|
||||
COMMAND_NAME@0..15 "\\declaretheorem"
|
||||
BRACK_GROUP_KEY_VALUE@15..36
|
||||
L_BRACK@15..16 "["
|
||||
KEY_VALUE_BODY@16..35
|
||||
KEY_VALUE_PAIR@16..25
|
||||
KEY@16..21
|
||||
WORD@16..21 "style"
|
||||
EQUALITY_SIGN@21..22 "="
|
||||
VALUE@22..25
|
||||
TEXT@22..25
|
||||
WORD@22..25 "foo"
|
||||
COMMA@25..26 ","
|
||||
WHITESPACE@26..27 " "
|
||||
KEY_VALUE_PAIR@27..35
|
||||
KEY@27..31
|
||||
WORD@27..31 "name"
|
||||
EQUALITY_SIGN@31..32 "="
|
||||
VALUE@32..35
|
||||
TEXT@32..35
|
||||
WORD@32..35 "bar"
|
||||
R_BRACK@35..36 "]"
|
||||
CURLY_GROUP_WORD@36..41
|
||||
L_CURLY@36..37 "{"
|
||||
KEY@37..40
|
||||
WORD@37..40 "baz"
|
||||
R_CURLY@40..41 "}"
|
||||
|
|
@ -0,0 +1 @@
|
|||
\declaretheorem[style=foo, name=bar]{baz}
|
|
@ -0,0 +1,53 @@
|
|||
---
|
||||
source: crates/symbols/src/document/tests.rs
|
||||
expression: "document_symbols(&fixture.workspace, document)"
|
||||
---
|
||||
[
|
||||
Symbol {
|
||||
name: "Lemma 1 (Foo)",
|
||||
kind: Theorem,
|
||||
label: Some(
|
||||
Span(
|
||||
"thm:foo",
|
||||
147..162,
|
||||
),
|
||||
),
|
||||
full_range: 129..182,
|
||||
selection_range: 147..162,
|
||||
children: [],
|
||||
},
|
||||
Symbol {
|
||||
name: "Lemma 2",
|
||||
kind: Theorem,
|
||||
label: Some(
|
||||
Span(
|
||||
"thm:bar",
|
||||
197..212,
|
||||
),
|
||||
),
|
||||
full_range: 184..232,
|
||||
selection_range: 197..212,
|
||||
children: [],
|
||||
},
|
||||
Symbol {
|
||||
name: "Lemma",
|
||||
kind: Theorem,
|
||||
label: Some(
|
||||
Span(
|
||||
"thm:baz",
|
||||
247..262,
|
||||
),
|
||||
),
|
||||
full_range: 234..282,
|
||||
selection_range: 247..262,
|
||||
children: [],
|
||||
},
|
||||
Symbol {
|
||||
name: "Lemma (Qux)",
|
||||
kind: Theorem,
|
||||
label: None,
|
||||
full_range: 284..322,
|
||||
selection_range: 284..322,
|
||||
children: [],
|
||||
},
|
||||
]
|
|
@ -138,7 +138,7 @@ fn test_section() {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn test_theorem() {
|
||||
fn test_theorem_amsthm() {
|
||||
let fixture = Fixture::parse(
|
||||
r#"
|
||||
%! main.tex
|
||||
|
@ -177,6 +177,46 @@ fn test_theorem() {
|
|||
assert_debug_snapshot!(document_symbols(&fixture.workspace, document));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_theorem_thmtools() {
|
||||
let fixture = Fixture::parse(
|
||||
r#"
|
||||
%! main.tex
|
||||
\documentclass{article}
|
||||
\declaretheoremstyle{lemmastyle}
|
||||
\declaretheorem[style=lemmastyle, name=Lemma]{lemma}
|
||||
|
||||
\begin{document}
|
||||
|
||||
\begin{lemma}[Foo]\label{thm:foo}
|
||||
Foo
|
||||
\end{lemma}
|
||||
|
||||
\begin{lemma}\label{thm:bar}
|
||||
Bar
|
||||
\end{lemma}
|
||||
|
||||
\begin{lemma}\label{thm:baz}
|
||||
Baz
|
||||
\end{lemma}
|
||||
|
||||
\begin{lemma}[Qux]
|
||||
Qux
|
||||
\end{lemma}
|
||||
|
||||
\end{document}
|
||||
|
|
||||
|
||||
%! main.aux
|
||||
\relax
|
||||
\newlabel{thm:foo}{{1}{1}}
|
||||
\newlabel{thm:bar}{{2}{1}}"#,
|
||||
);
|
||||
|
||||
let document = fixture.workspace.lookup(&fixture.documents[0].uri).unwrap();
|
||||
assert_debug_snapshot!(document_symbols(&fixture.workspace, document));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_allowed_patterns() {
|
||||
let mut fixture = Fixture::parse(
|
||||
|
|
|
@ -265,6 +265,15 @@ impl ToString for Key {
|
|||
|
||||
cst_node!(Value, VALUE);
|
||||
|
||||
impl Value {
|
||||
pub fn text(&self) -> Option<String> {
|
||||
match CurlyGroup::cast(self.syntax().clone()) {
|
||||
Some(group) => group.content_text(),
|
||||
None => Some(self.syntax().text().to_string()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cst_node!(KeyValuePair, KEY_VALUE_PAIR);
|
||||
|
||||
impl KeyValuePair {
|
||||
|
@ -528,7 +537,11 @@ impl LabelNumber {
|
|||
}
|
||||
}
|
||||
|
||||
cst_node!(TheoremDefinition, THEOREM_DEFINITION);
|
||||
cst_node!(
|
||||
TheoremDefinition,
|
||||
THEOREM_DEFINITION_AMSTHM,
|
||||
THEOREM_DEFINITION_THMTOOLS
|
||||
);
|
||||
|
||||
impl TheoremDefinition {
|
||||
pub fn command(&self) -> Option<SyntaxToken> {
|
||||
|
@ -539,8 +552,25 @@ impl TheoremDefinition {
|
|||
self.syntax().children().find_map(CurlyGroupWord::cast)
|
||||
}
|
||||
|
||||
pub fn heading(&self) -> Option<CurlyGroup> {
|
||||
self.syntax().children().find_map(CurlyGroup::cast)
|
||||
pub fn heading(&self) -> Option<String> {
|
||||
if self.0.kind() == THEOREM_DEFINITION_THMTOOLS {
|
||||
let options = self
|
||||
.syntax()
|
||||
.children()
|
||||
.find_map(BrackGroupKeyValue::cast)
|
||||
.and_then(|group| group.body())?;
|
||||
|
||||
options
|
||||
.pairs()
|
||||
.find(|pair| pair.key().map_or(false, |key| key.to_string() == "name"))
|
||||
.and_then(|pair| pair.value())
|
||||
.and_then(|name| name.text())
|
||||
} else {
|
||||
self.syntax()
|
||||
.children()
|
||||
.find_map(CurlyGroup::cast)
|
||||
.and_then(|group| group.content_text())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -73,7 +73,8 @@ pub enum SyntaxKind {
|
|||
ACRONYM_DEFINITION,
|
||||
ACRONYM_DECLARATION,
|
||||
ACRONYM_REFERENCE,
|
||||
THEOREM_DEFINITION,
|
||||
THEOREM_DEFINITION_AMSTHM,
|
||||
THEOREM_DEFINITION_THMTOOLS,
|
||||
COLOR_REFERENCE,
|
||||
COLOR_DEFINITION,
|
||||
COLOR_SET_DEFINITION,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue