9 releases

0.3.0 Mar 20, 2024
0.2.2 May 23, 2023
0.2.1 Mar 5, 2021
0.2.0 Nov 26, 2020
0.1.4 Jul 22, 2020

#166 in Text processing

Download history 394/week @ 2023-12-18 194/week @ 2023-12-25 233/week @ 2024-01-01 155/week @ 2024-01-08 170/week @ 2024-01-15 109/week @ 2024-01-22 94/week @ 2024-01-29 157/week @ 2024-02-05 339/week @ 2024-02-12 320/week @ 2024-02-19 256/week @ 2024-02-26 405/week @ 2024-03-04 302/week @ 2024-03-11 625/week @ 2024-03-18 307/week @ 2024-03-25 1096/week @ 2024-04-01

2,436 downloads per month
Used in lang_tester

Apache-2.0/MIT

42KB
899 lines

fm

fm is a simple non-backtracking fuzzy text matcher useful for matching multi-line patterns and text. At its most basic the wildcard operator ... default) can be used in the following ways:

  • If a line consists solely of ... it means "match zero or more lines of text".
  • If a line starts with ..., the search is not anchored to the start of the line.
  • If a line ends with ..., the search is not anchored to the end of the line.

Note that ... can appear both at the start and end of a line and if a line consists of ...... (i.e. starts and ends with the wildcard with nothing inbetween), it will match exactly one line. If the wildcard operator appears in any other locations, it is matched literally. Wildcard matching does not backtrack, so if a line consists solely of ... then the next matching line anchors the remainder of the search.

The following examples show fm in action using its defaults:

use fm::FMatcher;

assert!(FMatcher::new("a").unwrap().matches("a").is_ok());
assert!(FMatcher::new(" a ").unwrap().matches("a").is_ok());
assert!(FMatcher::new("a").unwrap().matches("b").is_err());
assert!(FMatcher::new("a\n...\nb").unwrap().matches("a\na\nb").is_ok());
assert!(FMatcher::new("a\n...\nb").unwrap().matches("a\na\nb\nb").is_err());

When a match fails, the matcher returns an error indicating the line number at which the match failed. The error can be formatted for human comprehension using the provided Display implementation.

If you want to use non-default options, you will first need to use FMBuilder before having access to an FMatcher. For example, to use "name matching" (where you specify that the same chunk of text must appear at multiple points in the text, but without specifying exactly what the chunk must contain) you can set options as follows:

use {fm::FMBuilder, regex::Regex};

let ptn_re = Regex::new(r"\$.+?\b").unwrap();
let text_re = Regex::new(r".+?\b").unwrap();
let matcher = FMBuilder::new("$1 $1")
                        .unwrap()
                        .name_matcher(ptn_re, text_re)
                        .build()
                        .unwrap();
assert!(matcher.matches("a a").is_ok());
assert!(matcher.matches("a b").is_err());

Dependencies

~2.1–3MB
~53K SLoC