From 357b1df803ef57171b237deb13aad09f53946d82 Mon Sep 17 00:00:00 2001 From: Riccardo Mazzarini Date: Sun, 26 Nov 2023 18:27:36 +0100 Subject: [PATCH] update `Metric` docs --- src/metric.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 74 insertions(+), 5 deletions(-) diff --git a/src/metric.rs b/src/metric.rs index 5dada59..bcd0d42 100644 --- a/src/metric.rs +++ b/src/metric.rs @@ -29,7 +29,7 @@ pub trait Metric { /// ``` /// /// if and only if `a` is a better match than `b`. In other words, a lower - /// distance value must indicate a closer or more relevant match. + /// distance value must indicate a more relevant match. type Distance: Ord; /// This method calculates the "distance" between an instance of the @@ -48,10 +48,79 @@ pub trait Metric { candidate: &str, ) -> Option; - /// This method always returns the same value as [`Self::distance`], but in - /// the case of a match it also fills the provided buffer with the **byte** - /// ranges of the candidate that matched the query. If the candidate does - /// not match the query, the buffer is left untouched. + /// This method has the same semantics and return value as + /// [`Self::distance`], but in the case of a match it also appends the + /// **byte** ranges of the candidate that matched the query to the provided + /// buffer. + /// + /// The appended ranges are guaranteed to be non-overlapping, but the order + /// in which they are appended is not specified by this trait's contract. + /// Any [`Metric`] implementation is free to choose its order as long as + /// the ranges don't overlap. + /// + /// If the candidate doesn't match the query, the buffer is left untouched. + /// + /// # Examples + /// + /// ```rust + /// # use norm::fzf::{FzfV1, FzfParser}; + /// # use norm::Metric; + /// let mut fzf = FzfV1::new(); + /// let mut parser = FzfParser::new(); + /// let mut ranges = Vec::new(); + /// + /// let query = parser.parse("foo"); + /// + /// let distance = fzf.distance_and_ranges(query, "bar", &mut ranges); + /// + /// assert!(distance.is_none()); + /// + /// // The candidate wasn't a match, so `ranges` is still empty. + /// assert!(ranges.is_empty()); + /// ``` + /// + /// ```rust + /// # use norm::fzf::{FzfV1, FzfParser}; + /// # use norm::Metric; + /// let mut fzf = FzfV1::new(); + /// let mut parser = FzfParser::new(); + /// let mut ranges = Vec::new(); + /// + /// let query = parser.parse("foo"); + /// + /// let _ = fzf.distance_and_ranges(query, "seafood", &mut ranges); + /// + /// // There was a match, so the vector should now contain the byte range + /// // of "foo" in "seafood". + /// assert_eq!(ranges, [3..6]); + /// + /// let _ = fzf.distance_and_ranges(query, "fancy igloo", &mut ranges); + /// + /// // You can call `distance_and_ranges` multiple times with the same + /// // vector, and it will keep appending to it. + /// // + /// // In this case, it appended the byte ranges of "f" and "oo" in + /// // "fancy igloo". + /// assert_eq!(ranges, [3..6, 0..1, 9..11]); + /// ``` + /// + /// ```rust + /// # use norm::fzf::{FzfV1, FzfParser}; + /// # use norm::Metric; + /// let mut fzf = FzfV1::new(); + /// let mut parser = FzfParser::new(); + /// let mut ranges = Vec::new(); + /// + /// fzf.set_normalization(true); + /// + /// let query = parser.parse("foo"); + /// + /// let _ = fzf.distance_and_ranges(query, "ƒöö", &mut ranges); + /// + /// // The start and end of each range are always byte offsets, not + /// // character offsets. + /// assert_eq!(ranges, [0..6]); + /// ``` fn distance_and_ranges( &mut self, query: Self::Query<'_>,