summaryrefslogtreecommitdiff
path: root/support/texlab/src/syntax/latex/cst.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/syntax/latex/cst.rs')
-rw-r--r--support/texlab/src/syntax/latex/cst.rs52
1 files changed, 36 insertions, 16 deletions
diff --git a/support/texlab/src/syntax/latex/cst.rs b/support/texlab/src/syntax/latex/cst.rs
index 0b839b706d..a800236ebf 100644
--- a/support/texlab/src/syntax/latex/cst.rs
+++ b/support/texlab/src/syntax/latex/cst.rs
@@ -1,4 +1,5 @@
use cstree::TextRange;
+use itertools::{EitherOrBoth, Itertools};
use crate::syntax::CstNode;
@@ -6,7 +7,7 @@ use super::{Language, SyntaxKind::*, SyntaxNode, SyntaxToken};
macro_rules! cst_node {
($name:ident, $($kind:pat),+) => {
- #[derive(Clone)]
+ #[derive(Clone, Copy)]
#[repr(transparent)]
pub struct $name<'a>(&'a SyntaxNode);
@@ -45,6 +46,15 @@ macro_rules! cst_node {
cst_node!(Text, TEXT);
+impl<'a> Text<'a> {
+ pub fn words(&self) -> impl Iterator<Item = &'a SyntaxToken> {
+ self.syntax()
+ .children_with_tokens()
+ .filter_map(|node| node.into_token())
+ .filter(|node| node.kind() == WORD)
+ }
+}
+
pub trait HasCurly<'a>: CstNode<'a, Lang = Language> {
fn left_curly(&self) -> Option<&'a SyntaxToken> {
self.syntax()
@@ -168,11 +178,8 @@ cst_node!(CurlyGroupWord, CURLY_GROUP_WORD);
impl<'a> HasCurly<'a> for CurlyGroupWord<'a> {}
impl<'a> CurlyGroupWord<'a> {
- pub fn word(&self) -> Option<&'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .find(|node| node.kind() == WORD)
+ pub fn key(&self) -> Option<Key<'a>> {
+ self.syntax().children().find_map(Key::cast)
}
}
@@ -181,11 +188,8 @@ cst_node!(BrackGroupWord, BRACK_GROUP_WORD);
impl<'a> HasBrack<'a> for BrackGroupWord<'a> {}
impl<'a> BrackGroupWord<'a> {
- pub fn word(&self) -> Option<&'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .find(|node| node.kind() == WORD)
+ pub fn key(&self) -> Option<Key<'a>> {
+ self.syntax().children().find_map(Key::cast)
}
}
@@ -194,11 +198,8 @@ cst_node!(CurlyGroupWordList, CURLY_GROUP_WORD_LIST);
impl<'a> HasCurly<'a> for CurlyGroupWordList<'a> {}
impl<'a> CurlyGroupWordList<'a> {
- pub fn words(&self) -> impl Iterator<Item = &'a SyntaxToken> {
- self.syntax()
- .children_with_tokens()
- .filter_map(|node| node.into_token())
- .filter(|node| node.kind() == WORD)
+ pub fn keys(&self) -> impl Iterator<Item = Key<'a>> {
+ self.syntax().children().filter_map(Key::cast)
}
}
@@ -226,6 +227,25 @@ impl<'a> Key<'a> {
}
}
+impl<'a> PartialEq for Key<'a> {
+ fn eq(&self, other: &Self) -> bool {
+ self.words()
+ .zip_longest(other.words())
+ .all(|result| match result {
+ EitherOrBoth::Both(left, right) => left.text() == right.text(),
+ EitherOrBoth::Left(_) | EitherOrBoth::Right(_) => false,
+ })
+ }
+}
+
+impl<'a> Eq for Key<'a> {}
+
+impl<'a> ToString for Key<'a> {
+ fn to_string(&self) -> String {
+ self.words().map(|word| word.text()).join(" ")
+ }
+}
+
cst_node!(Value, VALUE);
cst_node!(KeyValuePair, KEY_VALUE_PAIR);