use crate::Token;
use super::Step;
pub struct AnchorEnd;
impl Step for AnchorEnd {
fn step(&self, tokens: &[Token], cursor: usize, _source: &[char]) -> Option<isize> {
let last_non_ws = tokens
.iter()
.enumerate()
.rev()
.filter(|(_, t)| !t.kind.is_whitespace())
.map(|(i, _)| i)
.next();
if let Some(last) = last_non_ws
&& cursor >= last
{
return Some(0);
}
None
}
}
#[cfg(test)]
mod tests {
use crate::expr::{AnchorStart, ExprExt, SequenceExpr};
use crate::{Document, Span, TokenStringExt};
use super::AnchorEnd;
#[test]
fn matches_period() {
let document = Document::new_markdown_default_curated("This is a test.");
let matches: Vec<_> = AnchorEnd.iter_matches_in_doc(&document).collect();
assert_eq!(matches, vec![Span::new(7, 7)])
}
#[test]
fn does_not_match_empty() {
let document = Document::new_markdown_default_curated("");
let matches: Vec<_> = AnchorEnd.iter_matches_in_doc(&document).collect();
assert_eq!(matches, vec![])
}
#[test]
fn test_word_at_end_of_document() {
let document = Document::new_plain_english_curated("This is the end");
let expr = SequenceExpr::default()
.then_any_capitalization_of("end")
.then(AnchorEnd);
let matches: Vec<_> = expr.iter_matches_in_doc(&document).collect();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].start, 6);
}
#[test]
fn test_word_not_at_end_of_doc() {
let document = Document::new_plain_english_curated("This is the end, really");
let expr = SequenceExpr::default()
.then_any_capitalization_of("end")
.then(AnchorEnd);
let matches: Vec<_> = expr.iter_matches_in_doc(&document).collect();
assert_eq!(matches.len(), 0);
}
#[test]
fn test_word_at_end_of_chunk() {
let document = Document::new_plain_english_curated("hello, world");
let expr = SequenceExpr::default()
.then_any_capitalization_of("hello")
.then(AnchorEnd);
let first_chunk = document.iter_chunks().next().unwrap();
let matches: Vec<_> = expr
.iter_matches(first_chunk, document.get_source())
.collect();
assert_eq!(matches.len(), 1);
}
#[test]
fn test_compare_with_anchor_start() {
let document = Document::new_plain_english_curated("Start here");
let expr = SequenceExpr::default()
.then(AnchorStart)
.then_any_capitalization_of("start");
let matches: Vec<_> = expr.iter_matches_in_doc(&document).collect();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].start, 0);
}
#[test]
fn test_word_with_trailing_whitespace_at_end_of_doc() {
let document = Document::new_plain_english_curated("foo ");
let expr = SequenceExpr::default()
.then_any_capitalization_of("foo")
.then_whitespace()
.then(AnchorEnd);
let matches: Vec<_> = expr.iter_matches_in_doc(&document).collect();
assert_eq!(matches.len(), 1);
assert_eq!(matches[0].end, 2);
}
}