Skip to content

Commit

Permalink
Merge pull request #51 from ltratt/fm_0_4_0
Browse files Browse the repository at this point in the history
Prepare a 0.4.0 release.
  • Loading branch information
vext01 authored Aug 30, 2024
2 parents fab3b84 + 680444b commit ac0a253
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 50 deletions.
35 changes: 35 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,38 @@
# fm 0.4.0 (2024-08-30)

* Add the `..~` "group match" wildcard, which searches until it finds a match
for a group of lines. This means that fm now backtracks! The behaviour of the
`...` interline wildcard is unchanged, and is preferred, because it has more
predictable performance and leads to stronger tests.

* Report names matched when matching fails. When matching fails, it can be hard
to work out what went wrong, particularly when name matching is used. fm now
reports the set of names and their values at the point of failure, which
helps debug matching problems.

* Add support for "ignorable" name matchers. Sometimes one needs to match a
particular pattern, but the specific text matched is irrelevant. As a one-off
this was easily handled, but if you had multiple places where you wanted to
do this, you had to use a fresh name for each such instance, which is at best
obfuscatory and at worst error prone. Ignorable name matchers allow you to
use the same name (e.g. `_`) multiple times, each matching the same pattern,
but not comparing the text matched with other instances of the ignorable
name.

* Report the text line where pattern failed to match from. Previously when
`...` failed, it told you how-far-it-got before realising it had failed,
rather than the more useful where-it-started.

* Remove "distinct name matching" in favour of the more powerful "name
matching validator". Distinct name matching can now be expressed as:

```
.name_matching_validator(|names| {
names.values().collect::<HashSet<_>>().len() == names.len()
})
```


# fm 0.3.0 (2024-03-20)

* Add `OutputFormatter`s. The default output formatting has now changed from a
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
name = "fm"
description = "Non-backtracking fuzzy text matcher"
repository = "https://github.com/softdevteam/fm/"
version = "0.3.0"
version = "0.4.0"
authors = ["Edd Barrett <vext01@gmail.com>", "Laurence Tratt <laurie@tratt.net>"]
readme = "README.md"
license = "Apache-2.0/MIT"
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,10 @@ either:

The interline wildcards are:

* The *prefix match* wildcard `...` matches until it finds a match for the
* The *prefix match* wildcard `...` searches until it finds a match for the
line immediately after the interline operator ("the prefix"), at which
point the search is anchored. This wildcard does not backtrack.
* The *group match* wildcard `..~` matches until it finds a match for the
* The *group match* wildcard `..~` searches until it finds a match for the
next group, at which point the search is anchored. This wildcard
backtracks, though never further than one group.

Expand Down
50 changes: 3 additions & 47 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@
#![allow(clippy::type_complexity)]

use std::{
collections::{
hash_map::{Entry, HashMap},
HashSet,
},
collections::hash_map::{Entry, HashMap},
default::Default,
error::Error,
fmt,
Expand Down Expand Up @@ -180,26 +177,6 @@ impl<'a> FMBuilder<'a> {
self
}

/// If `yes`, then different names cannot match the same text value. For example if `$1` binds
/// to `a` then `$2` will refuse to match against `a` (though `$1` will continue to match
/// against only `a`). Note that ignorable name matches (see [Self::name_matcher_ignore]) are
/// never subject to distinct name matching. Defaults to `false`.
///
/// # Warning
///
/// If you call this function with `true` then later with `false`, the latter will not take
/// effect.
#[deprecated(since = "0.3.1", note = "Please use name_matching_validator instead")]
pub fn distinct_name_matching(self, yes: bool) -> Self {
if yes {
self.name_matching_validator(|names| {
names.values().collect::<HashSet<_>>().len() == names.len()
})
} else {
self
}
}

/// Add a name matching validator: this takes a [HashMap] of `(key, value)` pairs and must
/// return `true` if this is a valid set of pairs or false otherwise. Name matching validators
/// allow you to customise what names are valid matches. For example, if you want distinct
Expand Down Expand Up @@ -246,6 +223,7 @@ impl<'a> FMBuilder<'a> {
/// If `yes`, then:
/// 1. Blank lines at the start/end of the pattern and text are ignored.
/// 2. Leading/trailing whitespace is ignored on each line of the pattern and text.
///
/// Defaults to "yes".
pub fn trim_whitespace(mut self, yes: bool) -> Self {
self.options.trim_whitespace = yes;
Expand Down Expand Up @@ -693,7 +671,7 @@ impl Error for FMatchError {
/// If `trim` is set to true:
/// 1. Leading/trailing blank space within lines is trimmed.
/// 2. Leading/trailing blank lines (including blank space) are trimmed.
fn line_trimmer<'a>(trim: bool, s: &'a str) -> (Vec<&'a str>, usize) {
fn line_trimmer(trim: bool, s: &str) -> (Vec<&str>, usize) {
let mut lines = s.lines().collect::<Vec<_>>();
if !trim {
return (lines, 1);
Expand Down Expand Up @@ -1184,28 +1162,6 @@ mod tests {
assert!(!helper("$1 $2", "a a"));
}

/// This test can be removed when [FMBuilder::distinct_name_matching] is removed.
#[test]
fn distinct_names_deprecated() {
let nameptn_re = Regex::new(r"\$.+?\b").unwrap();
let name_re = Regex::new(r".+?\b").unwrap();
let helper = |ptn: &str, text: &str| -> bool {
#[allow(deprecated)]
FMBuilder::new(ptn)
.unwrap()
.name_matcher(nameptn_re.clone(), name_re.clone())
.distinct_name_matching(true)
.build()
.unwrap()
.matches(text)
.is_ok()
};

assert!(helper("$1 $1", "a a"));
assert!(!helper("$1 $1", "a b"));
assert!(!helper("$1 $2", "a a"));
}

#[test]
fn error_display() {
let ptn_re = Regex::new("\\$.+?\\b").unwrap();
Expand Down

0 comments on commit ac0a253

Please sign in to comment.