summaryrefslogtreecommitdiff
path: root/support/texlab/src/syntax/text.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/syntax/text.rs')
-rw-r--r--support/texlab/src/syntax/text.rs260
1 files changed, 0 insertions, 260 deletions
diff --git a/support/texlab/src/syntax/text.rs b/support/texlab/src/syntax/text.rs
deleted file mode 100644
index 17d6876126..0000000000
--- a/support/texlab/src/syntax/text.rs
+++ /dev/null
@@ -1,260 +0,0 @@
-use crate::protocol::{Position, Range};
-use serde::{Deserialize, Serialize};
-use std::{iter::Peekable, str::CharIndices};
-
-pub trait SyntaxNode {
- fn range(&self) -> Range;
-
- fn start(&self) -> Position {
- self.range().start
- }
-
- fn end(&self) -> Position {
- self.range().end
- }
-}
-
-#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
-#[serde(rename_all = "camelCase")]
-pub struct Span {
- pub range: Range,
- pub text: String,
-}
-
-impl Span {
- pub fn new(range: Range, text: String) -> Self {
- Self { range, text }
- }
-}
-
-impl SyntaxNode for Span {
- fn range(&self) -> Range {
- self.range
- }
-}
-
-#[derive(Debug)]
-pub struct CharStream<'a> {
- text: &'a str,
- chars: Peekable<CharIndices<'a>>,
- pub current_position: Position,
- pub current_index: usize,
- start_position: Position,
- start_index: usize,
-}
-
-impl<'a> CharStream<'a> {
- pub fn new(text: &'a str) -> Self {
- Self {
- text,
- chars: text.char_indices().peekable(),
- current_position: Position::new(0, 0),
- current_index: 0,
- start_position: Position::new(0, 0),
- start_index: 0,
- }
- }
-
- pub fn peek(&mut self) -> Option<char> {
- self.chars.peek().map(|(_, c)| *c)
- }
-
- pub fn satifies<P: FnOnce(&char) -> bool>(&mut self, predicate: P) -> bool {
- self.peek().filter(predicate).is_some()
- }
-
- pub fn skip_rest_of_line(&mut self) {
- loop {
- match self.peek() {
- Some('\n') => {
- self.next();
- break;
- }
- Some(_) => {
- self.next();
- }
- None => {
- break;
- }
- }
- }
- }
-
- pub fn start_span(&mut self) {
- self.start_index = self.current_index;
- self.start_position = self.current_position;
- }
-
- pub fn end_span(&mut self) -> Span {
- let range = Range::new(self.start_position, self.current_position);
- let text = &self.text[self.start_index..self.current_index];
- Span::new(range, text.to_owned())
- }
-
- pub fn seek(&mut self, position: Position) {
- while self.current_position < position {
- self.next();
- }
- }
-
- pub fn command(&mut self) -> Span {
- self.start_span();
- self.next();
- let mut escape = true;
- while self.satifies(|c| is_command_char(*c)) {
- self.next();
- escape = false;
- }
-
- if let Some(c) = self.peek() {
- if c != '\r' && c != '\n' && (escape || c == '*') {
- self.next();
- }
- }
-
- self.end_span()
- }
-
- fn update_position(&mut self, c: char) {
- if c == '\n' {
- self.current_position.line += 1;
- self.current_position.character = 0;
- } else {
- self.current_position.character += 1;
- }
- }
-
- pub fn extract(text: &'a str, range: Range) -> String {
- let mut stream = Self::new(text);
- stream.seek(range.start);
- stream.start_span();
- stream.seek(range.end);
- stream.end_span().text
- }
-}
-
-impl<'a> Iterator for CharStream<'a> {
- type Item = char;
-
- fn next(&mut self) -> Option<char> {
- if let Some((i, c)) = self.chars.next() {
- self.current_index = i + c.len_utf8();
- self.update_position(c);
- Some(c)
- } else {
- None
- }
- }
-}
-
-fn is_command_char(c: char) -> bool {
- c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z' || c == '@'
-}
-
-#[cfg(test)]
-mod tests {
- use super::*;
- use crate::protocol::RangeExt;
-
- #[test]
- fn peek() {
- let mut stream = CharStream::new("ab\nc");
- assert_eq!(Some('a'), stream.peek());
- assert_eq!(Some('a'), stream.next());
- assert_eq!(Some('b'), stream.peek());
- assert_eq!(Some('b'), stream.next());
- assert_eq!(Some('\n'), stream.peek());
- assert_eq!(Some('\n'), stream.next());
- assert_eq!(Some('c'), stream.peek());
- assert_eq!(Some('c'), stream.next());
- assert_eq!(None, stream.peek());
- assert_eq!(None, stream.next());
- }
-
- #[test]
- fn span() {
- let mut stream = CharStream::new("abc\ndef");
- stream.next();
- stream.start_span();
- stream.next();
- stream.next();
- let span = stream.end_span();
- assert_eq!(
- Span::new(Range::new_simple(0, 1, 0, 3), "bc".to_owned()),
- span
- );
- assert_eq!(Position::new(0, 1), span.start());
- assert_eq!(Position::new(0, 3), span.end());
- }
-
- #[test]
- fn span_unicode() {
- let mut stream = CharStream::new("😀😃😄😁");
- stream.next();
- stream.start_span();
- stream.next();
- stream.next();
- let span = stream.end_span();
- assert_eq!(
- Span::new(Range::new_simple(0, 1, 0, 3), "😃😄".to_owned()),
- span
- );
- }
-
- #[test]
- fn satifies() {
- let mut stream = CharStream::new("aBc");
- assert_eq!(true, stream.satifies(|c| c.is_lowercase()));
- stream.next();
- assert_eq!(false, stream.satifies(|c| c.is_lowercase()));
- }
-
- #[test]
- fn skip_rest_of_line() {
- let mut stream = CharStream::new("abc\ndef");
- stream.skip_rest_of_line();
- assert_eq!(Some('d'), stream.next());
- stream.skip_rest_of_line();
- assert_eq!(None, stream.next());
- stream.skip_rest_of_line();
- assert_eq!(None, stream.next());
- }
-
- #[test]
- fn seek() {
- let mut stream = CharStream::new("abc\ndefghi");
- let pos = Position::new(1, 2);
- stream.seek(pos);
- assert_eq!(Some('f'), stream.peek());
- }
-
- #[test]
- fn command_basic() {
- let mut stream = CharStream::new("\\foo@bar");
- let span = stream.command();
- assert_eq!(
- Span::new(Range::new_simple(0, 0, 0, 8), "\\foo@bar".to_owned()),
- span
- );
- }
-
- #[test]
- fn command_star() {
- let mut stream = CharStream::new("\\foo*");
- let span = stream.command();
- assert_eq!(
- Span::new(Range::new_simple(0, 0, 0, 5), "\\foo*".to_owned()),
- span
- );
- }
-
- #[test]
- fn command_escape() {
- let mut stream = CharStream::new("\\**");
- let span = stream.command();
- assert_eq!(
- Span::new(Range::new_simple(0, 0, 0, 2), "\\*".to_owned()),
- span
- );
- }
-}